add a trailing node example

This commit is contained in:
Hans Pagel 2021-04-23 21:58:05 +02:00
parent 52567c0f65
commit 181a54fb83
4 changed files with 139 additions and 0 deletions

View File

@ -0,0 +1,65 @@
<template>
<div v-if="editor">
<editor-content :editor="editor" />
</div>
</template>
<script>
import { Editor, EditorContent } from '@tiptap/vue-2'
import { defaultExtensions } from '@tiptap/starter-kit'
import { TrailingNode } from './trailing-node'
export default {
components: {
EditorContent,
},
data() {
return {
editor: null,
}
},
mounted() {
this.editor = new Editor({
extensions: [
...defaultExtensions(),
TrailingNode,
],
content: `
<p>Example text</p>
<pre><code>console.log('foo')</code></pre>
`,
})
},
beforeDestroy() {
this.editor.destroy()
},
}
</script>
<style lang="scss" scoped>
::v-deep {
.ProseMirror {
> * + * {
margin-top: 0.75em;
}
pre {
background: #0D0D0D;
color: #FFF;
font-family: 'JetBrainsMono', monospace;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
code {
color: inherit;
padding: 0;
background: none;
font-size: 0.8rem;
}
}
}
}
</style>

View File

@ -0,0 +1,68 @@
import { Extension } from '@tiptap/core'
import { PluginKey, Plugin } from 'prosemirror-state'
// @ts-ignore
function nodeEqualsType({ types, node }) {
return (Array.isArray(types) && types.includes(node.type)) || node.type === types
}
/**
* Extension based on:
* - https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap-extensions/src/extensions/TrailingNode.js
* - https://github.com/remirror/remirror/blob/e0f1bec4a1e8073ce8f5500d62193e52321155b9/packages/prosemirror-trailing-node/src/trailing-node-plugin.ts
*/
export interface TrailingNodeOptions {
node: string,
notAfter: string[],
}
export const TrailingNode = Extension.create<TrailingNodeOptions>({
name: 'trailingNode',
defaultOptions: {
node: 'paragraph',
notAfter: [
'paragraph',
],
},
addProseMirrorPlugins() {
const plugin = new PluginKey(this.name)
const disabledNodes = Object.entries(this.editor.schema.nodes)
.map(([, value]) => value)
.filter(node => this.options.notAfter.includes(node.name))
return [
new Plugin({
key: plugin,
appendTransaction: (_, __, state) => {
const { doc, tr, schema } = state
const shouldInsertNodeAtEnd = plugin.getState(state)
const endPosition = doc.content.size
const type = schema.nodes[this.options.node]
if (!shouldInsertNodeAtEnd) {
return
}
return tr.insert(endPosition, type.create())
},
state: {
init: (_, state) => {
const lastNode = state.tr.doc.lastChild
return !nodeEqualsType({ node: lastNode, types: disabledNodes })
},
apply: (tr, value) => {
if (!tr.docChanged) {
return value
}
const lastNode = tr.doc.lastChild
return !nodeEqualsType({ node: lastNode, types: disabledNodes })
},
},
}),
]
},
})

View File

@ -10,3 +10,4 @@ Congratulations! Youve found our playground with a list of experiments. Be aw
* [@tiptap/extension-toggle-list?](/experiments/details)
* [@tiptap/extension-collaboration-annotation](/experiments/collaboration-annotation)
* [@tiptap/extension-word-break](/experiments/word-break)
* [@tiptap/extension-trailing-node](/experiments/trailing-node)

View File

@ -0,0 +1,5 @@
# Trailing node
⚠️ Experiment
<demo name="Experiments/TrailingNode" />