@vmz/plugin-codemirror 0.0.0 β†’ 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,36 @@
1
1
  # @vmz/plugin-codemirror
2
2
 
3
- Placeholder package (0.0.0). Reserved for the VMZ project.
3
+ ## A capable editor without making every page an IDE
4
+
5
+ `@vmz/plugin-codemirror` brings CodeMirror 6 into VMZ applications. It is a strong choice for embedded editors,
6
+ documentation playgrounds, configuration surfaces, query builders, note-taking tools, and products that need serious
7
+ text editing while still respecting browser cost.
8
+
9
+ ## Why choose CodeMirror
10
+
11
+ CodeMirror is generally the lighter editor option in the VMZ ecosystem. It offers a flexible modern editing foundation
12
+ without assuming that every application needs the full weight of a desktop-IDE experience. That makes it especially
13
+ suitable when an editor is one interaction region inside an otherwise content- or data-oriented page.
14
+
15
+ Choose CodeMirror when you want a balanced editor. Choose `@vmz/plugin-monaco` when rich IDE-like behavior and VS Code
16
+ familiarity outweigh the additional delivery cost.
17
+
18
+ | Good fit | Less suitable |
19
+ |-------------------------------------------------------|----------------------------------------------------------|
20
+ | Embedded editors, playgrounds, and configurable tools | A product that requires the deepest IDE-style experience |
21
+ | Pages where editor weight still matters | A tiny input field that needs no code-editing behavior |
22
+
23
+ ## VMZ boundary
24
+
25
+ The editor is an interactive capability, not the page's architecture. VMZ remains responsible for deciding when the
26
+ editor code is delivered, how its region resumes, and how the rest of the page remains SSR-readable and independently
27
+ testable.
28
+
29
+ ## Product scenarios πŸ“
30
+
31
+ - A documentation playground that activates only when the reader starts editing.
32
+ - A query, rule, or configuration editor inside a larger operational UI.
33
+ - A focused coding exercise that does not need a full IDE workbench.
34
+ - A structured text tool whose extensions are chosen for the domain.
35
+
36
+ The surrounding page should load as a normal VMZ page. The editor region becomes interactive when needed and owns its state and lifetime without forcing unrelated content into an eager client shell. That is why CodeMirror is often an intentional choice, not merely β€œthe smaller Monaco.”
@@ -0,0 +1,33 @@
1
+ <template>
2
+ <div class="codemirror-host" data-vmz-codemirror style="min-height: 200px; width: 100%"></div>
3
+ </template>
4
+
5
+ <script client>
6
+ import { mountCodemirror } from '@vmz/plugin-codemirror/runtime';
7
+
8
+ export default class Codemirror {
9
+ public value: string = '';
10
+
11
+ #api: { dispose: () => void } | null = null;
12
+
13
+ async onMount() {
14
+ const root = this.__vmzDomRoot;
15
+ const el =
16
+ (root && root.nodeType === 1 && root.matches?.('[data-vmz-codemirror]') && root) ||
17
+ root?.querySelector?.('[data-vmz-codemirror]') ||
18
+ root;
19
+ if (!el || el.nodeType !== 1) return;
20
+ this.#api = await mountCodemirror(el, {
21
+ value: this.value,
22
+ onChange: (v) => {
23
+ this.value = v;
24
+ },
25
+ });
26
+ }
27
+
28
+ onDestroy() {
29
+ this.#api?.dispose();
30
+ this.#api = null;
31
+ }
32
+ }
33
+ </script>
package/package.json CHANGED
@@ -1,10 +1,40 @@
1
1
  {
2
2
  "name": "@vmz/plugin-codemirror",
3
- "version": "0.0.0",
4
- "description": "VMZ placeholder β€” not for production use.",
3
+ "version": "0.0.2",
4
+ "type": "module",
5
+ "description": "VMZ CodeMirror 6 editor adapter - <Codemirror>",
5
6
  "license": "MIT",
6
- "private": false,
7
- "files": [
8
- "README.md"
9
- ]
7
+ "main": "./vmz.plugin.ts",
8
+ "types": "./vmz.plugin.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./vmz.plugin.ts",
12
+ "default": "./vmz.plugin.ts"
13
+ },
14
+ "./runtime": {
15
+ "types": "./runtime.ts",
16
+ "default": "./runtime.ts"
17
+ }
18
+ },
19
+ "dependencies": {
20
+ "@vmz/plugin": "0.0.2"
21
+ },
22
+ "peerDependencies": {
23
+ "codemirror": ">=6",
24
+ "@codemirror/view": ">=6",
25
+ "@codemirror/state": ">=6"
26
+ },
27
+ "keywords": [
28
+ "vmz",
29
+ "plugin",
30
+ "codemirror",
31
+ "editor"
32
+ ],
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/doki-land/vmz-framework.git"
39
+ }
10
40
  }
package/runtime.ts ADDED
@@ -0,0 +1,40 @@
1
+ /**
2
+ * CodeMirror 6 mount helper (browser).
3
+ */
4
+
5
+ export type MountCodemirrorOptions = {
6
+ value?: string;
7
+ onChange?: (v: string) => void;
8
+ };
9
+
10
+ export async function mountCodemirror(el: HTMLElement, opts: MountCodemirrorOptions = {}) {
11
+ const { EditorView, basicSetup } = await import('codemirror').catch(async () => {
12
+ const view = await import('@codemirror/view');
13
+ const state = await import('@codemirror/state');
14
+ return {
15
+ EditorView: view.EditorView,
16
+ basicSetup: [] as unknown[],
17
+ EditorState: state.EditorState,
18
+ };
19
+ });
20
+ const { EditorState } = await import('@codemirror/state');
21
+ const sync = EditorView.updateListener.of((u) => {
22
+ if (u.docChanged && typeof opts.onChange === 'function') {
23
+ opts.onChange(u.state.doc.toString());
24
+ }
25
+ });
26
+ const state = EditorState.create({
27
+ doc: opts.value ?? '',
28
+ extensions: [basicSetup, sync].flat().filter(Boolean),
29
+ });
30
+ const view = new EditorView({ state, parent: el });
31
+ return {
32
+ view,
33
+ getValue: () => view.state.doc.toString(),
34
+ setValue: (v: string) =>
35
+ view.dispatch({
36
+ changes: { from: 0, to: view.state.doc.length, insert: v ?? '' },
37
+ }),
38
+ dispose: () => view.destroy(),
39
+ };
40
+ }
package/vmz.plugin.ts ADDED
@@ -0,0 +1,46 @@
1
+ import { definePlugin, loadPluginSource } from '@vmz/plugin';
2
+
3
+ const source = loadPluginSource(import.meta.url, 'components/Codemirror.vmz');
4
+
5
+ export default definePlugin({
6
+ name: '@vmz/plugin-codemirror',
7
+ version: '0.1.0',
8
+ protocol: '0.1.0',
9
+ stages: ['workspace_resolve', 'analyzer'],
10
+ deterministic: true,
11
+ async contribute(ctx) {
12
+ if (ctx.stage === 'workspace_resolve') {
13
+ return {
14
+ stage: 'workspace_resolve',
15
+ cacheKey: `@vmz/plugin-codemirror:Codemirror.vmz:${source.contentHash.slice(0, 12)}`,
16
+ items: [
17
+ {
18
+ id: 'component-codemirror',
19
+ kind: 'source',
20
+ path: 'src/components/Codemirror.vmz',
21
+ content: source.content,
22
+ contentHash: source.contentHash,
23
+ materialize: true,
24
+ },
25
+ ],
26
+ };
27
+ }
28
+ if (ctx.stage === 'analyzer') {
29
+ return {
30
+ stage: 'analyzer',
31
+ cacheKey: '@vmz/plugin-codemirror:analyzer',
32
+ items: [
33
+ {
34
+ id: 'component-codemirror-online',
35
+ kind: 'analyzer',
36
+ path: 'src/components/Codemirror.vmz',
37
+ severity: 'advice',
38
+ message: 'Codemirror component online',
39
+ code: 'vmz.plugin.codemirror',
40
+ },
41
+ ],
42
+ };
43
+ }
44
+ return { stage: ctx.stage, items: [] };
45
+ },
46
+ });