@tiptap/vue-3 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 +28 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +28 -1
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/NodeViewContent.ts +18 -0
- package/src/VueNodeViewRenderer.ts +36 -1
package/dist/index.cjs
CHANGED
|
@@ -167,6 +167,21 @@ var NodeViewContent = (0, import_vue3.defineComponent)({
|
|
|
167
167
|
default: "div"
|
|
168
168
|
}
|
|
169
169
|
},
|
|
170
|
+
inject: {
|
|
171
|
+
nodeViewContentRef: { default: void 0 }
|
|
172
|
+
},
|
|
173
|
+
mounted() {
|
|
174
|
+
const ref3 = this.nodeViewContentRef;
|
|
175
|
+
if (ref3 && this.$el) {
|
|
176
|
+
ref3(this.$el);
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
beforeUnmount() {
|
|
180
|
+
const ref3 = this.nodeViewContentRef;
|
|
181
|
+
if (ref3) {
|
|
182
|
+
ref3(null);
|
|
183
|
+
}
|
|
184
|
+
},
|
|
170
185
|
render() {
|
|
171
186
|
return (0, import_vue3.h)(this.as, {
|
|
172
187
|
style: {
|
|
@@ -501,6 +516,12 @@ var VueNodeView = class extends import_core3.NodeView {
|
|
|
501
516
|
var _a, _b;
|
|
502
517
|
(0, import_vue8.provide)("onDragStart", onDragStart);
|
|
503
518
|
(0, import_vue8.provide)("decorationClasses", this.decorationClasses);
|
|
519
|
+
(0, import_vue8.provide)("nodeViewContentRef", (el) => {
|
|
520
|
+
if (!this.contentDOMElement) return;
|
|
521
|
+
if (el && el.firstChild !== this.contentDOMElement) {
|
|
522
|
+
el.appendChild(this.contentDOMElement);
|
|
523
|
+
}
|
|
524
|
+
});
|
|
504
525
|
return (_b = (_a = this.component).setup) == null ? void 0 : _b.call(_a, reactiveProps, {
|
|
505
526
|
expose: () => void 0
|
|
506
527
|
});
|
|
@@ -524,6 +545,11 @@ var VueNodeView = class extends import_core3.NodeView {
|
|
|
524
545
|
this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
|
|
525
546
|
this.editor.on("selectionUpdate", this.handleSelectionUpdate);
|
|
526
547
|
this.currentPos = this.getPos();
|
|
548
|
+
if (!this.node.isLeaf) {
|
|
549
|
+
this.contentDOMElement = document.createElement(this.node.isInline ? "span" : "div");
|
|
550
|
+
this.contentDOMElement.style.whiteSpace = "inherit";
|
|
551
|
+
this.contentDOMElement.dataset.nodeViewContentVue = "";
|
|
552
|
+
}
|
|
527
553
|
this.renderer = new VueRenderer(extendedComponent, {
|
|
528
554
|
editor: this.editor,
|
|
529
555
|
props: mountProps
|
|
@@ -547,7 +573,7 @@ var VueNodeView = class extends import_core3.NodeView {
|
|
|
547
573
|
if (this.node.isLeaf) {
|
|
548
574
|
return null;
|
|
549
575
|
}
|
|
550
|
-
return this.
|
|
576
|
+
return this.contentDOMElement;
|
|
551
577
|
}
|
|
552
578
|
/**
|
|
553
579
|
* On editor selection update, check if the node is selected.
|
|
@@ -667,6 +693,7 @@ var VueNodeView = class extends import_core3.NodeView {
|
|
|
667
693
|
if (this.options.trackNodeViewPosition) {
|
|
668
694
|
this.editor.off("update", this.handlePositionUpdate);
|
|
669
695
|
}
|
|
696
|
+
this.contentDOMElement = null;
|
|
670
697
|
}
|
|
671
698
|
};
|
|
672
699
|
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/useEditor.ts","../src/VueMarkViewRenderer.ts","../src/VueRenderer.ts","../src/VueNodeViewRenderer.ts"],"sourcesContent":["export { Editor } from './Editor.js'\nexport * from './EditorContent.js'\nexport * from './NodeViewContent.js'\nexport * from './NodeViewWrapper.js'\nexport * from './useEditor.js'\nexport * from './VueMarkViewRenderer.js'\nexport * from './VueNodeViewRenderer.js'\nexport * from './VueRenderer.js'\nexport * from '@tiptap/core'\n","/* oslint-disable react-hooks/rules-of-hooks */\nimport type { EditorOptions, Storage } from '@tiptap/core'\nimport { Editor as CoreEditor } from '@tiptap/core'\nimport type { EditorState, Plugin, PluginKey } from '@tiptap/pm/state'\nimport type { AppContext, ComponentInternalInstance, ComponentPublicInstance, Ref } from 'vue'\nimport { customRef, markRaw } from 'vue'\n\nfunction useDebouncedRef<T>(value: T) {\n return customRef<T>((track, trigger) => {\n return {\n get() {\n track()\n return value\n },\n set(newValue) {\n // update state\n value = newValue\n\n // update view as soon as possible\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n trigger()\n })\n })\n },\n }\n })\n}\n\nexport type ContentComponent = ComponentInternalInstance & {\n ctx: ComponentPublicInstance\n}\n\nexport class Editor extends CoreEditor {\n private reactiveState: Ref<EditorState>\n\n private reactiveExtensionStorage: Ref<Storage>\n\n public contentComponent: ContentComponent | null = null\n\n public appContext: AppContext | null = null\n\n constructor(options: Partial<EditorOptions> = {}) {\n super(options)\n\n this.reactiveState = useDebouncedRef(this.view.state)\n this.reactiveExtensionStorage = useDebouncedRef(this.extensionStorage)\n\n this.on('beforeTransaction', ({ nextState }) => {\n this.reactiveState.value = nextState\n this.reactiveExtensionStorage.value = this.extensionStorage\n })\n\n return markRaw(this) // oxlint-disable-line\n }\n\n get state() {\n return this.reactiveState ? this.reactiveState.value : this.view.state\n }\n\n get storage() {\n return this.reactiveExtensionStorage ? this.reactiveExtensionStorage.value : super.storage\n }\n\n /**\n * Register a ProseMirror plugin.\n */\n public registerPlugin(\n plugin: Plugin,\n handlePlugins?: (newPlugin: Plugin, plugins: Plugin[]) => Plugin[],\n ): EditorState {\n const nextState = super.registerPlugin(plugin, handlePlugins)\n\n if (this.reactiveState) {\n this.reactiveState.value = nextState\n }\n\n return nextState\n }\n\n /**\n * Unregister a ProseMirror plugin.\n */\n public unregisterPlugin(nameOrPluginKey: string | PluginKey): EditorState | undefined {\n const nextState = super.unregisterPlugin(nameOrPluginKey)\n\n if (this.reactiveState && nextState) {\n this.reactiveState.value = nextState\n }\n\n return nextState\n }\n}\n","import type { PropType, Ref } from 'vue'\nimport {\n defineComponent,\n getCurrentInstance,\n h,\n nextTick,\n onBeforeUnmount,\n ref,\n unref,\n watchEffect,\n} from 'vue'\n\nimport type { Editor } from './Editor.js'\n\nexport const EditorContent = defineComponent({\n name: 'EditorContent',\n\n props: {\n editor: {\n default: null,\n type: Object as PropType<Editor>,\n },\n },\n\n setup(props) {\n const rootEl: Ref<Element | undefined> = ref()\n const instance = getCurrentInstance()\n\n watchEffect(() => {\n const editor = props.editor\n\n if (editor && editor.options.element && rootEl.value) {\n nextTick(() => {\n if (!rootEl.value || !editor.view.dom?.parentNode) {\n return\n }\n\n // TODO using the new editor.mount method might allow us to remove this\n const element = unref(rootEl.value)\n\n rootEl.value.append(...editor.view.dom.parentNode.childNodes)\n\n // @ts-ignore\n editor.contentComponent = instance.ctx._\n\n if (instance) {\n editor.appContext = {\n ...instance.appContext,\n // Vue internally uses prototype chain to forward/shadow injects across the entire component chain\n // so don't use object spread operator or 'Object.assign' and just set `provides` as is on editor's appContext\n // @ts-expect-error forward instance's 'provides' into appContext\n provides: instance.provides,\n }\n }\n\n editor.setOptions({\n element,\n })\n\n editor.createNodeViews()\n })\n }\n })\n\n onBeforeUnmount(() => {\n const editor = props.editor\n\n if (!editor) {\n return\n }\n\n editor.contentComponent = null\n editor.appContext = null\n })\n\n return { rootEl }\n },\n\n render() {\n return h('div', {\n ref: (el: any) => {\n this.rootEl = el\n },\n })\n },\n})\n","import { defineComponent, h } from 'vue'\n\nexport const NodeViewContent = defineComponent({\n name: 'NodeViewContent',\n\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n render() {\n return h(this.as, {\n style: {\n whiteSpace: 'pre-wrap',\n },\n 'data-node-view-content': '',\n })\n },\n})\n","import { defineComponent, h } from 'vue'\n\nexport const NodeViewWrapper = defineComponent({\n name: 'NodeViewWrapper',\n\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n inject: ['onDragStart', 'decorationClasses'],\n\n render() {\n return h(\n this.as,\n {\n // @ts-ignore\n class: this.decorationClasses,\n style: {\n whiteSpace: 'normal',\n },\n 'data-node-view-wrapper': '',\n // @ts-ignore (https://github.com/vuejs/vue-next/issues/3031)\n onDragstart: this.onDragStart,\n },\n this.$slots.default?.(),\n )\n },\n})\n","import type { EditorOptions } from '@tiptap/core'\nimport { onBeforeUnmount, onMounted, shallowRef } from 'vue'\n\nimport { Editor } from './Editor.js'\n\nexport const useEditor = (options: Partial<EditorOptions> = {}) => {\n const editor = shallowRef<Editor>()\n\n onMounted(() => {\n editor.value = new Editor(options)\n })\n\n onBeforeUnmount(() => {\n editor.value?.destroy()\n })\n\n return editor\n}\n","/* oslint-disable no-underscore-dangle */\nimport type { MarkViewProps, MarkViewRenderer, MarkViewRendererOptions } from '@tiptap/core'\nimport { MarkView } from '@tiptap/core'\nimport type { Component, PropType } from 'vue'\nimport { defineComponent, h, toRaw } from 'vue'\n\nimport type { Editor } from './Editor.js'\nimport { VueRenderer } from './VueRenderer.js'\n\nexport interface VueMarkViewRendererOptions extends MarkViewRendererOptions {\n as?: string\n className?: string\n attrs?: { [key: string]: string }\n}\n\nexport const markViewProps = {\n editor: {\n type: Object as PropType<MarkViewProps['editor']>,\n required: true as const,\n },\n mark: {\n type: Object as PropType<MarkViewProps['mark']>,\n required: true as const,\n },\n extension: {\n type: Object as PropType<MarkViewProps['extension']>,\n required: true as const,\n },\n inline: {\n type: Boolean as PropType<MarkViewProps['inline']>,\n required: true as const,\n },\n view: {\n type: Object as PropType<MarkViewProps['view']>,\n required: true as const,\n },\n updateAttributes: {\n type: Function as PropType<MarkViewProps['updateAttributes']>,\n required: true as const,\n },\n HTMLAttributes: {\n type: Object as PropType<MarkViewProps['HTMLAttributes']>,\n required: true as const,\n },\n}\n\nexport const MarkViewContent = defineComponent({\n name: 'MarkViewContent',\n\n props: {\n as: {\n type: String,\n default: 'span',\n },\n },\n\n render() {\n return h(this.as, {\n style: {\n whiteSpace: 'inherit',\n },\n 'data-mark-view-content': '',\n })\n },\n})\n\nexport class VueMarkView extends MarkView<Component, VueMarkViewRendererOptions> {\n renderer: VueRenderer\n\n constructor(\n component: Component,\n props: MarkViewProps,\n options?: Partial<VueMarkViewRendererOptions>,\n ) {\n super(component, props, options)\n\n const componentProps = {\n ...props,\n updateAttributes: this.updateAttributes.bind(this),\n } satisfies MarkViewProps\n\n // Create extended component with provide\n const extendedComponent = defineComponent({\n extends: { ...component },\n props: Object.keys(componentProps),\n template: (this.component as any).template,\n setup: reactiveProps => {\n return (component as any).setup?.(reactiveProps, {\n expose: () => undefined,\n })\n },\n // Add support for scoped styles\n __scopeId: (component as any).__scopeId,\n __cssModules: (component as any).__cssModules,\n __name: (component as any).__name,\n __file: (component as any).__file,\n })\n this.renderer = new VueRenderer(extendedComponent, {\n editor: this.editor,\n props: componentProps,\n })\n }\n\n get dom() {\n return this.renderer.element as HTMLElement\n }\n\n get contentDOM() {\n return this.dom.querySelector('[data-mark-view-content]') as HTMLElement | null\n }\n\n updateAttributes(attrs: Record<string, any>): void {\n // since this.mark is now an proxy, we need to get the actual mark from it\n const unproxiedMark = toRaw(this.mark)\n super.updateAttributes(attrs, unproxiedMark)\n }\n\n destroy() {\n this.renderer.destroy()\n }\n}\n\nexport function VueMarkViewRenderer(\n component: Component,\n options: Partial<VueMarkViewRendererOptions> = {},\n): MarkViewRenderer {\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 MarkView<any, any>\n }\n\n return new VueMarkView(component, props, options)\n }\n}\n","import type { Editor } from '@tiptap/core'\nimport type { Component, DefineComponent } from 'vue'\nimport { h, markRaw, reactive, render } from 'vue'\n\nimport type { Editor as ExtendedEditor } from './Editor.js'\n\nexport interface VueRendererOptions {\n editor: Editor\n props?: Record<string, any>\n}\n\ntype ExtendedVNode = ReturnType<typeof h> | null\n\ninterface RenderedComponent {\n vNode: ExtendedVNode\n destroy: () => void\n el: Element | null\n}\n\n/**\n * This class is used to render Vue components inside the editor.\n */\nexport class VueRenderer {\n renderedComponent!: RenderedComponent\n\n editor: ExtendedEditor\n\n component: Component\n\n el: Element | null\n\n props: Record<string, any>\n\n /**\n * Flag to track if the renderer has been destroyed, preventing queued or asynchronous renders from executing after teardown.\n */\n destroyed = false\n\n constructor(component: Component, { props = {}, editor }: VueRendererOptions) {\n this.editor = editor as ExtendedEditor\n this.component = markRaw(component)\n this.el = document.createElement('div')\n this.props = reactive(props)\n this.renderedComponent = this.renderComponent()\n }\n\n get element(): Element | null {\n return this.renderedComponent.el\n }\n\n get ref(): any {\n // Composition API\n if (this.renderedComponent.vNode?.component?.exposed) {\n return this.renderedComponent.vNode.component.exposed\n }\n // Option API\n return this.renderedComponent.vNode?.component?.proxy\n }\n\n renderComponent() {\n if (this.destroyed) {\n return this.renderedComponent\n }\n\n let vNode: ExtendedVNode = h(this.component as DefineComponent, this.props)\n\n if (this.editor.appContext) {\n vNode.appContext = this.editor.appContext\n }\n if (typeof document !== 'undefined' && this.el) {\n render(vNode, this.el)\n }\n\n const destroy = () => {\n if (this.el) {\n render(null, this.el)\n }\n this.el = null\n vNode = null\n }\n\n return { vNode, destroy, el: this.el ? this.el.firstElementChild : null }\n }\n\n updateProps(props: Record<string, any> = {}): void {\n if (this.destroyed) {\n return\n }\n\n Object.entries(props).forEach(([key, value]) => {\n this.props[key] = value\n })\n this.renderComponent()\n }\n\n destroy(): void {\n if (this.destroyed) {\n return\n }\n\n this.destroyed = true\n this.renderedComponent.destroy()\n }\n}\n","/* oslint-disable no-underscore-dangle */\nimport 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 { Component, PropType, Ref } from 'vue'\nimport { defineComponent, provide, ref } from 'vue'\n\nimport type { Editor } from './Editor.js'\nimport { VueRenderer } from './VueRenderer.js'\n\nexport const nodeViewProps = {\n editor: {\n type: Object as PropType<NodeViewProps['editor']>,\n required: true as const,\n },\n node: {\n type: Object as PropType<NodeViewProps['node']>,\n required: true as const,\n },\n decorations: {\n type: Object as PropType<NodeViewProps['decorations']>,\n required: true as const,\n },\n selected: {\n type: Boolean as PropType<NodeViewProps['selected']>,\n required: true as const,\n },\n extension: {\n type: Object as PropType<NodeViewProps['extension']>,\n required: true as const,\n },\n getPos: {\n type: Function as PropType<NodeViewProps['getPos']>,\n required: true as const,\n },\n updateAttributes: {\n type: Function as PropType<NodeViewProps['updateAttributes']>,\n required: true as const,\n },\n deleteNode: {\n type: Function as PropType<NodeViewProps['deleteNode']>,\n required: true as const,\n },\n view: {\n type: Object as PropType<NodeViewProps['view']>,\n required: true as const,\n },\n innerDecorations: {\n type: Object as PropType<NodeViewProps['innerDecorations']>,\n required: true as const,\n },\n HTMLAttributes: {\n type: Object as PropType<NodeViewProps['HTMLAttributes']>,\n required: true as const,\n },\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<Component, Editor, VueNodeViewRendererOptions> {\n renderer!: VueRenderer\n\n decorationClasses!: Ref<string>\n\n private currentPos: number | undefined\n\n private cachedExtensionWithSyncedStorage: NodeViewProps['extension'] | null = null\n\n constructor(\n component: Component,\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 /**\n * Returns a proxy of the extension that redirects storage access to the editor's mutable storage.\n * This preserves the original prototype chain (instanceof checks, methods like configure/extend work).\n * Cached to avoid proxy creation on every update.\n */\n get extensionWithSyncedStorage(): NodeViewProps['extension'] {\n if (!this.cachedExtensionWithSyncedStorage) {\n const editor = this.editor\n const extension = this.extension\n\n this.cachedExtensionWithSyncedStorage = new Proxy(extension, {\n get(target, prop, receiver) {\n if (prop === 'storage') {\n return editor.storage[extension.name as keyof typeof editor.storage] ?? {}\n }\n return Reflect.get(target, prop, receiver)\n },\n })\n }\n\n return this.cachedExtensionWithSyncedStorage\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.extensionWithSyncedStorage,\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 = ref(this.getDecorationClasses())\n\n const extendedComponent = defineComponent({\n extends: { ...this.component },\n props: Object.keys(props),\n template: (this.component as any).template,\n setup: reactiveProps => {\n provide('onDragStart', onDragStart)\n provide('decorationClasses', this.decorationClasses)\n\n return (this.component as any).setup?.(reactiveProps, {\n expose: () => undefined,\n })\n },\n // add support for scoped styles\n // @ts-ignore\n // oxlint-disable-next-line\n __scopeId: this.component.__scopeId,\n // add support for CSS Modules\n // @ts-ignore\n // oxlint-disable-next-line\n __cssModules: this.component.__cssModules,\n // add support for vue devtools\n // @ts-ignore\n // oxlint-disable-next-line\n __name: this.component.__name,\n // @ts-ignore\n // oxlint-disable-next-line\n __file: this.component.__file,\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(extendedComponent, {\n editor: this.editor,\n props: mountProps,\n })\n }\n\n /**\n * Fires on editor updates when trackNodeViewPosition is enabled.\n * Detects position shifts where update() is NOT called.\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 * 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 || !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.props.selected) {\n return\n }\n\n this.selectNode()\n } else {\n if (!this.renderer.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: () =>\n rerenderComponent({\n node,\n decorations,\n innerDecorations,\n extension: this.extensionWithSyncedStorage,\n }),\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 extension: this.extensionWithSyncedStorage,\n }\n\n if (this.options.trackNodeViewPosition) {\n extraProps.getPos = () => this.getPos()\n }\n\n rerenderComponent(extraProps)\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 if (this.renderer.element) {\n this.renderer.element.classList.add('ProseMirror-selectednode')\n }\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 if (this.renderer.element) {\n this.renderer.element.classList.remove('ProseMirror-selectednode')\n }\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: Component<NodeViewProps>,\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 // check for class-component and normalize if neccessary\n const normalizedComponent =\n typeof component === 'function' && '__vccOpts' in component\n ? (component.__vccOpts as Component)\n : component\n\n return new VueNodeView(normalizedComponent, props, options)\n }\n}\n"],"mappings":"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","names":["CoreEditor","import_vue","import_vue","import_vue","import_vue","import_core","import_vue","import_vue","import_core","import_vue"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Editor.ts","../src/EditorContent.ts","../src/NodeViewContent.ts","../src/NodeViewWrapper.ts","../src/useEditor.ts","../src/VueMarkViewRenderer.ts","../src/VueRenderer.ts","../src/VueNodeViewRenderer.ts"],"sourcesContent":["export { Editor } from './Editor.js'\nexport * from './EditorContent.js'\nexport * from './NodeViewContent.js'\nexport * from './NodeViewWrapper.js'\nexport * from './useEditor.js'\nexport * from './VueMarkViewRenderer.js'\nexport * from './VueNodeViewRenderer.js'\nexport * from './VueRenderer.js'\nexport * from '@tiptap/core'\n","/* oslint-disable react-hooks/rules-of-hooks */\nimport type { EditorOptions, Storage } from '@tiptap/core'\nimport { Editor as CoreEditor } from '@tiptap/core'\nimport type { EditorState, Plugin, PluginKey } from '@tiptap/pm/state'\nimport type { AppContext, ComponentInternalInstance, ComponentPublicInstance, Ref } from 'vue'\nimport { customRef, markRaw } from 'vue'\n\nfunction useDebouncedRef<T>(value: T) {\n return customRef<T>((track, trigger) => {\n return {\n get() {\n track()\n return value\n },\n set(newValue) {\n // update state\n value = newValue\n\n // update view as soon as possible\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n trigger()\n })\n })\n },\n }\n })\n}\n\nexport type ContentComponent = ComponentInternalInstance & {\n ctx: ComponentPublicInstance\n}\n\nexport class Editor extends CoreEditor {\n private reactiveState: Ref<EditorState>\n\n private reactiveExtensionStorage: Ref<Storage>\n\n public contentComponent: ContentComponent | null = null\n\n public appContext: AppContext | null = null\n\n constructor(options: Partial<EditorOptions> = {}) {\n super(options)\n\n this.reactiveState = useDebouncedRef(this.view.state)\n this.reactiveExtensionStorage = useDebouncedRef(this.extensionStorage)\n\n this.on('beforeTransaction', ({ nextState }) => {\n this.reactiveState.value = nextState\n this.reactiveExtensionStorage.value = this.extensionStorage\n })\n\n return markRaw(this) // oxlint-disable-line\n }\n\n get state() {\n return this.reactiveState ? this.reactiveState.value : this.view.state\n }\n\n get storage() {\n return this.reactiveExtensionStorage ? this.reactiveExtensionStorage.value : super.storage\n }\n\n /**\n * Register a ProseMirror plugin.\n */\n public registerPlugin(\n plugin: Plugin,\n handlePlugins?: (newPlugin: Plugin, plugins: Plugin[]) => Plugin[],\n ): EditorState {\n const nextState = super.registerPlugin(plugin, handlePlugins)\n\n if (this.reactiveState) {\n this.reactiveState.value = nextState\n }\n\n return nextState\n }\n\n /**\n * Unregister a ProseMirror plugin.\n */\n public unregisterPlugin(nameOrPluginKey: string | PluginKey): EditorState | undefined {\n const nextState = super.unregisterPlugin(nameOrPluginKey)\n\n if (this.reactiveState && nextState) {\n this.reactiveState.value = nextState\n }\n\n return nextState\n }\n}\n","import type { PropType, Ref } from 'vue'\nimport {\n defineComponent,\n getCurrentInstance,\n h,\n nextTick,\n onBeforeUnmount,\n ref,\n unref,\n watchEffect,\n} from 'vue'\n\nimport type { Editor } from './Editor.js'\n\nexport const EditorContent = defineComponent({\n name: 'EditorContent',\n\n props: {\n editor: {\n default: null,\n type: Object as PropType<Editor>,\n },\n },\n\n setup(props) {\n const rootEl: Ref<Element | undefined> = ref()\n const instance = getCurrentInstance()\n\n watchEffect(() => {\n const editor = props.editor\n\n if (editor && editor.options.element && rootEl.value) {\n nextTick(() => {\n if (!rootEl.value || !editor.view.dom?.parentNode) {\n return\n }\n\n // TODO using the new editor.mount method might allow us to remove this\n const element = unref(rootEl.value)\n\n rootEl.value.append(...editor.view.dom.parentNode.childNodes)\n\n // @ts-ignore\n editor.contentComponent = instance.ctx._\n\n if (instance) {\n editor.appContext = {\n ...instance.appContext,\n // Vue internally uses prototype chain to forward/shadow injects across the entire component chain\n // so don't use object spread operator or 'Object.assign' and just set `provides` as is on editor's appContext\n // @ts-expect-error forward instance's 'provides' into appContext\n provides: instance.provides,\n }\n }\n\n editor.setOptions({\n element,\n })\n\n editor.createNodeViews()\n })\n }\n })\n\n onBeforeUnmount(() => {\n const editor = props.editor\n\n if (!editor) {\n return\n }\n\n editor.contentComponent = null\n editor.appContext = null\n })\n\n return { rootEl }\n },\n\n render() {\n return h('div', {\n ref: (el: any) => {\n this.rootEl = el\n },\n })\n },\n})\n","import { defineComponent, h } from 'vue'\n\nexport const NodeViewContent = defineComponent({\n name: 'NodeViewContent',\n\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n inject: {\n nodeViewContentRef: { default: undefined },\n },\n\n mounted() {\n const ref = (this as any).nodeViewContentRef as ((el: HTMLElement | null) => void) | undefined\n if (ref && this.$el) {\n ref(this.$el)\n }\n },\n\n beforeUnmount() {\n const ref = (this as any).nodeViewContentRef as ((el: HTMLElement | null) => void) | undefined\n if (ref) {\n ref(null)\n }\n },\n\n render() {\n return h(this.as, {\n style: {\n whiteSpace: 'pre-wrap',\n },\n 'data-node-view-content': '',\n })\n },\n})\n","import { defineComponent, h } from 'vue'\n\nexport const NodeViewWrapper = defineComponent({\n name: 'NodeViewWrapper',\n\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n inject: ['onDragStart', 'decorationClasses'],\n\n render() {\n return h(\n this.as,\n {\n // @ts-ignore\n class: this.decorationClasses,\n style: {\n whiteSpace: 'normal',\n },\n 'data-node-view-wrapper': '',\n // @ts-ignore (https://github.com/vuejs/vue-next/issues/3031)\n onDragstart: this.onDragStart,\n },\n this.$slots.default?.(),\n )\n },\n})\n","import type { EditorOptions } from '@tiptap/core'\nimport { onBeforeUnmount, onMounted, shallowRef } from 'vue'\n\nimport { Editor } from './Editor.js'\n\nexport const useEditor = (options: Partial<EditorOptions> = {}) => {\n const editor = shallowRef<Editor>()\n\n onMounted(() => {\n editor.value = new Editor(options)\n })\n\n onBeforeUnmount(() => {\n editor.value?.destroy()\n })\n\n return editor\n}\n","/* oslint-disable no-underscore-dangle */\nimport type { MarkViewProps, MarkViewRenderer, MarkViewRendererOptions } from '@tiptap/core'\nimport { MarkView } from '@tiptap/core'\nimport type { Component, PropType } from 'vue'\nimport { defineComponent, h, toRaw } from 'vue'\n\nimport type { Editor } from './Editor.js'\nimport { VueRenderer } from './VueRenderer.js'\n\nexport interface VueMarkViewRendererOptions extends MarkViewRendererOptions {\n as?: string\n className?: string\n attrs?: { [key: string]: string }\n}\n\nexport const markViewProps = {\n editor: {\n type: Object as PropType<MarkViewProps['editor']>,\n required: true as const,\n },\n mark: {\n type: Object as PropType<MarkViewProps['mark']>,\n required: true as const,\n },\n extension: {\n type: Object as PropType<MarkViewProps['extension']>,\n required: true as const,\n },\n inline: {\n type: Boolean as PropType<MarkViewProps['inline']>,\n required: true as const,\n },\n view: {\n type: Object as PropType<MarkViewProps['view']>,\n required: true as const,\n },\n updateAttributes: {\n type: Function as PropType<MarkViewProps['updateAttributes']>,\n required: true as const,\n },\n HTMLAttributes: {\n type: Object as PropType<MarkViewProps['HTMLAttributes']>,\n required: true as const,\n },\n}\n\nexport const MarkViewContent = defineComponent({\n name: 'MarkViewContent',\n\n props: {\n as: {\n type: String,\n default: 'span',\n },\n },\n\n render() {\n return h(this.as, {\n style: {\n whiteSpace: 'inherit',\n },\n 'data-mark-view-content': '',\n })\n },\n})\n\nexport class VueMarkView extends MarkView<Component, VueMarkViewRendererOptions> {\n renderer: VueRenderer\n\n constructor(\n component: Component,\n props: MarkViewProps,\n options?: Partial<VueMarkViewRendererOptions>,\n ) {\n super(component, props, options)\n\n const componentProps = {\n ...props,\n updateAttributes: this.updateAttributes.bind(this),\n } satisfies MarkViewProps\n\n // Create extended component with provide\n const extendedComponent = defineComponent({\n extends: { ...component },\n props: Object.keys(componentProps),\n template: (this.component as any).template,\n setup: reactiveProps => {\n return (component as any).setup?.(reactiveProps, {\n expose: () => undefined,\n })\n },\n // Add support for scoped styles\n __scopeId: (component as any).__scopeId,\n __cssModules: (component as any).__cssModules,\n __name: (component as any).__name,\n __file: (component as any).__file,\n })\n this.renderer = new VueRenderer(extendedComponent, {\n editor: this.editor,\n props: componentProps,\n })\n }\n\n get dom() {\n return this.renderer.element as HTMLElement\n }\n\n get contentDOM() {\n return this.dom.querySelector('[data-mark-view-content]') as HTMLElement | null\n }\n\n updateAttributes(attrs: Record<string, any>): void {\n // since this.mark is now an proxy, we need to get the actual mark from it\n const unproxiedMark = toRaw(this.mark)\n super.updateAttributes(attrs, unproxiedMark)\n }\n\n destroy() {\n this.renderer.destroy()\n }\n}\n\nexport function VueMarkViewRenderer(\n component: Component,\n options: Partial<VueMarkViewRendererOptions> = {},\n): MarkViewRenderer {\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 MarkView<any, any>\n }\n\n return new VueMarkView(component, props, options)\n }\n}\n","import type { Editor } from '@tiptap/core'\nimport type { Component, DefineComponent } from 'vue'\nimport { h, markRaw, reactive, render } from 'vue'\n\nimport type { Editor as ExtendedEditor } from './Editor.js'\n\nexport interface VueRendererOptions {\n editor: Editor\n props?: Record<string, any>\n}\n\ntype ExtendedVNode = ReturnType<typeof h> | null\n\ninterface RenderedComponent {\n vNode: ExtendedVNode\n destroy: () => void\n el: Element | null\n}\n\n/**\n * This class is used to render Vue components inside the editor.\n */\nexport class VueRenderer {\n renderedComponent!: RenderedComponent\n\n editor: ExtendedEditor\n\n component: Component\n\n el: Element | null\n\n props: Record<string, any>\n\n /**\n * Flag to track if the renderer has been destroyed, preventing queued or asynchronous renders from executing after teardown.\n */\n destroyed = false\n\n constructor(component: Component, { props = {}, editor }: VueRendererOptions) {\n this.editor = editor as ExtendedEditor\n this.component = markRaw(component)\n this.el = document.createElement('div')\n this.props = reactive(props)\n this.renderedComponent = this.renderComponent()\n }\n\n get element(): Element | null {\n return this.renderedComponent.el\n }\n\n get ref(): any {\n // Composition API\n if (this.renderedComponent.vNode?.component?.exposed) {\n return this.renderedComponent.vNode.component.exposed\n }\n // Option API\n return this.renderedComponent.vNode?.component?.proxy\n }\n\n renderComponent() {\n if (this.destroyed) {\n return this.renderedComponent\n }\n\n let vNode: ExtendedVNode = h(this.component as DefineComponent, this.props)\n\n if (this.editor.appContext) {\n vNode.appContext = this.editor.appContext\n }\n if (typeof document !== 'undefined' && this.el) {\n render(vNode, this.el)\n }\n\n const destroy = () => {\n if (this.el) {\n render(null, this.el)\n }\n this.el = null\n vNode = null\n }\n\n return { vNode, destroy, el: this.el ? this.el.firstElementChild : null }\n }\n\n updateProps(props: Record<string, any> = {}): void {\n if (this.destroyed) {\n return\n }\n\n Object.entries(props).forEach(([key, value]) => {\n this.props[key] = value\n })\n this.renderComponent()\n }\n\n destroy(): void {\n if (this.destroyed) {\n return\n }\n\n this.destroyed = true\n this.renderedComponent.destroy()\n }\n}\n","/* oslint-disable no-underscore-dangle */\nimport 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 { Component, PropType, Ref } from 'vue'\nimport { defineComponent, provide, ref } from 'vue'\n\nimport type { Editor } from './Editor.js'\nimport { VueRenderer } from './VueRenderer.js'\n\nexport const nodeViewProps = {\n editor: {\n type: Object as PropType<NodeViewProps['editor']>,\n required: true as const,\n },\n node: {\n type: Object as PropType<NodeViewProps['node']>,\n required: true as const,\n },\n decorations: {\n type: Object as PropType<NodeViewProps['decorations']>,\n required: true as const,\n },\n selected: {\n type: Boolean as PropType<NodeViewProps['selected']>,\n required: true as const,\n },\n extension: {\n type: Object as PropType<NodeViewProps['extension']>,\n required: true as const,\n },\n getPos: {\n type: Function as PropType<NodeViewProps['getPos']>,\n required: true as const,\n },\n updateAttributes: {\n type: Function as PropType<NodeViewProps['updateAttributes']>,\n required: true as const,\n },\n deleteNode: {\n type: Function as PropType<NodeViewProps['deleteNode']>,\n required: true as const,\n },\n view: {\n type: Object as PropType<NodeViewProps['view']>,\n required: true as const,\n },\n innerDecorations: {\n type: Object as PropType<NodeViewProps['innerDecorations']>,\n required: true as const,\n },\n HTMLAttributes: {\n type: Object as PropType<NodeViewProps['HTMLAttributes']>,\n required: true as const,\n },\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<Component, Editor, VueNodeViewRendererOptions> {\n renderer!: VueRenderer\n\n decorationClasses!: Ref<string>\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 * This matches React's behavior and prevents ProseMirror from\n * thrashing the DOM when contentDOM is unexpectedly null.\n *\n * NOTE: must NOT have an initializer (= null), because class field\n * initializers run AFTER super() and would overwrite the value set\n * by mount() during the super() call.\n */\n contentDOMElement!: HTMLElement | null\n\n private currentPos: number | undefined\n\n private cachedExtensionWithSyncedStorage: NodeViewProps['extension'] | null = null\n\n constructor(\n component: Component,\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 /**\n * Returns a proxy of the extension that redirects storage access to the editor's mutable storage.\n * This preserves the original prototype chain (instanceof checks, methods like configure/extend work).\n * Cached to avoid proxy creation on every update.\n */\n get extensionWithSyncedStorage(): NodeViewProps['extension'] {\n if (!this.cachedExtensionWithSyncedStorage) {\n const editor = this.editor\n const extension = this.extension\n\n this.cachedExtensionWithSyncedStorage = new Proxy(extension, {\n get(target, prop, receiver) {\n if (prop === 'storage') {\n return editor.storage[extension.name as keyof typeof editor.storage] ?? {}\n }\n return Reflect.get(target, prop, receiver)\n },\n })\n }\n\n return this.cachedExtensionWithSyncedStorage\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.extensionWithSyncedStorage,\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 = ref(this.getDecorationClasses())\n\n const extendedComponent = defineComponent({\n extends: { ...this.component },\n props: Object.keys(props),\n template: (this.component as any).template,\n setup: reactiveProps => {\n provide('onDragStart', onDragStart)\n provide('decorationClasses', this.decorationClasses)\n provide('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 return (this.component as any).setup?.(reactiveProps, {\n expose: () => undefined,\n })\n },\n // add support for scoped styles\n // @ts-ignore\n // oxlint-disable-next-line\n __scopeId: this.component.__scopeId,\n // add support for CSS Modules\n // @ts-ignore\n // oxlint-disable-next-line\n __cssModules: this.component.__cssModules,\n // add support for vue devtools\n // @ts-ignore\n // oxlint-disable-next-line\n __name: this.component.__name,\n // @ts-ignore\n // oxlint-disable-next-line\n __file: this.component.__file,\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 // Create the content DOM element BEFORE rendering the Vue component,\n // so it is available immediately when ProseMirror accesses contentDOM\n // during the initial DOM build.\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(extendedComponent, {\n editor: this.editor,\n props: mountProps,\n })\n }\n\n /**\n * Fires on editor updates when trackNodeViewPosition is enabled.\n * Detects position shifts where update() is NOT called.\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 * 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 || !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.props.selected) {\n return\n }\n\n this.selectNode()\n } else {\n if (!this.renderer.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: () =>\n rerenderComponent({\n node,\n decorations,\n innerDecorations,\n extension: this.extensionWithSyncedStorage,\n }),\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 extension: this.extensionWithSyncedStorage,\n }\n\n if (this.options.trackNodeViewPosition) {\n extraProps.getPos = () => this.getPos()\n }\n\n rerenderComponent(extraProps)\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 if (this.renderer.element) {\n this.renderer.element.classList.add('ProseMirror-selectednode')\n }\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 if (this.renderer.element) {\n this.renderer.element.classList.remove('ProseMirror-selectednode')\n }\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: Component<NodeViewProps>,\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 // check for class-component and normalize if neccessary\n const normalizedComponent =\n typeof component === 'function' && '__vccOpts' in component\n ? (component.__vccOpts as Component)\n : component\n\n return new VueNodeView(normalizedComponent, props, options)\n }\n}\n"],"mappings":"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","names":["CoreEditor","import_vue","import_vue","ref","import_vue","import_vue","import_core","import_vue","import_vue","import_core","import_vue"]}
|
package/dist/index.js
CHANGED
|
@@ -138,6 +138,21 @@ var NodeViewContent = defineComponent2({
|
|
|
138
138
|
default: "div"
|
|
139
139
|
}
|
|
140
140
|
},
|
|
141
|
+
inject: {
|
|
142
|
+
nodeViewContentRef: { default: void 0 }
|
|
143
|
+
},
|
|
144
|
+
mounted() {
|
|
145
|
+
const ref3 = this.nodeViewContentRef;
|
|
146
|
+
if (ref3 && this.$el) {
|
|
147
|
+
ref3(this.$el);
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
beforeUnmount() {
|
|
151
|
+
const ref3 = this.nodeViewContentRef;
|
|
152
|
+
if (ref3) {
|
|
153
|
+
ref3(null);
|
|
154
|
+
}
|
|
155
|
+
},
|
|
141
156
|
render() {
|
|
142
157
|
return h2(this.as, {
|
|
143
158
|
style: {
|
|
@@ -472,6 +487,12 @@ var VueNodeView = class extends NodeView {
|
|
|
472
487
|
var _a, _b;
|
|
473
488
|
provide("onDragStart", onDragStart);
|
|
474
489
|
provide("decorationClasses", this.decorationClasses);
|
|
490
|
+
provide("nodeViewContentRef", (el) => {
|
|
491
|
+
if (!this.contentDOMElement) return;
|
|
492
|
+
if (el && el.firstChild !== this.contentDOMElement) {
|
|
493
|
+
el.appendChild(this.contentDOMElement);
|
|
494
|
+
}
|
|
495
|
+
});
|
|
475
496
|
return (_b = (_a = this.component).setup) == null ? void 0 : _b.call(_a, reactiveProps, {
|
|
476
497
|
expose: () => void 0
|
|
477
498
|
});
|
|
@@ -495,6 +516,11 @@ var VueNodeView = class extends NodeView {
|
|
|
495
516
|
this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
|
|
496
517
|
this.editor.on("selectionUpdate", this.handleSelectionUpdate);
|
|
497
518
|
this.currentPos = this.getPos();
|
|
519
|
+
if (!this.node.isLeaf) {
|
|
520
|
+
this.contentDOMElement = document.createElement(this.node.isInline ? "span" : "div");
|
|
521
|
+
this.contentDOMElement.style.whiteSpace = "inherit";
|
|
522
|
+
this.contentDOMElement.dataset.nodeViewContentVue = "";
|
|
523
|
+
}
|
|
498
524
|
this.renderer = new VueRenderer(extendedComponent, {
|
|
499
525
|
editor: this.editor,
|
|
500
526
|
props: mountProps
|
|
@@ -518,7 +544,7 @@ var VueNodeView = class extends NodeView {
|
|
|
518
544
|
if (this.node.isLeaf) {
|
|
519
545
|
return null;
|
|
520
546
|
}
|
|
521
|
-
return this.
|
|
547
|
+
return this.contentDOMElement;
|
|
522
548
|
}
|
|
523
549
|
/**
|
|
524
550
|
* On editor selection update, check if the node is selected.
|
|
@@ -638,6 +664,7 @@ var VueNodeView = class extends NodeView {
|
|
|
638
664
|
if (this.options.trackNodeViewPosition) {
|
|
639
665
|
this.editor.off("update", this.handlePositionUpdate);
|
|
640
666
|
}
|
|
667
|
+
this.contentDOMElement = null;
|
|
641
668
|
}
|
|
642
669
|
};
|
|
643
670
|
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/useEditor.ts","../src/VueMarkViewRenderer.ts","../src/VueRenderer.ts","../src/VueNodeViewRenderer.ts","../src/index.ts"],"sourcesContent":["/* oslint-disable react-hooks/rules-of-hooks */\nimport type { EditorOptions, Storage } from '@tiptap/core'\nimport { Editor as CoreEditor } from '@tiptap/core'\nimport type { EditorState, Plugin, PluginKey } from '@tiptap/pm/state'\nimport type { AppContext, ComponentInternalInstance, ComponentPublicInstance, Ref } from 'vue'\nimport { customRef, markRaw } from 'vue'\n\nfunction useDebouncedRef<T>(value: T) {\n return customRef<T>((track, trigger) => {\n return {\n get() {\n track()\n return value\n },\n set(newValue) {\n // update state\n value = newValue\n\n // update view as soon as possible\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n trigger()\n })\n })\n },\n }\n })\n}\n\nexport type ContentComponent = ComponentInternalInstance & {\n ctx: ComponentPublicInstance\n}\n\nexport class Editor extends CoreEditor {\n private reactiveState: Ref<EditorState>\n\n private reactiveExtensionStorage: Ref<Storage>\n\n public contentComponent: ContentComponent | null = null\n\n public appContext: AppContext | null = null\n\n constructor(options: Partial<EditorOptions> = {}) {\n super(options)\n\n this.reactiveState = useDebouncedRef(this.view.state)\n this.reactiveExtensionStorage = useDebouncedRef(this.extensionStorage)\n\n this.on('beforeTransaction', ({ nextState }) => {\n this.reactiveState.value = nextState\n this.reactiveExtensionStorage.value = this.extensionStorage\n })\n\n return markRaw(this) // oxlint-disable-line\n }\n\n get state() {\n return this.reactiveState ? this.reactiveState.value : this.view.state\n }\n\n get storage() {\n return this.reactiveExtensionStorage ? this.reactiveExtensionStorage.value : super.storage\n }\n\n /**\n * Register a ProseMirror plugin.\n */\n public registerPlugin(\n plugin: Plugin,\n handlePlugins?: (newPlugin: Plugin, plugins: Plugin[]) => Plugin[],\n ): EditorState {\n const nextState = super.registerPlugin(plugin, handlePlugins)\n\n if (this.reactiveState) {\n this.reactiveState.value = nextState\n }\n\n return nextState\n }\n\n /**\n * Unregister a ProseMirror plugin.\n */\n public unregisterPlugin(nameOrPluginKey: string | PluginKey): EditorState | undefined {\n const nextState = super.unregisterPlugin(nameOrPluginKey)\n\n if (this.reactiveState && nextState) {\n this.reactiveState.value = nextState\n }\n\n return nextState\n }\n}\n","import type { PropType, Ref } from 'vue'\nimport {\n defineComponent,\n getCurrentInstance,\n h,\n nextTick,\n onBeforeUnmount,\n ref,\n unref,\n watchEffect,\n} from 'vue'\n\nimport type { Editor } from './Editor.js'\n\nexport const EditorContent = defineComponent({\n name: 'EditorContent',\n\n props: {\n editor: {\n default: null,\n type: Object as PropType<Editor>,\n },\n },\n\n setup(props) {\n const rootEl: Ref<Element | undefined> = ref()\n const instance = getCurrentInstance()\n\n watchEffect(() => {\n const editor = props.editor\n\n if (editor && editor.options.element && rootEl.value) {\n nextTick(() => {\n if (!rootEl.value || !editor.view.dom?.parentNode) {\n return\n }\n\n // TODO using the new editor.mount method might allow us to remove this\n const element = unref(rootEl.value)\n\n rootEl.value.append(...editor.view.dom.parentNode.childNodes)\n\n // @ts-ignore\n editor.contentComponent = instance.ctx._\n\n if (instance) {\n editor.appContext = {\n ...instance.appContext,\n // Vue internally uses prototype chain to forward/shadow injects across the entire component chain\n // so don't use object spread operator or 'Object.assign' and just set `provides` as is on editor's appContext\n // @ts-expect-error forward instance's 'provides' into appContext\n provides: instance.provides,\n }\n }\n\n editor.setOptions({\n element,\n })\n\n editor.createNodeViews()\n })\n }\n })\n\n onBeforeUnmount(() => {\n const editor = props.editor\n\n if (!editor) {\n return\n }\n\n editor.contentComponent = null\n editor.appContext = null\n })\n\n return { rootEl }\n },\n\n render() {\n return h('div', {\n ref: (el: any) => {\n this.rootEl = el\n },\n })\n },\n})\n","import { defineComponent, h } from 'vue'\n\nexport const NodeViewContent = defineComponent({\n name: 'NodeViewContent',\n\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n render() {\n return h(this.as, {\n style: {\n whiteSpace: 'pre-wrap',\n },\n 'data-node-view-content': '',\n })\n },\n})\n","import { defineComponent, h } from 'vue'\n\nexport const NodeViewWrapper = defineComponent({\n name: 'NodeViewWrapper',\n\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n inject: ['onDragStart', 'decorationClasses'],\n\n render() {\n return h(\n this.as,\n {\n // @ts-ignore\n class: this.decorationClasses,\n style: {\n whiteSpace: 'normal',\n },\n 'data-node-view-wrapper': '',\n // @ts-ignore (https://github.com/vuejs/vue-next/issues/3031)\n onDragstart: this.onDragStart,\n },\n this.$slots.default?.(),\n )\n },\n})\n","import type { EditorOptions } from '@tiptap/core'\nimport { onBeforeUnmount, onMounted, shallowRef } from 'vue'\n\nimport { Editor } from './Editor.js'\n\nexport const useEditor = (options: Partial<EditorOptions> = {}) => {\n const editor = shallowRef<Editor>()\n\n onMounted(() => {\n editor.value = new Editor(options)\n })\n\n onBeforeUnmount(() => {\n editor.value?.destroy()\n })\n\n return editor\n}\n","/* oslint-disable no-underscore-dangle */\nimport type { MarkViewProps, MarkViewRenderer, MarkViewRendererOptions } from '@tiptap/core'\nimport { MarkView } from '@tiptap/core'\nimport type { Component, PropType } from 'vue'\nimport { defineComponent, h, toRaw } from 'vue'\n\nimport type { Editor } from './Editor.js'\nimport { VueRenderer } from './VueRenderer.js'\n\nexport interface VueMarkViewRendererOptions extends MarkViewRendererOptions {\n as?: string\n className?: string\n attrs?: { [key: string]: string }\n}\n\nexport const markViewProps = {\n editor: {\n type: Object as PropType<MarkViewProps['editor']>,\n required: true as const,\n },\n mark: {\n type: Object as PropType<MarkViewProps['mark']>,\n required: true as const,\n },\n extension: {\n type: Object as PropType<MarkViewProps['extension']>,\n required: true as const,\n },\n inline: {\n type: Boolean as PropType<MarkViewProps['inline']>,\n required: true as const,\n },\n view: {\n type: Object as PropType<MarkViewProps['view']>,\n required: true as const,\n },\n updateAttributes: {\n type: Function as PropType<MarkViewProps['updateAttributes']>,\n required: true as const,\n },\n HTMLAttributes: {\n type: Object as PropType<MarkViewProps['HTMLAttributes']>,\n required: true as const,\n },\n}\n\nexport const MarkViewContent = defineComponent({\n name: 'MarkViewContent',\n\n props: {\n as: {\n type: String,\n default: 'span',\n },\n },\n\n render() {\n return h(this.as, {\n style: {\n whiteSpace: 'inherit',\n },\n 'data-mark-view-content': '',\n })\n },\n})\n\nexport class VueMarkView extends MarkView<Component, VueMarkViewRendererOptions> {\n renderer: VueRenderer\n\n constructor(\n component: Component,\n props: MarkViewProps,\n options?: Partial<VueMarkViewRendererOptions>,\n ) {\n super(component, props, options)\n\n const componentProps = {\n ...props,\n updateAttributes: this.updateAttributes.bind(this),\n } satisfies MarkViewProps\n\n // Create extended component with provide\n const extendedComponent = defineComponent({\n extends: { ...component },\n props: Object.keys(componentProps),\n template: (this.component as any).template,\n setup: reactiveProps => {\n return (component as any).setup?.(reactiveProps, {\n expose: () => undefined,\n })\n },\n // Add support for scoped styles\n __scopeId: (component as any).__scopeId,\n __cssModules: (component as any).__cssModules,\n __name: (component as any).__name,\n __file: (component as any).__file,\n })\n this.renderer = new VueRenderer(extendedComponent, {\n editor: this.editor,\n props: componentProps,\n })\n }\n\n get dom() {\n return this.renderer.element as HTMLElement\n }\n\n get contentDOM() {\n return this.dom.querySelector('[data-mark-view-content]') as HTMLElement | null\n }\n\n updateAttributes(attrs: Record<string, any>): void {\n // since this.mark is now an proxy, we need to get the actual mark from it\n const unproxiedMark = toRaw(this.mark)\n super.updateAttributes(attrs, unproxiedMark)\n }\n\n destroy() {\n this.renderer.destroy()\n }\n}\n\nexport function VueMarkViewRenderer(\n component: Component,\n options: Partial<VueMarkViewRendererOptions> = {},\n): MarkViewRenderer {\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 MarkView<any, any>\n }\n\n return new VueMarkView(component, props, options)\n }\n}\n","import type { Editor } from '@tiptap/core'\nimport type { Component, DefineComponent } from 'vue'\nimport { h, markRaw, reactive, render } from 'vue'\n\nimport type { Editor as ExtendedEditor } from './Editor.js'\n\nexport interface VueRendererOptions {\n editor: Editor\n props?: Record<string, any>\n}\n\ntype ExtendedVNode = ReturnType<typeof h> | null\n\ninterface RenderedComponent {\n vNode: ExtendedVNode\n destroy: () => void\n el: Element | null\n}\n\n/**\n * This class is used to render Vue components inside the editor.\n */\nexport class VueRenderer {\n renderedComponent!: RenderedComponent\n\n editor: ExtendedEditor\n\n component: Component\n\n el: Element | null\n\n props: Record<string, any>\n\n /**\n * Flag to track if the renderer has been destroyed, preventing queued or asynchronous renders from executing after teardown.\n */\n destroyed = false\n\n constructor(component: Component, { props = {}, editor }: VueRendererOptions) {\n this.editor = editor as ExtendedEditor\n this.component = markRaw(component)\n this.el = document.createElement('div')\n this.props = reactive(props)\n this.renderedComponent = this.renderComponent()\n }\n\n get element(): Element | null {\n return this.renderedComponent.el\n }\n\n get ref(): any {\n // Composition API\n if (this.renderedComponent.vNode?.component?.exposed) {\n return this.renderedComponent.vNode.component.exposed\n }\n // Option API\n return this.renderedComponent.vNode?.component?.proxy\n }\n\n renderComponent() {\n if (this.destroyed) {\n return this.renderedComponent\n }\n\n let vNode: ExtendedVNode = h(this.component as DefineComponent, this.props)\n\n if (this.editor.appContext) {\n vNode.appContext = this.editor.appContext\n }\n if (typeof document !== 'undefined' && this.el) {\n render(vNode, this.el)\n }\n\n const destroy = () => {\n if (this.el) {\n render(null, this.el)\n }\n this.el = null\n vNode = null\n }\n\n return { vNode, destroy, el: this.el ? this.el.firstElementChild : null }\n }\n\n updateProps(props: Record<string, any> = {}): void {\n if (this.destroyed) {\n return\n }\n\n Object.entries(props).forEach(([key, value]) => {\n this.props[key] = value\n })\n this.renderComponent()\n }\n\n destroy(): void {\n if (this.destroyed) {\n return\n }\n\n this.destroyed = true\n this.renderedComponent.destroy()\n }\n}\n","/* oslint-disable no-underscore-dangle */\nimport 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 { Component, PropType, Ref } from 'vue'\nimport { defineComponent, provide, ref } from 'vue'\n\nimport type { Editor } from './Editor.js'\nimport { VueRenderer } from './VueRenderer.js'\n\nexport const nodeViewProps = {\n editor: {\n type: Object as PropType<NodeViewProps['editor']>,\n required: true as const,\n },\n node: {\n type: Object as PropType<NodeViewProps['node']>,\n required: true as const,\n },\n decorations: {\n type: Object as PropType<NodeViewProps['decorations']>,\n required: true as const,\n },\n selected: {\n type: Boolean as PropType<NodeViewProps['selected']>,\n required: true as const,\n },\n extension: {\n type: Object as PropType<NodeViewProps['extension']>,\n required: true as const,\n },\n getPos: {\n type: Function as PropType<NodeViewProps['getPos']>,\n required: true as const,\n },\n updateAttributes: {\n type: Function as PropType<NodeViewProps['updateAttributes']>,\n required: true as const,\n },\n deleteNode: {\n type: Function as PropType<NodeViewProps['deleteNode']>,\n required: true as const,\n },\n view: {\n type: Object as PropType<NodeViewProps['view']>,\n required: true as const,\n },\n innerDecorations: {\n type: Object as PropType<NodeViewProps['innerDecorations']>,\n required: true as const,\n },\n HTMLAttributes: {\n type: Object as PropType<NodeViewProps['HTMLAttributes']>,\n required: true as const,\n },\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<Component, Editor, VueNodeViewRendererOptions> {\n renderer!: VueRenderer\n\n decorationClasses!: Ref<string>\n\n private currentPos: number | undefined\n\n private cachedExtensionWithSyncedStorage: NodeViewProps['extension'] | null = null\n\n constructor(\n component: Component,\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 /**\n * Returns a proxy of the extension that redirects storage access to the editor's mutable storage.\n * This preserves the original prototype chain (instanceof checks, methods like configure/extend work).\n * Cached to avoid proxy creation on every update.\n */\n get extensionWithSyncedStorage(): NodeViewProps['extension'] {\n if (!this.cachedExtensionWithSyncedStorage) {\n const editor = this.editor\n const extension = this.extension\n\n this.cachedExtensionWithSyncedStorage = new Proxy(extension, {\n get(target, prop, receiver) {\n if (prop === 'storage') {\n return editor.storage[extension.name as keyof typeof editor.storage] ?? {}\n }\n return Reflect.get(target, prop, receiver)\n },\n })\n }\n\n return this.cachedExtensionWithSyncedStorage\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.extensionWithSyncedStorage,\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 = ref(this.getDecorationClasses())\n\n const extendedComponent = defineComponent({\n extends: { ...this.component },\n props: Object.keys(props),\n template: (this.component as any).template,\n setup: reactiveProps => {\n provide('onDragStart', onDragStart)\n provide('decorationClasses', this.decorationClasses)\n\n return (this.component as any).setup?.(reactiveProps, {\n expose: () => undefined,\n })\n },\n // add support for scoped styles\n // @ts-ignore\n // oxlint-disable-next-line\n __scopeId: this.component.__scopeId,\n // add support for CSS Modules\n // @ts-ignore\n // oxlint-disable-next-line\n __cssModules: this.component.__cssModules,\n // add support for vue devtools\n // @ts-ignore\n // oxlint-disable-next-line\n __name: this.component.__name,\n // @ts-ignore\n // oxlint-disable-next-line\n __file: this.component.__file,\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(extendedComponent, {\n editor: this.editor,\n props: mountProps,\n })\n }\n\n /**\n * Fires on editor updates when trackNodeViewPosition is enabled.\n * Detects position shifts where update() is NOT called.\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 * 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 || !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.props.selected) {\n return\n }\n\n this.selectNode()\n } else {\n if (!this.renderer.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: () =>\n rerenderComponent({\n node,\n decorations,\n innerDecorations,\n extension: this.extensionWithSyncedStorage,\n }),\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 extension: this.extensionWithSyncedStorage,\n }\n\n if (this.options.trackNodeViewPosition) {\n extraProps.getPos = () => this.getPos()\n }\n\n rerenderComponent(extraProps)\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 if (this.renderer.element) {\n this.renderer.element.classList.add('ProseMirror-selectednode')\n }\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 if (this.renderer.element) {\n this.renderer.element.classList.remove('ProseMirror-selectednode')\n }\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: Component<NodeViewProps>,\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 // check for class-component and normalize if neccessary\n const normalizedComponent =\n typeof component === 'function' && '__vccOpts' in component\n ? (component.__vccOpts as Component)\n : component\n\n return new VueNodeView(normalizedComponent, props, options)\n }\n}\n","export { Editor } from './Editor.js'\nexport * from './EditorContent.js'\nexport * from './NodeViewContent.js'\nexport * from './NodeViewWrapper.js'\nexport * from './useEditor.js'\nexport * from './VueMarkViewRenderer.js'\nexport * from './VueNodeViewRenderer.js'\nexport * from './VueRenderer.js'\nexport * from '@tiptap/core'\n"],"mappings":"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","names":["defineComponent","h","defineComponent","h","onBeforeUnmount","onBeforeUnmount","defineComponent","h","h","markRaw","defineComponent","h","defineComponent","ref","ref","defineComponent"]}
|
|
1
|
+
{"version":3,"sources":["../src/Editor.ts","../src/EditorContent.ts","../src/NodeViewContent.ts","../src/NodeViewWrapper.ts","../src/useEditor.ts","../src/VueMarkViewRenderer.ts","../src/VueRenderer.ts","../src/VueNodeViewRenderer.ts","../src/index.ts"],"sourcesContent":["/* oslint-disable react-hooks/rules-of-hooks */\nimport type { EditorOptions, Storage } from '@tiptap/core'\nimport { Editor as CoreEditor } from '@tiptap/core'\nimport type { EditorState, Plugin, PluginKey } from '@tiptap/pm/state'\nimport type { AppContext, ComponentInternalInstance, ComponentPublicInstance, Ref } from 'vue'\nimport { customRef, markRaw } from 'vue'\n\nfunction useDebouncedRef<T>(value: T) {\n return customRef<T>((track, trigger) => {\n return {\n get() {\n track()\n return value\n },\n set(newValue) {\n // update state\n value = newValue\n\n // update view as soon as possible\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n trigger()\n })\n })\n },\n }\n })\n}\n\nexport type ContentComponent = ComponentInternalInstance & {\n ctx: ComponentPublicInstance\n}\n\nexport class Editor extends CoreEditor {\n private reactiveState: Ref<EditorState>\n\n private reactiveExtensionStorage: Ref<Storage>\n\n public contentComponent: ContentComponent | null = null\n\n public appContext: AppContext | null = null\n\n constructor(options: Partial<EditorOptions> = {}) {\n super(options)\n\n this.reactiveState = useDebouncedRef(this.view.state)\n this.reactiveExtensionStorage = useDebouncedRef(this.extensionStorage)\n\n this.on('beforeTransaction', ({ nextState }) => {\n this.reactiveState.value = nextState\n this.reactiveExtensionStorage.value = this.extensionStorage\n })\n\n return markRaw(this) // oxlint-disable-line\n }\n\n get state() {\n return this.reactiveState ? this.reactiveState.value : this.view.state\n }\n\n get storage() {\n return this.reactiveExtensionStorage ? this.reactiveExtensionStorage.value : super.storage\n }\n\n /**\n * Register a ProseMirror plugin.\n */\n public registerPlugin(\n plugin: Plugin,\n handlePlugins?: (newPlugin: Plugin, plugins: Plugin[]) => Plugin[],\n ): EditorState {\n const nextState = super.registerPlugin(plugin, handlePlugins)\n\n if (this.reactiveState) {\n this.reactiveState.value = nextState\n }\n\n return nextState\n }\n\n /**\n * Unregister a ProseMirror plugin.\n */\n public unregisterPlugin(nameOrPluginKey: string | PluginKey): EditorState | undefined {\n const nextState = super.unregisterPlugin(nameOrPluginKey)\n\n if (this.reactiveState && nextState) {\n this.reactiveState.value = nextState\n }\n\n return nextState\n }\n}\n","import type { PropType, Ref } from 'vue'\nimport {\n defineComponent,\n getCurrentInstance,\n h,\n nextTick,\n onBeforeUnmount,\n ref,\n unref,\n watchEffect,\n} from 'vue'\n\nimport type { Editor } from './Editor.js'\n\nexport const EditorContent = defineComponent({\n name: 'EditorContent',\n\n props: {\n editor: {\n default: null,\n type: Object as PropType<Editor>,\n },\n },\n\n setup(props) {\n const rootEl: Ref<Element | undefined> = ref()\n const instance = getCurrentInstance()\n\n watchEffect(() => {\n const editor = props.editor\n\n if (editor && editor.options.element && rootEl.value) {\n nextTick(() => {\n if (!rootEl.value || !editor.view.dom?.parentNode) {\n return\n }\n\n // TODO using the new editor.mount method might allow us to remove this\n const element = unref(rootEl.value)\n\n rootEl.value.append(...editor.view.dom.parentNode.childNodes)\n\n // @ts-ignore\n editor.contentComponent = instance.ctx._\n\n if (instance) {\n editor.appContext = {\n ...instance.appContext,\n // Vue internally uses prototype chain to forward/shadow injects across the entire component chain\n // so don't use object spread operator or 'Object.assign' and just set `provides` as is on editor's appContext\n // @ts-expect-error forward instance's 'provides' into appContext\n provides: instance.provides,\n }\n }\n\n editor.setOptions({\n element,\n })\n\n editor.createNodeViews()\n })\n }\n })\n\n onBeforeUnmount(() => {\n const editor = props.editor\n\n if (!editor) {\n return\n }\n\n editor.contentComponent = null\n editor.appContext = null\n })\n\n return { rootEl }\n },\n\n render() {\n return h('div', {\n ref: (el: any) => {\n this.rootEl = el\n },\n })\n },\n})\n","import { defineComponent, h } from 'vue'\n\nexport const NodeViewContent = defineComponent({\n name: 'NodeViewContent',\n\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n inject: {\n nodeViewContentRef: { default: undefined },\n },\n\n mounted() {\n const ref = (this as any).nodeViewContentRef as ((el: HTMLElement | null) => void) | undefined\n if (ref && this.$el) {\n ref(this.$el)\n }\n },\n\n beforeUnmount() {\n const ref = (this as any).nodeViewContentRef as ((el: HTMLElement | null) => void) | undefined\n if (ref) {\n ref(null)\n }\n },\n\n render() {\n return h(this.as, {\n style: {\n whiteSpace: 'pre-wrap',\n },\n 'data-node-view-content': '',\n })\n },\n})\n","import { defineComponent, h } from 'vue'\n\nexport const NodeViewWrapper = defineComponent({\n name: 'NodeViewWrapper',\n\n props: {\n as: {\n type: String,\n default: 'div',\n },\n },\n\n inject: ['onDragStart', 'decorationClasses'],\n\n render() {\n return h(\n this.as,\n {\n // @ts-ignore\n class: this.decorationClasses,\n style: {\n whiteSpace: 'normal',\n },\n 'data-node-view-wrapper': '',\n // @ts-ignore (https://github.com/vuejs/vue-next/issues/3031)\n onDragstart: this.onDragStart,\n },\n this.$slots.default?.(),\n )\n },\n})\n","import type { EditorOptions } from '@tiptap/core'\nimport { onBeforeUnmount, onMounted, shallowRef } from 'vue'\n\nimport { Editor } from './Editor.js'\n\nexport const useEditor = (options: Partial<EditorOptions> = {}) => {\n const editor = shallowRef<Editor>()\n\n onMounted(() => {\n editor.value = new Editor(options)\n })\n\n onBeforeUnmount(() => {\n editor.value?.destroy()\n })\n\n return editor\n}\n","/* oslint-disable no-underscore-dangle */\nimport type { MarkViewProps, MarkViewRenderer, MarkViewRendererOptions } from '@tiptap/core'\nimport { MarkView } from '@tiptap/core'\nimport type { Component, PropType } from 'vue'\nimport { defineComponent, h, toRaw } from 'vue'\n\nimport type { Editor } from './Editor.js'\nimport { VueRenderer } from './VueRenderer.js'\n\nexport interface VueMarkViewRendererOptions extends MarkViewRendererOptions {\n as?: string\n className?: string\n attrs?: { [key: string]: string }\n}\n\nexport const markViewProps = {\n editor: {\n type: Object as PropType<MarkViewProps['editor']>,\n required: true as const,\n },\n mark: {\n type: Object as PropType<MarkViewProps['mark']>,\n required: true as const,\n },\n extension: {\n type: Object as PropType<MarkViewProps['extension']>,\n required: true as const,\n },\n inline: {\n type: Boolean as PropType<MarkViewProps['inline']>,\n required: true as const,\n },\n view: {\n type: Object as PropType<MarkViewProps['view']>,\n required: true as const,\n },\n updateAttributes: {\n type: Function as PropType<MarkViewProps['updateAttributes']>,\n required: true as const,\n },\n HTMLAttributes: {\n type: Object as PropType<MarkViewProps['HTMLAttributes']>,\n required: true as const,\n },\n}\n\nexport const MarkViewContent = defineComponent({\n name: 'MarkViewContent',\n\n props: {\n as: {\n type: String,\n default: 'span',\n },\n },\n\n render() {\n return h(this.as, {\n style: {\n whiteSpace: 'inherit',\n },\n 'data-mark-view-content': '',\n })\n },\n})\n\nexport class VueMarkView extends MarkView<Component, VueMarkViewRendererOptions> {\n renderer: VueRenderer\n\n constructor(\n component: Component,\n props: MarkViewProps,\n options?: Partial<VueMarkViewRendererOptions>,\n ) {\n super(component, props, options)\n\n const componentProps = {\n ...props,\n updateAttributes: this.updateAttributes.bind(this),\n } satisfies MarkViewProps\n\n // Create extended component with provide\n const extendedComponent = defineComponent({\n extends: { ...component },\n props: Object.keys(componentProps),\n template: (this.component as any).template,\n setup: reactiveProps => {\n return (component as any).setup?.(reactiveProps, {\n expose: () => undefined,\n })\n },\n // Add support for scoped styles\n __scopeId: (component as any).__scopeId,\n __cssModules: (component as any).__cssModules,\n __name: (component as any).__name,\n __file: (component as any).__file,\n })\n this.renderer = new VueRenderer(extendedComponent, {\n editor: this.editor,\n props: componentProps,\n })\n }\n\n get dom() {\n return this.renderer.element as HTMLElement\n }\n\n get contentDOM() {\n return this.dom.querySelector('[data-mark-view-content]') as HTMLElement | null\n }\n\n updateAttributes(attrs: Record<string, any>): void {\n // since this.mark is now an proxy, we need to get the actual mark from it\n const unproxiedMark = toRaw(this.mark)\n super.updateAttributes(attrs, unproxiedMark)\n }\n\n destroy() {\n this.renderer.destroy()\n }\n}\n\nexport function VueMarkViewRenderer(\n component: Component,\n options: Partial<VueMarkViewRendererOptions> = {},\n): MarkViewRenderer {\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 MarkView<any, any>\n }\n\n return new VueMarkView(component, props, options)\n }\n}\n","import type { Editor } from '@tiptap/core'\nimport type { Component, DefineComponent } from 'vue'\nimport { h, markRaw, reactive, render } from 'vue'\n\nimport type { Editor as ExtendedEditor } from './Editor.js'\n\nexport interface VueRendererOptions {\n editor: Editor\n props?: Record<string, any>\n}\n\ntype ExtendedVNode = ReturnType<typeof h> | null\n\ninterface RenderedComponent {\n vNode: ExtendedVNode\n destroy: () => void\n el: Element | null\n}\n\n/**\n * This class is used to render Vue components inside the editor.\n */\nexport class VueRenderer {\n renderedComponent!: RenderedComponent\n\n editor: ExtendedEditor\n\n component: Component\n\n el: Element | null\n\n props: Record<string, any>\n\n /**\n * Flag to track if the renderer has been destroyed, preventing queued or asynchronous renders from executing after teardown.\n */\n destroyed = false\n\n constructor(component: Component, { props = {}, editor }: VueRendererOptions) {\n this.editor = editor as ExtendedEditor\n this.component = markRaw(component)\n this.el = document.createElement('div')\n this.props = reactive(props)\n this.renderedComponent = this.renderComponent()\n }\n\n get element(): Element | null {\n return this.renderedComponent.el\n }\n\n get ref(): any {\n // Composition API\n if (this.renderedComponent.vNode?.component?.exposed) {\n return this.renderedComponent.vNode.component.exposed\n }\n // Option API\n return this.renderedComponent.vNode?.component?.proxy\n }\n\n renderComponent() {\n if (this.destroyed) {\n return this.renderedComponent\n }\n\n let vNode: ExtendedVNode = h(this.component as DefineComponent, this.props)\n\n if (this.editor.appContext) {\n vNode.appContext = this.editor.appContext\n }\n if (typeof document !== 'undefined' && this.el) {\n render(vNode, this.el)\n }\n\n const destroy = () => {\n if (this.el) {\n render(null, this.el)\n }\n this.el = null\n vNode = null\n }\n\n return { vNode, destroy, el: this.el ? this.el.firstElementChild : null }\n }\n\n updateProps(props: Record<string, any> = {}): void {\n if (this.destroyed) {\n return\n }\n\n Object.entries(props).forEach(([key, value]) => {\n this.props[key] = value\n })\n this.renderComponent()\n }\n\n destroy(): void {\n if (this.destroyed) {\n return\n }\n\n this.destroyed = true\n this.renderedComponent.destroy()\n }\n}\n","/* oslint-disable no-underscore-dangle */\nimport 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 { Component, PropType, Ref } from 'vue'\nimport { defineComponent, provide, ref } from 'vue'\n\nimport type { Editor } from './Editor.js'\nimport { VueRenderer } from './VueRenderer.js'\n\nexport const nodeViewProps = {\n editor: {\n type: Object as PropType<NodeViewProps['editor']>,\n required: true as const,\n },\n node: {\n type: Object as PropType<NodeViewProps['node']>,\n required: true as const,\n },\n decorations: {\n type: Object as PropType<NodeViewProps['decorations']>,\n required: true as const,\n },\n selected: {\n type: Boolean as PropType<NodeViewProps['selected']>,\n required: true as const,\n },\n extension: {\n type: Object as PropType<NodeViewProps['extension']>,\n required: true as const,\n },\n getPos: {\n type: Function as PropType<NodeViewProps['getPos']>,\n required: true as const,\n },\n updateAttributes: {\n type: Function as PropType<NodeViewProps['updateAttributes']>,\n required: true as const,\n },\n deleteNode: {\n type: Function as PropType<NodeViewProps['deleteNode']>,\n required: true as const,\n },\n view: {\n type: Object as PropType<NodeViewProps['view']>,\n required: true as const,\n },\n innerDecorations: {\n type: Object as PropType<NodeViewProps['innerDecorations']>,\n required: true as const,\n },\n HTMLAttributes: {\n type: Object as PropType<NodeViewProps['HTMLAttributes']>,\n required: true as const,\n },\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<Component, Editor, VueNodeViewRendererOptions> {\n renderer!: VueRenderer\n\n decorationClasses!: Ref<string>\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 * This matches React's behavior and prevents ProseMirror from\n * thrashing the DOM when contentDOM is unexpectedly null.\n *\n * NOTE: must NOT have an initializer (= null), because class field\n * initializers run AFTER super() and would overwrite the value set\n * by mount() during the super() call.\n */\n contentDOMElement!: HTMLElement | null\n\n private currentPos: number | undefined\n\n private cachedExtensionWithSyncedStorage: NodeViewProps['extension'] | null = null\n\n constructor(\n component: Component,\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 /**\n * Returns a proxy of the extension that redirects storage access to the editor's mutable storage.\n * This preserves the original prototype chain (instanceof checks, methods like configure/extend work).\n * Cached to avoid proxy creation on every update.\n */\n get extensionWithSyncedStorage(): NodeViewProps['extension'] {\n if (!this.cachedExtensionWithSyncedStorage) {\n const editor = this.editor\n const extension = this.extension\n\n this.cachedExtensionWithSyncedStorage = new Proxy(extension, {\n get(target, prop, receiver) {\n if (prop === 'storage') {\n return editor.storage[extension.name as keyof typeof editor.storage] ?? {}\n }\n return Reflect.get(target, prop, receiver)\n },\n })\n }\n\n return this.cachedExtensionWithSyncedStorage\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.extensionWithSyncedStorage,\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 = ref(this.getDecorationClasses())\n\n const extendedComponent = defineComponent({\n extends: { ...this.component },\n props: Object.keys(props),\n template: (this.component as any).template,\n setup: reactiveProps => {\n provide('onDragStart', onDragStart)\n provide('decorationClasses', this.decorationClasses)\n provide('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 return (this.component as any).setup?.(reactiveProps, {\n expose: () => undefined,\n })\n },\n // add support for scoped styles\n // @ts-ignore\n // oxlint-disable-next-line\n __scopeId: this.component.__scopeId,\n // add support for CSS Modules\n // @ts-ignore\n // oxlint-disable-next-line\n __cssModules: this.component.__cssModules,\n // add support for vue devtools\n // @ts-ignore\n // oxlint-disable-next-line\n __name: this.component.__name,\n // @ts-ignore\n // oxlint-disable-next-line\n __file: this.component.__file,\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 // Create the content DOM element BEFORE rendering the Vue component,\n // so it is available immediately when ProseMirror accesses contentDOM\n // during the initial DOM build.\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(extendedComponent, {\n editor: this.editor,\n props: mountProps,\n })\n }\n\n /**\n * Fires on editor updates when trackNodeViewPosition is enabled.\n * Detects position shifts where update() is NOT called.\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 * 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 || !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.props.selected) {\n return\n }\n\n this.selectNode()\n } else {\n if (!this.renderer.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: () =>\n rerenderComponent({\n node,\n decorations,\n innerDecorations,\n extension: this.extensionWithSyncedStorage,\n }),\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 extension: this.extensionWithSyncedStorage,\n }\n\n if (this.options.trackNodeViewPosition) {\n extraProps.getPos = () => this.getPos()\n }\n\n rerenderComponent(extraProps)\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 if (this.renderer.element) {\n this.renderer.element.classList.add('ProseMirror-selectednode')\n }\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 if (this.renderer.element) {\n this.renderer.element.classList.remove('ProseMirror-selectednode')\n }\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: Component<NodeViewProps>,\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 // check for class-component and normalize if neccessary\n const normalizedComponent =\n typeof component === 'function' && '__vccOpts' in component\n ? (component.__vccOpts as Component)\n : component\n\n return new VueNodeView(normalizedComponent, props, options)\n }\n}\n","export { Editor } from './Editor.js'\nexport * from './EditorContent.js'\nexport * from './NodeViewContent.js'\nexport * from './NodeViewWrapper.js'\nexport * from './useEditor.js'\nexport * from './VueMarkViewRenderer.js'\nexport * from './VueNodeViewRenderer.js'\nexport * from './VueRenderer.js'\nexport * from '@tiptap/core'\n"],"mappings":";AAEA,SAAS,UAAU,kBAAkB;AAGrC,SAAS,WAAW,eAAe;AAEnC,SAAS,gBAAmB,OAAU;AACpC,SAAO,UAAa,CAAC,OAAO,YAAY;AACtC,WAAO;AAAA,MACL,MAAM;AACJ,cAAM;AACN,eAAO;AAAA,MACT;AAAA,MACA,IAAI,UAAU;AAEZ,gBAAQ;AAGR,8BAAsB,MAAM;AAC1B,gCAAsB,MAAM;AAC1B,oBAAQ;AAAA,UACV,CAAC;AAAA,QACH,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAMO,IAAM,SAAN,cAAqB,WAAW;AAAA,EASrC,YAAY,UAAkC,CAAC,GAAG;AAChD,UAAM,OAAO;AALf,SAAO,mBAA4C;AAEnD,SAAO,aAAgC;AAKrC,SAAK,gBAAgB,gBAAgB,KAAK,KAAK,KAAK;AACpD,SAAK,2BAA2B,gBAAgB,KAAK,gBAAgB;AAErE,SAAK,GAAG,qBAAqB,CAAC,EAAE,UAAU,MAAM;AAC9C,WAAK,cAAc,QAAQ;AAC3B,WAAK,yBAAyB,QAAQ,KAAK;AAAA,IAC7C,CAAC;AAED,WAAO,QAAQ,IAAI;AAAA,EACrB;AAAA,EAEA,IAAI,QAAQ;AACV,WAAO,KAAK,gBAAgB,KAAK,cAAc,QAAQ,KAAK,KAAK;AAAA,EACnE;AAAA,EAEA,IAAI,UAAU;AACZ,WAAO,KAAK,2BAA2B,KAAK,yBAAyB,QAAQ,MAAM;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA,EAKO,eACL,QACA,eACa;AACb,UAAM,YAAY,MAAM,eAAe,QAAQ,aAAa;AAE5D,QAAI,KAAK,eAAe;AACtB,WAAK,cAAc,QAAQ;AAAA,IAC7B;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,iBAAiB,iBAA8D;AACpF,UAAM,YAAY,MAAM,iBAAiB,eAAe;AAExD,QAAI,KAAK,iBAAiB,WAAW;AACnC,WAAK,cAAc,QAAQ;AAAA,IAC7B;AAEA,WAAO;AAAA,EACT;AACF;;;AC3FA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAIA,IAAM,gBAAgB,gBAAgB;AAAA,EAC3C,MAAM;AAAA,EAEN,OAAO;AAAA,IACL,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,OAAO;AACX,UAAM,SAAmC,IAAI;AAC7C,UAAM,WAAW,mBAAmB;AAEpC,gBAAY,MAAM;AAChB,YAAM,SAAS,MAAM;AAErB,UAAI,UAAU,OAAO,QAAQ,WAAW,OAAO,OAAO;AACpD,iBAAS,MAAM;AAhCvB;AAiCU,cAAI,CAAC,OAAO,SAAS,GAAC,YAAO,KAAK,QAAZ,mBAAiB,aAAY;AACjD;AAAA,UACF;AAGA,gBAAM,UAAU,MAAM,OAAO,KAAK;AAElC,iBAAO,MAAM,OAAO,GAAG,OAAO,KAAK,IAAI,WAAW,UAAU;AAG5D,iBAAO,mBAAmB,SAAS,IAAI;AAEvC,cAAI,UAAU;AACZ,mBAAO,aAAa;AAAA,cAClB,GAAG,SAAS;AAAA;AAAA;AAAA;AAAA,cAIZ,UAAU,SAAS;AAAA,YACrB;AAAA,UACF;AAEA,iBAAO,WAAW;AAAA,YAChB;AAAA,UACF,CAAC;AAED,iBAAO,gBAAgB;AAAA,QACzB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,oBAAgB,MAAM;AACpB,YAAM,SAAS,MAAM;AAErB,UAAI,CAAC,QAAQ;AACX;AAAA,MACF;AAEA,aAAO,mBAAmB;AAC1B,aAAO,aAAa;AAAA,IACtB,CAAC;AAED,WAAO,EAAE,OAAO;AAAA,EAClB;AAAA,EAEA,SAAS;AACP,WAAO,EAAE,OAAO;AAAA,MACd,KAAK,CAAC,OAAY;AAChB,aAAK,SAAS;AAAA,MAChB;AAAA,IACF,CAAC;AAAA,EACH;AACF,CAAC;;;ACrFD,SAAS,mBAAAA,kBAAiB,KAAAC,UAAS;AAE5B,IAAM,kBAAkBD,iBAAgB;AAAA,EAC7C,MAAM;AAAA,EAEN,OAAO;AAAA,IACL,IAAI;AAAA,MACF,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,QAAQ;AAAA,IACN,oBAAoB,EAAE,SAAS,OAAU;AAAA,EAC3C;AAAA,EAEA,UAAU;AACR,UAAME,OAAO,KAAa;AAC1B,QAAIA,QAAO,KAAK,KAAK;AACnB,MAAAA,KAAI,KAAK,GAAG;AAAA,IACd;AAAA,EACF;AAAA,EAEA,gBAAgB;AACd,UAAMA,OAAO,KAAa;AAC1B,QAAIA,MAAK;AACP,MAAAA,KAAI,IAAI;AAAA,IACV;AAAA,EACF;AAAA,EAEA,SAAS;AACP,WAAOD,GAAE,KAAK,IAAI;AAAA,MAChB,OAAO;AAAA,QACL,YAAY;AAAA,MACd;AAAA,MACA,0BAA0B;AAAA,IAC5B,CAAC;AAAA,EACH;AACF,CAAC;;;ACtCD,SAAS,mBAAAE,kBAAiB,KAAAC,UAAS;AAE5B,IAAM,kBAAkBD,iBAAgB;AAAA,EAC7C,MAAM;AAAA,EAEN,OAAO;AAAA,IACL,IAAI;AAAA,MACF,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,QAAQ,CAAC,eAAe,mBAAmB;AAAA,EAE3C,SAAS;AAdX;AAeI,WAAOC;AAAA,MACL,KAAK;AAAA,MACL;AAAA;AAAA,QAEE,OAAO,KAAK;AAAA,QACZ,OAAO;AAAA,UACL,YAAY;AAAA,QACd;AAAA,QACA,0BAA0B;AAAA;AAAA,QAE1B,aAAa,KAAK;AAAA,MACpB;AAAA,OACA,gBAAK,QAAO,YAAZ;AAAA,IACF;AAAA,EACF;AACF,CAAC;;;AC7BD,SAAS,mBAAAC,kBAAiB,WAAW,kBAAkB;AAIhD,IAAM,YAAY,CAAC,UAAkC,CAAC,MAAM;AACjE,QAAM,SAAS,WAAmB;AAElC,YAAU,MAAM;AACd,WAAO,QAAQ,IAAI,OAAO,OAAO;AAAA,EACnC,CAAC;AAED,EAAAC,iBAAgB,MAAM;AAZxB;AAaI,iBAAO,UAAP,mBAAc;AAAA,EAChB,CAAC;AAED,SAAO;AACT;;;ACfA,SAAS,gBAAgB;AAEzB,SAAS,mBAAAC,kBAAiB,KAAAC,IAAG,aAAa;;;ACF1C,SAAS,KAAAC,IAAG,WAAAC,UAAS,UAAU,cAAc;AAoBtC,IAAM,cAAN,MAAkB;AAAA,EAgBvB,YAAY,WAAsB,EAAE,QAAQ,CAAC,GAAG,OAAO,GAAuB;AAF9E;AAAA;AAAA;AAAA,qBAAY;AAGV,SAAK,SAAS;AACd,SAAK,YAAYA,SAAQ,SAAS;AAClC,SAAK,KAAK,SAAS,cAAc,KAAK;AACtC,SAAK,QAAQ,SAAS,KAAK;AAC3B,SAAK,oBAAoB,KAAK,gBAAgB;AAAA,EAChD;AAAA,EAEA,IAAI,UAA0B;AAC5B,WAAO,KAAK,kBAAkB;AAAA,EAChC;AAAA,EAEA,IAAI,MAAW;AAlDjB;AAoDI,SAAI,gBAAK,kBAAkB,UAAvB,mBAA8B,cAA9B,mBAAyC,SAAS;AACpD,aAAO,KAAK,kBAAkB,MAAM,UAAU;AAAA,IAChD;AAEA,YAAO,gBAAK,kBAAkB,UAAvB,mBAA8B,cAA9B,mBAAyC;AAAA,EAClD;AAAA,EAEA,kBAAkB;AAChB,QAAI,KAAK,WAAW;AAClB,aAAO,KAAK;AAAA,IACd;AAEA,QAAI,QAAuBD,GAAE,KAAK,WAA8B,KAAK,KAAK;AAE1E,QAAI,KAAK,OAAO,YAAY;AAC1B,YAAM,aAAa,KAAK,OAAO;AAAA,IACjC;AACA,QAAI,OAAO,aAAa,eAAe,KAAK,IAAI;AAC9C,aAAO,OAAO,KAAK,EAAE;AAAA,IACvB;AAEA,UAAM,UAAU,MAAM;AACpB,UAAI,KAAK,IAAI;AACX,eAAO,MAAM,KAAK,EAAE;AAAA,MACtB;AACA,WAAK,KAAK;AACV,cAAQ;AAAA,IACV;AAEA,WAAO,EAAE,OAAO,SAAS,IAAI,KAAK,KAAK,KAAK,GAAG,oBAAoB,KAAK;AAAA,EAC1E;AAAA,EAEA,YAAY,QAA6B,CAAC,GAAS;AACjD,QAAI,KAAK,WAAW;AAClB;AAAA,IACF;AAEA,WAAO,QAAQ,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC9C,WAAK,MAAM,GAAG,IAAI;AAAA,IACpB,CAAC;AACD,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,WAAW;AAClB;AAAA,IACF;AAEA,SAAK,YAAY;AACjB,SAAK,kBAAkB,QAAQ;AAAA,EACjC;AACF;;;ADxFO,IAAM,gBAAgB;AAAA,EAC3B,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,WAAW;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,kBAAkB;AAAA,IAChB,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,gBAAgB;AAAA,IACd,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AACF;AAEO,IAAM,kBAAkBE,iBAAgB;AAAA,EAC7C,MAAM;AAAA,EAEN,OAAO;AAAA,IACL,IAAI;AAAA,MACF,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,SAAS;AACP,WAAOC,GAAE,KAAK,IAAI;AAAA,MAChB,OAAO;AAAA,QACL,YAAY;AAAA,MACd;AAAA,MACA,0BAA0B;AAAA,IAC5B,CAAC;AAAA,EACH;AACF,CAAC;AAEM,IAAM,cAAN,cAA0B,SAAgD;AAAA,EAG/E,YACE,WACA,OACA,SACA;AACA,UAAM,WAAW,OAAO,OAAO;AAE/B,UAAM,iBAAiB;AAAA,MACrB,GAAG;AAAA,MACH,kBAAkB,KAAK,iBAAiB,KAAK,IAAI;AAAA,IACnD;AAGA,UAAM,oBAAoBD,iBAAgB;AAAA,MACxC,SAAS,EAAE,GAAG,UAAU;AAAA,MACxB,OAAO,OAAO,KAAK,cAAc;AAAA,MACjC,UAAW,KAAK,UAAkB;AAAA,MAClC,OAAO,mBAAiB;AAtF9B;AAuFQ,gBAAQ,eAAkB,UAAlB,mCAA0B,eAAe;AAAA,UAC/C,QAAQ,MAAM;AAAA,QAChB;AAAA,MACF;AAAA;AAAA,MAEA,WAAY,UAAkB;AAAA,MAC9B,cAAe,UAAkB;AAAA,MACjC,QAAS,UAAkB;AAAA,MAC3B,QAAS,UAAkB;AAAA,IAC7B,CAAC;AACD,SAAK,WAAW,IAAI,YAAY,mBAAmB;AAAA,MACjD,QAAQ,KAAK;AAAA,MACb,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,MAAM;AACR,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA,EAEA,IAAI,aAAa;AACf,WAAO,KAAK,IAAI,cAAc,0BAA0B;AAAA,EAC1D;AAAA,EAEA,iBAAiB,OAAkC;AAEjD,UAAM,gBAAgB,MAAM,KAAK,IAAI;AACrC,UAAM,iBAAiB,OAAO,aAAa;AAAA,EAC7C;AAAA,EAEA,UAAU;AACR,SAAK,SAAS,QAAQ;AAAA,EACxB;AACF;AAEO,SAAS,oBACd,WACA,UAA+C,CAAC,GAC9B;AAClB,SAAO,WAAS;AAId,QAAI,CAAE,MAAM,OAAkB,kBAAkB;AAC9C,aAAO,CAAC;AAAA,IACV;AAEA,WAAO,IAAI,YAAY,WAAW,OAAO,OAAO;AAAA,EAClD;AACF;;;AEhIA,SAAS,oBAAoB,gBAAgB;AAI7C,SAAS,mBAAAE,kBAAiB,SAAS,OAAAC,YAAW;AAKvC,IAAM,gBAAgB;AAAA,EAC3B,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,UAAU;AAAA,IACR,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,WAAW;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,kBAAkB;AAAA,IAChB,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,YAAY;AAAA,IACV,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,kBAAkB;AAAA,IAChB,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAAA,EACA,gBAAgB;AAAA,IACd,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AACF;AAgBA,IAAM,cAAN,cAA0B,SAAwD;AAAA,EAsBhF,YACE,WACA,OACA,SACA;AACA,UAAM,WAAW,OAAO,OAAO;AAPjC,SAAQ,mCAAsE;AA0H9E;AAAA;AAAA;AAAA;AAAA,SAAQ,uBAAuB,MAAM;AACnC,YAAM,SAAS,KAAK,OAAO;AAC3B,UAAI,OAAO,WAAW,YAAY,WAAW,KAAK,YAAY;AAC5D;AAAA,MACF;AACA,WAAK,aAAa;AAClB,WAAK,SAAS,YAAY,EAAE,QAAQ,MAAM,KAAK,OAAO,EAAE,CAAC;AAAA,IAC3D;AAxHE,QAAI,KAAK,QAAQ,uBAAuB;AACtC,WAAK,OAAO,GAAG,UAAU,KAAK,oBAAoB;AAAA,IACpD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,6BAAyD;AAC3D,QAAI,CAAC,KAAK,kCAAkC;AAC1C,YAAM,SAAS,KAAK;AACpB,YAAM,YAAY,KAAK;AAEvB,WAAK,mCAAmC,IAAI,MAAM,WAAW;AAAA,QAC3D,IAAI,QAAQ,MAAM,UAAU;AA3HpC;AA4HU,cAAI,SAAS,WAAW;AACtB,oBAAO,YAAO,QAAQ,UAAU,IAAmC,MAA5D,YAAiE,CAAC;AAAA,UAC3E;AACA,iBAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAAA,QAC3C;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAQ;AACN,UAAM,QAA6B;AAAA,MACjC,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,aAAa,KAAK;AAAA,MAClB,kBAAkB,KAAK;AAAA,MACvB,MAAM,KAAK;AAAA,MACX,UAAU;AAAA,MACV,WAAW,KAAK;AAAA,MAChB,gBAAgB,KAAK;AAAA,MACrB,QAAQ,MAAM,KAAK,OAAO;AAAA,MAC1B,kBAAkB,CAAC,aAAa,CAAC,MAAM,KAAK,iBAAiB,UAAU;AAAA,MACvE,YAAY,MAAM,KAAK,WAAW;AAAA,IACpC;AAEA,UAAM,aAAa;AAEnB,UAAM,cAAc,KAAK,YAAY,KAAK,IAAI;AAE9C,SAAK,oBAAoBC,KAAI,KAAK,qBAAqB,CAAC;AAExD,UAAM,oBAAoBC,iBAAgB;AAAA,MACxC,SAAS,EAAE,GAAG,KAAK,UAAU;AAAA,MAC7B,OAAO,OAAO,KAAK,KAAK;AAAA,MACxB,UAAW,KAAK,UAAkB;AAAA,MAClC,OAAO,mBAAiB;AAhK9B;AAiKQ,gBAAQ,eAAe,WAAW;AAClC,gBAAQ,qBAAqB,KAAK,iBAAiB;AACnD,gBAAQ,sBAAsB,CAAC,OAA2B;AACxD,cAAI,CAAC,KAAK,kBAAmB;AAE7B,cAAI,MAAM,GAAG,eAAe,KAAK,mBAAmB;AAElD,eAAG,YAAY,KAAK,iBAAiB;AAAA,UACvC;AAAA,QACF,CAAC;AAED,gBAAQ,gBAAK,WAAkB,UAAvB,4BAA+B,eAAe;AAAA,UACpD,QAAQ,MAAM;AAAA,QAChB;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAIA,WAAW,KAAK,UAAU;AAAA;AAAA;AAAA;AAAA,MAI1B,cAAc,KAAK,UAAU;AAAA;AAAA;AAAA;AAAA,MAI7B,QAAQ,KAAK,UAAU;AAAA;AAAA;AAAA,MAGvB,QAAQ,KAAK,UAAU;AAAA,IACzB,CAAC;AAED,SAAK,wBAAwB,KAAK,sBAAsB,KAAK,IAAI;AACjE,SAAK,OAAO,GAAG,mBAAmB,KAAK,qBAAqB;AAE5D,SAAK,aAAa,KAAK,OAAO;AAE9B,QAAI,CAAC,KAAK,KAAK,QAAQ;AAIrB,WAAK,oBAAoB,SAAS,cAAc,KAAK,KAAK,WAAW,SAAS,KAAK;AACnF,WAAK,kBAAkB,MAAM,aAAa;AAI1C,WAAK,kBAAkB,QAAQ,qBAAqB;AAAA,IACtD;AAEA,SAAK,WAAW,IAAI,YAAY,mBAAmB;AAAA,MACjD,QAAQ,KAAK;AAAA,MACb,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,IAAI,MAAM;AACR,QAAI,CAAC,KAAK,SAAS,WAAW,CAAC,KAAK,SAAS,QAAQ,aAAa,wBAAwB,GAAG;AAC3F,YAAM,MAAM,8DAA8D;AAAA,IAC5E;AAEA,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,aAAa;AACf,QAAI,KAAK,KAAK,QAAQ;AACpB,aAAO;AAAA,IACT;AAEA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,wBAAwB;AACtB,UAAM,MAAM,KAAK,OAAO;AAExB,QAAI,OAAO,QAAQ,UAAU;AAC3B;AAAA,IACF;AAEA,UAAM,aAAa,mBAAmB;AAAA,MACpC,WAAW,KAAK,OAAO,MAAM;AAAA,MAC7B;AAAA,MACA,UAAU,KAAK,KAAK;AAAA,MACpB,yBAAyB,KAAK,QAAQ;AAAA,IACxC,CAAC;AAED,QAAI,YAAY;AACd,UAAI,KAAK,SAAS,MAAM,UAAU;AAChC;AAAA,MACF;AAEA,WAAK,WAAW;AAAA,IAClB,OAAO;AACL,UAAI,CAAC,KAAK,SAAS,MAAM,UAAU;AACjC;AAAA,MACF;AAEA,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OACE,MACA,aACA,kBACS;AACT,UAAM,oBAAoB,CAAC,UAAgC;AACzD,WAAK,kBAAkB,QAAQ,KAAK,qBAAqB;AACzD,WAAK,SAAS,YAAY,KAAK;AAAA,IACjC;AAEA,QAAI,OAAO,KAAK,QAAQ,WAAW,YAAY;AAC7C,YAAM,UAAU,KAAK;AACrB,YAAM,iBAAiB,KAAK;AAC5B,YAAM,sBAAsB,KAAK;AAEjC,WAAK,OAAO;AACZ,WAAK,cAAc;AACnB,WAAK,mBAAmB;AAExB,aAAO,KAAK,QAAQ,OAAO;AAAA,QACzB;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB;AAAA,QACA;AAAA,QACA,aAAa,MACX,kBAAkB;AAAA,UAChB;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW,KAAK;AAAA,QAClB,CAAC;AAAA,MACL,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,SAAS,KAAK,KAAK,MAAM;AAChC,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,SAAS,KAAK;AAQlC,QAAI,CAAC,aAAa;AAChB,WAAK,OAAO;AACZ,WAAK,cAAc;AACnB,WAAK,mBAAmB;AACxB,WAAK,kBAAkB,QAAQ,KAAK,qBAAqB;AACzD,aAAO;AAAA,IACT;AAEA,SAAK,OAAO;AACZ,SAAK,cAAc;AACnB,SAAK,mBAAmB;AACxB,SAAK,aAAa,KAAK,OAAO;AAE9B,UAAM,aAAkC;AAAA,MACtC;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,KAAK;AAAA,IAClB;AAEA,QAAI,KAAK,QAAQ,uBAAuB;AACtC,iBAAW,SAAS,MAAM,KAAK,OAAO;AAAA,IACxC;AAEA,sBAAkB,UAAU;AAC5B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa;AACX,SAAK,SAAS,YAAY;AAAA,MACxB,UAAU;AAAA,IACZ,CAAC;AACD,QAAI,KAAK,SAAS,SAAS;AACzB,WAAK,SAAS,QAAQ,UAAU,IAAI,0BAA0B;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe;AACb,SAAK,SAAS,YAAY;AAAA,MACxB,UAAU;AAAA,IACZ,CAAC;AACD,QAAI,KAAK,SAAS,SAAS;AACzB,WAAK,SAAS,QAAQ,UAAU,OAAO,0BAA0B;AAAA,IACnE;AAAA,EACF;AAAA,EAEA,uBAAuB;AACrB,WACE,KAAK,YAEF,QAAQ,UAAQ,KAAK,KAAK,MAAM,KAAK,EACrC,KAAK,GAAG;AAAA,EAEf;AAAA,EAEA,UAAU;AACR,SAAK,SAAS,QAAQ;AACtB,SAAK,OAAO,IAAI,mBAAmB,KAAK,qBAAqB;AAE7D,QAAI,KAAK,QAAQ,uBAAuB;AACtC,WAAK,OAAO,IAAI,UAAU,KAAK,oBAAoB;AAAA,IACrD;AAEA,SAAK,oBAAoB;AAAA,EAC3B;AACF;AAEO,SAAS,oBACd,WACA,SACkB;AAClB,SAAO,WAAS;AAId,QAAI,CAAE,MAAM,OAAkB,kBAAkB;AAC9C,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,sBACJ,OAAO,cAAc,cAAc,eAAe,YAC7C,UAAU,YACX;AAEN,WAAO,IAAI,YAAY,qBAAqB,OAAO,OAAO;AAAA,EAC5D;AACF;;;ACxaA,cAAc;","names":["defineComponent","h","ref","defineComponent","h","onBeforeUnmount","onBeforeUnmount","defineComponent","h","h","markRaw","defineComponent","h","defineComponent","ref","ref","defineComponent"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiptap/vue-3",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.26.0",
|
|
4
4
|
"description": "Vue components for tiptap",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tiptap",
|
|
@@ -46,18 +46,18 @@
|
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"vue": "^3.5.13",
|
|
49
|
-
"@tiptap/
|
|
50
|
-
"@tiptap/
|
|
49
|
+
"@tiptap/core": "^3.26.0",
|
|
50
|
+
"@tiptap/pm": "^3.26.0"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"@floating-ui/dom": "^1.0.0",
|
|
54
54
|
"vue": "^3.0.0",
|
|
55
|
-
"@tiptap/core": "3.
|
|
56
|
-
"@tiptap/pm": "3.
|
|
55
|
+
"@tiptap/core": "3.26.0",
|
|
56
|
+
"@tiptap/pm": "3.26.0"
|
|
57
57
|
},
|
|
58
58
|
"optionalDependencies": {
|
|
59
|
-
"@tiptap/extension-bubble-menu": "^3.
|
|
60
|
-
"@tiptap/extension-floating-menu": "^3.
|
|
59
|
+
"@tiptap/extension-bubble-menu": "^3.26.0",
|
|
60
|
+
"@tiptap/extension-floating-menu": "^3.26.0"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "tsup"
|
package/src/NodeViewContent.ts
CHANGED
|
@@ -10,6 +10,24 @@ export const NodeViewContent = defineComponent({
|
|
|
10
10
|
},
|
|
11
11
|
},
|
|
12
12
|
|
|
13
|
+
inject: {
|
|
14
|
+
nodeViewContentRef: { default: undefined },
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
mounted() {
|
|
18
|
+
const ref = (this as any).nodeViewContentRef as ((el: HTMLElement | null) => void) | undefined
|
|
19
|
+
if (ref && this.$el) {
|
|
20
|
+
ref(this.$el)
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
beforeUnmount() {
|
|
25
|
+
const ref = (this as any).nodeViewContentRef as ((el: HTMLElement | null) => void) | undefined
|
|
26
|
+
if (ref) {
|
|
27
|
+
ref(null)
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
|
|
13
31
|
render() {
|
|
14
32
|
return h(this.as, {
|
|
15
33
|
style: {
|
|
@@ -81,6 +81,19 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
81
81
|
|
|
82
82
|
decorationClasses!: Ref<string>
|
|
83
83
|
|
|
84
|
+
/**
|
|
85
|
+
* The element that holds the rich-text content of the node.
|
|
86
|
+
* Always created for non-leaf nodes to guarantee a valid contentDOM,
|
|
87
|
+
* even when the user's component does not include a NodeViewContent.
|
|
88
|
+
* This matches React's behavior and prevents ProseMirror from
|
|
89
|
+
* thrashing the DOM when contentDOM is unexpectedly null.
|
|
90
|
+
*
|
|
91
|
+
* NOTE: must NOT have an initializer (= null), because class field
|
|
92
|
+
* initializers run AFTER super() and would overwrite the value set
|
|
93
|
+
* by mount() during the super() call.
|
|
94
|
+
*/
|
|
95
|
+
contentDOMElement!: HTMLElement | null
|
|
96
|
+
|
|
84
97
|
private currentPos: number | undefined
|
|
85
98
|
|
|
86
99
|
private cachedExtensionWithSyncedStorage: NodeViewProps['extension'] | null = null
|
|
@@ -148,6 +161,14 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
148
161
|
setup: reactiveProps => {
|
|
149
162
|
provide('onDragStart', onDragStart)
|
|
150
163
|
provide('decorationClasses', this.decorationClasses)
|
|
164
|
+
provide('nodeViewContentRef', (el: HTMLElement | null) => {
|
|
165
|
+
if (!this.contentDOMElement) return
|
|
166
|
+
|
|
167
|
+
if (el && el.firstChild !== this.contentDOMElement) {
|
|
168
|
+
// NodeViewContent mounted: move the contentDOMElement inside it
|
|
169
|
+
el.appendChild(this.contentDOMElement)
|
|
170
|
+
}
|
|
171
|
+
})
|
|
151
172
|
|
|
152
173
|
return (this.component as any).setup?.(reactiveProps, {
|
|
153
174
|
expose: () => undefined,
|
|
@@ -175,6 +196,18 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
175
196
|
|
|
176
197
|
this.currentPos = this.getPos()
|
|
177
198
|
|
|
199
|
+
if (!this.node.isLeaf) {
|
|
200
|
+
// Create the content DOM element BEFORE rendering the Vue component,
|
|
201
|
+
// so it is available immediately when ProseMirror accesses contentDOM
|
|
202
|
+
// during the initial DOM build.
|
|
203
|
+
this.contentDOMElement = document.createElement(this.node.isInline ? 'span' : 'div')
|
|
204
|
+
this.contentDOMElement.style.whiteSpace = 'inherit'
|
|
205
|
+
// Use a distinct attribute to avoid clashing with the user's
|
|
206
|
+
// <node-view-content> element (which carries data-node-view-content).
|
|
207
|
+
// Matches React's data-node-view-content-react convention.
|
|
208
|
+
this.contentDOMElement.dataset.nodeViewContentVue = ''
|
|
209
|
+
}
|
|
210
|
+
|
|
178
211
|
this.renderer = new VueRenderer(extendedComponent, {
|
|
179
212
|
editor: this.editor,
|
|
180
213
|
props: mountProps,
|
|
@@ -215,7 +248,7 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
215
248
|
return null
|
|
216
249
|
}
|
|
217
250
|
|
|
218
|
-
return this.
|
|
251
|
+
return this.contentDOMElement
|
|
219
252
|
}
|
|
220
253
|
|
|
221
254
|
/**
|
|
@@ -373,6 +406,8 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
373
406
|
if (this.options.trackNodeViewPosition) {
|
|
374
407
|
this.editor.off('update', this.handlePositionUpdate)
|
|
375
408
|
}
|
|
409
|
+
|
|
410
|
+
this.contentDOMElement = null
|
|
376
411
|
}
|
|
377
412
|
}
|
|
378
413
|
|