don’t use __vue__

This commit is contained in:
Philipp Kühn
2021-03-05 11:01:26 +01:00
parent a073d75dff
commit e9e3418a0f
6 changed files with 63 additions and 33 deletions

View File

@@ -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
}

View File

@@ -1,4 +1,5 @@
import Vue from 'vue' import Vue, { PropType } from 'vue'
import { Editor } from './Editor'
export const EditorContent = Vue.extend({ export const EditorContent = Vue.extend({
name: 'EditorContent', name: 'EditorContent',
@@ -6,17 +7,30 @@ export const EditorContent = Vue.extend({
props: { props: {
editor: { editor: {
default: null, default: null,
type: Object, type: Object as PropType<Editor>,
}, },
}, },
watch: { watch: {
editor: { editor: {
immediate: true, immediate: true,
handler(editor) { handler(editor: Editor) {
if (editor && editor.options.element) { if (editor && editor.options.element) {
this.$nextTick(() => { 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() editor.createNodeViews()
}) })
} }
@@ -29,8 +43,26 @@ export const EditorContent = Vue.extend({
}, },
beforeDestroy() { beforeDestroy() {
this.editor.setOptions({ const { editor } = this
element: this.$el,
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,
}) })
}, },
}) })

View File

@@ -1,22 +1,12 @@
import { import { Node, NodeViewRenderer, NodeViewRendererProps } from '@tiptap/core'
Editor,
Node,
NodeViewRenderer,
NodeViewRendererProps,
} from '@tiptap/core'
import { Decoration, NodeView } from 'prosemirror-view' import { Decoration, NodeView } from 'prosemirror-view'
import { NodeSelection } from 'prosemirror-state' import { NodeSelection } from 'prosemirror-state'
import { Node as ProseMirrorNode } from 'prosemirror-model' import { Node as ProseMirrorNode } from 'prosemirror-model'
import Vue from 'vue' import Vue from 'vue'
import { VueConstructor } from 'vue/types/umd' import { VueConstructor } from 'vue/types/umd'
import { Editor } from './Editor'
import { VueRenderer } from './VueRenderer' import { VueRenderer } from './VueRenderer'
function getComponentFromElement(element: HTMLElement): Vue {
// @ts-ignore
// eslint-disable-next-line
return element.__vue__
}
interface VueNodeViewRendererOptions { interface VueNodeViewRendererOptions {
stopEvent: ((event: Event) => boolean) | null, stopEvent: ((event: Event) => boolean) | null,
update: ((node: ProseMirrorNode, decorations: Decoration[]) => 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, { this.renderer = new VueRenderer(Component, {
parent, parent: this.editor.contentComponent,
propsData: props, propsData: props,
}) })
} }
@@ -271,11 +257,7 @@ export function VueNodeViewRenderer(component: Vue | VueConstructor, options?: P
// try to get the parent component // try to get the parent component
// this is important for vue devtools to show the component hierarchy correctly // this is important for vue devtools to show the component hierarchy correctly
// maybe its `undefined` because <editor-content> isnt rendered yet // maybe its `undefined` because <editor-content> isnt rendered yet
const parent = props.editor.view.dom.parentElement if (!props.editor.contentComponent) {
? getComponentFromElement(props.editor.view.dom.parentElement)
: undefined
if (!parent) {
return {} return {}
} }

View File

@@ -1,4 +1,5 @@
export * from '@tiptap/core' export * from '@tiptap/core'
export { Editor } from './Editor'
export * from './VueRenderer' export * from './VueRenderer'
export * from './VueNodeViewRenderer' export * from './VueNodeViewRenderer'
export * from './EditorContent' export * from './EditorContent'

View File

@@ -37,7 +37,7 @@ export const EditorContent = defineComponent({
return return
} }
const el = unref(rootEl.value) const element = unref(rootEl.value)
rootEl.value.appendChild(editor.options.element.firstChild) rootEl.value.appendChild(editor.options.element.firstChild)
@@ -45,7 +45,7 @@ export const EditorContent = defineComponent({
editor.contentComponent = instance.ctx._ editor.contentComponent = instance.ctx._
editor.setOptions({ editor.setOptions({
element: el, element,
}) })
editor.createNodeViews() editor.createNodeViews()
@@ -69,12 +69,12 @@ export const EditorContent = defineComponent({
return 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({ editor.setOptions({
element: newEl, element: newElement,
}) })
}) })

View File

@@ -255,6 +255,9 @@ class VueNodeView implements NodeView {
export function VueNodeViewRenderer(component: Component, options?: Partial<VueNodeViewRendererOptions>): NodeViewRenderer { export function VueNodeViewRenderer(component: Component, options?: Partial<VueNodeViewRendererOptions>): NodeViewRenderer {
return (props: NodeViewRendererProps) => { return (props: NodeViewRendererProps) => {
// try to get the parent component
// this is important for vue devtools to show the component hierarchy correctly
// maybe its `undefined` because <editor-content> isnt rendered yet
if (!props.editor.contentComponent) { if (!props.editor.contentComponent) {
return {} return {}
} }