@vmz/plugin-codemirror 0.0.0 β 0.0.3
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 +36 -1
- package/components/Codemirror.vmz +33 -0
- package/package.json +36 -6
- package/runtime.ts +40 -0
- package/vmz.plugin.ts +46 -0
package/README.md
CHANGED
|
@@ -1,3 +1,38 @@
|
|
|
1
1
|
# @vmz/plugin-codemirror
|
|
2
2
|
|
|
3
|
-
|
|
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
|
|
37
|
+
state and lifetime without forcing unrelated content into an eager client shell. That is why CodeMirror is often an
|
|
38
|
+
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.
|
|
4
|
-
"
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "VMZ CodeMirror 6 editor adapter - <Codemirror>",
|
|
5
6
|
"license": "MIT",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
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.3"
|
|
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
|
+
});
|