@blocknote/core
Version:
A "Notion-style" block-based extensible text editor built on top of Prosemirror and Tiptap.
44 lines (41 loc) • 1.89 kB
text/typescript
import { Editor, getExtensionField } from "@tiptap/core";
/**
* The mark schema group shared by every "suggestion" mark — both the Yjs
* collaboration marks (`y-attributed-*`) and the AI marks (`insertion` /
* `deletion` / `modification`). A mark opts into being allowed on block nodes by
* declaring this group in its spec (`group: BLOCK_LEVEL_SUGGESTION_GROUP`).
*/
export const BLOCK_LEVEL_SUGGESTION_GROUP = "blockLevelSuggestion";
/**
* Block node specs (blockContainer, blockGroup, doc, table cells, columns...)
* allow the suggestion marks so that a whole block can be marked inserted /
* deleted / modified in suggestion mode.
*
* These marks only exist when the extension that provides them is loaded; a node
* spec that referenced them unconditionally would make ProseMirror throw
* "Unknown mark type" while building the schema of an editor that doesn't have
* them (e.g. a plain, non-collaborative, non-AI editor) — this applies to a mark
* group with no members too.
*
* Use this as a node's `marks` field: it returns the {@link
* BLOCK_LEVEL_SUGGESTION_GROUP} group name (which ProseMirror expands to every
* mark in the group) when at least one such mark is registered on the editor, or
* `""` otherwise. It's evaluated at schema-build time, where the tiptap editor's
* fully-flattened extension list is available on `this.editor`.
*/
export function suggestionMarks(editor: Editor | undefined): string {
if (!editor) {
return "";
}
const hasAttributionMark = editor.options.extensions.some((extension) => {
if (extension.type !== "mark") {
return false;
}
const group = getExtensionField(extension, "group") as string | undefined;
return (
typeof group === "string" &&
group.split(" ").includes(BLOCK_LEVEL_SUGGESTION_GROUP)
);
});
return hasAttributionMark ? BLOCK_LEVEL_SUGGESTION_GROUP : "";
}