UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

128 lines (127 loc) 3.78 kB
// src/components/RichEditor/components/MathNode.tsx import { Node, mergeAttributes } from "@tiptap/core"; import { ReactNodeViewRenderer, NodeViewWrapper } from "@tiptap/react"; import katex from "katex"; import { useMemo } from "react"; import { jsx } from "react/jsx-runtime"; function MathNodeView({ node, editor, getPos }) { const latex = typeof node.attrs.latex === "string" ? node.attrs.latex : ""; const renderedHtml = useMemo(() => { try { return katex.renderToString(latex, { throwOnError: false, displayMode: false }); } catch { return `<span class="text-error-600">${latex}</span>`; } }, [latex]); const handleClick = () => { const pos = getPos(); if (typeof pos !== "number" || !Number.isFinite(pos)) return; editor.chain().focus().deleteRange({ from: pos, to: pos + node.nodeSize }).insertContent(`$${latex}$`).run(); const docSize = editor.state.doc.content.size; const newPos = Math.min(Math.max(pos + latex.length + 1, 0), docSize); editor.commands.setTextSelection(newPos); }; return /* @__PURE__ */ jsx( NodeViewWrapper, { as: "span", className: "inline-math cursor-pointer hover:bg-primary-50 rounded px-0.5 transition-colors", onClick: handleClick, title: "Clique para editar", children: /* @__PURE__ */ jsx( "span", { dangerouslySetInnerHTML: { __html: renderedHtml }, className: "inline" } ) } ); } var MathNode = Node.create({ name: "mathInline", group: "inline", inline: true, atom: true, selectable: true, addAttributes() { return { latex: { default: "" } }; }, parseHTML() { return [ { tag: 'span[data-type="math-inline"]', getAttrs: (dom) => { return { latex: dom.dataset.latex ?? "" }; } } ]; }, renderHTML({ node, HTMLAttributes }) { return [ "span", mergeAttributes(HTMLAttributes, { "data-type": "math-inline", "data-latex": node.attrs.latex }) ]; }, addNodeView() { return ReactNodeViewRenderer(MathNodeView); }, // Disable default input rules addInputRules() { return []; }, addKeyboardShortcuts() { return { // When space is pressed after closing $, convert to math node Space: ({ editor }) => { const { state } = editor; const { selection } = state; const { $from } = selection; const textBefore = $from.parent.textBetween( Math.max(0, $from.parentOffset - 200), $from.parentOffset, "\n" ); const regex = /\$([^$]+)\$$/; const match = regex.exec(textBefore); if (match?.[1]?.trim()) { const latex = match[1]; const matchStart = $from.pos - match[0].length; editor.chain().deleteRange({ from: matchStart, to: $from.pos }).insertContent([ { type: "mathInline", attrs: { latex } }, { type: "text", text: " " } ]).run(); return true; } return false; }, // When backspace is pressed on a math node, convert it back to text for editing Backspace: ({ editor }) => { const { selection } = editor.state; const { $from } = selection; const nodeBefore = $from.nodeBefore; if (nodeBefore?.type.name === "mathInline") { const pos = $from.pos - nodeBefore.nodeSize; const latex = nodeBefore.attrs.latex; editor.chain().deleteRange({ from: pos, to: $from.pos }).insertContent(`$${latex}`).run(); return true; } return false; } }; } }); export { MathNode }; //# sourceMappingURL=chunk-NVNYYFHH.mjs.map