don’t use __vue__
This commit is contained in:
12
packages/vue-2/src/Editor.ts
Normal file
12
packages/vue-2/src/Editor.ts
Normal 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
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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 it’s `undefined` because <editor-content> isn’t rendered yet
|
// maybe it’s `undefined` because <editor-content> isn’t rendered yet
|
||||||
const parent = props.editor.view.dom.parentElement
|
if (!props.editor.contentComponent) {
|
||||||
? getComponentFromElement(props.editor.view.dom.parentElement)
|
|
||||||
: undefined
|
|
||||||
|
|
||||||
if (!parent) {
|
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -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 it’s `undefined` because <editor-content> isn’t rendered yet
|
||||||
if (!props.editor.contentComponent) {
|
if (!props.editor.contentComponent) {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user