diff --git a/docs/src/demos/Examples/NodeView/Component.vue b/docs/src/demos/Examples/NodeView/Component.vue
index dcc31796..07385fdb 100644
--- a/docs/src/demos/Examples/NodeView/Component.vue
+++ b/docs/src/demos/Examples/NodeView/Component.vue
@@ -4,10 +4,21 @@
-
+
+ attrs {{ node.attrs }}
+
-->
-
+
+
+
+ hey {{ node.attrs.checked }}
+
+
+
+
@@ -19,19 +30,44 @@ export default {
required: true,
},
+ node: {
+ type: Object,
+ required: true,
+ },
+
inner: {
type: [Object, Function],
required: true,
},
+
+ updateAttrs: {
+ type: Function,
+ required: true,
+ },
},
data() {
return {
- foo: 'foo',
+ random: 'foo',
}
},
+ methods: {
+ toggleChecked() {
+ this.editor.commands.focus()
+ this.updateAttrs({
+ checked: !this.node.attrs.checked,
+ })
+ },
+ },
+
mounted() {
+ // console.log(this.node)
+
+ console.log('mounted')
+ // setInterval(() => {
+ // this.random = `foo${Math.random()}`
+ // }, 1000)
// console.log(this)
},
}
diff --git a/docs/src/demos/Examples/NodeView/Test.ts b/docs/src/demos/Examples/NodeView/Test.ts
index 33c790ee..981386cf 100644
--- a/docs/src/demos/Examples/NodeView/Test.ts
+++ b/docs/src/demos/Examples/NodeView/Test.ts
@@ -1,4 +1,4 @@
-import { Node } from '@tiptap/core'
+import { Node, mergeAttributes } from '@tiptap/core'
import { VueRenderer } from '@tiptap/vue'
import Component from './Component.vue'
@@ -13,6 +13,16 @@ export default Node.create({
selectable: false,
+ // atom: true,
+
+ addAttributes() {
+ return {
+ checked: {
+ default: false,
+ },
+ }
+ },
+
parseHTML() {
return [
{
@@ -21,8 +31,8 @@ export default Node.create({
]
},
- renderHTML() {
- return ['div', { 'data-type': 'test' }, 0]
+ renderHTML({ HTMLAttributes }) {
+ return ['div', mergeAttributes(HTMLAttributes, { 'data-type': 'test' }), 0]
},
addNodeView() {
diff --git a/packages/vue/src/VueRenderer.ts b/packages/vue/src/VueRenderer.ts
index 46053db7..40ec5394 100644
--- a/packages/vue/src/VueRenderer.ts
+++ b/packages/vue/src/VueRenderer.ts
@@ -1,5 +1,5 @@
import { Editor, Node, NodeViewRendererProps } from '@tiptap/core'
-import { NodeView } from 'prosemirror-view'
+import { Decoration, NodeView } from 'prosemirror-view'
import {
Node as ProseMirrorNode,
@@ -20,18 +20,17 @@ class VueNodeView implements NodeView {
node!: ProseMirrorNode
+ decorations!: Decoration[]
+
id!: string
- constructor(component: Vue | VueConstructor, props: NodeViewRendererProps) {
- // eslint-disable-next-line
- const { node, editor, getPos } = props
- // eslint-disable-next-line
- const { view } = editor
+ getPos!: any
+ constructor(component: Vue | VueConstructor, props: NodeViewRendererProps) {
this.editor = props.editor
this.extension = props.extension
this.node = props.node
-
+ this.getPos = props.getPos
this.mount(component)
}
@@ -52,11 +51,13 @@ class VueNodeView implements NodeView {
render(createElement, context) {
return createElement(
context.props.as, {
+ // this.as, {
style: {
whiteSpace: 'pre-wrap',
},
attrs: {
id,
+ // contenteditable: true,
},
},
)
@@ -74,6 +75,8 @@ class VueNodeView implements NodeView {
const props = {
editor: this.editor,
inner: Inner,
+ node: this.node,
+ updateAttrs: (attrs: {}) => this.updateAttrs(attrs),
}
this.vm = new Component({
@@ -95,6 +98,8 @@ class VueNodeView implements NodeView {
}
stopEvent(event: Event): boolean {
+ // console.log(event.type)
+
const isDraggable = this.node.type.spec.draggable
const isCopy = event.type === 'copy'
const isPaste = event.type === 'paste'
@@ -108,6 +113,66 @@ class VueNodeView implements NodeView {
return true
}
+ ignoreMutation(mutation: MutationRecord | { type: 'selection'; target: Element }) {
+ // return false
+ // if (mutation.type === 'selection') {
+ // console.log({ mutation })
+ // return true
+ // }
+ // return true
+ // console.log({ mutation })
+
+ if (!this.contentDOM) {
+ return true
+ }
+
+ return !this.contentDOM.contains(mutation.target)
+ }
+
+ update(node: ProseMirrorNode, decorations: Decoration[]) {
+ if (node.type !== this.node.type) {
+ return false
+ }
+
+ if (node === this.node && this.decorations === decorations) {
+ return true
+ }
+
+ this.node = node
+ this.decorations = decorations
+
+ this.updateComponentProps()
+
+ return true
+ }
+
+ updateComponentProps() {
+ this.vm.$props.node = this.node
+ this.vm.$props.decorations = this.decorations
+ }
+
+ updateAttrs(attrs: {}) {
+ if (!this.editor.view.editable) {
+ return
+ }
+
+ const { state } = this.editor.view
+ // const { type } = this.node
+ const pos = this.getPos()
+ const newAttrs = {
+ ...this.node.attrs,
+ ...attrs,
+ }
+ // const transaction = this.isMark
+ // ? state.tr
+ // .removeMark(pos.from, pos.to, type)
+ // .addMark(pos.from, pos.to, type.create(newAttrs))
+ // : state.tr.setNodeMarkup(pos, null, newAttrs)
+ const transaction = state.tr.setNodeMarkup(pos, undefined, newAttrs)
+
+ this.editor.view.dispatch(transaction)
+ }
+
}
export default function VueRenderer(component: Vue | VueConstructor) {