@milkdown/vue 5.2.1 → 5.3.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/lib/index.d.ts +1 -3
- package/lib/index.es.js +161 -105
- package/lib/index.es.js.map +1 -1
- package/lib/src/Editor.d.ts +27 -0
- package/lib/src/Editor.d.ts.map +1 -0
- package/lib/src/VueNode.d.ts +18 -0
- package/lib/src/VueNode.d.ts.map +1 -0
- package/lib/{VueNodeView.d.ts → src/VueNodeView.d.ts} +9 -5
- package/lib/src/VueNodeView.d.ts.map +1 -0
- package/lib/src/index.d.ts +3 -0
- package/lib/src/index.d.ts.map +1 -0
- package/lib/{utils.d.ts → src/utils.d.ts} +2 -0
- package/lib/src/utils.d.ts.map +1 -0
- package/package.json +11 -20
- package/src/Editor.tsx +68 -33
- package/src/VueNode.tsx +22 -18
- package/src/VueNodeView.tsx +85 -40
- package/src/utils.ts +5 -0
- package/lib/Editor.d.ts +0 -25
- package/lib/Editor.d.ts.map +0 -1
- package/lib/Portals.d.ts +0 -8
- package/lib/Portals.d.ts.map +0 -1
- package/lib/VueNode.d.ts +0 -27
- package/lib/VueNode.d.ts.map +0 -1
- package/lib/VueNodeView.d.ts.map +0 -1
- package/lib/index.cjs.js +0 -3
- package/lib/index.cjs.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/utils.d.ts.map +0 -1
- package/src/Portals.tsx +0 -31
package/lib/index.d.ts
CHANGED
package/lib/index.es.js
CHANGED
|
@@ -1,62 +1,54 @@
|
|
|
1
|
-
import { defineComponent,
|
|
1
|
+
import { defineComponent, provide, createVNode, Teleport, markRaw, shallowReactive, getCurrentInstance, onBeforeMount, onUnmounted, isVNode, ref, inject, onMounted } from "vue";
|
|
2
2
|
import { editorViewCtx, rootCtx } from "@milkdown/core";
|
|
3
3
|
import { Mark, Node } from "@milkdown/prose";
|
|
4
4
|
import { customAlphabet } from "nanoid";
|
|
5
|
-
const getId = (pairs) => pairs.map((p) => p[0]).join("\n");
|
|
6
|
-
const Portals = defineComponent((props) => {
|
|
7
|
-
const portalComponents = shallowRef([]);
|
|
8
|
-
const prev = ref("");
|
|
9
|
-
const renderList = shallowRef(() => []);
|
|
10
|
-
watch(() => getId(props.portals), (ids) => {
|
|
11
|
-
if (ids !== prev.value) {
|
|
12
|
-
prev.value = ids;
|
|
13
|
-
const next = props.portals.map((p) => p[1]);
|
|
14
|
-
portalComponents.value = next;
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
nextTick(() => {
|
|
18
|
-
renderList.value = () => portalComponents.value.map((P) => createVNode(P, null, null));
|
|
19
|
-
});
|
|
20
|
-
return () => {
|
|
21
|
-
return createVNode(Fragment, null, [renderList.value()]);
|
|
22
|
-
};
|
|
23
|
-
});
|
|
24
|
-
Portals.props = ["portals"];
|
|
25
5
|
const nodeMetadata = Symbol();
|
|
26
|
-
const VueNodeContainer = defineComponent(
|
|
27
|
-
node,
|
|
28
|
-
|
|
29
|
-
getPos,
|
|
30
|
-
decorations
|
|
31
|
-
}, context) => {
|
|
32
|
-
provide(nodeMetadata, {
|
|
6
|
+
const VueNodeContainer = defineComponent({
|
|
7
|
+
name: "milkdown-node-container",
|
|
8
|
+
setup: ({
|
|
33
9
|
node,
|
|
34
10
|
view,
|
|
35
11
|
getPos,
|
|
36
|
-
decorations
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
12
|
+
decorations,
|
|
13
|
+
ctx
|
|
14
|
+
}, context) => {
|
|
15
|
+
provide(nodeMetadata, {
|
|
16
|
+
ctx,
|
|
17
|
+
node,
|
|
18
|
+
view,
|
|
19
|
+
getPos,
|
|
20
|
+
decorations
|
|
21
|
+
});
|
|
22
|
+
return () => {
|
|
23
|
+
var _a, _b;
|
|
24
|
+
return createVNode("div", {
|
|
25
|
+
"data-view-container": true
|
|
26
|
+
}, [(_b = (_a = context.slots).default) == null ? void 0 : _b.call(_a)]);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
42
29
|
});
|
|
43
|
-
VueNodeContainer.props = ["editor", "node", "view", "getPos", "decorations"];
|
|
44
|
-
const Content = defineComponent(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
30
|
+
VueNodeContainer.props = ["ctx", "editor", "node", "view", "getPos", "decorations"];
|
|
31
|
+
const Content = defineComponent({
|
|
32
|
+
name: "milkdown-content",
|
|
33
|
+
setup: ({
|
|
34
|
+
isInline
|
|
35
|
+
}) => {
|
|
36
|
+
return () => isInline ? createVNode("span", {
|
|
37
|
+
"data-view-content": true
|
|
38
|
+
}, null) : createVNode("div", {
|
|
39
|
+
"data-view-content": true
|
|
40
|
+
}, null);
|
|
41
|
+
}
|
|
54
42
|
});
|
|
55
|
-
Content.props = ["
|
|
43
|
+
Content.props = ["isMark"];
|
|
56
44
|
const nanoid = customAlphabet("abcedfghicklmn", 10);
|
|
57
|
-
const createVueView = (addPortal, removePortalByKey) => (component) => (node, view, getPos, decorations) => new VueNodeView(component, addPortal, removePortalByKey, node, view, getPos, decorations);
|
|
45
|
+
const createVueView = (addPortal, removePortalByKey) => (component) => (ctx) => (node, view, getPos, decorations) => new VueNodeView(ctx, component, addPortal, removePortalByKey, node, view, getPos, decorations);
|
|
58
46
|
class VueNodeView {
|
|
59
|
-
|
|
47
|
+
get isInlineOrMark() {
|
|
48
|
+
return this.node instanceof Mark || this.node.isInline;
|
|
49
|
+
}
|
|
50
|
+
constructor(ctx, component, addPortal, removePortalByKey, node, view, getPos, decorations) {
|
|
51
|
+
this.ctx = ctx;
|
|
60
52
|
this.component = component;
|
|
61
53
|
this.addPortal = addPortal;
|
|
62
54
|
this.removePortalByKey = removePortalByKey;
|
|
@@ -65,54 +57,89 @@ class VueNodeView {
|
|
|
65
57
|
this.getPos = getPos;
|
|
66
58
|
this.decorations = decorations;
|
|
67
59
|
this.key = nanoid();
|
|
68
|
-
|
|
69
|
-
dom.classList.add("dom-wrapper");
|
|
70
|
-
const contentDOM = node instanceof Node && node.isLeaf ? void 0 : document.createElement(node instanceof Mark ? "span" : "div");
|
|
71
|
-
if (contentDOM) {
|
|
72
|
-
contentDOM.classList.add("content-dom");
|
|
73
|
-
dom.appendChild(contentDOM);
|
|
74
|
-
}
|
|
75
|
-
this.dom = dom;
|
|
76
|
-
this.contentDOM = contentDOM;
|
|
60
|
+
this.teleportDOM = document.createElement(this.isInlineOrMark ? "span" : "div");
|
|
77
61
|
this.renderPortal();
|
|
78
62
|
}
|
|
63
|
+
get dom() {
|
|
64
|
+
return this.teleportDOM.firstElementChild || this.teleportDOM;
|
|
65
|
+
}
|
|
66
|
+
get contentDOM() {
|
|
67
|
+
if (this.node instanceof Node && this.node.isLeaf) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
return this.teleportDOM.querySelector("[data-view-content]") || this.dom;
|
|
71
|
+
}
|
|
79
72
|
renderPortal() {
|
|
80
|
-
if (!this.
|
|
73
|
+
if (!this.teleportDOM)
|
|
81
74
|
return;
|
|
82
75
|
const CustomComponent = this.component;
|
|
83
|
-
const Portal = defineComponent(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
default: () => [createVNode(VueNodeContainer, {
|
|
76
|
+
const Portal = defineComponent({
|
|
77
|
+
name: "milkdown-portal",
|
|
78
|
+
setup: () => {
|
|
79
|
+
return () => createVNode(Teleport, {
|
|
88
80
|
"key": this.key,
|
|
89
|
-
"
|
|
90
|
-
"view": this.view,
|
|
91
|
-
"getPos": this.getPos,
|
|
92
|
-
"decorations": this.decorations
|
|
81
|
+
"to": this.teleportDOM
|
|
93
82
|
}, {
|
|
94
|
-
default: () => [createVNode(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
83
|
+
default: () => [createVNode(VueNodeContainer, {
|
|
84
|
+
"ctx": this.ctx,
|
|
85
|
+
"node": this.node,
|
|
86
|
+
"view": this.view,
|
|
87
|
+
"getPos": this.getPos,
|
|
88
|
+
"decorations": this.decorations
|
|
89
|
+
}, {
|
|
90
|
+
default: () => [createVNode(CustomComponent, null, {
|
|
91
|
+
default: () => [createVNode(Content, {
|
|
92
|
+
"isInline": this.isInlineOrMark
|
|
93
|
+
}, null)]
|
|
94
|
+
})]
|
|
98
95
|
})]
|
|
99
|
-
})
|
|
100
|
-
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
101
98
|
});
|
|
102
|
-
this.addPortal(Portal, this.key);
|
|
99
|
+
this.addPortal(markRaw(Portal), this.key);
|
|
100
|
+
const instance = getRootInstance();
|
|
101
|
+
if (instance) {
|
|
102
|
+
instance.update();
|
|
103
|
+
}
|
|
103
104
|
}
|
|
104
105
|
destroy() {
|
|
105
|
-
this.dom = void 0;
|
|
106
|
-
this.contentDOM = void 0;
|
|
107
106
|
this.removePortalByKey(this.key);
|
|
108
107
|
}
|
|
109
108
|
ignoreMutation(mutation) {
|
|
110
|
-
if (!this.contentDOM) {
|
|
109
|
+
if (!this.dom || !this.contentDOM) {
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
if (this.node instanceof Node) {
|
|
113
|
+
if (this.node.isLeaf || this.node.isAtom) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (mutation.type === "selection") {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if (this.contentDOM === this.dom) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
if (this.contentDOM.contains(mutation.target)) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
update(node, decorations) {
|
|
129
|
+
if (this.node.type !== node.type) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
if (node === this.node && this.decorations === decorations) {
|
|
111
133
|
return true;
|
|
112
134
|
}
|
|
113
|
-
|
|
135
|
+
this.node = node;
|
|
136
|
+
this.decorations = decorations;
|
|
137
|
+
return true;
|
|
114
138
|
}
|
|
115
139
|
}
|
|
140
|
+
function _isSlot(s) {
|
|
141
|
+
return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
|
|
142
|
+
}
|
|
116
143
|
const rendererKey = Symbol();
|
|
117
144
|
const useGetEditor = (getEditor) => {
|
|
118
145
|
const divRef = ref(null);
|
|
@@ -140,40 +167,69 @@ const useGetEditor = (getEditor) => {
|
|
|
140
167
|
editorRef
|
|
141
168
|
};
|
|
142
169
|
};
|
|
143
|
-
const EditorComponent = defineComponent(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
170
|
+
const EditorComponent = defineComponent({
|
|
171
|
+
name: "milkdown-dom-root",
|
|
172
|
+
setup: (props, {
|
|
173
|
+
slots
|
|
174
|
+
}) => {
|
|
175
|
+
const refs = useGetEditor(props.editor);
|
|
176
|
+
if (props.editorRef) {
|
|
177
|
+
props.editorRef.value = {
|
|
178
|
+
get: () => refs.editorRef.editor,
|
|
179
|
+
dom: () => refs.divRef.value
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return () => {
|
|
183
|
+
var _a;
|
|
184
|
+
return createVNode("div", {
|
|
185
|
+
"ref": refs.divRef
|
|
186
|
+
}, [(_a = slots.default) == null ? void 0 : _a.call(slots)]);
|
|
149
187
|
};
|
|
150
188
|
}
|
|
151
|
-
return () => createVNode("div", {
|
|
152
|
-
"ref": refs.divRef
|
|
153
|
-
}, null);
|
|
154
189
|
});
|
|
155
190
|
EditorComponent.props = ["editor", "editorRef"];
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
191
|
+
const rootInstance = {
|
|
192
|
+
instance: null
|
|
193
|
+
};
|
|
194
|
+
const getRootInstance = () => {
|
|
195
|
+
return rootInstance.instance;
|
|
196
|
+
};
|
|
197
|
+
const VueEditor = defineComponent({
|
|
198
|
+
name: "milkdown-vue-root",
|
|
199
|
+
setup: (props) => {
|
|
200
|
+
const portals = shallowReactive([]);
|
|
201
|
+
const instance = getCurrentInstance();
|
|
202
|
+
onBeforeMount(() => {
|
|
203
|
+
rootInstance.instance = instance.ctx._;
|
|
204
|
+
});
|
|
205
|
+
onUnmounted(() => {
|
|
206
|
+
rootInstance.instance = null;
|
|
207
|
+
});
|
|
208
|
+
const addPortal = markRaw((component, key) => {
|
|
209
|
+
portals.push([key, component]);
|
|
210
|
+
});
|
|
211
|
+
const removePortalByKey = markRaw((key) => {
|
|
212
|
+
const index = portals.findIndex((p) => p[0] === key);
|
|
213
|
+
portals.splice(index, 1);
|
|
214
|
+
});
|
|
215
|
+
const renderVue = createVueView(addPortal, removePortalByKey);
|
|
216
|
+
provide(rendererKey, renderVue);
|
|
217
|
+
return () => {
|
|
218
|
+
const portalElements = portals.map(([id, P]) => createVNode(P, {
|
|
219
|
+
"key": id
|
|
220
|
+
}, null));
|
|
221
|
+
return createVNode(EditorComponent, {
|
|
222
|
+
"editorRef": props.editorRef,
|
|
223
|
+
"editor": props.editor
|
|
224
|
+
}, _isSlot(portalElements) ? portalElements : {
|
|
225
|
+
default: () => [portalElements]
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
}
|
|
173
229
|
});
|
|
174
230
|
VueEditor.props = ["editor", "editorRef"];
|
|
175
231
|
const useEditor = (getEditor) => {
|
|
176
232
|
return (...args) => getEditor(...args);
|
|
177
233
|
};
|
|
178
|
-
export { EditorComponent, VueEditor, nodeMetadata, useEditor };
|
|
234
|
+
export { EditorComponent, VueEditor, getRootInstance, nodeMetadata, useEditor };
|
|
179
235
|
//# sourceMappingURL=index.es.js.map
|
package/lib/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../src/Portals.tsx","../src/VueNode.tsx","../src/VueNodeView.tsx","../src/Editor.tsx"],"sourcesContent":["/* Copyright 2021, Milkdown by Mirone. */\nimport { DefineComponent, defineComponent, Fragment, h, nextTick, ref, shallowRef, watch } from 'vue';\nexport type PortalPair = [key: string, component: DefineComponent];\n\nconst getId = (pairs: PortalPair[]) => pairs.map((p) => p[0]).join('\\n');\n\nexport const Portals = defineComponent((props: { portals: PortalPair[] }) => {\n const portalComponents = shallowRef<Array<DefineComponent>>([]);\n const prev = ref<string>('');\n const renderList = shallowRef<() => JSX.Element[]>(() => []);\n\n watch(\n () => getId(props.portals),\n (ids) => {\n if (ids !== prev.value) {\n prev.value = ids;\n const next = props.portals.map((p) => p[1]);\n portalComponents.value = next;\n }\n },\n );\n\n nextTick(() => {\n renderList.value = () => portalComponents.value.map((P) => <P />);\n });\n\n return () => {\n return <>{renderList.value()}</>;\n };\n});\nPortals.props = ['portals'];\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { Decoration, EditorView, Mark, Node } from '@milkdown/prose';\nimport { defineComponent, Fragment, h, InjectionKey, provide, ref, watchEffect } from 'vue';\n\nexport type NodeContext = {\n node: Node | Mark;\n view: EditorView;\n getPos: boolean | (() => number);\n decorations: Decoration[];\n};\n\nexport const nodeMetadata: InjectionKey<NodeContext> = Symbol();\n\nexport const VueNodeContainer = defineComponent(({ node, view, getPos, decorations }: NodeContext, context) => {\n provide(nodeMetadata, {\n node,\n view,\n getPos,\n decorations,\n });\n return () => <>{context.slots.default?.() ?? []}</>;\n});\nVueNodeContainer.props = ['editor', 'node', 'view', 'getPos', 'decorations'];\n\nexport const Content = defineComponent((props: { dom?: HTMLElement }) => {\n const containerRef = ref<HTMLDivElement | null>(null);\n watchEffect(() => {\n if (!props.dom || !containerRef.value) return;\n containerRef.value.appendChild(props.dom);\n });\n return () => <div ref={containerRef} />;\n});\nContent.props = ['dom'];\n","/* Copyright 2021, Milkdown by Mirone. */\nimport type { Decoration, EditorView, NodeView, ViewFactory } from '@milkdown/prose';\nimport { Mark, Node } from '@milkdown/prose';\nimport { customAlphabet } from 'nanoid';\nimport { DefineComponent, defineComponent, h, Teleport } from 'vue';\n\nimport { Content, VueNodeContainer } from './VueNode';\n\nconst nanoid = customAlphabet('abcedfghicklmn', 10);\n\nexport const createVueView =\n (addPortal: (portal: DefineComponent, key: string) => void, removePortalByKey: (key: string) => void) =>\n (component: DefineComponent): ViewFactory =>\n (node, view, getPos, decorations) =>\n new VueNodeView(component, addPortal, removePortalByKey, node, view, getPos, decorations);\n\nexport class VueNodeView implements NodeView {\n dom: HTMLElement | undefined;\n contentDOM: HTMLElement | undefined;\n key: string;\n\n constructor(\n private component: DefineComponent,\n private addPortal: (portal: DefineComponent, key: string) => void,\n private removePortalByKey: (key: string) => void,\n private node: Node | Mark,\n private view: EditorView,\n private getPos: boolean | (() => number),\n private decorations: Decoration[],\n ) {\n this.key = nanoid();\n const dom = document.createElement(node instanceof Mark ? 'span' : 'div');\n dom.classList.add('dom-wrapper');\n\n const contentDOM =\n node instanceof Node && node.isLeaf\n ? undefined\n : document.createElement(node instanceof Mark ? 'span' : 'div');\n if (contentDOM) {\n contentDOM.classList.add('content-dom');\n dom.appendChild(contentDOM);\n }\n this.dom = dom;\n this.contentDOM = contentDOM;\n this.renderPortal();\n }\n\n renderPortal() {\n if (!this.dom) return;\n\n const CustomComponent = this.component;\n const Portal = defineComponent(() => {\n return () => (\n <Teleport to={this.dom}>\n <VueNodeContainer\n key={this.key}\n node={this.node}\n view={this.view}\n getPos={this.getPos}\n decorations={this.decorations}\n >\n <CustomComponent>\n <Content dom={this.contentDOM} />\n </CustomComponent>\n </VueNodeContainer>\n </Teleport>\n );\n });\n this.addPortal(Portal, this.key);\n }\n\n destroy() {\n this.dom = undefined;\n this.contentDOM = undefined;\n this.removePortalByKey(this.key);\n }\n\n ignoreMutation(mutation: MutationRecord | { type: 'selection'; target: Element }) {\n if (!this.contentDOM) {\n return true;\n }\n return !this.contentDOM.contains(mutation.target);\n }\n}\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { Editor, editorViewCtx, rootCtx } from '@milkdown/core';\nimport { ViewFactory } from '@milkdown/prose';\nimport {\n DefineComponent,\n defineComponent,\n Fragment,\n h,\n inject,\n InjectionKey,\n markRaw,\n onMounted,\n onUnmounted,\n provide,\n Ref,\n ref,\n shallowReactive,\n} from 'vue';\n\nimport { PortalPair, Portals } from './Portals';\nimport { createVueView } from './VueNodeView';\n\nconst rendererKey: InjectionKey<(component: DefineComponent) => ViewFactory> = Symbol();\n\ntype GetEditor = (container: HTMLDivElement, renderVue: (Component: DefineComponent) => ViewFactory) => Editor;\n\nconst useGetEditor = (getEditor: GetEditor) => {\n const divRef = ref<HTMLDivElement | null>(null);\n const renderVue = inject<(Component: DefineComponent) => ViewFactory>(rendererKey, () => {\n throw new Error();\n });\n const editorRef = markRaw<{ editor?: Editor }>({});\n onMounted(() => {\n if (!divRef.value) return;\n\n getEditor(divRef.value, renderVue)\n .create()\n .then((editor) => {\n editorRef.editor = editor;\n return;\n })\n .catch((e) => console.error(e));\n });\n onUnmounted(() => {\n const view = editorRef.editor?.action((ctx) => ctx.get(editorViewCtx));\n const root = editorRef.editor?.action((ctx) => ctx.get(rootCtx)) as HTMLElement;\n\n root?.firstChild?.remove();\n view?.destroy();\n });\n\n return { divRef, editorRef };\n};\n\nexport const EditorComponent = defineComponent((props: { editor: GetEditor; editorRef?: Ref<EditorRef> }) => {\n const refs = useGetEditor(props.editor);\n if (props.editorRef) {\n props.editorRef.value = {\n get: () => refs.editorRef.editor,\n dom: () => refs.divRef.value,\n };\n }\n\n return () => <div ref={refs.divRef} />;\n});\nEditorComponent.props = ['editor', 'editorRef'];\n\nexport type EditorRef = { get: () => Editor | undefined; dom: () => HTMLDivElement | null };\n\nexport const VueEditor = defineComponent((props: { editor: GetEditor; editorRef?: Ref<EditorRef> }) => {\n const portals = shallowReactive<PortalPair[]>([]);\n const addPortal = markRaw((component: DefineComponent, key: string) => {\n portals.push([key, component]);\n });\n const removePortalByKey = markRaw((key: string) => {\n const index = portals.findIndex((p) => p[0] === key);\n portals.splice(index, 1);\n });\n const renderVue = createVueView(addPortal, removePortalByKey);\n provide(rendererKey, renderVue);\n\n return () => (\n <>\n <Portals portals={portals} />\n <EditorComponent editorRef={props.editorRef} editor={props.editor} />\n </>\n );\n});\nVueEditor.props = ['editor', 'editorRef'];\n\nexport const useEditor = (getEditor: GetEditor) => {\n return (...args: Parameters<GetEditor>) => getEditor(...args);\n};\n"],"names":["getId","pairs","map","p","join","Portals","defineComponent","props","portalComponents","shallowRef","prev","ref","renderList","watch","portals","ids","value","next","nextTick","P","nodeMetadata","Symbol","VueNodeContainer","node","view","getPos","decorations","context","provide","slots","default","Content","containerRef","watchEffect","dom","appendChild","nanoid","customAlphabet","createVueView","addPortal","removePortalByKey","component","VueNodeView","constructor","key","document","createElement","Mark","classList","add","contentDOM","Node","isLeaf","undefined","renderPortal","CustomComponent","Portal","destroy","ignoreMutation","mutation","contains","target","rendererKey","useGetEditor","getEditor","divRef","renderVue","inject","Error","editorRef","markRaw","onMounted","create","then","editor","catch","e","console","error","onUnmounted","action","ctx","get","editorViewCtx","root","rootCtx","firstChild","remove","EditorComponent","refs","VueEditor","shallowReactive","push","index","findIndex","splice","useEditor","args"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../src/VueNode.tsx","../src/VueNodeView.tsx","../src/Editor.tsx"],"sourcesContent":["/* Copyright 2021, Milkdown by Mirone. */\nimport { Ctx } from '@milkdown/core';\nimport { Decoration, EditorView, Mark, Node } from '@milkdown/prose';\nimport { defineComponent, h, InjectionKey, provide } from 'vue';\n\nexport type NodeContext = {\n ctx: Ctx;\n node: Node | Mark;\n view: EditorView;\n getPos: boolean | (() => number);\n decorations: Decoration[];\n};\n\nexport const nodeMetadata: InjectionKey<NodeContext> = Symbol();\n\nexport const VueNodeContainer = defineComponent<NodeContext>({\n name: 'milkdown-node-container',\n setup: ({ node, view, getPos, decorations, ctx }, context) => {\n provide(nodeMetadata, {\n ctx,\n node,\n view,\n getPos,\n decorations,\n });\n return () => <div data-view-container>{context.slots.default?.()}</div>;\n },\n});\nVueNodeContainer.props = ['ctx', 'editor', 'node', 'view', 'getPos', 'decorations'];\n\nexport const Content = defineComponent<{ isInline?: boolean }>({\n name: 'milkdown-content',\n setup: ({ isInline }) => {\n return () => (isInline ? <span data-view-content /> : <div data-view-content />);\n },\n});\nContent.props = ['isMark'];\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { Ctx } from '@milkdown/core';\nimport type { Decoration, EditorView, NodeView, ViewFactory } from '@milkdown/prose';\nimport { Mark, Node } from '@milkdown/prose';\nimport { customAlphabet } from 'nanoid';\nimport { DefineComponent, defineComponent, h, markRaw, Teleport } from 'vue';\n\nimport { getRootInstance } from '.';\nimport { Content, VueNodeContainer } from './VueNode';\n\nconst nanoid = customAlphabet('abcedfghicklmn', 10);\n\nexport const createVueView =\n (addPortal: (portal: DefineComponent, key: string) => void, removePortalByKey: (key: string) => void) =>\n (component: DefineComponent): ((ctx: Ctx) => ViewFactory) =>\n (ctx) =>\n (node, view, getPos, decorations) =>\n new VueNodeView(ctx, component, addPortal, removePortalByKey, node, view, getPos, decorations);\n\nexport class VueNodeView implements NodeView {\n teleportDOM: HTMLElement;\n key: string;\n\n get isInlineOrMark() {\n return this.node instanceof Mark || this.node.isInline;\n }\n\n constructor(\n private ctx: Ctx,\n private component: DefineComponent,\n private addPortal: (portal: DefineComponent, key: string) => void,\n private removePortalByKey: (key: string) => void,\n private node: Node | Mark,\n private view: EditorView,\n private getPos: boolean | (() => number),\n private decorations: Decoration[],\n ) {\n this.key = nanoid();\n this.teleportDOM = document.createElement(this.isInlineOrMark ? 'span' : 'div');\n this.renderPortal();\n }\n\n get dom() {\n return this.teleportDOM.firstElementChild || this.teleportDOM;\n }\n\n get contentDOM() {\n if (this.node instanceof Node && this.node.isLeaf) {\n return null;\n }\n\n return this.teleportDOM.querySelector('[data-view-content]') || this.dom;\n }\n\n renderPortal() {\n if (!this.teleportDOM) return;\n\n const CustomComponent = this.component;\n const Portal = defineComponent({\n name: 'milkdown-portal',\n setup: () => {\n return () => (\n <Teleport key={this.key} to={this.teleportDOM}>\n <VueNodeContainer\n ctx={this.ctx}\n node={this.node}\n view={this.view}\n getPos={this.getPos}\n decorations={this.decorations}\n >\n <CustomComponent>\n <Content isInline={this.isInlineOrMark} />\n </CustomComponent>\n </VueNodeContainer>\n </Teleport>\n );\n },\n });\n this.addPortal(markRaw(Portal) as DefineComponent, this.key);\n const instance = getRootInstance();\n if (instance) {\n instance.update();\n }\n }\n\n destroy() {\n this.removePortalByKey(this.key);\n }\n\n ignoreMutation(mutation: MutationRecord | { type: 'selection'; target: Element }) {\n if (!this.dom || !this.contentDOM) {\n return true;\n }\n\n if (this.node instanceof Node) {\n if (this.node.isLeaf || this.node.isAtom) {\n return true;\n }\n }\n\n if (mutation.type === 'selection') {\n return false;\n }\n\n if (this.contentDOM === this.dom) {\n return false;\n }\n\n if (this.contentDOM.contains(mutation.target)) {\n return false;\n }\n\n return true;\n }\n\n update(node: Node | Mark, decorations: Decoration[]) {\n if (this.node.type !== node.type) {\n return false;\n }\n\n if (node === this.node && this.decorations === decorations) {\n return true;\n }\n\n this.node = node;\n this.decorations = decorations;\n return true;\n }\n}\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { Ctx, Editor, editorViewCtx, rootCtx } from '@milkdown/core';\nimport { ViewFactory } from '@milkdown/prose';\nimport {\n ComponentInternalInstance,\n DefineComponent,\n defineComponent,\n getCurrentInstance,\n h,\n inject,\n InjectionKey,\n markRaw,\n onBeforeMount,\n onMounted,\n onUnmounted,\n provide,\n Ref,\n ref,\n shallowReactive,\n} from 'vue';\n\nimport { AnyVueComponent } from './utils';\nimport { createVueView } from './VueNodeView';\n\nconst rendererKey: InjectionKey<(component: DefineComponent) => (ctx: Ctx) => ViewFactory> = Symbol();\n\ntype GetEditor = (\n container: HTMLDivElement,\n renderVue: (Component: AnyVueComponent) => (ctx: Ctx) => ViewFactory,\n) => Editor;\n\nconst useGetEditor = (getEditor: GetEditor) => {\n const divRef = ref<HTMLDivElement | null>(null);\n const renderVue = inject<(Component: DefineComponent) => (ctx: Ctx) => ViewFactory>(rendererKey, () => {\n throw new Error();\n });\n const editorRef = markRaw<{ editor?: Editor }>({});\n onMounted(() => {\n if (!divRef.value) return;\n\n getEditor(divRef.value, renderVue)\n .create()\n .then((editor) => {\n editorRef.editor = editor;\n return;\n })\n .catch((e) => console.error(e));\n });\n onUnmounted(() => {\n const view = editorRef.editor?.action((ctx) => ctx.get(editorViewCtx));\n const root = editorRef.editor?.action((ctx) => ctx.get(rootCtx)) as HTMLElement;\n\n root?.firstChild?.remove();\n view?.destroy();\n });\n\n return { divRef, editorRef };\n};\n\nexport const EditorComponent = defineComponent<{ editor: GetEditor; editorRef?: Ref<EditorRef> }>({\n name: 'milkdown-dom-root',\n setup: (props, { slots }) => {\n const refs = useGetEditor(props.editor);\n if (props.editorRef) {\n props.editorRef.value = {\n get: () => refs.editorRef.editor,\n dom: () => refs.divRef.value,\n };\n }\n\n return () => <div ref={refs.divRef}>{slots.default?.()}</div>;\n },\n});\nEditorComponent.props = ['editor', 'editorRef'];\n\nexport type EditorRef = { get: () => Editor | undefined; dom: () => HTMLDivElement | null };\n\nconst rootInstance: {\n instance: null | ComponentInternalInstance;\n} = {\n instance: null,\n};\nexport const getRootInstance = () => {\n return rootInstance.instance;\n};\n\ntype PortalPair = [key: string, component: DefineComponent];\nexport const VueEditor = defineComponent<{ editor: GetEditor; editorRef?: Ref<EditorRef> }>({\n name: 'milkdown-vue-root',\n setup: (props) => {\n const portals = shallowReactive<PortalPair[]>([]);\n\n const instance = getCurrentInstance();\n\n onBeforeMount(() => {\n rootInstance.instance = (instance as ComponentInternalInstance & { ctx: { _: ComponentInternalInstance } })\n .ctx._ as ComponentInternalInstance;\n });\n\n onUnmounted(() => {\n rootInstance.instance = null;\n });\n\n const addPortal = markRaw((component: DefineComponent, key: string) => {\n portals.push([key, component]);\n });\n const removePortalByKey = markRaw((key: string) => {\n const index = portals.findIndex((p) => p[0] === key);\n portals.splice(index, 1);\n });\n const renderVue = createVueView(addPortal, removePortalByKey);\n provide(rendererKey, renderVue);\n\n return () => {\n const portalElements = portals.map(([id, P]) => <P key={id} />);\n return (\n <EditorComponent editorRef={props.editorRef} editor={props.editor}>\n {portalElements}\n </EditorComponent>\n );\n };\n },\n});\nVueEditor.props = ['editor', 'editorRef'];\n\nexport const useEditor = (getEditor: GetEditor) => {\n return (...args: Parameters<GetEditor>) => getEditor(...args);\n};\n"],"names":["nodeMetadata","Symbol","VueNodeContainer","defineComponent","name","setup","node","view","getPos","decorations","ctx","context","provide","slots","default","props","Content","isInline","nanoid","customAlphabet","createVueView","addPortal","removePortalByKey","component","VueNodeView","isInlineOrMark","Mark","constructor","key","teleportDOM","document","createElement","renderPortal","dom","firstElementChild","contentDOM","Node","isLeaf","querySelector","CustomComponent","Portal","markRaw","instance","getRootInstance","update","destroy","ignoreMutation","mutation","isAtom","type","contains","target","rendererKey","useGetEditor","getEditor","divRef","ref","renderVue","inject","Error","editorRef","onMounted","value","create","then","editor","catch","e","console","error","onUnmounted","action","get","editorViewCtx","root","rootCtx","firstChild","remove","EditorComponent","refs","rootInstance","VueEditor","portals","shallowReactive","getCurrentInstance","onBeforeMount","_","push","index","findIndex","p","splice","portalElements","map","id","P","useEditor","args"],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Ctx, Editor } from '@milkdown/core';
|
|
2
|
+
import { ViewFactory } from '@milkdown/prose';
|
|
3
|
+
import { ComponentInternalInstance, DefineComponent, Ref } from 'vue';
|
|
4
|
+
import { AnyVueComponent } from './utils';
|
|
5
|
+
declare type GetEditor = (container: HTMLDivElement, renderVue: (Component: AnyVueComponent) => (ctx: Ctx) => ViewFactory) => Editor;
|
|
6
|
+
export declare const EditorComponent: DefineComponent<{
|
|
7
|
+
editor: GetEditor;
|
|
8
|
+
editorRef?: Ref<EditorRef> | undefined;
|
|
9
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, import("vue").EmitsOptions, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<{
|
|
10
|
+
editor: GetEditor;
|
|
11
|
+
editorRef?: Ref<EditorRef> | undefined;
|
|
12
|
+
}>, {}>;
|
|
13
|
+
export declare type EditorRef = {
|
|
14
|
+
get: () => Editor | undefined;
|
|
15
|
+
dom: () => HTMLDivElement | null;
|
|
16
|
+
};
|
|
17
|
+
export declare const getRootInstance: () => ComponentInternalInstance | null;
|
|
18
|
+
export declare const VueEditor: DefineComponent<{
|
|
19
|
+
editor: GetEditor;
|
|
20
|
+
editorRef?: Ref<EditorRef> | undefined;
|
|
21
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, import("vue").EmitsOptions, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<{
|
|
22
|
+
editor: GetEditor;
|
|
23
|
+
editorRef?: Ref<EditorRef> | undefined;
|
|
24
|
+
}>, {}>;
|
|
25
|
+
export declare const useEditor: (getEditor: GetEditor) => (container: HTMLDivElement, renderVue: (Component: AnyVueComponent) => (ctx: Ctx) => ViewFactory) => Editor;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=Editor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Editor.d.ts","sourceRoot":"","sources":["Editor.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,EAA0B,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACH,yBAAyB,EACzB,eAAe,EAWf,GAAG,EAGN,MAAM,KAAK,CAAC;AAEb,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK1C,aAAK,SAAS,GAAG,CACb,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,WAAW,KACnE,MAAM,CAAC;AA8BZ,eAAO,MAAM,eAAe;YAA6B,SAAS;;;YAAT,SAAS;;OAahE,CAAC;AAGH,oBAAY,SAAS,GAAG;IAAE,GAAG,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,cAAc,GAAG,IAAI,CAAA;CAAE,CAAC;AAO5F,eAAO,MAAM,eAAe,wCAE3B,CAAC;AAGF,eAAO,MAAM,SAAS;YAA6B,SAAS;;;YAAT,SAAS;;OAmC1D,CAAC;AAGH,eAAO,MAAM,SAAS,cAAe,SAAS,wDAjGnB,eAAe,WAAW,GAAG,KAAK,WAAW,WAmGvE,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Ctx } from '@milkdown/core';
|
|
2
|
+
import { Decoration, EditorView, Mark, Node } from '@milkdown/prose';
|
|
3
|
+
import { InjectionKey } from 'vue';
|
|
4
|
+
export declare type NodeContext = {
|
|
5
|
+
ctx: Ctx;
|
|
6
|
+
node: Node | Mark;
|
|
7
|
+
view: EditorView;
|
|
8
|
+
getPos: boolean | (() => number);
|
|
9
|
+
decorations: Decoration[];
|
|
10
|
+
};
|
|
11
|
+
export declare const nodeMetadata: InjectionKey<NodeContext>;
|
|
12
|
+
export declare const VueNodeContainer: import("vue").DefineComponent<NodeContext, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, import("vue").EmitsOptions, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<NodeContext>, {}>;
|
|
13
|
+
export declare const Content: import("vue").DefineComponent<{
|
|
14
|
+
isInline?: boolean | undefined;
|
|
15
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, import("vue").EmitsOptions, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<{
|
|
16
|
+
isInline?: boolean | undefined;
|
|
17
|
+
}>, {}>;
|
|
18
|
+
//# sourceMappingURL=VueNode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VueNode.d.ts","sourceRoot":"","sources":["VueNode.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAsB,YAAY,EAAW,MAAM,KAAK,CAAC;AAEhE,oBAAY,WAAW,GAAG;IACtB,GAAG,EAAE,GAAG,CAAC;IACT,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IACjC,WAAW,EAAE,UAAU,EAAE,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,YAAY,CAAC,WAAW,CAAY,CAAC;AAEhE,eAAO,MAAM,gBAAgB,0SAY3B,CAAC;AAGH,eAAO,MAAM,OAAO;;;;OAKlB,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import { Ctx } from '@milkdown/core';
|
|
2
2
|
import type { Decoration, EditorView, NodeView, ViewFactory } from '@milkdown/prose';
|
|
3
3
|
import { Mark, Node } from '@milkdown/prose';
|
|
4
4
|
import { DefineComponent } from 'vue';
|
|
5
|
-
export declare const createVueView: (addPortal: (portal: DefineComponent, key: string) => void, removePortalByKey: (key: string) => void) => (component: DefineComponent) => ViewFactory;
|
|
5
|
+
export declare const createVueView: (addPortal: (portal: DefineComponent, key: string) => void, removePortalByKey: (key: string) => void) => (component: DefineComponent) => (ctx: Ctx) => ViewFactory;
|
|
6
6
|
export declare class VueNodeView implements NodeView {
|
|
7
|
+
private ctx;
|
|
7
8
|
private component;
|
|
8
9
|
private addPortal;
|
|
9
10
|
private removePortalByKey;
|
|
@@ -11,15 +12,18 @@ export declare class VueNodeView implements NodeView {
|
|
|
11
12
|
private view;
|
|
12
13
|
private getPos;
|
|
13
14
|
private decorations;
|
|
14
|
-
|
|
15
|
-
contentDOM: HTMLElement | undefined;
|
|
15
|
+
teleportDOM: HTMLElement;
|
|
16
16
|
key: string;
|
|
17
|
-
|
|
17
|
+
get isInlineOrMark(): boolean;
|
|
18
|
+
constructor(ctx: Ctx, component: DefineComponent, addPortal: (portal: DefineComponent, key: string) => void, removePortalByKey: (key: string) => void, node: Node | Mark, view: EditorView, getPos: boolean | (() => number), decorations: Decoration[]);
|
|
19
|
+
get dom(): Element;
|
|
20
|
+
get contentDOM(): Element | null;
|
|
18
21
|
renderPortal(): void;
|
|
19
22
|
destroy(): void;
|
|
20
23
|
ignoreMutation(mutation: MutationRecord | {
|
|
21
24
|
type: 'selection';
|
|
22
25
|
target: Element;
|
|
23
26
|
}): boolean;
|
|
27
|
+
update(node: Node | Mark, decorations: Decoration[]): boolean;
|
|
24
28
|
}
|
|
25
29
|
//# sourceMappingURL=VueNodeView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VueNodeView.d.ts","sourceRoot":"","sources":["VueNodeView.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,eAAe,EAAyC,MAAM,KAAK,CAAC;AAO7E,eAAO,MAAM,aAAa,uBACD,eAAe,OAAO,MAAM,KAAK,IAAI,2BAA2B,MAAM,KAAK,IAAI,iBACxF,eAAe,WAAU,GAAG,KAAK,WAGqD,CAAC;AAEvG,qBAAa,WAAY,YAAW,QAAQ;IASpC,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,iBAAiB;IACzB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,WAAW;IAfvB,WAAW,EAAE,WAAW,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IAEZ,IAAI,cAAc,YAEjB;gBAGW,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,eAAe,EAC1B,SAAS,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,EACzD,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EACxC,IAAI,EAAE,IAAI,GAAG,IAAI,EACjB,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC,EAChC,WAAW,EAAE,UAAU,EAAE;IAOrC,IAAI,GAAG,YAEN;IAED,IAAI,UAAU,mBAMb;IAED,YAAY;IA+BZ,OAAO;IAIP,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE;IA0BhF,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE;CAatD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AACA,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { DefineComponent } from 'vue';
|
|
1
2
|
declare type Prepend<T, U extends unknown[]> = [T, ...U];
|
|
2
3
|
declare type Keys_<T extends Record<string, unknown>, U extends PropertyKey[]> = {
|
|
3
4
|
[P in keyof T]: Record<string, unknown> extends Omit<T, P> ? [P] : Prepend<P, Keys_<Omit<T, P>, U>>;
|
|
4
5
|
}[keyof T];
|
|
5
6
|
export declare type Keys<T extends Record<string, unknown>> = Keys_<T, []>;
|
|
7
|
+
export declare type AnyVueComponent = DefineComponent<any, any, any, any, any, any, any, any, any, any, any, any>;
|
|
6
8
|
export {};
|
|
7
9
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,KAAK,CAAC;AAEtC,aAAK,OAAO,CAAC,CAAC,EAAE,CAAC,SAAS,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AACjD,aAAK,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,WAAW,EAAE,IAAI;KACpE,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACtG,CAAC,MAAM,CAAC,CAAC,CAAC;AACX,oBAAY,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAGnE,oBAAY,eAAe,GAAG,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milkdown/vue",
|
|
3
|
-
"version": "5.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "5.3.3",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./lib/index.es.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": {
|
|
9
|
-
"import": "./lib/index.es.js",
|
|
10
|
-
"require": "./lib/index.cjs.js"
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
7
|
"sideEffects": false,
|
|
14
8
|
"license": "MIT",
|
|
15
9
|
"files": [
|
|
@@ -22,26 +16,23 @@
|
|
|
22
16
|
"vue"
|
|
23
17
|
],
|
|
24
18
|
"dependencies": {
|
|
25
|
-
"@milkdown/
|
|
19
|
+
"@milkdown/core": "5.3.3",
|
|
20
|
+
"@milkdown/utils": "5.3.3",
|
|
21
|
+
"@milkdown/prose": "5.3.3",
|
|
26
22
|
"nanoid": "^3.1.25",
|
|
27
23
|
"tslib": "^2.3.1"
|
|
28
24
|
},
|
|
29
25
|
"peerDependencies": {
|
|
30
|
-
"@milkdown/core": "*",
|
|
31
26
|
"vue": "^3.0.0"
|
|
32
27
|
},
|
|
33
28
|
"devDependencies": {
|
|
34
|
-
"@milkdown/core": "5.2.1",
|
|
35
|
-
"@milkdown/prose": "5.2.1",
|
|
36
|
-
"@milkdown/preset-commonmark": "5.2.1",
|
|
37
|
-
"@milkdown/theme-nord": "5.2.1",
|
|
38
29
|
"vue": "^3.0.0"
|
|
39
30
|
},
|
|
40
31
|
"scripts": {
|
|
41
|
-
"start": "vite",
|
|
42
|
-
"
|
|
43
|
-
"test": "jest",
|
|
32
|
+
"start": "vite build --watch",
|
|
33
|
+
"test": "vitest",
|
|
44
34
|
"tsc": "tsc --noEmit",
|
|
45
|
-
"build": "vite build
|
|
46
|
-
}
|
|
35
|
+
"build": "vite build"
|
|
36
|
+
},
|
|
37
|
+
"readme": "# @milkdown/vue\n\nVue integration for [milkdown](https://saul-mirone.github.io/milkdown/).\n\n# Example Usage\n\n```typescript\nimport { defineComponent } from 'vue';\nimport { Editor, rootCtx } from '@milkdown/core';\nimport { VueEditor, useEditor } from '@milkdown/vue';\nimport { commonmark } from '@milkdown/preset-commonmark';\nimport { nord } from '@milkdown/theme-nord';\n\nexport const MilkdownEditor = defineComponent(() => {\n const editor = useEditor((root) =>\n Editor.make()\n .config((ctx) => {\n ctx.set(rootCtx, root);\n })\n .use(nord)\n .use(commonmark),\n );\n\n return () => <VueEditor editor={editor} />;\n});\n```\n\n# License\n\nMilkdown is open sourced software licensed under [MIT license](https://github.com/Saul-Mirone/milkdown/blob/main/LICENSE).\n"
|
|
47
38
|
}
|
package/src/Editor.tsx
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
-
import { Editor, editorViewCtx, rootCtx } from '@milkdown/core';
|
|
2
|
+
import { Ctx, Editor, editorViewCtx, rootCtx } from '@milkdown/core';
|
|
3
3
|
import { ViewFactory } from '@milkdown/prose';
|
|
4
4
|
import {
|
|
5
|
+
ComponentInternalInstance,
|
|
5
6
|
DefineComponent,
|
|
6
7
|
defineComponent,
|
|
7
|
-
|
|
8
|
+
getCurrentInstance,
|
|
8
9
|
h,
|
|
9
10
|
inject,
|
|
10
11
|
InjectionKey,
|
|
11
12
|
markRaw,
|
|
13
|
+
onBeforeMount,
|
|
12
14
|
onMounted,
|
|
13
15
|
onUnmounted,
|
|
14
16
|
provide,
|
|
@@ -17,16 +19,19 @@ import {
|
|
|
17
19
|
shallowReactive,
|
|
18
20
|
} from 'vue';
|
|
19
21
|
|
|
20
|
-
import {
|
|
22
|
+
import { AnyVueComponent } from './utils';
|
|
21
23
|
import { createVueView } from './VueNodeView';
|
|
22
24
|
|
|
23
|
-
const rendererKey: InjectionKey<(component: DefineComponent) => ViewFactory> = Symbol();
|
|
25
|
+
const rendererKey: InjectionKey<(component: DefineComponent) => (ctx: Ctx) => ViewFactory> = Symbol();
|
|
24
26
|
|
|
25
|
-
type GetEditor = (
|
|
27
|
+
type GetEditor = (
|
|
28
|
+
container: HTMLDivElement,
|
|
29
|
+
renderVue: (Component: AnyVueComponent) => (ctx: Ctx) => ViewFactory,
|
|
30
|
+
) => Editor;
|
|
26
31
|
|
|
27
32
|
const useGetEditor = (getEditor: GetEditor) => {
|
|
28
33
|
const divRef = ref<HTMLDivElement | null>(null);
|
|
29
|
-
const renderVue = inject<(Component: DefineComponent) => ViewFactory>(rendererKey, () => {
|
|
34
|
+
const renderVue = inject<(Component: DefineComponent) => (ctx: Ctx) => ViewFactory>(rendererKey, () => {
|
|
30
35
|
throw new Error();
|
|
31
36
|
});
|
|
32
37
|
const editorRef = markRaw<{ editor?: Editor }>({});
|
|
@@ -52,39 +57,69 @@ const useGetEditor = (getEditor: GetEditor) => {
|
|
|
52
57
|
return { divRef, editorRef };
|
|
53
58
|
};
|
|
54
59
|
|
|
55
|
-
export const EditorComponent = defineComponent
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
export const EditorComponent = defineComponent<{ editor: GetEditor; editorRef?: Ref<EditorRef> }>({
|
|
61
|
+
name: 'milkdown-dom-root',
|
|
62
|
+
setup: (props, { slots }) => {
|
|
63
|
+
const refs = useGetEditor(props.editor);
|
|
64
|
+
if (props.editorRef) {
|
|
65
|
+
props.editorRef.value = {
|
|
66
|
+
get: () => refs.editorRef.editor,
|
|
67
|
+
dom: () => refs.divRef.value,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
63
70
|
|
|
64
|
-
|
|
71
|
+
return () => <div ref={refs.divRef}>{slots.default?.()}</div>;
|
|
72
|
+
},
|
|
65
73
|
});
|
|
66
74
|
EditorComponent.props = ['editor', 'editorRef'];
|
|
67
75
|
|
|
68
76
|
export type EditorRef = { get: () => Editor | undefined; dom: () => HTMLDivElement | null };
|
|
69
77
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
78
|
+
const rootInstance: {
|
|
79
|
+
instance: null | ComponentInternalInstance;
|
|
80
|
+
} = {
|
|
81
|
+
instance: null,
|
|
82
|
+
};
|
|
83
|
+
export const getRootInstance = () => {
|
|
84
|
+
return rootInstance.instance;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
type PortalPair = [key: string, component: DefineComponent];
|
|
88
|
+
export const VueEditor = defineComponent<{ editor: GetEditor; editorRef?: Ref<EditorRef> }>({
|
|
89
|
+
name: 'milkdown-vue-root',
|
|
90
|
+
setup: (props) => {
|
|
91
|
+
const portals = shallowReactive<PortalPair[]>([]);
|
|
92
|
+
|
|
93
|
+
const instance = getCurrentInstance();
|
|
94
|
+
|
|
95
|
+
onBeforeMount(() => {
|
|
96
|
+
rootInstance.instance = (instance as ComponentInternalInstance & { ctx: { _: ComponentInternalInstance } })
|
|
97
|
+
.ctx._ as ComponentInternalInstance;
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
onUnmounted(() => {
|
|
101
|
+
rootInstance.instance = null;
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const addPortal = markRaw((component: DefineComponent, key: string) => {
|
|
105
|
+
portals.push([key, component]);
|
|
106
|
+
});
|
|
107
|
+
const removePortalByKey = markRaw((key: string) => {
|
|
108
|
+
const index = portals.findIndex((p) => p[0] === key);
|
|
109
|
+
portals.splice(index, 1);
|
|
110
|
+
});
|
|
111
|
+
const renderVue = createVueView(addPortal, removePortalByKey);
|
|
112
|
+
provide(rendererKey, renderVue);
|
|
113
|
+
|
|
114
|
+
return () => {
|
|
115
|
+
const portalElements = portals.map(([id, P]) => <P key={id} />);
|
|
116
|
+
return (
|
|
117
|
+
<EditorComponent editorRef={props.editorRef} editor={props.editor}>
|
|
118
|
+
{portalElements}
|
|
119
|
+
</EditorComponent>
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
},
|
|
88
123
|
});
|
|
89
124
|
VueEditor.props = ['editor', 'editorRef'];
|
|
90
125
|
|
package/src/VueNode.tsx
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import { Ctx } from '@milkdown/core';
|
|
2
3
|
import { Decoration, EditorView, Mark, Node } from '@milkdown/prose';
|
|
3
|
-
import { defineComponent,
|
|
4
|
+
import { defineComponent, h, InjectionKey, provide } from 'vue';
|
|
4
5
|
|
|
5
6
|
export type NodeContext = {
|
|
7
|
+
ctx: Ctx;
|
|
6
8
|
node: Node | Mark;
|
|
7
9
|
view: EditorView;
|
|
8
10
|
getPos: boolean | (() => number);
|
|
@@ -11,23 +13,25 @@ export type NodeContext = {
|
|
|
11
13
|
|
|
12
14
|
export const nodeMetadata: InjectionKey<NodeContext> = Symbol();
|
|
13
15
|
|
|
14
|
-
export const VueNodeContainer = defineComponent(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
export const VueNodeContainer = defineComponent<NodeContext>({
|
|
17
|
+
name: 'milkdown-node-container',
|
|
18
|
+
setup: ({ node, view, getPos, decorations, ctx }, context) => {
|
|
19
|
+
provide(nodeMetadata, {
|
|
20
|
+
ctx,
|
|
21
|
+
node,
|
|
22
|
+
view,
|
|
23
|
+
getPos,
|
|
24
|
+
decorations,
|
|
25
|
+
});
|
|
26
|
+
return () => <div data-view-container>{context.slots.default?.()}</div>;
|
|
27
|
+
},
|
|
22
28
|
});
|
|
23
|
-
VueNodeContainer.props = ['editor', 'node', 'view', 'getPos', 'decorations'];
|
|
29
|
+
VueNodeContainer.props = ['ctx', 'editor', 'node', 'view', 'getPos', 'decorations'];
|
|
24
30
|
|
|
25
|
-
export const Content = defineComponent
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
});
|
|
31
|
-
return () => <div ref={containerRef} />;
|
|
31
|
+
export const Content = defineComponent<{ isInline?: boolean }>({
|
|
32
|
+
name: 'milkdown-content',
|
|
33
|
+
setup: ({ isInline }) => {
|
|
34
|
+
return () => (isInline ? <span data-view-content /> : <div data-view-content />);
|
|
35
|
+
},
|
|
32
36
|
});
|
|
33
|
-
Content.props = ['
|
|
37
|
+
Content.props = ['isMark'];
|
package/src/VueNodeView.tsx
CHANGED
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import { Ctx } from '@milkdown/core';
|
|
2
3
|
import type { Decoration, EditorView, NodeView, ViewFactory } from '@milkdown/prose';
|
|
3
4
|
import { Mark, Node } from '@milkdown/prose';
|
|
4
5
|
import { customAlphabet } from 'nanoid';
|
|
5
|
-
import { DefineComponent, defineComponent, h, Teleport } from 'vue';
|
|
6
|
+
import { DefineComponent, defineComponent, h, markRaw, Teleport } from 'vue';
|
|
6
7
|
|
|
8
|
+
import { getRootInstance } from '.';
|
|
7
9
|
import { Content, VueNodeContainer } from './VueNode';
|
|
8
10
|
|
|
9
11
|
const nanoid = customAlphabet('abcedfghicklmn', 10);
|
|
10
12
|
|
|
11
13
|
export const createVueView =
|
|
12
14
|
(addPortal: (portal: DefineComponent, key: string) => void, removePortalByKey: (key: string) => void) =>
|
|
13
|
-
(component: DefineComponent): ViewFactory =>
|
|
15
|
+
(component: DefineComponent): ((ctx: Ctx) => ViewFactory) =>
|
|
16
|
+
(ctx) =>
|
|
14
17
|
(node, view, getPos, decorations) =>
|
|
15
|
-
new VueNodeView(component, addPortal, removePortalByKey, node, view, getPos, decorations);
|
|
18
|
+
new VueNodeView(ctx, component, addPortal, removePortalByKey, node, view, getPos, decorations);
|
|
16
19
|
|
|
17
20
|
export class VueNodeView implements NodeView {
|
|
18
|
-
|
|
19
|
-
contentDOM: HTMLElement | undefined;
|
|
21
|
+
teleportDOM: HTMLElement;
|
|
20
22
|
key: string;
|
|
21
23
|
|
|
24
|
+
get isInlineOrMark() {
|
|
25
|
+
return this.node instanceof Mark || this.node.isInline;
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
constructor(
|
|
29
|
+
private ctx: Ctx,
|
|
23
30
|
private component: DefineComponent,
|
|
24
31
|
private addPortal: (portal: DefineComponent, key: string) => void,
|
|
25
32
|
private removePortalByKey: (key: string) => void,
|
|
@@ -29,56 +36,94 @@ export class VueNodeView implements NodeView {
|
|
|
29
36
|
private decorations: Decoration[],
|
|
30
37
|
) {
|
|
31
38
|
this.key = nanoid();
|
|
32
|
-
|
|
33
|
-
dom.classList.add('dom-wrapper');
|
|
34
|
-
|
|
35
|
-
const contentDOM =
|
|
36
|
-
node instanceof Node && node.isLeaf
|
|
37
|
-
? undefined
|
|
38
|
-
: document.createElement(node instanceof Mark ? 'span' : 'div');
|
|
39
|
-
if (contentDOM) {
|
|
40
|
-
contentDOM.classList.add('content-dom');
|
|
41
|
-
dom.appendChild(contentDOM);
|
|
42
|
-
}
|
|
43
|
-
this.dom = dom;
|
|
44
|
-
this.contentDOM = contentDOM;
|
|
39
|
+
this.teleportDOM = document.createElement(this.isInlineOrMark ? 'span' : 'div');
|
|
45
40
|
this.renderPortal();
|
|
46
41
|
}
|
|
47
42
|
|
|
43
|
+
get dom() {
|
|
44
|
+
return this.teleportDOM.firstElementChild || this.teleportDOM;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get contentDOM() {
|
|
48
|
+
if (this.node instanceof Node && this.node.isLeaf) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return this.teleportDOM.querySelector('[data-view-content]') || this.dom;
|
|
53
|
+
}
|
|
54
|
+
|
|
48
55
|
renderPortal() {
|
|
49
|
-
if (!this.
|
|
56
|
+
if (!this.teleportDOM) return;
|
|
50
57
|
|
|
51
58
|
const CustomComponent = this.component;
|
|
52
|
-
const Portal = defineComponent(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
const Portal = defineComponent({
|
|
60
|
+
name: 'milkdown-portal',
|
|
61
|
+
setup: () => {
|
|
62
|
+
return () => (
|
|
63
|
+
<Teleport key={this.key} to={this.teleportDOM}>
|
|
64
|
+
<VueNodeContainer
|
|
65
|
+
ctx={this.ctx}
|
|
66
|
+
node={this.node}
|
|
67
|
+
view={this.view}
|
|
68
|
+
getPos={this.getPos}
|
|
69
|
+
decorations={this.decorations}
|
|
70
|
+
>
|
|
71
|
+
<CustomComponent>
|
|
72
|
+
<Content isInline={this.isInlineOrMark} />
|
|
73
|
+
</CustomComponent>
|
|
74
|
+
</VueNodeContainer>
|
|
75
|
+
</Teleport>
|
|
76
|
+
);
|
|
77
|
+
},
|
|
68
78
|
});
|
|
69
|
-
this.addPortal(Portal, this.key);
|
|
79
|
+
this.addPortal(markRaw(Portal) as DefineComponent, this.key);
|
|
80
|
+
const instance = getRootInstance();
|
|
81
|
+
if (instance) {
|
|
82
|
+
instance.update();
|
|
83
|
+
}
|
|
70
84
|
}
|
|
71
85
|
|
|
72
86
|
destroy() {
|
|
73
|
-
this.dom = undefined;
|
|
74
|
-
this.contentDOM = undefined;
|
|
75
87
|
this.removePortalByKey(this.key);
|
|
76
88
|
}
|
|
77
89
|
|
|
78
90
|
ignoreMutation(mutation: MutationRecord | { type: 'selection'; target: Element }) {
|
|
79
|
-
if (!this.contentDOM) {
|
|
91
|
+
if (!this.dom || !this.contentDOM) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (this.node instanceof Node) {
|
|
96
|
+
if (this.node.isLeaf || this.node.isAtom) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (mutation.type === 'selection') {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (this.contentDOM === this.dom) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (this.contentDOM.contains(mutation.target)) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
update(node: Node | Mark, decorations: Decoration[]) {
|
|
117
|
+
if (this.node.type !== node.type) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (node === this.node && this.decorations === decorations) {
|
|
80
122
|
return true;
|
|
81
123
|
}
|
|
82
|
-
|
|
124
|
+
|
|
125
|
+
this.node = node;
|
|
126
|
+
this.decorations = decorations;
|
|
127
|
+
return true;
|
|
83
128
|
}
|
|
84
129
|
}
|
package/src/utils.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
2
|
|
|
3
|
+
import { DefineComponent } from 'vue';
|
|
4
|
+
|
|
3
5
|
type Prepend<T, U extends unknown[]> = [T, ...U];
|
|
4
6
|
type Keys_<T extends Record<string, unknown>, U extends PropertyKey[]> = {
|
|
5
7
|
[P in keyof T]: Record<string, unknown> extends Omit<T, P> ? [P] : Prepend<P, Keys_<Omit<T, P>, U>>;
|
|
6
8
|
}[keyof T];
|
|
7
9
|
export type Keys<T extends Record<string, unknown>> = Keys_<T, []>;
|
|
10
|
+
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
export type AnyVueComponent = DefineComponent<any, any, any, any, any, any, any, any, any, any, any, any>;
|
package/lib/Editor.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { Editor } from '@milkdown/core';
|
|
2
|
-
import { ViewFactory } from '@milkdown/prose';
|
|
3
|
-
import { DefineComponent, Ref } from 'vue';
|
|
4
|
-
declare type GetEditor = (container: HTMLDivElement, renderVue: (Component: DefineComponent) => ViewFactory) => Editor;
|
|
5
|
-
export declare const EditorComponent: DefineComponent<{
|
|
6
|
-
editor: GetEditor;
|
|
7
|
-
editorRef?: Ref<EditorRef> | undefined;
|
|
8
|
-
}, () => JSX.Element, {}, import("vue").ComputedOptions, import("vue").MethodOptions, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<{
|
|
9
|
-
editor: GetEditor;
|
|
10
|
-
editorRef?: Ref<EditorRef> | undefined;
|
|
11
|
-
}>, {}>;
|
|
12
|
-
export declare type EditorRef = {
|
|
13
|
-
get: () => Editor | undefined;
|
|
14
|
-
dom: () => HTMLDivElement | null;
|
|
15
|
-
};
|
|
16
|
-
export declare const VueEditor: DefineComponent<{
|
|
17
|
-
editor: GetEditor;
|
|
18
|
-
editorRef?: Ref<EditorRef> | undefined;
|
|
19
|
-
}, () => JSX.Element, {}, import("vue").ComputedOptions, import("vue").MethodOptions, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<{
|
|
20
|
-
editor: GetEditor;
|
|
21
|
-
editorRef?: Ref<EditorRef> | undefined;
|
|
22
|
-
}>, {}>;
|
|
23
|
-
export declare const useEditor: (getEditor: GetEditor) => (container: HTMLDivElement, renderVue: (Component: DefineComponent) => ViewFactory) => Editor;
|
|
24
|
-
export {};
|
|
25
|
-
//# sourceMappingURL=Editor.d.ts.map
|
package/lib/Editor.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Editor.d.ts","sourceRoot":"","sources":["../src/Editor.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAA0B,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACH,eAAe,EAUf,GAAG,EAGN,MAAM,KAAK,CAAC;AAOb,aAAK,SAAS,GAAG,CAAC,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,WAAW,KAAK,MAAM,CAAC;AA8B/G,eAAO,MAAM,eAAe;YAAqC,SAAS;;;YAAT,SAAS;;OAUxE,CAAC;AAGH,oBAAY,SAAS,GAAG;IAAE,GAAG,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,cAAc,GAAG,IAAI,CAAA;CAAE,CAAC;AAE5F,eAAO,MAAM,SAAS;YAAqC,SAAS;;;YAAT,SAAS;;OAkBlE,CAAC;AAGH,eAAO,MAAM,SAAS,cAAe,SAAS,wDAlEsB,eAAe,KAAK,WAAW,WAoElG,CAAC"}
|
package/lib/Portals.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { DefineComponent } from 'vue';
|
|
2
|
-
export declare type PortalPair = [key: string, component: DefineComponent];
|
|
3
|
-
export declare const Portals: DefineComponent<{
|
|
4
|
-
portals: PortalPair[];
|
|
5
|
-
}, () => JSX.Element, {}, import("vue").ComputedOptions, import("vue").MethodOptions, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<{
|
|
6
|
-
portals: PortalPair[];
|
|
7
|
-
}>, {}>;
|
|
8
|
-
//# sourceMappingURL=Portals.d.ts.map
|
package/lib/Portals.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Portals.d.ts","sourceRoot":"","sources":["../src/Portals.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAkE,MAAM,KAAK,CAAC;AACtG,oBAAY,UAAU,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;AAInE,eAAO,MAAM,OAAO;aAAsC,UAAU,EAAE;;aAAZ,UAAU,EAAE;OAuBpE,CAAC"}
|
package/lib/VueNode.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/// <reference types="prosemirror-model" />
|
|
2
|
-
import { Decoration, EditorView, Mark, Node } from '@milkdown/prose';
|
|
3
|
-
import { InjectionKey } from 'vue';
|
|
4
|
-
export declare type NodeContext = {
|
|
5
|
-
node: Node | Mark;
|
|
6
|
-
view: EditorView;
|
|
7
|
-
getPos: boolean | (() => number);
|
|
8
|
-
decorations: Decoration[];
|
|
9
|
-
};
|
|
10
|
-
export declare const nodeMetadata: InjectionKey<NodeContext>;
|
|
11
|
-
export declare const VueNodeContainer: import("vue").DefineComponent<{
|
|
12
|
-
node: Node | Mark;
|
|
13
|
-
view: EditorView;
|
|
14
|
-
getPos: boolean | (() => number);
|
|
15
|
-
decorations: Decoration[];
|
|
16
|
-
}, () => JSX.Element, {}, import("vue").ComputedOptions, import("vue").MethodOptions, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<{
|
|
17
|
-
node: Node | Mark;
|
|
18
|
-
view: EditorView;
|
|
19
|
-
getPos: boolean | (() => number);
|
|
20
|
-
decorations: Decoration[];
|
|
21
|
-
}>, {}>;
|
|
22
|
-
export declare const Content: import("vue").DefineComponent<{
|
|
23
|
-
dom?: HTMLElement | undefined;
|
|
24
|
-
}, () => JSX.Element, {}, import("vue").ComputedOptions, import("vue").MethodOptions, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<{
|
|
25
|
-
dom?: HTMLElement | undefined;
|
|
26
|
-
}>, {}>;
|
|
27
|
-
//# sourceMappingURL=VueNode.d.ts.map
|
package/lib/VueNode.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"VueNode.d.ts","sourceRoot":"","sources":["../src/VueNode.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAgC,YAAY,EAA6B,MAAM,KAAK,CAAC;AAE5F,oBAAY,WAAW,GAAG;IACtB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IACjC,WAAW,EAAE,UAAU,EAAE,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,YAAY,CAAC,WAAW,CAAY,CAAC;AAEhE,eAAO,MAAM,gBAAgB;UARnB,IAAI,GAAG,IAAI;UACX,UAAU;YACR,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC;iBACnB,UAAU,EAAE;;UAHnB,IAAI,GAAG,IAAI;UACX,UAAU;YACR,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC;iBACnB,UAAU,EAAE;OAa3B,CAAC;AAGH,eAAO,MAAM,OAAO;;;;OAOlB,CAAC"}
|
package/lib/VueNodeView.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"VueNodeView.d.ts","sourceRoot":"","sources":["../src/VueNodeView.tsx"],"names":[],"mappings":";AACA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,eAAe,EAAgC,MAAM,KAAK,CAAC;AAMpE,eAAO,MAAM,aAAa,uBACD,eAAe,OAAO,MAAM,KAAK,IAAI,2BAA2B,MAAM,KAAK,IAAI,iBACxF,eAAe,KAAG,WAE+D,CAAC;AAElG,qBAAa,WAAY,YAAW,QAAQ;IAMpC,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,iBAAiB;IACzB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,WAAW;IAXvB,GAAG,EAAE,WAAW,GAAG,SAAS,CAAC;IAC7B,UAAU,EAAE,WAAW,GAAG,SAAS,CAAC;IACpC,GAAG,EAAE,MAAM,CAAC;gBAGA,SAAS,EAAE,eAAe,EAC1B,SAAS,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,EACzD,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EACxC,IAAI,EAAE,IAAI,GAAG,IAAI,EACjB,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC,EAChC,WAAW,EAAE,UAAU,EAAE;IAmBrC,YAAY;IAwBZ,OAAO;IAMP,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE;CAMnF"}
|
package/lib/index.cjs.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});exports[Symbol.toStringTag]="Module";var e=require("vue"),m=require("@milkdown/core"),u=require("@milkdown/prose"),C=require("nanoid");const R=n=>n.map(t=>t[0]).join(`
|
|
2
|
-
`),h=e.defineComponent(n=>{const t=e.shallowRef([]),a=e.ref(""),i=e.shallowRef(()=>[]);return e.watch(()=>R(n.portals),o=>{if(o!==a.value){a.value=o;const r=n.portals.map(d=>d[1]);t.value=r}}),e.nextTick(()=>{i.value=()=>t.value.map(o=>e.createVNode(o,null,null))}),()=>e.createVNode(e.Fragment,null,[i.value()])});h.props=["portals"];const p=Symbol(),v=e.defineComponent(({node:n,view:t,getPos:a,decorations:i},o)=>(e.provide(p,{node:n,view:t,getPos:a,decorations:i}),()=>{var r,d,s;return e.createVNode(e.Fragment,null,[(s=(d=(r=o.slots).default)==null?void 0:d.call(r))!=null?s:[]])}));v.props=["editor","node","view","getPos","decorations"];const V=e.defineComponent(n=>{const t=e.ref(null);return e.watchEffect(()=>{!n.dom||!t.value||t.value.appendChild(n.dom)}),()=>e.createVNode("div",{ref:t},null)});V.props=["dom"];const g=C.customAlphabet("abcedfghicklmn",10),N=(n,t)=>a=>(i,o,r,d)=>new P(a,n,t,i,o,r,d);class P{constructor(t,a,i,o,r,d,s){this.component=t,this.addPortal=a,this.removePortalByKey=i,this.node=o,this.view=r,this.getPos=d,this.decorations=s,this.key=g();const l=document.createElement(o instanceof u.Mark?"span":"div");l.classList.add("dom-wrapper");const c=o instanceof u.Node&&o.isLeaf?void 0:document.createElement(o instanceof u.Mark?"span":"div");c&&(c.classList.add("content-dom"),l.appendChild(c)),this.dom=l,this.contentDOM=c,this.renderPortal()}renderPortal(){if(!this.dom)return;const t=this.component,a=e.defineComponent(()=>()=>e.createVNode(e.Teleport,{to:this.dom},{default:()=>[e.createVNode(v,{key:this.key,node:this.node,view:this.view,getPos:this.getPos,decorations:this.decorations},{default:()=>[e.createVNode(t,null,{default:()=>[e.createVNode(V,{dom:this.contentDOM},null)]})]})]}));this.addPortal(a,this.key)}destroy(){this.dom=void 0,this.contentDOM=void 0,this.removePortalByKey(this.key)}ignoreMutation(t){return this.contentDOM?!this.contentDOM.contains(t.target):!0}}const w=Symbol(),k=n=>{const t=e.ref(null),a=e.inject(w,()=>{throw new Error}),i=e.markRaw({});return e.onMounted(()=>{!t.value||n(t.value,a).create().then(o=>{i.editor=o}).catch(o=>console.error(o))}),e.onUnmounted(()=>{var d,s,l;const o=(d=i.editor)==null?void 0:d.action(c=>c.get(m.editorViewCtx)),r=(s=i.editor)==null?void 0:s.action(c=>c.get(m.rootCtx));(l=r==null?void 0:r.firstChild)==null||l.remove(),o==null||o.destroy()}),{divRef:t,editorRef:i}},f=e.defineComponent(n=>{const t=k(n.editor);return n.editorRef&&(n.editorRef.value={get:()=>t.editorRef.editor,dom:()=>t.divRef.value}),()=>e.createVNode("div",{ref:t.divRef},null)});f.props=["editor","editorRef"];const y=e.defineComponent(n=>{const t=e.shallowReactive([]),a=e.markRaw((r,d)=>{t.push([d,r])}),i=e.markRaw(r=>{const d=t.findIndex(s=>s[0]===r);t.splice(d,1)}),o=N(a,i);return e.provide(w,o),()=>e.createVNode(e.Fragment,null,[e.createVNode(h,{portals:t},null),e.createVNode(f,{editorRef:n.editorRef,editor:n.editor},null)])});y.props=["editor","editorRef"];const M=n=>(...t)=>n(...t);exports.EditorComponent=f;exports.VueEditor=y;exports.nodeMetadata=p;exports.useEditor=M;
|
|
3
|
-
//# sourceMappingURL=index.cjs.js.map
|
package/lib/index.cjs.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/Portals.tsx","../src/VueNode.tsx","../src/VueNodeView.tsx","../src/Editor.tsx"],"sourcesContent":["/* Copyright 2021, Milkdown by Mirone. */\nimport { DefineComponent, defineComponent, Fragment, h, nextTick, ref, shallowRef, watch } from 'vue';\nexport type PortalPair = [key: string, component: DefineComponent];\n\nconst getId = (pairs: PortalPair[]) => pairs.map((p) => p[0]).join('\\n');\n\nexport const Portals = defineComponent((props: { portals: PortalPair[] }) => {\n const portalComponents = shallowRef<Array<DefineComponent>>([]);\n const prev = ref<string>('');\n const renderList = shallowRef<() => JSX.Element[]>(() => []);\n\n watch(\n () => getId(props.portals),\n (ids) => {\n if (ids !== prev.value) {\n prev.value = ids;\n const next = props.portals.map((p) => p[1]);\n portalComponents.value = next;\n }\n },\n );\n\n nextTick(() => {\n renderList.value = () => portalComponents.value.map((P) => <P />);\n });\n\n return () => {\n return <>{renderList.value()}</>;\n };\n});\nPortals.props = ['portals'];\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { Decoration, EditorView, Mark, Node } from '@milkdown/prose';\nimport { defineComponent, Fragment, h, InjectionKey, provide, ref, watchEffect } from 'vue';\n\nexport type NodeContext = {\n node: Node | Mark;\n view: EditorView;\n getPos: boolean | (() => number);\n decorations: Decoration[];\n};\n\nexport const nodeMetadata: InjectionKey<NodeContext> = Symbol();\n\nexport const VueNodeContainer = defineComponent(({ node, view, getPos, decorations }: NodeContext, context) => {\n provide(nodeMetadata, {\n node,\n view,\n getPos,\n decorations,\n });\n return () => <>{context.slots.default?.() ?? []}</>;\n});\nVueNodeContainer.props = ['editor', 'node', 'view', 'getPos', 'decorations'];\n\nexport const Content = defineComponent((props: { dom?: HTMLElement }) => {\n const containerRef = ref<HTMLDivElement | null>(null);\n watchEffect(() => {\n if (!props.dom || !containerRef.value) return;\n containerRef.value.appendChild(props.dom);\n });\n return () => <div ref={containerRef} />;\n});\nContent.props = ['dom'];\n","/* Copyright 2021, Milkdown by Mirone. */\nimport type { Decoration, EditorView, NodeView, ViewFactory } from '@milkdown/prose';\nimport { Mark, Node } from '@milkdown/prose';\nimport { customAlphabet } from 'nanoid';\nimport { DefineComponent, defineComponent, h, Teleport } from 'vue';\n\nimport { Content, VueNodeContainer } from './VueNode';\n\nconst nanoid = customAlphabet('abcedfghicklmn', 10);\n\nexport const createVueView =\n (addPortal: (portal: DefineComponent, key: string) => void, removePortalByKey: (key: string) => void) =>\n (component: DefineComponent): ViewFactory =>\n (node, view, getPos, decorations) =>\n new VueNodeView(component, addPortal, removePortalByKey, node, view, getPos, decorations);\n\nexport class VueNodeView implements NodeView {\n dom: HTMLElement | undefined;\n contentDOM: HTMLElement | undefined;\n key: string;\n\n constructor(\n private component: DefineComponent,\n private addPortal: (portal: DefineComponent, key: string) => void,\n private removePortalByKey: (key: string) => void,\n private node: Node | Mark,\n private view: EditorView,\n private getPos: boolean | (() => number),\n private decorations: Decoration[],\n ) {\n this.key = nanoid();\n const dom = document.createElement(node instanceof Mark ? 'span' : 'div');\n dom.classList.add('dom-wrapper');\n\n const contentDOM =\n node instanceof Node && node.isLeaf\n ? undefined\n : document.createElement(node instanceof Mark ? 'span' : 'div');\n if (contentDOM) {\n contentDOM.classList.add('content-dom');\n dom.appendChild(contentDOM);\n }\n this.dom = dom;\n this.contentDOM = contentDOM;\n this.renderPortal();\n }\n\n renderPortal() {\n if (!this.dom) return;\n\n const CustomComponent = this.component;\n const Portal = defineComponent(() => {\n return () => (\n <Teleport to={this.dom}>\n <VueNodeContainer\n key={this.key}\n node={this.node}\n view={this.view}\n getPos={this.getPos}\n decorations={this.decorations}\n >\n <CustomComponent>\n <Content dom={this.contentDOM} />\n </CustomComponent>\n </VueNodeContainer>\n </Teleport>\n );\n });\n this.addPortal(Portal, this.key);\n }\n\n destroy() {\n this.dom = undefined;\n this.contentDOM = undefined;\n this.removePortalByKey(this.key);\n }\n\n ignoreMutation(mutation: MutationRecord | { type: 'selection'; target: Element }) {\n if (!this.contentDOM) {\n return true;\n }\n return !this.contentDOM.contains(mutation.target);\n }\n}\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { Editor, editorViewCtx, rootCtx } from '@milkdown/core';\nimport { ViewFactory } from '@milkdown/prose';\nimport {\n DefineComponent,\n defineComponent,\n Fragment,\n h,\n inject,\n InjectionKey,\n markRaw,\n onMounted,\n onUnmounted,\n provide,\n Ref,\n ref,\n shallowReactive,\n} from 'vue';\n\nimport { PortalPair, Portals } from './Portals';\nimport { createVueView } from './VueNodeView';\n\nconst rendererKey: InjectionKey<(component: DefineComponent) => ViewFactory> = Symbol();\n\ntype GetEditor = (container: HTMLDivElement, renderVue: (Component: DefineComponent) => ViewFactory) => Editor;\n\nconst useGetEditor = (getEditor: GetEditor) => {\n const divRef = ref<HTMLDivElement | null>(null);\n const renderVue = inject<(Component: DefineComponent) => ViewFactory>(rendererKey, () => {\n throw new Error();\n });\n const editorRef = markRaw<{ editor?: Editor }>({});\n onMounted(() => {\n if (!divRef.value) return;\n\n getEditor(divRef.value, renderVue)\n .create()\n .then((editor) => {\n editorRef.editor = editor;\n return;\n })\n .catch((e) => console.error(e));\n });\n onUnmounted(() => {\n const view = editorRef.editor?.action((ctx) => ctx.get(editorViewCtx));\n const root = editorRef.editor?.action((ctx) => ctx.get(rootCtx)) as HTMLElement;\n\n root?.firstChild?.remove();\n view?.destroy();\n });\n\n return { divRef, editorRef };\n};\n\nexport const EditorComponent = defineComponent((props: { editor: GetEditor; editorRef?: Ref<EditorRef> }) => {\n const refs = useGetEditor(props.editor);\n if (props.editorRef) {\n props.editorRef.value = {\n get: () => refs.editorRef.editor,\n dom: () => refs.divRef.value,\n };\n }\n\n return () => <div ref={refs.divRef} />;\n});\nEditorComponent.props = ['editor', 'editorRef'];\n\nexport type EditorRef = { get: () => Editor | undefined; dom: () => HTMLDivElement | null };\n\nexport const VueEditor = defineComponent((props: { editor: GetEditor; editorRef?: Ref<EditorRef> }) => {\n const portals = shallowReactive<PortalPair[]>([]);\n const addPortal = markRaw((component: DefineComponent, key: string) => {\n portals.push([key, component]);\n });\n const removePortalByKey = markRaw((key: string) => {\n const index = portals.findIndex((p) => p[0] === key);\n portals.splice(index, 1);\n });\n const renderVue = createVueView(addPortal, removePortalByKey);\n provide(rendererKey, renderVue);\n\n return () => (\n <>\n <Portals portals={portals} />\n <EditorComponent editorRef={props.editorRef} editor={props.editor} />\n </>\n );\n});\nVueEditor.props = ['editor', 'editorRef'];\n\nexport const useEditor = (getEditor: GetEditor) => {\n return (...args: Parameters<GetEditor>) => getEditor(...args);\n};\n"],"names":["getId","pairs","map","p","join","Portals","defineComponent","props","portalComponents","shallowRef","prev","ref","renderList","watch","portals","ids","value","next","nextTick","P","nodeMetadata","Symbol","VueNodeContainer","node","view","getPos","decorations","context","provide","slots","default","Content","containerRef","watchEffect","dom","appendChild","nanoid","customAlphabet","createVueView","addPortal","removePortalByKey","component","VueNodeView","constructor","key","document","createElement","Mark","classList","add","contentDOM","Node","isLeaf","undefined","renderPortal","CustomComponent","Portal","destroy","ignoreMutation","mutation","contains","target","rendererKey","useGetEditor","getEditor","divRef","renderVue","inject","Error","editorRef","markRaw","onMounted","create","then","editor","catch","e","console","error","onUnmounted","action","ctx","get","editorViewCtx","root","rootCtx","firstChild","remove","EditorComponent","refs","VueEditor","shallowReactive","push","index","findIndex","splice","useEditor","args"],"mappings":"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"}
|
package/lib/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}
|
package/lib/utils.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,aAAK,OAAO,CAAC,CAAC,EAAE,CAAC,SAAS,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AACjD,aAAK,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,WAAW,EAAE,IAAI;KACpE,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACtG,CAAC,MAAM,CAAC,CAAC,CAAC;AACX,oBAAY,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC"}
|
package/src/Portals.tsx
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
-
import { DefineComponent, defineComponent, Fragment, h, nextTick, ref, shallowRef, watch } from 'vue';
|
|
3
|
-
export type PortalPair = [key: string, component: DefineComponent];
|
|
4
|
-
|
|
5
|
-
const getId = (pairs: PortalPair[]) => pairs.map((p) => p[0]).join('\n');
|
|
6
|
-
|
|
7
|
-
export const Portals = defineComponent((props: { portals: PortalPair[] }) => {
|
|
8
|
-
const portalComponents = shallowRef<Array<DefineComponent>>([]);
|
|
9
|
-
const prev = ref<string>('');
|
|
10
|
-
const renderList = shallowRef<() => JSX.Element[]>(() => []);
|
|
11
|
-
|
|
12
|
-
watch(
|
|
13
|
-
() => getId(props.portals),
|
|
14
|
-
(ids) => {
|
|
15
|
-
if (ids !== prev.value) {
|
|
16
|
-
prev.value = ids;
|
|
17
|
-
const next = props.portals.map((p) => p[1]);
|
|
18
|
-
portalComponents.value = next;
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
nextTick(() => {
|
|
24
|
-
renderList.value = () => portalComponents.value.map((P) => <P />);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
return () => {
|
|
28
|
-
return <>{renderList.value()}</>;
|
|
29
|
-
};
|
|
30
|
-
});
|
|
31
|
-
Portals.props = ['portals'];
|