From 181a54fb8355702c95f0237f863efad4f9b15bee Mon Sep 17 00:00:00 2001 From: Hans Pagel Date: Fri, 23 Apr 2021 21:58:05 +0200 Subject: [PATCH] add a trailing node example --- .../demos/Experiments/TrailingNode/index.vue | 65 ++++++++++++++++++ .../Experiments/TrailingNode/trailing-node.ts | 68 +++++++++++++++++++ docs/src/docPages/experiments.md | 1 + .../src/docPages/experiments/trailing-node.md | 5 ++ 4 files changed, 139 insertions(+) create mode 100644 docs/src/demos/Experiments/TrailingNode/index.vue create mode 100644 docs/src/demos/Experiments/TrailingNode/trailing-node.ts create mode 100644 docs/src/docPages/experiments/trailing-node.md diff --git a/docs/src/demos/Experiments/TrailingNode/index.vue b/docs/src/demos/Experiments/TrailingNode/index.vue new file mode 100644 index 000000000..b818885a1 --- /dev/null +++ b/docs/src/demos/Experiments/TrailingNode/index.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/docs/src/demos/Experiments/TrailingNode/trailing-node.ts b/docs/src/demos/Experiments/TrailingNode/trailing-node.ts new file mode 100644 index 000000000..e2c47c09b --- /dev/null +++ b/docs/src/demos/Experiments/TrailingNode/trailing-node.ts @@ -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({ + 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 }) + }, + }, + }), + ] + }, +}) diff --git a/docs/src/docPages/experiments.md b/docs/src/docPages/experiments.md index 33957c718..41e29d5d6 100644 --- a/docs/src/docPages/experiments.md +++ b/docs/src/docPages/experiments.md @@ -10,3 +10,4 @@ Congratulations! You’ve 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) diff --git a/docs/src/docPages/experiments/trailing-node.md b/docs/src/docPages/experiments/trailing-node.md new file mode 100644 index 000000000..36c25ea52 --- /dev/null +++ b/docs/src/docPages/experiments/trailing-node.md @@ -0,0 +1,5 @@ +# Trailing node + +⚠️ Experiment + +