Tiptap: Trailing Node extension (#18446)

This commit is contained in:
Lee Kelleher
2025-02-25 14:04:14 +00:00
committed by GitHub
parent 5db67ae6b9
commit 0794ff9bf5
3 changed files with 81 additions and 1 deletions

View File

@@ -0,0 +1,71 @@
/* This Source Code has been derived from Tiptap.
* https://github.com/ueberdosis/tiptap/blob/v2.11.5/demos/src/Experiments/TrailingNode/Vue/trailing-node.ts
* SPDX-License-Identifier: MIT
* Copyright © 2023 Tiptap GmbH.
* Modifications are licensed under the MIT License.
*/
import { Extension } from '@tiptap/core';
import { Plugin, PluginKey } from '@tiptap/pm/state';
// @ts-ignore
function nodeEqualsType({ types, node }) {
return (Array.isArray(types) && types.includes(node.type)) || node.type === types;
}
export interface TrailingNodeOptions {
node: string;
notAfter: string[];
}
export const TrailingNode = Extension.create<TrailingNodeOptions>({
name: 'trailingNode',
addOptions() {
return {
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

@@ -33,6 +33,7 @@ export * from './extensions/tiptap-figcaption.extension.js';
export * from './extensions/tiptap-figure.extension.js';
export * from './extensions/tiptap-span.extension.js';
export * from './extensions/tiptap-html-global-attributes.extension.js';
export * from './extensions/tiptap-trailing-node.extension.js';
export * from './extensions/tiptap-umb-embedded-media.extension.js';
export * from './extensions/tiptap-umb-image.extension.js';
export * from './extensions/tiptap-umb-link.extension.js';

View File

@@ -1,6 +1,13 @@
import { UmbTiptapExtensionApiBase } from '../base.js';
import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api';
import { Div, HtmlGlobalAttributes, Placeholder, Span, StarterKit } from '@umbraco-cms/backoffice/external/tiptap';
import {
Div,
HtmlGlobalAttributes,
Placeholder,
Span,
StarterKit,
TrailingNode,
} from '@umbraco-cms/backoffice/external/tiptap';
export class UmbTiptapRichTextEssentialsExtensionApi extends UmbTiptapExtensionApiBase {
#localize = new UmbLocalizationController(this);
@@ -44,6 +51,7 @@ export class UmbTiptapRichTextEssentialsExtensionApi extends UmbTiptapExtensionA
'umbLink',
],
}),
TrailingNode,
];
}