UNPKG

@rtdui/editor

Version:

React rich text editor based on tiptap

74 lines (71 loc) 2.38 kB
import { findChildren } from "@tiptap/core"; import katex from "katex"; import { Plugin, PluginKey } from "prosemirror-state"; import { Decoration, DecorationSet } from "prosemirror-view"; //#region packages/editor/src/RichTextEditor/tiptap_extensions/extension-math/math-katex-inline-plugin.ts function getDecorations({ editor, doc, name, katexOptions, selection }) { const decorations = []; const texts = []; findChildren(doc, (node) => node.type.name === "paragraph").forEach((block) => { const pos = block.pos + 1; texts.push({ pos, text: block.node.textContent }); }); texts.forEach((txt) => { if (txt.text) { const inlineMatchs = txt.text.matchAll(/\$([^$]+)\$/g); for (const match of inlineMatchs) { if (!match[1]) continue; match[1] = match[1].replace(/\s\\\s/g, " \\\\ "); const mathStart = txt.pos + (match.index ?? 0); const mathEnd = txt.pos + (match.index ?? 0) + match[0].length; if (selection.$anchor.pos < mathStart || selection.$anchor.pos > mathEnd || !editor.isEditable) { const mathRender = document.createElement("span"); mathRender.classList.add("tiptap-math-render"); katex.render(match[1], mathRender, { output: "html" }); const decoration = Decoration.widget(mathStart, mathRender); decorations.push(decoration); const decoration2 = Decoration.inline(mathStart, mathEnd, { class: "titap-math-source hidden" }); decorations.push(decoration2); } else if (editor.isEditable) { const decoration3 = Decoration.inline(mathStart, mathEnd, { class: "titap-math-source" }); decorations.push(decoration3); } } } }); return DecorationSet.create(doc, decorations); } /** 处理粘贴的数学公式 */ function KatexInlinePlugin({ editor, name, katexOptions }) { const katexInlinePlugin = new Plugin({ key: new PluginKey("mathKatex"), state: { init: (_, { doc, selection }) => getDecorations({ editor, doc, name, katexOptions, selection }), apply: (transaction, decorationSet, oldState, newState) => { const { selection } = newState; return getDecorations({ editor, doc: transaction.doc, name, katexOptions, selection }); } }, props: { decorations(state) { return katexInlinePlugin.getState(state); } } }); return katexInlinePlugin; } //#endregion export { KatexInlinePlugin };