@tiptap/vue-2 3.24.0 → 3.26.0
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/dist/index.cjs +30 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +30 -2
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/NodeViewContent.ts +16 -0
- package/src/VueNodeViewRenderer.ts +32 -1
package/dist/index.cjs
CHANGED
|
@@ -115,6 +115,19 @@ var NodeViewContent = {
|
|
|
115
115
|
default: "div"
|
|
116
116
|
}
|
|
117
117
|
},
|
|
118
|
+
inject: {
|
|
119
|
+
nodeViewContentRef: { default: void 0 }
|
|
120
|
+
},
|
|
121
|
+
mounted() {
|
|
122
|
+
if (this.nodeViewContentRef && this.$el) {
|
|
123
|
+
this.nodeViewContentRef(this.$el);
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
beforeDestroy() {
|
|
127
|
+
if (this.nodeViewContentRef) {
|
|
128
|
+
this.nodeViewContentRef(null);
|
|
129
|
+
}
|
|
130
|
+
},
|
|
118
131
|
render(createElement) {
|
|
119
132
|
return createElement(this.as, {
|
|
120
133
|
style: {
|
|
@@ -217,6 +230,9 @@ var VueNodeView = class extends import_core2.NodeView {
|
|
|
217
230
|
this.editor.on("update", this.handlePositionUpdate);
|
|
218
231
|
}
|
|
219
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Called when the node view is mounted.
|
|
235
|
+
*/
|
|
220
236
|
mount() {
|
|
221
237
|
var _a, _b;
|
|
222
238
|
const props = {
|
|
@@ -243,13 +259,24 @@ var VueNodeView = class extends import_core2.NodeView {
|
|
|
243
259
|
provide: () => {
|
|
244
260
|
return {
|
|
245
261
|
onDragStart,
|
|
246
|
-
decorationClasses: this.decorationClasses
|
|
262
|
+
decorationClasses: this.decorationClasses,
|
|
263
|
+
nodeViewContentRef: (el) => {
|
|
264
|
+
if (!this.contentDOMElement) return;
|
|
265
|
+
if (el && el.firstChild !== this.contentDOMElement) {
|
|
266
|
+
el.appendChild(this.contentDOMElement);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
247
269
|
};
|
|
248
270
|
}
|
|
249
271
|
});
|
|
250
272
|
this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
|
|
251
273
|
this.editor.on("selectionUpdate", this.handleSelectionUpdate);
|
|
252
274
|
this.currentPos = this.getPos();
|
|
275
|
+
if (!this.node.isLeaf) {
|
|
276
|
+
this.contentDOMElement = document.createElement(this.node.isInline ? "span" : "div");
|
|
277
|
+
this.contentDOMElement.style.whiteSpace = "inherit";
|
|
278
|
+
this.contentDOMElement.dataset.nodeViewContentVue = "";
|
|
279
|
+
}
|
|
253
280
|
this.renderer = new VueRenderer(Component, {
|
|
254
281
|
parent: this.editor.contentComponent,
|
|
255
282
|
propsData: mountProps
|
|
@@ -273,7 +300,7 @@ var VueNodeView = class extends import_core2.NodeView {
|
|
|
273
300
|
if (this.node.isLeaf) {
|
|
274
301
|
return null;
|
|
275
302
|
}
|
|
276
|
-
return this.
|
|
303
|
+
return this.contentDOMElement;
|
|
277
304
|
}
|
|
278
305
|
/**
|
|
279
306
|
* On editor selection update, check if the node is selected.
|
|
@@ -383,6 +410,7 @@ var VueNodeView = class extends import_core2.NodeView {
|
|
|
383
410
|
if (this.options.trackNodeViewPosition) {
|
|
384
411
|
this.editor.off("update", this.handlePositionUpdate);
|
|
385
412
|
}
|
|
413
|
+
this.contentDOMElement = null;
|
|
386
414
|
}
|
|
387
415
|
};
|
|
388
416
|
function VueNodeViewRenderer(component, options) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/Editor.ts","../src/EditorContent.ts","../src/NodeViewContent.ts","../src/NodeViewWrapper.ts","../src/VueNodeViewRenderer.ts","../src/Vue.ts","../src/VueRenderer.ts"],"sourcesContent":["export { Editor } from './Editor.js'\nexport * from './EditorContent.js'\nexport * from './NodeViewContent.js'\nexport * from './NodeViewWrapper.js'\nexport * from './VueNodeViewRenderer.js'\nexport * from './VueRenderer.js'\nexport * from '@tiptap/core'\n","import { Editor as CoreEditor } from '@tiptap/core'\nimport type Vue from 'vue'\n\nexport class Editor extends CoreEditor {\n public contentComponent: Vue | null = null\n}\n","import type { Component, CreateElement, PropType } from 'vue'\nimport type Vue from 'vue'\n\nimport type { Editor } from './Editor.js'\n\nexport interface EditorContentInterface extends Vue {\n editor: Editor\n}\n\nexport const EditorContent: Component = {\n name: 'EditorContent',\n\n props: {\n editor: {\n default: null,\n type: Object as PropType<Editor>,\n },\n },\n\n watch: {\n editor: {\n immediate: true,\n handler(this: EditorContentInterface, editor: Editor) {\n if (editor && editor.options.element) {\n this.$nextTick(() => {\n const element = this.$el\n\n if (!element || !editor.view.dom?.parentNode) {\n return\n }\n\n element.append(...editor.view.dom.parentNode.childNodes)\n editor.contentComponent = this\n\n editor.setOptions({\n element,\n })\n\n editor.createNodeViews()\n })\n }\n },\n },\n },\n\n render(createElement: CreateElement) {\n return createElement('div')\n },\n\n beforeDestroy(this: EditorContentInterface) {\n const { editor } = this\n\n if (!editor) {\n return\n }\n\n if (!editor.isDestroyed) {\n editor.view.setProps({\n nodeViews: {},\n })\n }\n\n editor.contentComponent = null\n\n if (!editor.view.dom?.parentNode) {\n return\n }\n\n // TODO using the new editor.mount method might allow us to remove this\n const newElement = document.createElement('div')\n\n newElement.append(...editor.view.dom.parentNode.childNodes)\n\n editor.setOptions({\n element: newElement,\n })\n },\n}\n","import type { Component, CreateElement } from 'vue'\nimport type Vue from 'vue'\n\nexport interface NodeViewContentInterface extends Vue {\n as: string\n}\n\nexport const NodeViewContent: Component = {\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n render(this: NodeViewContentInterface, createElement: CreateElement) {\n return createElement(this.as, {\n style: {\n whiteSpace: 'pre-wrap',\n },\n attrs: {\n 'data-node-view-content': '',\n },\n })\n },\n}\n","import type { Component, CreateElement } from 'vue'\nimport type Vue from 'vue'\n\nexport interface NodeViewWrapperInterface extends Vue {\n as: string\n decorationClasses: {\n value: string\n }\n onDragStart: () => void\n}\n\nexport const NodeViewWrapper: Component = {\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n inject: ['onDragStart', 'decorationClasses'],\n\n render(this: NodeViewWrapperInterface, createElement: CreateElement) {\n return createElement(\n this.as,\n {\n class: this.decorationClasses.value,\n style: {\n whiteSpace: 'normal',\n },\n attrs: {\n 'data-node-view-wrapper': '',\n },\n on: {\n dragstart: this.onDragStart,\n },\n },\n this.$slots.default,\n )\n },\n}\n","import type {\n DecorationWithType,\n NodeViewProps,\n NodeViewRenderer,\n NodeViewRendererOptions,\n NodeViewRendererProps,\n} from '@tiptap/core'\nimport { isNodeViewSelected, NodeView } from '@tiptap/core'\nimport type { Node as ProseMirrorNode } from '@tiptap/pm/model'\nimport type { Decoration, DecorationSource, NodeView as ProseMirrorNodeView } from '@tiptap/pm/view'\nimport type { VueConstructor } from 'vue'\nimport { booleanProp, functionProp, objectProp } from 'vue-ts-types'\n\nimport type { Editor } from './Editor.js'\nimport { Vue } from './Vue.js'\nimport { VueRenderer } from './VueRenderer.js'\n\nexport const nodeViewProps = {\n editor: objectProp<NodeViewProps['editor']>().required,\n node: objectProp<NodeViewProps['node']>().required,\n decorations: objectProp<NodeViewProps['decorations']>().required,\n selected: booleanProp().required,\n extension: objectProp<NodeViewProps['extension']>().required,\n getPos: functionProp<NodeViewProps['getPos']>().required,\n updateAttributes: functionProp<NodeViewProps['updateAttributes']>().required,\n deleteNode: functionProp<NodeViewProps['deleteNode']>().required,\n}\n\nexport interface VueNodeViewRendererOptions extends NodeViewRendererOptions {\n update:\n | ((props: {\n oldNode: ProseMirrorNode\n oldDecorations: readonly Decoration[]\n oldInnerDecorations: DecorationSource\n newNode: ProseMirrorNode\n newDecorations: readonly Decoration[]\n innerDecorations: DecorationSource\n updateProps: () => void\n }) => boolean)\n | null\n}\n\nclass VueNodeView extends NodeView<Vue | VueConstructor, Editor, VueNodeViewRendererOptions> {\n renderer!: VueRenderer\n\n decorationClasses!: {\n value: string\n }\n\n private currentPos: number | undefined\n\n constructor(\n component: Vue | VueConstructor,\n props: NodeViewRendererProps,\n options?: Partial<VueNodeViewRendererOptions>,\n ) {\n super(component, props, options)\n\n if (this.options.trackNodeViewPosition) {\n this.editor.on('update', this.handlePositionUpdate)\n }\n }\n\n private handlePositionUpdate = () => {\n const newPos = this.getPos()\n if (typeof newPos !== 'number' || newPos === this.currentPos) {\n return\n }\n this.currentPos = newPos\n this.renderer.updateProps({ getPos: () => this.getPos() })\n }\n\n mount() {\n const props: Record<string, any> = {\n editor: this.editor,\n node: this.node,\n decorations: this.decorations as DecorationWithType[],\n innerDecorations: this.innerDecorations,\n view: this.view,\n selected: false,\n extension: this.extension,\n HTMLAttributes: this.HTMLAttributes,\n getPos: () => this.getPos(),\n updateAttributes: (attributes = {}) => this.updateAttributes(attributes),\n deleteNode: () => this.deleteNode(),\n }\n\n const mountProps = props as NodeViewProps\n\n const onDragStart = this.onDragStart.bind(this)\n\n this.decorationClasses = Vue.observable({\n value: this.getDecorationClasses(),\n })\n\n // @ts-ignore\n const vue = this.editor.contentComponent?.$options._base ?? Vue // oxlint-disable-line\n\n const Component = vue.extend(this.component).extend({\n props: Object.keys(props),\n provide: () => {\n return {\n onDragStart,\n decorationClasses: this.decorationClasses,\n }\n },\n })\n\n this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this)\n this.editor.on('selectionUpdate', this.handleSelectionUpdate)\n\n this.currentPos = this.getPos()\n\n this.renderer = new VueRenderer(Component, {\n parent: this.editor.contentComponent,\n propsData: mountProps,\n })\n }\n\n /**\n * Return the DOM element.\n * This is the element that will be used to display the node view.\n */\n get dom() {\n if (!this.renderer.element.hasAttribute('data-node-view-wrapper')) {\n throw Error('Please use the NodeViewWrapper component for your node view.')\n }\n\n return this.renderer.element as HTMLElement\n }\n\n /**\n * Return the content DOM element.\n * This is the element that will be used to display the rich-text content of the node.\n */\n get contentDOM() {\n if (this.node.isLeaf) {\n return null\n }\n\n return this.dom.querySelector('[data-node-view-content]') as HTMLElement | null\n }\n\n /**\n * On editor selection update, check if the node is selected.\n * If it is, call `selectNode`, otherwise call `deselectNode`.\n */\n handleSelectionUpdate() {\n const pos = this.getPos()\n\n if (typeof pos !== 'number') {\n return\n }\n\n const isSelected = isNodeViewSelected({\n selection: this.editor.state.selection,\n pos,\n nodeSize: this.node.nodeSize,\n selectedOnTextSelection: this.options.selectedOnTextSelection,\n })\n\n if (isSelected) {\n if (this.renderer.ref.$props.selected) {\n return\n }\n\n this.selectNode()\n } else {\n if (!this.renderer.ref.$props.selected) {\n return\n }\n\n this.deselectNode()\n }\n }\n\n /**\n * On update, update the React component.\n * To prevent unnecessary updates, the `update` option can be used.\n */\n update(\n node: ProseMirrorNode,\n decorations: readonly Decoration[],\n innerDecorations: DecorationSource,\n ): boolean {\n const rerenderComponent = (props?: Record<string, any>) => {\n this.decorationClasses.value = this.getDecorationClasses()\n this.renderer.updateProps(props)\n }\n\n if (typeof this.options.update === 'function') {\n const oldNode = this.node\n const oldDecorations = this.decorations\n const oldInnerDecorations = this.innerDecorations\n\n this.node = node\n this.decorations = decorations\n this.innerDecorations = innerDecorations\n\n return this.options.update({\n oldNode,\n oldDecorations,\n newNode: node,\n newDecorations: decorations,\n oldInnerDecorations,\n innerDecorations,\n updateProps: () => rerenderComponent({ node, decorations, innerDecorations }),\n })\n }\n\n if (node.type !== this.node.type) {\n return false\n }\n\n const nodeChanged = node !== this.node\n\n // Node reference unchanged — only decorations may have changed.\n // ProseMirror renders decorations independently on the contentDOM,\n // and the getPos closure (bound in mount()) calls through to\n // ProseMirror's position function at call time, so it is always\n // current. Update internal refs, refresh decoration classes for\n // the wrapper component, and skip the Vue re-render.\n if (!nodeChanged) {\n this.node = node\n this.decorations = decorations\n this.innerDecorations = innerDecorations\n this.decorationClasses.value = this.getDecorationClasses()\n return true\n }\n\n this.node = node\n this.decorations = decorations\n this.innerDecorations = innerDecorations\n this.currentPos = this.getPos()\n\n const extraProps: Record<string, any> = {\n node,\n decorations,\n innerDecorations,\n }\n\n if (this.options.trackNodeViewPosition) {\n extraProps.getPos = () => this.getPos()\n }\n\n rerenderComponent(extraProps)\n\n return true\n }\n\n /**\n * Select the node.\n * Add the `selected` prop and the `ProseMirror-selectednode` class.\n */\n selectNode() {\n this.renderer.updateProps({\n selected: true,\n })\n this.renderer.element.classList.add('ProseMirror-selectednode')\n }\n\n /**\n * Deselect the node.\n * Remove the `selected` prop and the `ProseMirror-selectednode` class.\n */\n deselectNode() {\n this.renderer.updateProps({\n selected: false,\n })\n this.renderer.element.classList.remove('ProseMirror-selectednode')\n }\n\n getDecorationClasses() {\n return (\n this.decorations\n // @ts-ignore\n .flatMap(item => item.type.attrs.class)\n .join(' ')\n )\n }\n\n destroy() {\n this.renderer.destroy()\n this.editor.off('selectionUpdate', this.handleSelectionUpdate)\n\n if (this.options.trackNodeViewPosition) {\n this.editor.off('update', this.handlePositionUpdate)\n }\n }\n}\n\nexport function VueNodeViewRenderer(\n component: Vue | VueConstructor,\n options?: Partial<VueNodeViewRendererOptions>,\n): NodeViewRenderer {\n return props => {\n // try to get the parent component\n // this is important for vue devtools to show the component hierarchy correctly\n // maybe it’s `undefined` because <editor-content> isn’t rendered yet\n if (!(props.editor as Editor).contentComponent) {\n return {} as unknown as ProseMirrorNodeView\n }\n\n return new VueNodeView(component, props, options)\n }\n}\n","import type { VueConstructor } from 'vue'\nimport VueDefault from 'vue'\n\n// With nodenext module resolution, TypeScript treats the default import as the module type.\n// We need to explicitly type it as VueConstructor to access static methods like extend and observable.\n// This is necessary because Vue 2's type definitions export Vue as VueConstructor, but nodenext\n// doesn't correctly infer the default export type.\nexport const Vue: VueConstructor = VueDefault as unknown as VueConstructor\n","import type { VueConstructor } from 'vue'\n\nimport { Vue } from './Vue.js'\n\n/**\n * The VueRenderer class is responsible for rendering a Vue component as a ProseMirror node view.\n */\nexport class VueRenderer {\n ref!: Vue\n\n constructor(component: Vue | VueConstructor, props: any) {\n const Component = typeof component === 'function' ? component : Vue.extend(component)\n\n this.ref = new Component(props).$mount()\n }\n\n get element(): Element {\n return this.ref.$el\n }\n\n updateProps(props: Record<string, any> = {}): void {\n if (!this.ref.$props) {\n return\n }\n\n // prevents `Avoid mutating a prop directly` error message\n // Fix: `VueNodeViewRenderer` change vue Constructor `config.silent` not working\n const currentVueConstructor = this.ref.$props.editor?.contentComponent?.$options._base ?? Vue // oxlint-disable-line\n const originalSilent = currentVueConstructor.config.silent\n\n currentVueConstructor.config.silent = true\n\n Object.entries(props).forEach(([key, value]) => {\n this.ref.$props[key] = value\n })\n\n currentVueConstructor.config.silent = originalSilent\n }\n\n destroy(): void {\n this.ref.$destroy()\n }\n}\n"],"mappings":"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","names":["CoreEditor","import_core","VueDefault"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Editor.ts","../src/EditorContent.ts","../src/NodeViewContent.ts","../src/NodeViewWrapper.ts","../src/VueNodeViewRenderer.ts","../src/Vue.ts","../src/VueRenderer.ts"],"sourcesContent":["export { Editor } from './Editor.js'\nexport * from './EditorContent.js'\nexport * from './NodeViewContent.js'\nexport * from './NodeViewWrapper.js'\nexport * from './VueNodeViewRenderer.js'\nexport * from './VueRenderer.js'\nexport * from '@tiptap/core'\n","import { Editor as CoreEditor } from '@tiptap/core'\nimport type Vue from 'vue'\n\nexport class Editor extends CoreEditor {\n public contentComponent: Vue | null = null\n}\n","import type { Component, CreateElement, PropType } from 'vue'\nimport type Vue from 'vue'\n\nimport type { Editor } from './Editor.js'\n\nexport interface EditorContentInterface extends Vue {\n editor: Editor\n}\n\nexport const EditorContent: Component = {\n name: 'EditorContent',\n\n props: {\n editor: {\n default: null,\n type: Object as PropType<Editor>,\n },\n },\n\n watch: {\n editor: {\n immediate: true,\n handler(this: EditorContentInterface, editor: Editor) {\n if (editor && editor.options.element) {\n this.$nextTick(() => {\n const element = this.$el\n\n if (!element || !editor.view.dom?.parentNode) {\n return\n }\n\n element.append(...editor.view.dom.parentNode.childNodes)\n editor.contentComponent = this\n\n editor.setOptions({\n element,\n })\n\n editor.createNodeViews()\n })\n }\n },\n },\n },\n\n render(createElement: CreateElement) {\n return createElement('div')\n },\n\n beforeDestroy(this: EditorContentInterface) {\n const { editor } = this\n\n if (!editor) {\n return\n }\n\n if (!editor.isDestroyed) {\n editor.view.setProps({\n nodeViews: {},\n })\n }\n\n editor.contentComponent = null\n\n if (!editor.view.dom?.parentNode) {\n return\n }\n\n // TODO using the new editor.mount method might allow us to remove this\n const newElement = document.createElement('div')\n\n newElement.append(...editor.view.dom.parentNode.childNodes)\n\n editor.setOptions({\n element: newElement,\n })\n },\n}\n","import type { Component, CreateElement } from 'vue'\nimport type Vue from 'vue'\n\nexport interface NodeViewContentInterface extends Vue {\n as: string\n}\n\nexport const NodeViewContent: Component = {\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n inject: {\n nodeViewContentRef: { default: undefined },\n },\n\n mounted(this: any) {\n if (this.nodeViewContentRef && this.$el) {\n this.nodeViewContentRef(this.$el)\n }\n },\n\n beforeDestroy(this: any) {\n if (this.nodeViewContentRef) {\n this.nodeViewContentRef(null)\n }\n },\n\n render(this: NodeViewContentInterface, createElement: CreateElement) {\n return createElement(this.as, {\n style: {\n whiteSpace: 'pre-wrap',\n },\n attrs: {\n 'data-node-view-content': '',\n },\n })\n },\n}\n","import type { Component, CreateElement } from 'vue'\nimport type Vue from 'vue'\n\nexport interface NodeViewWrapperInterface extends Vue {\n as: string\n decorationClasses: {\n value: string\n }\n onDragStart: () => void\n}\n\nexport const NodeViewWrapper: Component = {\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n inject: ['onDragStart', 'decorationClasses'],\n\n render(this: NodeViewWrapperInterface, createElement: CreateElement) {\n return createElement(\n this.as,\n {\n class: this.decorationClasses.value,\n style: {\n whiteSpace: 'normal',\n },\n attrs: {\n 'data-node-view-wrapper': '',\n },\n on: {\n dragstart: this.onDragStart,\n },\n },\n this.$slots.default,\n )\n },\n}\n","import type {\n DecorationWithType,\n NodeViewProps,\n NodeViewRenderer,\n NodeViewRendererOptions,\n NodeViewRendererProps,\n} from '@tiptap/core'\nimport { isNodeViewSelected, NodeView } from '@tiptap/core'\nimport type { Node as ProseMirrorNode } from '@tiptap/pm/model'\nimport type { Decoration, DecorationSource, NodeView as ProseMirrorNodeView } from '@tiptap/pm/view'\nimport type { VueConstructor } from 'vue'\nimport { booleanProp, functionProp, objectProp } from 'vue-ts-types'\n\nimport type { Editor } from './Editor.js'\nimport { Vue } from './Vue.js'\nimport { VueRenderer } from './VueRenderer.js'\n\nexport const nodeViewProps = {\n editor: objectProp<NodeViewProps['editor']>().required,\n node: objectProp<NodeViewProps['node']>().required,\n decorations: objectProp<NodeViewProps['decorations']>().required,\n selected: booleanProp().required,\n extension: objectProp<NodeViewProps['extension']>().required,\n getPos: functionProp<NodeViewProps['getPos']>().required,\n updateAttributes: functionProp<NodeViewProps['updateAttributes']>().required,\n deleteNode: functionProp<NodeViewProps['deleteNode']>().required,\n}\n\nexport interface VueNodeViewRendererOptions extends NodeViewRendererOptions {\n update:\n | ((props: {\n oldNode: ProseMirrorNode\n oldDecorations: readonly Decoration[]\n oldInnerDecorations: DecorationSource\n newNode: ProseMirrorNode\n newDecorations: readonly Decoration[]\n innerDecorations: DecorationSource\n updateProps: () => void\n }) => boolean)\n | null\n}\n\nclass VueNodeView extends NodeView<Vue | VueConstructor, Editor, VueNodeViewRendererOptions> {\n renderer!: VueRenderer\n\n decorationClasses!: {\n value: string\n }\n\n /**\n * The element that holds the rich-text content of the node.\n * Always created for non-leaf nodes to guarantee a valid contentDOM,\n * even when the user's component does not include a NodeViewContent.\n * Must NOT have an initializer because class field initializers run\n * after super() and would overwrite the value set by mount().\n */\n contentDOMElement!: HTMLElement | null\n\n private currentPos: number | undefined\n\n constructor(\n component: Vue | VueConstructor,\n props: NodeViewRendererProps,\n options?: Partial<VueNodeViewRendererOptions>,\n ) {\n super(component, props, options)\n\n if (this.options.trackNodeViewPosition) {\n this.editor.on('update', this.handlePositionUpdate)\n }\n }\n\n private handlePositionUpdate = () => {\n const newPos = this.getPos()\n if (typeof newPos !== 'number' || newPos === this.currentPos) {\n return\n }\n this.currentPos = newPos\n this.renderer.updateProps({ getPos: () => this.getPos() })\n }\n\n /**\n * Called when the node view is mounted.\n */\n mount() {\n const props: Record<string, any> = {\n editor: this.editor,\n node: this.node,\n decorations: this.decorations as DecorationWithType[],\n innerDecorations: this.innerDecorations,\n view: this.view,\n selected: false,\n extension: this.extension,\n HTMLAttributes: this.HTMLAttributes,\n getPos: () => this.getPos(),\n updateAttributes: (attributes = {}) => this.updateAttributes(attributes),\n deleteNode: () => this.deleteNode(),\n }\n\n const mountProps = props as NodeViewProps\n\n const onDragStart = this.onDragStart.bind(this)\n\n this.decorationClasses = Vue.observable({\n value: this.getDecorationClasses(),\n })\n\n // @ts-ignore\n const vue = this.editor.contentComponent?.$options._base ?? Vue // oxlint-disable-line\n\n const Component = vue.extend(this.component).extend({\n props: Object.keys(props),\n provide: () => {\n return {\n onDragStart,\n decorationClasses: this.decorationClasses,\n nodeViewContentRef: (el: HTMLElement | null) => {\n if (!this.contentDOMElement) return\n\n if (el && el.firstChild !== this.contentDOMElement) {\n // NodeViewContent mounted: move the contentDOMElement inside it\n el.appendChild(this.contentDOMElement)\n }\n },\n }\n },\n })\n\n this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this)\n this.editor.on('selectionUpdate', this.handleSelectionUpdate)\n\n this.currentPos = this.getPos()\n\n if (!this.node.isLeaf) {\n this.contentDOMElement = document.createElement(this.node.isInline ? 'span' : 'div')\n this.contentDOMElement.style.whiteSpace = 'inherit'\n // Use a distinct attribute to avoid clashing with the user's\n // <node-view-content> element (which carries data-node-view-content).\n // Matches React's data-node-view-content-react convention.\n this.contentDOMElement.dataset.nodeViewContentVue = ''\n }\n\n this.renderer = new VueRenderer(Component, {\n parent: this.editor.contentComponent,\n propsData: mountProps,\n })\n }\n\n /**\n * Return the DOM element.\n * This is the element that will be used to display the node view.\n */\n get dom() {\n if (!this.renderer.element.hasAttribute('data-node-view-wrapper')) {\n throw Error('Please use the NodeViewWrapper component for your node view.')\n }\n\n return this.renderer.element as HTMLElement\n }\n\n /**\n * Return the content DOM element.\n * This is the element that will be used to display the rich-text content of the node.\n */\n get contentDOM() {\n if (this.node.isLeaf) {\n return null\n }\n\n return this.contentDOMElement\n }\n\n /**\n * On editor selection update, check if the node is selected.\n * If it is, call `selectNode`, otherwise call `deselectNode`.\n */\n handleSelectionUpdate() {\n const pos = this.getPos()\n\n if (typeof pos !== 'number') {\n return\n }\n\n const isSelected = isNodeViewSelected({\n selection: this.editor.state.selection,\n pos,\n nodeSize: this.node.nodeSize,\n selectedOnTextSelection: this.options.selectedOnTextSelection,\n })\n\n if (isSelected) {\n if (this.renderer.ref.$props.selected) {\n return\n }\n\n this.selectNode()\n } else {\n if (!this.renderer.ref.$props.selected) {\n return\n }\n\n this.deselectNode()\n }\n }\n\n /**\n * On update, update the React component.\n * To prevent unnecessary updates, the `update` option can be used.\n */\n update(\n node: ProseMirrorNode,\n decorations: readonly Decoration[],\n innerDecorations: DecorationSource,\n ): boolean {\n const rerenderComponent = (props?: Record<string, any>) => {\n this.decorationClasses.value = this.getDecorationClasses()\n this.renderer.updateProps(props)\n }\n\n if (typeof this.options.update === 'function') {\n const oldNode = this.node\n const oldDecorations = this.decorations\n const oldInnerDecorations = this.innerDecorations\n\n this.node = node\n this.decorations = decorations\n this.innerDecorations = innerDecorations\n\n return this.options.update({\n oldNode,\n oldDecorations,\n newNode: node,\n newDecorations: decorations,\n oldInnerDecorations,\n innerDecorations,\n updateProps: () => rerenderComponent({ node, decorations, innerDecorations }),\n })\n }\n\n if (node.type !== this.node.type) {\n return false\n }\n\n const nodeChanged = node !== this.node\n\n // Node reference unchanged — only decorations may have changed.\n // ProseMirror renders decorations independently on the contentDOM,\n // and the getPos closure (bound in mount()) calls through to\n // ProseMirror's position function at call time, so it is always\n // current. Update internal refs, refresh decoration classes for\n // the wrapper component, and skip the Vue re-render.\n if (!nodeChanged) {\n this.node = node\n this.decorations = decorations\n this.innerDecorations = innerDecorations\n this.decorationClasses.value = this.getDecorationClasses()\n return true\n }\n\n this.node = node\n this.decorations = decorations\n this.innerDecorations = innerDecorations\n this.currentPos = this.getPos()\n\n const extraProps: Record<string, any> = {\n node,\n decorations,\n innerDecorations,\n }\n\n if (this.options.trackNodeViewPosition) {\n extraProps.getPos = () => this.getPos()\n }\n\n rerenderComponent(extraProps)\n\n return true\n }\n\n /**\n * Select the node.\n * Add the `selected` prop and the `ProseMirror-selectednode` class.\n */\n selectNode() {\n this.renderer.updateProps({\n selected: true,\n })\n this.renderer.element.classList.add('ProseMirror-selectednode')\n }\n\n /**\n * Deselect the node.\n * Remove the `selected` prop and the `ProseMirror-selectednode` class.\n */\n deselectNode() {\n this.renderer.updateProps({\n selected: false,\n })\n this.renderer.element.classList.remove('ProseMirror-selectednode')\n }\n\n getDecorationClasses() {\n return (\n this.decorations\n // @ts-ignore\n .flatMap(item => item.type.attrs.class)\n .join(' ')\n )\n }\n\n destroy() {\n this.renderer.destroy()\n this.editor.off('selectionUpdate', this.handleSelectionUpdate)\n\n if (this.options.trackNodeViewPosition) {\n this.editor.off('update', this.handlePositionUpdate)\n }\n\n this.contentDOMElement = null\n }\n}\n\nexport function VueNodeViewRenderer(\n component: Vue | VueConstructor,\n options?: Partial<VueNodeViewRendererOptions>,\n): NodeViewRenderer {\n return props => {\n // try to get the parent component\n // this is important for vue devtools to show the component hierarchy correctly\n // maybe it’s `undefined` because <editor-content> isn’t rendered yet\n if (!(props.editor as Editor).contentComponent) {\n return {} as unknown as ProseMirrorNodeView\n }\n\n return new VueNodeView(component, props, options)\n }\n}\n","import type { VueConstructor } from 'vue'\nimport VueDefault from 'vue'\n\n// With nodenext module resolution, TypeScript treats the default import as the module type.\n// We need to explicitly type it as VueConstructor to access static methods like extend and observable.\n// This is necessary because Vue 2's type definitions export Vue as VueConstructor, but nodenext\n// doesn't correctly infer the default export type.\nexport const Vue: VueConstructor = VueDefault as unknown as VueConstructor\n","import type { VueConstructor } from 'vue'\n\nimport { Vue } from './Vue.js'\n\n/**\n * The VueRenderer class is responsible for rendering a Vue component as a ProseMirror node view.\n */\nexport class VueRenderer {\n ref!: Vue\n\n constructor(component: Vue | VueConstructor, props: any) {\n const Component = typeof component === 'function' ? component : Vue.extend(component)\n\n this.ref = new Component(props).$mount()\n }\n\n get element(): Element {\n return this.ref.$el\n }\n\n updateProps(props: Record<string, any> = {}): void {\n if (!this.ref.$props) {\n return\n }\n\n // prevents `Avoid mutating a prop directly` error message\n // Fix: `VueNodeViewRenderer` change vue Constructor `config.silent` not working\n const currentVueConstructor = this.ref.$props.editor?.contentComponent?.$options._base ?? Vue // oxlint-disable-line\n const originalSilent = currentVueConstructor.config.silent\n\n currentVueConstructor.config.silent = true\n\n Object.entries(props).forEach(([key, value]) => {\n this.ref.$props[key] = value\n })\n\n currentVueConstructor.config.silent = originalSilent\n }\n\n destroy(): void {\n this.ref.$destroy()\n }\n}\n"],"mappings":"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","names":["CoreEditor","import_core","VueDefault"]}
|
package/dist/index.js
CHANGED
|
@@ -72,6 +72,19 @@ var NodeViewContent = {
|
|
|
72
72
|
default: "div"
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
|
+
inject: {
|
|
76
|
+
nodeViewContentRef: { default: void 0 }
|
|
77
|
+
},
|
|
78
|
+
mounted() {
|
|
79
|
+
if (this.nodeViewContentRef && this.$el) {
|
|
80
|
+
this.nodeViewContentRef(this.$el);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
beforeDestroy() {
|
|
84
|
+
if (this.nodeViewContentRef) {
|
|
85
|
+
this.nodeViewContentRef(null);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
75
88
|
render(createElement) {
|
|
76
89
|
return createElement(this.as, {
|
|
77
90
|
style: {
|
|
@@ -174,6 +187,9 @@ var VueNodeView = class extends NodeView {
|
|
|
174
187
|
this.editor.on("update", this.handlePositionUpdate);
|
|
175
188
|
}
|
|
176
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* Called when the node view is mounted.
|
|
192
|
+
*/
|
|
177
193
|
mount() {
|
|
178
194
|
var _a, _b;
|
|
179
195
|
const props = {
|
|
@@ -200,13 +216,24 @@ var VueNodeView = class extends NodeView {
|
|
|
200
216
|
provide: () => {
|
|
201
217
|
return {
|
|
202
218
|
onDragStart,
|
|
203
|
-
decorationClasses: this.decorationClasses
|
|
219
|
+
decorationClasses: this.decorationClasses,
|
|
220
|
+
nodeViewContentRef: (el) => {
|
|
221
|
+
if (!this.contentDOMElement) return;
|
|
222
|
+
if (el && el.firstChild !== this.contentDOMElement) {
|
|
223
|
+
el.appendChild(this.contentDOMElement);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
204
226
|
};
|
|
205
227
|
}
|
|
206
228
|
});
|
|
207
229
|
this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
|
|
208
230
|
this.editor.on("selectionUpdate", this.handleSelectionUpdate);
|
|
209
231
|
this.currentPos = this.getPos();
|
|
232
|
+
if (!this.node.isLeaf) {
|
|
233
|
+
this.contentDOMElement = document.createElement(this.node.isInline ? "span" : "div");
|
|
234
|
+
this.contentDOMElement.style.whiteSpace = "inherit";
|
|
235
|
+
this.contentDOMElement.dataset.nodeViewContentVue = "";
|
|
236
|
+
}
|
|
210
237
|
this.renderer = new VueRenderer(Component, {
|
|
211
238
|
parent: this.editor.contentComponent,
|
|
212
239
|
propsData: mountProps
|
|
@@ -230,7 +257,7 @@ var VueNodeView = class extends NodeView {
|
|
|
230
257
|
if (this.node.isLeaf) {
|
|
231
258
|
return null;
|
|
232
259
|
}
|
|
233
|
-
return this.
|
|
260
|
+
return this.contentDOMElement;
|
|
234
261
|
}
|
|
235
262
|
/**
|
|
236
263
|
* On editor selection update, check if the node is selected.
|
|
@@ -340,6 +367,7 @@ var VueNodeView = class extends NodeView {
|
|
|
340
367
|
if (this.options.trackNodeViewPosition) {
|
|
341
368
|
this.editor.off("update", this.handlePositionUpdate);
|
|
342
369
|
}
|
|
370
|
+
this.contentDOMElement = null;
|
|
343
371
|
}
|
|
344
372
|
};
|
|
345
373
|
function VueNodeViewRenderer(component, options) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Editor.ts","../src/EditorContent.ts","../src/NodeViewContent.ts","../src/NodeViewWrapper.ts","../src/VueNodeViewRenderer.ts","../src/Vue.ts","../src/VueRenderer.ts","../src/index.ts"],"sourcesContent":["import { Editor as CoreEditor } from '@tiptap/core'\nimport type Vue from 'vue'\n\nexport class Editor extends CoreEditor {\n public contentComponent: Vue | null = null\n}\n","import type { Component, CreateElement, PropType } from 'vue'\nimport type Vue from 'vue'\n\nimport type { Editor } from './Editor.js'\n\nexport interface EditorContentInterface extends Vue {\n editor: Editor\n}\n\nexport const EditorContent: Component = {\n name: 'EditorContent',\n\n props: {\n editor: {\n default: null,\n type: Object as PropType<Editor>,\n },\n },\n\n watch: {\n editor: {\n immediate: true,\n handler(this: EditorContentInterface, editor: Editor) {\n if (editor && editor.options.element) {\n this.$nextTick(() => {\n const element = this.$el\n\n if (!element || !editor.view.dom?.parentNode) {\n return\n }\n\n element.append(...editor.view.dom.parentNode.childNodes)\n editor.contentComponent = this\n\n editor.setOptions({\n element,\n })\n\n editor.createNodeViews()\n })\n }\n },\n },\n },\n\n render(createElement: CreateElement) {\n return createElement('div')\n },\n\n beforeDestroy(this: EditorContentInterface) {\n const { editor } = this\n\n if (!editor) {\n return\n }\n\n if (!editor.isDestroyed) {\n editor.view.setProps({\n nodeViews: {},\n })\n }\n\n editor.contentComponent = null\n\n if (!editor.view.dom?.parentNode) {\n return\n }\n\n // TODO using the new editor.mount method might allow us to remove this\n const newElement = document.createElement('div')\n\n newElement.append(...editor.view.dom.parentNode.childNodes)\n\n editor.setOptions({\n element: newElement,\n })\n },\n}\n","import type { Component, CreateElement } from 'vue'\nimport type Vue from 'vue'\n\nexport interface NodeViewContentInterface extends Vue {\n as: string\n}\n\nexport const NodeViewContent: Component = {\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n render(this: NodeViewContentInterface, createElement: CreateElement) {\n return createElement(this.as, {\n style: {\n whiteSpace: 'pre-wrap',\n },\n attrs: {\n 'data-node-view-content': '',\n },\n })\n },\n}\n","import type { Component, CreateElement } from 'vue'\nimport type Vue from 'vue'\n\nexport interface NodeViewWrapperInterface extends Vue {\n as: string\n decorationClasses: {\n value: string\n }\n onDragStart: () => void\n}\n\nexport const NodeViewWrapper: Component = {\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n inject: ['onDragStart', 'decorationClasses'],\n\n render(this: NodeViewWrapperInterface, createElement: CreateElement) {\n return createElement(\n this.as,\n {\n class: this.decorationClasses.value,\n style: {\n whiteSpace: 'normal',\n },\n attrs: {\n 'data-node-view-wrapper': '',\n },\n on: {\n dragstart: this.onDragStart,\n },\n },\n this.$slots.default,\n )\n },\n}\n","import type {\n DecorationWithType,\n NodeViewProps,\n NodeViewRenderer,\n NodeViewRendererOptions,\n NodeViewRendererProps,\n} from '@tiptap/core'\nimport { isNodeViewSelected, NodeView } from '@tiptap/core'\nimport type { Node as ProseMirrorNode } from '@tiptap/pm/model'\nimport type { Decoration, DecorationSource, NodeView as ProseMirrorNodeView } from '@tiptap/pm/view'\nimport type { VueConstructor } from 'vue'\nimport { booleanProp, functionProp, objectProp } from 'vue-ts-types'\n\nimport type { Editor } from './Editor.js'\nimport { Vue } from './Vue.js'\nimport { VueRenderer } from './VueRenderer.js'\n\nexport const nodeViewProps = {\n editor: objectProp<NodeViewProps['editor']>().required,\n node: objectProp<NodeViewProps['node']>().required,\n decorations: objectProp<NodeViewProps['decorations']>().required,\n selected: booleanProp().required,\n extension: objectProp<NodeViewProps['extension']>().required,\n getPos: functionProp<NodeViewProps['getPos']>().required,\n updateAttributes: functionProp<NodeViewProps['updateAttributes']>().required,\n deleteNode: functionProp<NodeViewProps['deleteNode']>().required,\n}\n\nexport interface VueNodeViewRendererOptions extends NodeViewRendererOptions {\n update:\n | ((props: {\n oldNode: ProseMirrorNode\n oldDecorations: readonly Decoration[]\n oldInnerDecorations: DecorationSource\n newNode: ProseMirrorNode\n newDecorations: readonly Decoration[]\n innerDecorations: DecorationSource\n updateProps: () => void\n }) => boolean)\n | null\n}\n\nclass VueNodeView extends NodeView<Vue | VueConstructor, Editor, VueNodeViewRendererOptions> {\n renderer!: VueRenderer\n\n decorationClasses!: {\n value: string\n }\n\n private currentPos: number | undefined\n\n constructor(\n component: Vue | VueConstructor,\n props: NodeViewRendererProps,\n options?: Partial<VueNodeViewRendererOptions>,\n ) {\n super(component, props, options)\n\n if (this.options.trackNodeViewPosition) {\n this.editor.on('update', this.handlePositionUpdate)\n }\n }\n\n private handlePositionUpdate = () => {\n const newPos = this.getPos()\n if (typeof newPos !== 'number' || newPos === this.currentPos) {\n return\n }\n this.currentPos = newPos\n this.renderer.updateProps({ getPos: () => this.getPos() })\n }\n\n mount() {\n const props: Record<string, any> = {\n editor: this.editor,\n node: this.node,\n decorations: this.decorations as DecorationWithType[],\n innerDecorations: this.innerDecorations,\n view: this.view,\n selected: false,\n extension: this.extension,\n HTMLAttributes: this.HTMLAttributes,\n getPos: () => this.getPos(),\n updateAttributes: (attributes = {}) => this.updateAttributes(attributes),\n deleteNode: () => this.deleteNode(),\n }\n\n const mountProps = props as NodeViewProps\n\n const onDragStart = this.onDragStart.bind(this)\n\n this.decorationClasses = Vue.observable({\n value: this.getDecorationClasses(),\n })\n\n // @ts-ignore\n const vue = this.editor.contentComponent?.$options._base ?? Vue // oxlint-disable-line\n\n const Component = vue.extend(this.component).extend({\n props: Object.keys(props),\n provide: () => {\n return {\n onDragStart,\n decorationClasses: this.decorationClasses,\n }\n },\n })\n\n this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this)\n this.editor.on('selectionUpdate', this.handleSelectionUpdate)\n\n this.currentPos = this.getPos()\n\n this.renderer = new VueRenderer(Component, {\n parent: this.editor.contentComponent,\n propsData: mountProps,\n })\n }\n\n /**\n * Return the DOM element.\n * This is the element that will be used to display the node view.\n */\n get dom() {\n if (!this.renderer.element.hasAttribute('data-node-view-wrapper')) {\n throw Error('Please use the NodeViewWrapper component for your node view.')\n }\n\n return this.renderer.element as HTMLElement\n }\n\n /**\n * Return the content DOM element.\n * This is the element that will be used to display the rich-text content of the node.\n */\n get contentDOM() {\n if (this.node.isLeaf) {\n return null\n }\n\n return this.dom.querySelector('[data-node-view-content]') as HTMLElement | null\n }\n\n /**\n * On editor selection update, check if the node is selected.\n * If it is, call `selectNode`, otherwise call `deselectNode`.\n */\n handleSelectionUpdate() {\n const pos = this.getPos()\n\n if (typeof pos !== 'number') {\n return\n }\n\n const isSelected = isNodeViewSelected({\n selection: this.editor.state.selection,\n pos,\n nodeSize: this.node.nodeSize,\n selectedOnTextSelection: this.options.selectedOnTextSelection,\n })\n\n if (isSelected) {\n if (this.renderer.ref.$props.selected) {\n return\n }\n\n this.selectNode()\n } else {\n if (!this.renderer.ref.$props.selected) {\n return\n }\n\n this.deselectNode()\n }\n }\n\n /**\n * On update, update the React component.\n * To prevent unnecessary updates, the `update` option can be used.\n */\n update(\n node: ProseMirrorNode,\n decorations: readonly Decoration[],\n innerDecorations: DecorationSource,\n ): boolean {\n const rerenderComponent = (props?: Record<string, any>) => {\n this.decorationClasses.value = this.getDecorationClasses()\n this.renderer.updateProps(props)\n }\n\n if (typeof this.options.update === 'function') {\n const oldNode = this.node\n const oldDecorations = this.decorations\n const oldInnerDecorations = this.innerDecorations\n\n this.node = node\n this.decorations = decorations\n this.innerDecorations = innerDecorations\n\n return this.options.update({\n oldNode,\n oldDecorations,\n newNode: node,\n newDecorations: decorations,\n oldInnerDecorations,\n innerDecorations,\n updateProps: () => rerenderComponent({ node, decorations, innerDecorations }),\n })\n }\n\n if (node.type !== this.node.type) {\n return false\n }\n\n const nodeChanged = node !== this.node\n\n // Node reference unchanged — only decorations may have changed.\n // ProseMirror renders decorations independently on the contentDOM,\n // and the getPos closure (bound in mount()) calls through to\n // ProseMirror's position function at call time, so it is always\n // current. Update internal refs, refresh decoration classes for\n // the wrapper component, and skip the Vue re-render.\n if (!nodeChanged) {\n this.node = node\n this.decorations = decorations\n this.innerDecorations = innerDecorations\n this.decorationClasses.value = this.getDecorationClasses()\n return true\n }\n\n this.node = node\n this.decorations = decorations\n this.innerDecorations = innerDecorations\n this.currentPos = this.getPos()\n\n const extraProps: Record<string, any> = {\n node,\n decorations,\n innerDecorations,\n }\n\n if (this.options.trackNodeViewPosition) {\n extraProps.getPos = () => this.getPos()\n }\n\n rerenderComponent(extraProps)\n\n return true\n }\n\n /**\n * Select the node.\n * Add the `selected` prop and the `ProseMirror-selectednode` class.\n */\n selectNode() {\n this.renderer.updateProps({\n selected: true,\n })\n this.renderer.element.classList.add('ProseMirror-selectednode')\n }\n\n /**\n * Deselect the node.\n * Remove the `selected` prop and the `ProseMirror-selectednode` class.\n */\n deselectNode() {\n this.renderer.updateProps({\n selected: false,\n })\n this.renderer.element.classList.remove('ProseMirror-selectednode')\n }\n\n getDecorationClasses() {\n return (\n this.decorations\n // @ts-ignore\n .flatMap(item => item.type.attrs.class)\n .join(' ')\n )\n }\n\n destroy() {\n this.renderer.destroy()\n this.editor.off('selectionUpdate', this.handleSelectionUpdate)\n\n if (this.options.trackNodeViewPosition) {\n this.editor.off('update', this.handlePositionUpdate)\n }\n }\n}\n\nexport function VueNodeViewRenderer(\n component: Vue | VueConstructor,\n options?: Partial<VueNodeViewRendererOptions>,\n): NodeViewRenderer {\n return props => {\n // try to get the parent component\n // this is important for vue devtools to show the component hierarchy correctly\n // maybe it’s `undefined` because <editor-content> isn’t rendered yet\n if (!(props.editor as Editor).contentComponent) {\n return {} as unknown as ProseMirrorNodeView\n }\n\n return new VueNodeView(component, props, options)\n }\n}\n","import type { VueConstructor } from 'vue'\nimport VueDefault from 'vue'\n\n// With nodenext module resolution, TypeScript treats the default import as the module type.\n// We need to explicitly type it as VueConstructor to access static methods like extend and observable.\n// This is necessary because Vue 2's type definitions export Vue as VueConstructor, but nodenext\n// doesn't correctly infer the default export type.\nexport const Vue: VueConstructor = VueDefault as unknown as VueConstructor\n","import type { VueConstructor } from 'vue'\n\nimport { Vue } from './Vue.js'\n\n/**\n * The VueRenderer class is responsible for rendering a Vue component as a ProseMirror node view.\n */\nexport class VueRenderer {\n ref!: Vue\n\n constructor(component: Vue | VueConstructor, props: any) {\n const Component = typeof component === 'function' ? component : Vue.extend(component)\n\n this.ref = new Component(props).$mount()\n }\n\n get element(): Element {\n return this.ref.$el\n }\n\n updateProps(props: Record<string, any> = {}): void {\n if (!this.ref.$props) {\n return\n }\n\n // prevents `Avoid mutating a prop directly` error message\n // Fix: `VueNodeViewRenderer` change vue Constructor `config.silent` not working\n const currentVueConstructor = this.ref.$props.editor?.contentComponent?.$options._base ?? Vue // oxlint-disable-line\n const originalSilent = currentVueConstructor.config.silent\n\n currentVueConstructor.config.silent = true\n\n Object.entries(props).forEach(([key, value]) => {\n this.ref.$props[key] = value\n })\n\n currentVueConstructor.config.silent = originalSilent\n }\n\n destroy(): void {\n this.ref.$destroy()\n }\n}\n","export { Editor } from './Editor.js'\nexport * from './EditorContent.js'\nexport * from './NodeViewContent.js'\nexport * from './NodeViewWrapper.js'\nexport * from './VueNodeViewRenderer.js'\nexport * from './VueRenderer.js'\nexport * from '@tiptap/core'\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/Editor.ts","../src/EditorContent.ts","../src/NodeViewContent.ts","../src/NodeViewWrapper.ts","../src/VueNodeViewRenderer.ts","../src/Vue.ts","../src/VueRenderer.ts","../src/index.ts"],"sourcesContent":["import { Editor as CoreEditor } from '@tiptap/core'\nimport type Vue from 'vue'\n\nexport class Editor extends CoreEditor {\n public contentComponent: Vue | null = null\n}\n","import type { Component, CreateElement, PropType } from 'vue'\nimport type Vue from 'vue'\n\nimport type { Editor } from './Editor.js'\n\nexport interface EditorContentInterface extends Vue {\n editor: Editor\n}\n\nexport const EditorContent: Component = {\n name: 'EditorContent',\n\n props: {\n editor: {\n default: null,\n type: Object as PropType<Editor>,\n },\n },\n\n watch: {\n editor: {\n immediate: true,\n handler(this: EditorContentInterface, editor: Editor) {\n if (editor && editor.options.element) {\n this.$nextTick(() => {\n const element = this.$el\n\n if (!element || !editor.view.dom?.parentNode) {\n return\n }\n\n element.append(...editor.view.dom.parentNode.childNodes)\n editor.contentComponent = this\n\n editor.setOptions({\n element,\n })\n\n editor.createNodeViews()\n })\n }\n },\n },\n },\n\n render(createElement: CreateElement) {\n return createElement('div')\n },\n\n beforeDestroy(this: EditorContentInterface) {\n const { editor } = this\n\n if (!editor) {\n return\n }\n\n if (!editor.isDestroyed) {\n editor.view.setProps({\n nodeViews: {},\n })\n }\n\n editor.contentComponent = null\n\n if (!editor.view.dom?.parentNode) {\n return\n }\n\n // TODO using the new editor.mount method might allow us to remove this\n const newElement = document.createElement('div')\n\n newElement.append(...editor.view.dom.parentNode.childNodes)\n\n editor.setOptions({\n element: newElement,\n })\n },\n}\n","import type { Component, CreateElement } from 'vue'\nimport type Vue from 'vue'\n\nexport interface NodeViewContentInterface extends Vue {\n as: string\n}\n\nexport const NodeViewContent: Component = {\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n inject: {\n nodeViewContentRef: { default: undefined },\n },\n\n mounted(this: any) {\n if (this.nodeViewContentRef && this.$el) {\n this.nodeViewContentRef(this.$el)\n }\n },\n\n beforeDestroy(this: any) {\n if (this.nodeViewContentRef) {\n this.nodeViewContentRef(null)\n }\n },\n\n render(this: NodeViewContentInterface, createElement: CreateElement) {\n return createElement(this.as, {\n style: {\n whiteSpace: 'pre-wrap',\n },\n attrs: {\n 'data-node-view-content': '',\n },\n })\n },\n}\n","import type { Component, CreateElement } from 'vue'\nimport type Vue from 'vue'\n\nexport interface NodeViewWrapperInterface extends Vue {\n as: string\n decorationClasses: {\n value: string\n }\n onDragStart: () => void\n}\n\nexport const NodeViewWrapper: Component = {\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n inject: ['onDragStart', 'decorationClasses'],\n\n render(this: NodeViewWrapperInterface, createElement: CreateElement) {\n return createElement(\n this.as,\n {\n class: this.decorationClasses.value,\n style: {\n whiteSpace: 'normal',\n },\n attrs: {\n 'data-node-view-wrapper': '',\n },\n on: {\n dragstart: this.onDragStart,\n },\n },\n this.$slots.default,\n )\n },\n}\n","import type {\n DecorationWithType,\n NodeViewProps,\n NodeViewRenderer,\n NodeViewRendererOptions,\n NodeViewRendererProps,\n} from '@tiptap/core'\nimport { isNodeViewSelected, NodeView } from '@tiptap/core'\nimport type { Node as ProseMirrorNode } from '@tiptap/pm/model'\nimport type { Decoration, DecorationSource, NodeView as ProseMirrorNodeView } from '@tiptap/pm/view'\nimport type { VueConstructor } from 'vue'\nimport { booleanProp, functionProp, objectProp } from 'vue-ts-types'\n\nimport type { Editor } from './Editor.js'\nimport { Vue } from './Vue.js'\nimport { VueRenderer } from './VueRenderer.js'\n\nexport const nodeViewProps = {\n editor: objectProp<NodeViewProps['editor']>().required,\n node: objectProp<NodeViewProps['node']>().required,\n decorations: objectProp<NodeViewProps['decorations']>().required,\n selected: booleanProp().required,\n extension: objectProp<NodeViewProps['extension']>().required,\n getPos: functionProp<NodeViewProps['getPos']>().required,\n updateAttributes: functionProp<NodeViewProps['updateAttributes']>().required,\n deleteNode: functionProp<NodeViewProps['deleteNode']>().required,\n}\n\nexport interface VueNodeViewRendererOptions extends NodeViewRendererOptions {\n update:\n | ((props: {\n oldNode: ProseMirrorNode\n oldDecorations: readonly Decoration[]\n oldInnerDecorations: DecorationSource\n newNode: ProseMirrorNode\n newDecorations: readonly Decoration[]\n innerDecorations: DecorationSource\n updateProps: () => void\n }) => boolean)\n | null\n}\n\nclass VueNodeView extends NodeView<Vue | VueConstructor, Editor, VueNodeViewRendererOptions> {\n renderer!: VueRenderer\n\n decorationClasses!: {\n value: string\n }\n\n /**\n * The element that holds the rich-text content of the node.\n * Always created for non-leaf nodes to guarantee a valid contentDOM,\n * even when the user's component does not include a NodeViewContent.\n * Must NOT have an initializer because class field initializers run\n * after super() and would overwrite the value set by mount().\n */\n contentDOMElement!: HTMLElement | null\n\n private currentPos: number | undefined\n\n constructor(\n component: Vue | VueConstructor,\n props: NodeViewRendererProps,\n options?: Partial<VueNodeViewRendererOptions>,\n ) {\n super(component, props, options)\n\n if (this.options.trackNodeViewPosition) {\n this.editor.on('update', this.handlePositionUpdate)\n }\n }\n\n private handlePositionUpdate = () => {\n const newPos = this.getPos()\n if (typeof newPos !== 'number' || newPos === this.currentPos) {\n return\n }\n this.currentPos = newPos\n this.renderer.updateProps({ getPos: () => this.getPos() })\n }\n\n /**\n * Called when the node view is mounted.\n */\n mount() {\n const props: Record<string, any> = {\n editor: this.editor,\n node: this.node,\n decorations: this.decorations as DecorationWithType[],\n innerDecorations: this.innerDecorations,\n view: this.view,\n selected: false,\n extension: this.extension,\n HTMLAttributes: this.HTMLAttributes,\n getPos: () => this.getPos(),\n updateAttributes: (attributes = {}) => this.updateAttributes(attributes),\n deleteNode: () => this.deleteNode(),\n }\n\n const mountProps = props as NodeViewProps\n\n const onDragStart = this.onDragStart.bind(this)\n\n this.decorationClasses = Vue.observable({\n value: this.getDecorationClasses(),\n })\n\n // @ts-ignore\n const vue = this.editor.contentComponent?.$options._base ?? Vue // oxlint-disable-line\n\n const Component = vue.extend(this.component).extend({\n props: Object.keys(props),\n provide: () => {\n return {\n onDragStart,\n decorationClasses: this.decorationClasses,\n nodeViewContentRef: (el: HTMLElement | null) => {\n if (!this.contentDOMElement) return\n\n if (el && el.firstChild !== this.contentDOMElement) {\n // NodeViewContent mounted: move the contentDOMElement inside it\n el.appendChild(this.contentDOMElement)\n }\n },\n }\n },\n })\n\n this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this)\n this.editor.on('selectionUpdate', this.handleSelectionUpdate)\n\n this.currentPos = this.getPos()\n\n if (!this.node.isLeaf) {\n this.contentDOMElement = document.createElement(this.node.isInline ? 'span' : 'div')\n this.contentDOMElement.style.whiteSpace = 'inherit'\n // Use a distinct attribute to avoid clashing with the user's\n // <node-view-content> element (which carries data-node-view-content).\n // Matches React's data-node-view-content-react convention.\n this.contentDOMElement.dataset.nodeViewContentVue = ''\n }\n\n this.renderer = new VueRenderer(Component, {\n parent: this.editor.contentComponent,\n propsData: mountProps,\n })\n }\n\n /**\n * Return the DOM element.\n * This is the element that will be used to display the node view.\n */\n get dom() {\n if (!this.renderer.element.hasAttribute('data-node-view-wrapper')) {\n throw Error('Please use the NodeViewWrapper component for your node view.')\n }\n\n return this.renderer.element as HTMLElement\n }\n\n /**\n * Return the content DOM element.\n * This is the element that will be used to display the rich-text content of the node.\n */\n get contentDOM() {\n if (this.node.isLeaf) {\n return null\n }\n\n return this.contentDOMElement\n }\n\n /**\n * On editor selection update, check if the node is selected.\n * If it is, call `selectNode`, otherwise call `deselectNode`.\n */\n handleSelectionUpdate() {\n const pos = this.getPos()\n\n if (typeof pos !== 'number') {\n return\n }\n\n const isSelected = isNodeViewSelected({\n selection: this.editor.state.selection,\n pos,\n nodeSize: this.node.nodeSize,\n selectedOnTextSelection: this.options.selectedOnTextSelection,\n })\n\n if (isSelected) {\n if (this.renderer.ref.$props.selected) {\n return\n }\n\n this.selectNode()\n } else {\n if (!this.renderer.ref.$props.selected) {\n return\n }\n\n this.deselectNode()\n }\n }\n\n /**\n * On update, update the React component.\n * To prevent unnecessary updates, the `update` option can be used.\n */\n update(\n node: ProseMirrorNode,\n decorations: readonly Decoration[],\n innerDecorations: DecorationSource,\n ): boolean {\n const rerenderComponent = (props?: Record<string, any>) => {\n this.decorationClasses.value = this.getDecorationClasses()\n this.renderer.updateProps(props)\n }\n\n if (typeof this.options.update === 'function') {\n const oldNode = this.node\n const oldDecorations = this.decorations\n const oldInnerDecorations = this.innerDecorations\n\n this.node = node\n this.decorations = decorations\n this.innerDecorations = innerDecorations\n\n return this.options.update({\n oldNode,\n oldDecorations,\n newNode: node,\n newDecorations: decorations,\n oldInnerDecorations,\n innerDecorations,\n updateProps: () => rerenderComponent({ node, decorations, innerDecorations }),\n })\n }\n\n if (node.type !== this.node.type) {\n return false\n }\n\n const nodeChanged = node !== this.node\n\n // Node reference unchanged — only decorations may have changed.\n // ProseMirror renders decorations independently on the contentDOM,\n // and the getPos closure (bound in mount()) calls through to\n // ProseMirror's position function at call time, so it is always\n // current. Update internal refs, refresh decoration classes for\n // the wrapper component, and skip the Vue re-render.\n if (!nodeChanged) {\n this.node = node\n this.decorations = decorations\n this.innerDecorations = innerDecorations\n this.decorationClasses.value = this.getDecorationClasses()\n return true\n }\n\n this.node = node\n this.decorations = decorations\n this.innerDecorations = innerDecorations\n this.currentPos = this.getPos()\n\n const extraProps: Record<string, any> = {\n node,\n decorations,\n innerDecorations,\n }\n\n if (this.options.trackNodeViewPosition) {\n extraProps.getPos = () => this.getPos()\n }\n\n rerenderComponent(extraProps)\n\n return true\n }\n\n /**\n * Select the node.\n * Add the `selected` prop and the `ProseMirror-selectednode` class.\n */\n selectNode() {\n this.renderer.updateProps({\n selected: true,\n })\n this.renderer.element.classList.add('ProseMirror-selectednode')\n }\n\n /**\n * Deselect the node.\n * Remove the `selected` prop and the `ProseMirror-selectednode` class.\n */\n deselectNode() {\n this.renderer.updateProps({\n selected: false,\n })\n this.renderer.element.classList.remove('ProseMirror-selectednode')\n }\n\n getDecorationClasses() {\n return (\n this.decorations\n // @ts-ignore\n .flatMap(item => item.type.attrs.class)\n .join(' ')\n )\n }\n\n destroy() {\n this.renderer.destroy()\n this.editor.off('selectionUpdate', this.handleSelectionUpdate)\n\n if (this.options.trackNodeViewPosition) {\n this.editor.off('update', this.handlePositionUpdate)\n }\n\n this.contentDOMElement = null\n }\n}\n\nexport function VueNodeViewRenderer(\n component: Vue | VueConstructor,\n options?: Partial<VueNodeViewRendererOptions>,\n): NodeViewRenderer {\n return props => {\n // try to get the parent component\n // this is important for vue devtools to show the component hierarchy correctly\n // maybe it’s `undefined` because <editor-content> isn’t rendered yet\n if (!(props.editor as Editor).contentComponent) {\n return {} as unknown as ProseMirrorNodeView\n }\n\n return new VueNodeView(component, props, options)\n }\n}\n","import type { VueConstructor } from 'vue'\nimport VueDefault from 'vue'\n\n// With nodenext module resolution, TypeScript treats the default import as the module type.\n// We need to explicitly type it as VueConstructor to access static methods like extend and observable.\n// This is necessary because Vue 2's type definitions export Vue as VueConstructor, but nodenext\n// doesn't correctly infer the default export type.\nexport const Vue: VueConstructor = VueDefault as unknown as VueConstructor\n","import type { VueConstructor } from 'vue'\n\nimport { Vue } from './Vue.js'\n\n/**\n * The VueRenderer class is responsible for rendering a Vue component as a ProseMirror node view.\n */\nexport class VueRenderer {\n ref!: Vue\n\n constructor(component: Vue | VueConstructor, props: any) {\n const Component = typeof component === 'function' ? component : Vue.extend(component)\n\n this.ref = new Component(props).$mount()\n }\n\n get element(): Element {\n return this.ref.$el\n }\n\n updateProps(props: Record<string, any> = {}): void {\n if (!this.ref.$props) {\n return\n }\n\n // prevents `Avoid mutating a prop directly` error message\n // Fix: `VueNodeViewRenderer` change vue Constructor `config.silent` not working\n const currentVueConstructor = this.ref.$props.editor?.contentComponent?.$options._base ?? Vue // oxlint-disable-line\n const originalSilent = currentVueConstructor.config.silent\n\n currentVueConstructor.config.silent = true\n\n Object.entries(props).forEach(([key, value]) => {\n this.ref.$props[key] = value\n })\n\n currentVueConstructor.config.silent = originalSilent\n }\n\n destroy(): void {\n this.ref.$destroy()\n }\n}\n","export { Editor } from './Editor.js'\nexport * from './EditorContent.js'\nexport * from './NodeViewContent.js'\nexport * from './NodeViewWrapper.js'\nexport * from './VueNodeViewRenderer.js'\nexport * from './VueRenderer.js'\nexport * from '@tiptap/core'\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiptap/vue-2",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.26.0",
|
|
4
4
|
"description": "Vue components for tiptap",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tiptap",
|
|
@@ -49,17 +49,17 @@
|
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"vue": "^2.7.16",
|
|
52
|
-
"@tiptap/core": "^3.
|
|
53
|
-
"@tiptap/pm": "^3.
|
|
52
|
+
"@tiptap/core": "^3.26.0",
|
|
53
|
+
"@tiptap/pm": "^3.26.0"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"vue": "^2.6.0",
|
|
57
|
-
"@tiptap/core": "3.
|
|
58
|
-
"@tiptap/pm": "3.
|
|
57
|
+
"@tiptap/core": "3.26.0",
|
|
58
|
+
"@tiptap/pm": "3.26.0"
|
|
59
59
|
},
|
|
60
60
|
"optionalDependencies": {
|
|
61
|
-
"@tiptap/extension-bubble-menu": "^3.
|
|
62
|
-
"@tiptap/extension-floating-menu": "^3.
|
|
61
|
+
"@tiptap/extension-bubble-menu": "^3.26.0",
|
|
62
|
+
"@tiptap/extension-floating-menu": "^3.26.0"
|
|
63
63
|
},
|
|
64
64
|
"scripts": {
|
|
65
65
|
"build": "tsup"
|
package/src/NodeViewContent.ts
CHANGED
|
@@ -13,6 +13,22 @@ export const NodeViewContent: Component = {
|
|
|
13
13
|
},
|
|
14
14
|
},
|
|
15
15
|
|
|
16
|
+
inject: {
|
|
17
|
+
nodeViewContentRef: { default: undefined },
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
mounted(this: any) {
|
|
21
|
+
if (this.nodeViewContentRef && this.$el) {
|
|
22
|
+
this.nodeViewContentRef(this.$el)
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
beforeDestroy(this: any) {
|
|
27
|
+
if (this.nodeViewContentRef) {
|
|
28
|
+
this.nodeViewContentRef(null)
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
|
|
16
32
|
render(this: NodeViewContentInterface, createElement: CreateElement) {
|
|
17
33
|
return createElement(this.as, {
|
|
18
34
|
style: {
|
|
@@ -47,6 +47,15 @@ class VueNodeView extends NodeView<Vue | VueConstructor, Editor, VueNodeViewRend
|
|
|
47
47
|
value: string
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* The element that holds the rich-text content of the node.
|
|
52
|
+
* Always created for non-leaf nodes to guarantee a valid contentDOM,
|
|
53
|
+
* even when the user's component does not include a NodeViewContent.
|
|
54
|
+
* Must NOT have an initializer because class field initializers run
|
|
55
|
+
* after super() and would overwrite the value set by mount().
|
|
56
|
+
*/
|
|
57
|
+
contentDOMElement!: HTMLElement | null
|
|
58
|
+
|
|
50
59
|
private currentPos: number | undefined
|
|
51
60
|
|
|
52
61
|
constructor(
|
|
@@ -70,6 +79,9 @@ class VueNodeView extends NodeView<Vue | VueConstructor, Editor, VueNodeViewRend
|
|
|
70
79
|
this.renderer.updateProps({ getPos: () => this.getPos() })
|
|
71
80
|
}
|
|
72
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Called when the node view is mounted.
|
|
84
|
+
*/
|
|
73
85
|
mount() {
|
|
74
86
|
const props: Record<string, any> = {
|
|
75
87
|
editor: this.editor,
|
|
@@ -102,6 +114,14 @@ class VueNodeView extends NodeView<Vue | VueConstructor, Editor, VueNodeViewRend
|
|
|
102
114
|
return {
|
|
103
115
|
onDragStart,
|
|
104
116
|
decorationClasses: this.decorationClasses,
|
|
117
|
+
nodeViewContentRef: (el: HTMLElement | null) => {
|
|
118
|
+
if (!this.contentDOMElement) return
|
|
119
|
+
|
|
120
|
+
if (el && el.firstChild !== this.contentDOMElement) {
|
|
121
|
+
// NodeViewContent mounted: move the contentDOMElement inside it
|
|
122
|
+
el.appendChild(this.contentDOMElement)
|
|
123
|
+
}
|
|
124
|
+
},
|
|
105
125
|
}
|
|
106
126
|
},
|
|
107
127
|
})
|
|
@@ -111,6 +131,15 @@ class VueNodeView extends NodeView<Vue | VueConstructor, Editor, VueNodeViewRend
|
|
|
111
131
|
|
|
112
132
|
this.currentPos = this.getPos()
|
|
113
133
|
|
|
134
|
+
if (!this.node.isLeaf) {
|
|
135
|
+
this.contentDOMElement = document.createElement(this.node.isInline ? 'span' : 'div')
|
|
136
|
+
this.contentDOMElement.style.whiteSpace = 'inherit'
|
|
137
|
+
// Use a distinct attribute to avoid clashing with the user's
|
|
138
|
+
// <node-view-content> element (which carries data-node-view-content).
|
|
139
|
+
// Matches React's data-node-view-content-react convention.
|
|
140
|
+
this.contentDOMElement.dataset.nodeViewContentVue = ''
|
|
141
|
+
}
|
|
142
|
+
|
|
114
143
|
this.renderer = new VueRenderer(Component, {
|
|
115
144
|
parent: this.editor.contentComponent,
|
|
116
145
|
propsData: mountProps,
|
|
@@ -138,7 +167,7 @@ class VueNodeView extends NodeView<Vue | VueConstructor, Editor, VueNodeViewRend
|
|
|
138
167
|
return null
|
|
139
168
|
}
|
|
140
169
|
|
|
141
|
-
return this.
|
|
170
|
+
return this.contentDOMElement
|
|
142
171
|
}
|
|
143
172
|
|
|
144
173
|
/**
|
|
@@ -286,6 +315,8 @@ class VueNodeView extends NodeView<Vue | VueConstructor, Editor, VueNodeViewRend
|
|
|
286
315
|
if (this.options.trackNodeViewPosition) {
|
|
287
316
|
this.editor.off('update', this.handlePositionUpdate)
|
|
288
317
|
}
|
|
318
|
+
|
|
319
|
+
this.contentDOMElement = null
|
|
289
320
|
}
|
|
290
321
|
}
|
|
291
322
|
|