add GuideNodeViews demos

This commit is contained in:
Philipp Kühn 2021-08-25 18:32:54 +02:00
parent b1a87e4ad6
commit 8a5a491d8e
32 changed files with 1264 additions and 0 deletions

View File

@ -0,0 +1,56 @@
<template>
<node-view-wrapper class="draggable-item">
<div
class="drag-handle"
contenteditable="false"
draggable="true"
data-drag-handle
/>
<node-view-content class="content" />
</node-view-wrapper>
</template>
<script>
import { NodeViewWrapper, NodeViewContent, nodeViewProps } from '@tiptap/vue-3'
export default {
props: nodeViewProps,
components: {
NodeViewWrapper,
NodeViewContent,
},
}
</script>
<style lang="scss">
.draggable-item {
display: flex;
padding: 0.5rem;
margin: 0.5rem 0;
border-radius: 0.5rem;
background: white;
box-shadow:
0 0 0 1px rgba(0, 0, 0, 0.1),
0px 10px 20px rgba(0, 0, 0, 0.1),
;
.drag-handle {
flex: 0 0 auto;
position: relative;
width: 1rem;
height: 1rem;
top: 0.3rem;
margin-right: 0.5rem;
cursor: grab;
background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 16"><path fill-opacity="0.2" d="M4 14c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zM2 6C.9 6 0 6.9 0 8s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6C.9 0 0 .9 0 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" /></svg>');
background-repeat: no-repeat;
background-size: contain;
background-position: center;
}
.content {
flex: 1 1 auto;
}
}
</style>

View File

@ -0,0 +1,29 @@
import { Node, mergeAttributes } from '@tiptap/core'
import { VueNodeViewRenderer } from '@tiptap/vue-3'
import Component from './Component.vue'
export default Node.create({
name: 'draggableItem',
group: 'block',
content: 'block+',
draggable: true,
parseHTML() {
return [
{
tag: 'div[data-type="draggable-item"]',
},
]
},
renderHTML({ HTMLAttributes }) {
return ['div', mergeAttributes(HTMLAttributes, { 'data-type': 'draggable-item' }), 0]
},
addNodeView() {
return VueNodeViewRenderer(Component)
},
})

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
<div id="app"></div>
<script type="module">
import setup from '../../../../setup/vue.ts'
import source from '@source'
setup('GuideNodeViews/DragHandle', source)
</script>
</body>
</html>

View File

@ -0,0 +1,52 @@
<template>
<div v-if="editor">
<editor-content :editor="editor" />
</div>
</template>
<script>
import { Editor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
import DraggableItem from './DraggableItem.js'
export default {
components: {
EditorContent,
},
data() {
return {
editor: null,
}
},
mounted() {
this.editor = new Editor({
extensions: [
StarterKit,
DraggableItem,
],
content: `
<p>This is a boring paragraph.</p>
<div data-type="draggable-item">
<p>Followed by a fancy draggable item.</p>
</div>
<div data-type="draggable-item">
<p>And another draggable item.</p>
<div data-type="draggable-item">
<p>And a nested one.</p>
<div data-type="draggable-item">
<p>But can we go deeper?</p>
</div>
</div>
</div>
<p>Lets finish with a boring paragraph.</p>
`,
})
},
beforeDestroy() {
this.editor.destroy()
},
}
</script>

View File

@ -0,0 +1,77 @@
import { Node, mergeAttributes } from '@tiptap/core'
export default Node.create({
name: 'nodeView',
group: 'block',
atom: true,
addAttributes() {
return {
count: {
default: 0,
},
}
},
parseHTML() {
return [
{
tag: 'node-view',
},
]
},
renderHTML({ HTMLAttributes }) {
return ['node-view', mergeAttributes(HTMLAttributes)]
},
addNodeView() {
return ({ editor, node, getPos }) => {
const { view } = editor
// Markup
/*
<div class="node-view">
<span class="label">Node view</span>
<div class="content">
<button>
This button has been clicked ${node.attrs.count} times.
</button>
</div>
</div>
*/
const dom = document.createElement('div')
dom.classList.add('node-view')
const label = document.createElement('span')
label.classList.add('label')
label.innerHTML = 'Node view'
const content = document.createElement('div')
content.classList.add('content')
const button = document.createElement('button')
button.innerHTML = `This button has been clicked ${node.attrs.count} times.`
button.addEventListener('click', () => {
if (typeof getPos === 'function') {
view.dispatch(view.state.tr.setNodeMarkup(getPos(), undefined, {
count: node.attrs.count + 1,
}))
editor.commands.focus()
}
})
content.append(button)
dom.append(label, content)
return {
dom,
}
}
},
})

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
<div id="app"></div>
<script type="module">
import setup from '../../../../setup/vue.ts'
import source from '@source'
setup('GuideNodeViews/JavaScript', source)
</script>
</body>
</html>

View File

@ -0,0 +1,79 @@
<template>
<editor-content :editor="editor" />
</template>
<script>
import { Editor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
import NodeView from './Extension.js'
export default {
components: {
EditorContent,
},
data() {
return {
editor: null,
}
},
mounted() {
this.editor = new Editor({
extensions: [
StarterKit,
NodeView,
],
content: `
<p>
This is still the text editor youre used to, but enriched with node views.
</p>
<node-view></node-view>
<p>
Did you see that? Thats a JavaScript node view. We are really living in the future.
</p>
`,
})
},
beforeDestroy() {
this.editor.destroy()
},
}
</script>
<style lang="scss">
/* Basic editor styles */
.ProseMirror {
> * + * {
margin-top: 0.75em;
}
}
.node-view {
background: #FAF594;
border: 3px solid #0D0D0D;
border-radius: 0.5rem;
margin: 1rem 0;
position: relative;
}
.label {
margin-left: 1rem;
background-color: #0D0D0D;
font-size: 0.6rem;
letter-spacing: 1px;
font-weight: bold;
text-transform: uppercase;
color: #fff;
position: absolute;
top: 0;
padding: 0.25rem 0.75rem;
border-radius: 0 0 0.5rem 0.5rem;
}
.content {
margin-top: 1.5rem;
padding: 1rem;
}
</style>

View File

@ -0,0 +1,52 @@
import { Node, mergeAttributes } from '@tiptap/core'
export default Node.create({
name: 'nodeView',
group: 'block',
content: 'inline*',
parseHTML() {
return [
{
tag: 'node-view',
},
]
},
renderHTML({ HTMLAttributes }) {
return ['node-view', mergeAttributes(HTMLAttributes), 0]
},
addNodeView() {
return () => {
// Markup
/*
<div class="node-view">
<span class="label">Node view</span>
<div class="content"></div>
</div>
*/
const dom = document.createElement('div')
dom.classList.add('node-view')
const label = document.createElement('span')
label.classList.add('label')
label.innerHTML = 'Node view'
label.contentEditable = false
const content = document.createElement('div')
content.classList.add('content')
dom.append(label, content)
return {
dom,
contentDOM: content,
}
}
},
})

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
<div id="app"></div>
<script type="module">
import setup from '../../../../setup/vue.ts'
import source from '@source'
setup('GuideNodeViews/JavaScriptContent', source)
</script>
</body>
</html>

View File

@ -0,0 +1,83 @@
<template>
<editor-content :editor="editor" />
</template>
<script>
import { Editor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
import NodeView from './Extension.js'
export default {
components: {
EditorContent,
},
data() {
return {
editor: null,
}
},
mounted() {
this.editor = new Editor({
extensions: [
StarterKit,
NodeView,
],
content: `
<p>
This is still the text editor youre used to, but enriched with node views.
</p>
<node-view>
<p>This is editable.</p>
</node-view>
<p>
Did you see that? Thats a JavaScript node view. We are really living in the future.
</p>
`,
})
},
beforeDestroy() {
this.editor.destroy()
},
}
</script>
<style lang="scss">
/* Basic editor styles */
.ProseMirror {
> * + * {
margin-top: 0.75em;
}
}
.node-view {
background: #FAF594;
border: 3px solid #0D0D0D;
border-radius: 0.5rem;
margin: 1rem 0;
position: relative;
}
.label {
margin-left: 1rem;
background-color: #0D0D0D;
font-size: 0.6rem;
letter-spacing: 1px;
font-weight: bold;
text-transform: uppercase;
color: #fff;
position: absolute;
top: 0;
padding: 0.25rem 0.75rem;
border-radius: 0 0 0.5rem 0.5rem;
}
.content {
margin: 2.5rem 1rem 1rem;
padding: 0.5rem;
border: 2px dashed #0D0D0D20;
border-radius: 0.5rem;
}
</style>

View File

@ -0,0 +1,22 @@
import React from 'react'
import { NodeViewWrapper } from '@tiptap/react'
export default props => {
const increase = () => {
props.updateAttributes({
count: props.node.attrs.count + 1,
})
}
return (
<NodeViewWrapper className="react-component">
<span className="label">React Component</span>
<div className="content">
<button onClick={increase}>
This button has been clicked {props.node.attrs.count} times.
</button>
</div>
</NodeViewWrapper>
)
}

View File

@ -0,0 +1,35 @@
import { Node, mergeAttributes } from '@tiptap/core'
import { ReactNodeViewRenderer } from '@tiptap/react'
import Component from './Component.jsx'
export default Node.create({
name: 'reactComponent',
group: 'block',
atom: true,
addAttributes() {
return {
count: {
default: 0,
},
}
},
parseHTML() {
return [
{
tag: 'react-component',
},
]
},
renderHTML({ HTMLAttributes }) {
return ['react-component', mergeAttributes(HTMLAttributes)]
},
addNodeView() {
return ReactNodeViewRenderer(Component)
},
})

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
<div id="app"></div>
<script type="module">
import setup from '../../../../setup/react.tsx'
import source from '@source'
setup('GuideNodeViews/ReactComponent', source)
</script>
</body>
</html>

View File

@ -0,0 +1,27 @@
import React from 'react'
import { useEditor, EditorContent } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import ReactComponent from './Extension.js'
import './styles.scss'
export default () => {
const editor = useEditor({
extensions: [
StarterKit,
ReactComponent,
],
content: `
<p>
This is still the text editor youre used to, but enriched with node views.
</p>
<react-component count="0"></react-component>
<p>
Did you see that? Thats a React component. We are really living in the future.
</p>
`,
})
return (
<EditorContent editor={editor} />
)
}

View File

@ -0,0 +1,33 @@
/* Basic editor styles */
.ProseMirror {
> * + * {
margin-top: 0.75em;
}
}
.react-component {
background: #FAF594;
border: 3px solid #0D0D0D;
border-radius: 0.5rem;
margin: 1rem 0;
position: relative;
.label {
margin-left: 1rem;
background-color: #0D0D0D;
font-size: 0.6rem;
letter-spacing: 1px;
font-weight: bold;
text-transform: uppercase;
color: #fff;
position: absolute;
top: 0;
padding: 0.25rem 0.75rem;
border-radius: 0 0 0.5rem 0.5rem;
}
.content {
margin-top: 1.5rem;
padding: 1rem;
}
}

View File

@ -0,0 +1,12 @@
import React from 'react'
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react'
export default () => {
return (
<NodeViewWrapper className="react-component-with-content">
<span className="label" contentEditable={false}>React Component</span>
<NodeViewContent className="content" />
</NodeViewWrapper>
)
}

View File

@ -0,0 +1,27 @@
import { Node, mergeAttributes } from '@tiptap/core'
import { ReactNodeViewRenderer } from '@tiptap/react'
import Component from './Component.jsx'
export default Node.create({
name: 'reactComponent',
group: 'block',
content: 'inline*',
parseHTML() {
return [
{
tag: 'react-component',
},
]
},
renderHTML({ HTMLAttributes }) {
return ['react-component', mergeAttributes(HTMLAttributes), 0]
},
addNodeView() {
return ReactNodeViewRenderer(Component)
},
})

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
<div id="app"></div>
<script type="module">
import setup from '../../../../setup/react.tsx'
import source from '@source'
setup('GuideNodeViews/ReactComponentContent', source)
</script>
</body>
</html>

View File

@ -0,0 +1,29 @@
import React from 'react'
import { useEditor, EditorContent } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import ReactComponent from './Extension.js'
import './styles.scss'
export default () => {
const editor = useEditor({
extensions: [
StarterKit,
ReactComponent,
],
content: `
<p>
This is still the text editor youre used to, but enriched with node views.
</p>
<react-component>
<p>This is editable.</p>
</react-component>
<p>
Did you see that? Thats a React component. We are really living in the future.
</p>
`,
})
return (
<EditorContent editor={editor} />
)
}

View File

@ -0,0 +1,36 @@
/* Basic editor styles */
.ProseMirror {
> * + * {
margin-top: 0.75em;
}
}
.react-component-with-content {
background: #FAF594;
border: 3px solid #0D0D0D;
border-radius: 0.5rem;
margin: 1rem 0;
position: relative;
.label {
margin-left: 1rem;
background-color: #0D0D0D;
font-size: 0.6rem;
letter-spacing: 1px;
font-weight: bold;
text-transform: uppercase;
color: #fff;
position: absolute;
top: 0;
padding: 0.25rem 0.75rem;
border-radius: 0 0 0.5rem 0.5rem;
}
.content {
margin: 2.5rem 1rem 1rem;
padding: 0.5rem;
border: 2px dashed #0D0D0D20;
border-radius: 0.5rem;
}
}

View File

@ -0,0 +1,126 @@
<template>
<node-view-wrapper class="toc">
<ul class="toc__list">
<li
class="toc__item"
:class="`toc__item--${heading.level}`"
v-for="(heading, index) in headings"
:key="index"
>
<a :href="`#${heading.id}`">
{{ heading.text }}
</a>
</li>
</ul>
</node-view-wrapper>
</template>
<script>
import { NodeViewWrapper, nodeViewProps } from '@tiptap/vue-3'
export default {
components: {
NodeViewWrapper,
},
props: nodeViewProps,
data() {
return {
headings: [],
}
},
methods: {
handleUpdate() {
const headings = []
const transaction = this.editor.state.tr
this.editor.state.doc.descendants((node, pos) => {
if (node.type.name === 'heading') {
const id = `heading-${headings.length + 1}`
if (node.attrs.id !== id) {
transaction.setNodeMarkup(pos, undefined, {
...node.attrs,
id,
})
}
headings.push({
level: node.attrs.level,
text: node.textContent,
id,
})
}
})
transaction.setMeta('preventUpdate', true)
this.editor.view.dispatch(transaction)
this.headings = headings
},
},
mounted() {
this.editor.on('update', this.handleUpdate)
this.$nextTick(this.handleUpdate)
},
}
</script>
<style lang="scss">
/* Basic editor styles */
.ProseMirror {
> * + * {
margin-top: 0.75em;
}
}
</style>
<style lang="scss">
.toc {
opacity: 0.75;
border-radius: 0.5rem;
padding: 0.75rem;
background: rgba(black, 0.1);
&__list {
list-style: none;
padding: 0;
&::before {
display: block;
content: "Table of Contents";
font-weight: 700;
letter-spacing: 0.025rem;
font-size: 0.75rem;
text-transform: uppercase;
opacity: 0.5;
}
}
&__item {
a:hover {
opacity: 0.5;
}
&--3 {
padding-left: 1rem;
}
&--4 {
padding-left: 2rem;
}
&--5 {
padding-left: 3rem;
}
&--6 {
padding-left: 4rem;
}
}
}
</style>

View File

@ -0,0 +1,42 @@
import { Node, mergeAttributes } from '@tiptap/core'
import { VueNodeViewRenderer } from '@tiptap/vue-3'
import Component from './Component.vue'
export default Node.create({
name: 'tableOfContents',
group: 'block',
atom: true,
parseHTML() {
return [
{
tag: 'toc',
},
]
},
renderHTML({ HTMLAttributes }) {
return ['toc', mergeAttributes(HTMLAttributes)]
},
addNodeView() {
return VueNodeViewRenderer(Component)
},
addGlobalAttributes() {
return [
{
types: [
'heading',
],
attributes: {
id: {
default: null,
},
},
},
]
},
})

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
<div id="app"></div>
<script type="module">
import setup from '../../../../setup/vue.ts'
import source from '@source'
setup('GuideNodeViews/TableOfContents', source)
</script>
</body>
</html>

View File

@ -0,0 +1,49 @@
<template>
<div v-if="editor">
<editor-content :editor="editor" />
</div>
</template>
<script>
import { Editor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
import TableOfContents from './TableOfContents.js'
export default {
components: {
EditorContent,
},
data() {
return {
editor: null,
}
},
mounted() {
this.editor = new Editor({
extensions: [
StarterKit,
TableOfContents,
],
content: `
<toc></toc>
<h2>1 heading</h2>
<p>paragraph</p>
<h3>1.1 heading</h3>
<p>paragraph</p>
<h3>1.2 heading</h3>
<p>paragraph</p>
<h2>2 heading</h2>
<p>paragraph</p>
<h3>2.1 heading</h3>
<p>paragraph</p>
`,
})
},
beforeDestroy() {
this.editor.destroy()
},
}
</script>

View File

@ -0,0 +1,60 @@
<template>
<node-view-wrapper class="vue-component">
<span class="label">Vue Component</span>
<div class="content">
<button @click="increase">
This button has been clicked {{ node.attrs.count }} times.
</button>
</div>
</node-view-wrapper>
</template>
<script>
import { NodeViewWrapper, nodeViewProps } from '@tiptap/vue-3'
export default {
components: {
NodeViewWrapper,
},
props: nodeViewProps,
methods: {
increase() {
this.updateAttributes({
count: this.node.attrs.count + 1,
})
},
},
}
</script>
<style lang="scss">
.vue-component {
background: #FAF594;
border: 3px solid #0D0D0D;
border-radius: 0.5rem;
margin: 1rem 0;
position: relative;
}
.label {
margin-left: 1rem;
background-color: #0D0D0D;
font-size: 0.6rem;
letter-spacing: 1px;
font-weight: bold;
text-transform: uppercase;
color: #fff;
position: absolute;
top: 0;
padding: 0.25rem 0.75rem;
border-radius: 0 0 0.5rem 0.5rem;
}
.content {
margin-top: 1.5rem;
padding: 1rem;
}
</style>

View File

@ -0,0 +1,35 @@
import { Node, mergeAttributes } from '@tiptap/core'
import { VueNodeViewRenderer } from '@tiptap/vue-3'
import Component from './Component.vue'
export default Node.create({
name: 'vueComponent',
group: 'block',
atom: true,
addAttributes() {
return {
count: {
default: 0,
},
}
},
parseHTML() {
return [
{
tag: 'vue-component',
},
]
},
renderHTML({ HTMLAttributes }) {
return ['vue-component', mergeAttributes(HTMLAttributes)]
},
addNodeView() {
return VueNodeViewRenderer(Component)
},
})

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
<div id="app"></div>
<script type="module">
import setup from '../../../../setup/vue.ts'
import source from '@source'
setup('GuideNodeViews/VueComponent', source)
</script>
</body>
</html>

View File

@ -0,0 +1,52 @@
<template>
<editor-content :editor="editor" />
</template>
<script>
import { Editor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
import VueComponent from './Extension.js'
export default {
components: {
EditorContent,
},
data() {
return {
editor: null,
}
},
mounted() {
this.editor = new Editor({
extensions: [
StarterKit,
VueComponent,
],
content: `
<p>
This is still the text editor youre used to, but enriched with node views.
</p>
<vue-component count="0"></vue-component>
<p>
Did you see that? Thats a Vue component. We are really living in the future.
</p>
`,
})
},
beforeDestroy() {
this.editor.destroy()
},
}
</script>
<style lang="scss">
/* Basic editor styles */
.ProseMirror {
> * + * {
margin-top: 0.75em;
}
}
</style>

View File

@ -0,0 +1,50 @@
<template>
<node-view-wrapper class="vue-component">
<span class="label" contenteditable="false">Vue Component</span>
<node-view-content class="content" />
</node-view-wrapper>
</template>
<script>
import { NodeViewWrapper, NodeViewContent, nodeViewProps } from '@tiptap/vue-3'
export default {
components: {
NodeViewWrapper,
NodeViewContent,
},
props: nodeViewProps,
}
</script>
<style lang="scss">
.vue-component {
background: #FAF594;
border: 3px solid #0D0D0D;
border-radius: 0.5rem;
margin: 1rem 0;
position: relative;
}
.label {
margin-left: 1rem;
background-color: #0D0D0D;
font-size: 0.6rem;
letter-spacing: 1px;
font-weight: bold;
text-transform: uppercase;
color: #fff;
position: absolute;
top: 0;
padding: 0.25rem 0.75rem;
border-radius: 0 0 0.5rem 0.5rem;
}
.content {
margin: 2.5rem 1rem 1rem;
padding: 0.5rem;
border: 2px dashed #0D0D0D20;
border-radius: 0.5rem;
}
</style>

View File

@ -0,0 +1,27 @@
import { Node, mergeAttributes } from '@tiptap/core'
import { VueNodeViewRenderer } from '@tiptap/vue-3'
import Component from './Component.vue'
export default Node.create({
name: 'vueComponent',
group: 'block',
content: 'inline*',
parseHTML() {
return [
{
tag: 'vue-component',
},
]
},
renderHTML({ HTMLAttributes }) {
return ['vue-component', mergeAttributes(HTMLAttributes), 0]
},
addNodeView() {
return VueNodeViewRenderer(Component)
},
})

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
<div id="app"></div>
<script type="module">
import setup from '../../../../setup/vue.ts'
import source from '@source'
setup('GuideNodeViews/VueComponentContent', source)
</script>
</body>
</html>

View File

@ -0,0 +1,54 @@
<template>
<editor-content :editor="editor" />
</template>
<script>
import { Editor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
import VueComponent from './Extension.js'
export default {
components: {
EditorContent,
},
data() {
return {
editor: null,
}
},
mounted() {
this.editor = new Editor({
extensions: [
StarterKit,
VueComponent,
],
content: `
<p>
This is still the text editor youre used to, but enriched with node views.
</p>
<vue-component>
<p>This is editable.</p>
</vue-component>
<p>
Did you see that? Thats a Vue component. We are really living in the future.
</p>
`,
})
},
beforeDestroy() {
this.editor.destroy()
},
}
</script>
<style lang="scss">
/* Basic editor styles */
.ProseMirror {
> * + * {
margin-top: 0.75em;
}
}
</style>