UNPKG

@rtdui/editor

Version:

React rich text editor based on tiptap

101 lines (98 loc) 3.06 kB
import { KatexBlockPlugin } from "./math-katex-block-plugin.mjs"; import { Node, mergeAttributes, textblockTypeInputRule } from "@tiptap/core"; //#region packages/editor/src/RichTextEditor/tiptap_extensions/extension-math/math-katex-block.ts const mathDollorBlockInputRegex = /^\$\$[\s\n]$/; /** 处理在编辑器中的输入 */ const MathKatexBlock = Node.create({ name: "mathKatexBlock", priority: 1e3, addOptions() { return { exitOnTripleEnter: true, exitOnArrowDown: true, katexOptions: {}, HTMLAttributes: {} }; }, content: "text*", marks: "", group: "block", code: true, defining: true, parseHTML() { return [{ tag: `div[data-type="${this.name}"]`, preserveWhitespace: "full" }]; }, renderHTML({ node, HTMLAttributes }) { return [ "div", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { "data-type": this.name }), 0 ]; }, addCommands() { return { setMathBlock: (attributes) => ({ commands }) => { return commands.setNode(this.name, attributes); }, toggleMathBlock: (attributes) => ({ commands }) => { return commands.toggleNode(this.name, "paragraph", attributes); } }; }, addKeyboardShortcuts() { return { "Mod-Alt-m": () => this.editor.commands.toggleMathBlock(), Backspace: () => { const { empty, $anchor } = this.editor.state.selection; const isAtStart = $anchor.pos === 1; if (!empty || $anchor.parent.type.name !== this.name) return false; if (isAtStart || !$anchor.parent.textContent.length) return this.editor.commands.clearNodes(); return false; }, Enter: ({ editor }) => { if (!this.options.exitOnTripleEnter) return false; const { state } = editor; const { selection } = state; const { $from, empty } = selection; if (!empty || $from.parent.type !== this.type) return false; const isAtEnd = $from.parentOffset === $from.parent.nodeSize - 2; const endsWithDoubleNewline = $from.parent.textContent.endsWith("\n\n"); if (!isAtEnd || !endsWithDoubleNewline) return false; return editor.chain().command(({ tr }) => { tr.delete($from.pos - 2, $from.pos); return true; }).exitCode().run(); }, ArrowDown: ({ editor }) => { if (!this.options.exitOnArrowDown) return false; const { state } = editor; const { selection, doc } = state; const { $from, empty } = selection; if (!empty || $from.parent.type !== this.type) return false; if (!($from.parentOffset === $from.parent.nodeSize - 2)) return false; const after = $from.after(); if (after === void 0) return false; if (doc.nodeAt(after)) return false; return editor.commands.exitCode(); } }; }, addInputRules() { return [textblockTypeInputRule({ find: mathDollorBlockInputRegex, type: this.type })]; }, addProseMirrorPlugins() { return [...this.parent?.() || [], KatexBlockPlugin({ editor: this.editor, name: this.name, katexOptions: this.options.katexOptions })]; } }); //#endregion export { MathKatexBlock, mathDollorBlockInputRegex };