diff --git a/packages/vue-2/src/Editor.ts b/packages/vue-2/src/Editor.ts new file mode 100644 index 000000000..5c6d2a6a4 --- /dev/null +++ b/packages/vue-2/src/Editor.ts @@ -0,0 +1,12 @@ +import { Editor as CoreEditor } from '@tiptap/core' +import Vue from 'vue' + +declare module '@tiptap/core' { + interface Editor { + contentComponent: Vue | null, + } +} + +export class Editor extends CoreEditor { + public contentComponent: Vue | null = null +} diff --git a/packages/vue-2/src/EditorContent.ts b/packages/vue-2/src/EditorContent.ts index 1665a2f28..0fcb6ca55 100644 --- a/packages/vue-2/src/EditorContent.ts +++ b/packages/vue-2/src/EditorContent.ts @@ -1,4 +1,5 @@ -import Vue from 'vue' +import Vue, { PropType } from 'vue' +import { Editor } from './Editor' export const EditorContent = Vue.extend({ name: 'EditorContent', @@ -6,17 +7,30 @@ export const EditorContent = Vue.extend({ props: { editor: { default: null, - type: Object, + type: Object as PropType, }, }, watch: { editor: { immediate: true, - handler(editor) { + handler(editor: Editor) { if (editor && editor.options.element) { this.$nextTick(() => { - this.$el.appendChild(editor.options.element.firstChild) + const element = this.$el + + if (!element || !editor.options.element.firstChild) { + return + } + + element.appendChild(editor.options.element.firstChild) + + editor.contentComponent = this + + editor.setOptions({ + element, + }) + editor.createNodeViews() }) } @@ -29,8 +43,26 @@ export const EditorContent = Vue.extend({ }, beforeDestroy() { - this.editor.setOptions({ - element: this.$el, + const { editor } = this + + if (!editor.isDestroyed) { + editor.view.setProps({ + nodeViews: {}, + }) + } + + editor.contentComponent = null + + if (!editor.options.element.firstChild) { + return + } + + const newElement = document.createElement('div') + + newElement.appendChild(editor.options.element.firstChild) + + editor.setOptions({ + element: newElement, }) }, }) diff --git a/packages/vue-2/src/VueNodeViewRenderer.ts b/packages/vue-2/src/VueNodeViewRenderer.ts index 413bfbfc2..a5206a087 100644 --- a/packages/vue-2/src/VueNodeViewRenderer.ts +++ b/packages/vue-2/src/VueNodeViewRenderer.ts @@ -1,22 +1,12 @@ -import { - Editor, - Node, - NodeViewRenderer, - NodeViewRendererProps, -} from '@tiptap/core' +import { Node, NodeViewRenderer, NodeViewRendererProps } from '@tiptap/core' import { Decoration, NodeView } from 'prosemirror-view' import { NodeSelection } from 'prosemirror-state' import { Node as ProseMirrorNode } from 'prosemirror-model' import Vue from 'vue' import { VueConstructor } from 'vue/types/umd' +import { Editor } from './Editor' import { VueRenderer } from './VueRenderer' -function getComponentFromElement(element: HTMLElement): Vue { - // @ts-ignore - // eslint-disable-next-line - return element.__vue__ -} - interface VueNodeViewRendererOptions { stopEvent: ((event: Event) => boolean) | null, update: ((node: ProseMirrorNode, decorations: Decoration[]) => boolean) | null, @@ -101,12 +91,8 @@ class VueNodeView implements NodeView { }, }) - const parent = this.editor.view.dom.parentElement - ? getComponentFromElement(this.editor.view.dom.parentElement) - : undefined - this.renderer = new VueRenderer(Component, { - parent, + parent: this.editor.contentComponent, propsData: props, }) } @@ -271,11 +257,7 @@ export function VueNodeViewRenderer(component: Vue | VueConstructor, options?: P // try to get the parent component // this is important for vue devtools to show the component hierarchy correctly // maybe it’s `undefined` because isn’t rendered yet - const parent = props.editor.view.dom.parentElement - ? getComponentFromElement(props.editor.view.dom.parentElement) - : undefined - - if (!parent) { + if (!props.editor.contentComponent) { return {} } diff --git a/packages/vue-2/src/index.ts b/packages/vue-2/src/index.ts index 52ec60d66..c13271f29 100644 --- a/packages/vue-2/src/index.ts +++ b/packages/vue-2/src/index.ts @@ -1,4 +1,5 @@ export * from '@tiptap/core' +export { Editor } from './Editor' export * from './VueRenderer' export * from './VueNodeViewRenderer' export * from './EditorContent' diff --git a/packages/vue-3/src/EditorContent.ts b/packages/vue-3/src/EditorContent.ts index 2a2966840..a88247e8e 100644 --- a/packages/vue-3/src/EditorContent.ts +++ b/packages/vue-3/src/EditorContent.ts @@ -37,7 +37,7 @@ export const EditorContent = defineComponent({ return } - const el = unref(rootEl.value) + const element = unref(rootEl.value) rootEl.value.appendChild(editor.options.element.firstChild) @@ -45,7 +45,7 @@ export const EditorContent = defineComponent({ editor.contentComponent = instance.ctx._ editor.setOptions({ - element: el, + element, }) editor.createNodeViews() @@ -69,12 +69,12 @@ export const EditorContent = defineComponent({ return } - const newEl = document.createElement('div') + const newElement = document.createElement('div') - newEl.appendChild(editor.options.element.firstChild) + newElement.appendChild(editor.options.element.firstChild) editor.setOptions({ - element: newEl, + element: newElement, }) }) diff --git a/packages/vue-3/src/VueNodeViewRenderer.ts b/packages/vue-3/src/VueNodeViewRenderer.ts index 0a806cfd4..21b3c537f 100644 --- a/packages/vue-3/src/VueNodeViewRenderer.ts +++ b/packages/vue-3/src/VueNodeViewRenderer.ts @@ -255,6 +255,9 @@ class VueNodeView implements NodeView { export function VueNodeViewRenderer(component: Component, options?: Partial): NodeViewRenderer { return (props: NodeViewRendererProps) => { + // try to get the parent component + // this is important for vue devtools to show the component hierarchy correctly + // maybe it’s `undefined` because isn’t rendered yet if (!props.editor.contentComponent) { return {} }