mirror of
https://github.com/docmost/docmost.git
synced 2026-08-15 07:21:37 +10:00
fix: stale placeholder decorations on empty paragraphs (#2374)
This commit is contained in:
@@ -3,7 +3,8 @@ import { StarterKit } from "@tiptap/starter-kit";
|
|||||||
import { Code } from "@tiptap/extension-code";
|
import { Code } from "@tiptap/extension-code";
|
||||||
import { TextAlign } from "@tiptap/extension-text-align";
|
import { TextAlign } from "@tiptap/extension-text-align";
|
||||||
import { TaskList, TaskItem } from "@tiptap/extension-list";
|
import { TaskList, TaskItem } from "@tiptap/extension-list";
|
||||||
import { Placeholder, CharacterCount, UndoRedo } from "@tiptap/extensions";
|
import { CharacterCount, UndoRedo } from "@tiptap/extensions";
|
||||||
|
import { Placeholder } from "@/features/editor/extensions/placeholder";
|
||||||
import { Superscript } from "@tiptap/extension-superscript";
|
import { Superscript } from "@tiptap/extension-superscript";
|
||||||
import SubScript from "@tiptap/extension-subscript";
|
import SubScript from "@tiptap/extension-subscript";
|
||||||
import { Typography } from "@tiptap/extension-typography";
|
import { Typography } from "@tiptap/extension-typography";
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import { isNodeEmpty } from "@tiptap/core";
|
||||||
|
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
||||||
|
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
||||||
|
import { Placeholder as TiptapPlaceholder } from "@tiptap/extensions";
|
||||||
|
|
||||||
|
export const Placeholder = TiptapPlaceholder.extend({
|
||||||
|
addProseMirrorPlugins() {
|
||||||
|
const editor = this.editor;
|
||||||
|
const options = this.options;
|
||||||
|
const dataAttribute = `data-${options.dataAttribute || "placeholder"}`;
|
||||||
|
|
||||||
|
return [
|
||||||
|
new Plugin({
|
||||||
|
key: new PluginKey("docmostPlaceholder"),
|
||||||
|
props: {
|
||||||
|
decorations: (state) => {
|
||||||
|
if (options.showOnlyWhenEditable && !editor.isEditable) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { doc, selection } = state;
|
||||||
|
const { anchor } = selection;
|
||||||
|
const decorations: Decoration[] = [];
|
||||||
|
const isEmptyDoc = editor.isEmpty;
|
||||||
|
|
||||||
|
doc.descendants((node, pos) => {
|
||||||
|
if (!node.type.isTextblock) {
|
||||||
|
return options.includeChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize;
|
||||||
|
const isEmpty = !node.isLeaf && isNodeEmpty(node);
|
||||||
|
|
||||||
|
if ((hasAnchor || !options.showOnlyCurrent) && isEmpty) {
|
||||||
|
const emptyNodeClass =
|
||||||
|
typeof options.emptyNodeClass === "function"
|
||||||
|
? options.emptyNodeClass({ editor, node, pos, hasAnchor })
|
||||||
|
: options.emptyNodeClass;
|
||||||
|
const classes = [emptyNodeClass];
|
||||||
|
if (isEmptyDoc) {
|
||||||
|
classes.push(options.emptyEditorClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
decorations.push(
|
||||||
|
Decoration.node(pos, pos + node.nodeSize, {
|
||||||
|
class: classes.join(" "),
|
||||||
|
[dataAttribute]:
|
||||||
|
typeof options.placeholder === "function"
|
||||||
|
? options.placeholder({ editor, node, pos, hasAnchor })
|
||||||
|
: options.placeholder,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return options.includeChildren;
|
||||||
|
});
|
||||||
|
|
||||||
|
return DecorationSet.create(doc, decorations);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user