@rtdui/editor
Version:
React rich text editor based on tiptap
74 lines (71 loc) • 2.38 kB
JavaScript
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 };