import type { Transformer } from "./types.js"; import katex from "katex"; /** * Renders math placeholders into static KaTeX HTML. * * `@tiptap/extension-mathematics` only produces empty placeholders in its * static `renderHTML` (the actual KaTeX rendering lives in a client-side * NodeView): * - inline: `` * - block: `
` * * `generateHTML()` (used by the publisher) never runs the NodeView, so without * this transformer the published page would contain empty, invisible math * nodes. We render the `data-latex` server-side with `katex.renderToString` * so the published article is fully static (the page already loads the KaTeX * stylesheet; no client-side JS is required). */ const SELECTOR = '[data-type="inline-math"], [data-type="block-math"]'; export const mathTransformer: Transformer = { name: "math", apply(document) { for (const el of [...document.querySelectorAll(SELECTOR)]) { const latex = el.getAttribute("data-latex") || ""; const displayMode = el.getAttribute("data-type") === "block-math"; if (!latex.trim()) { // Nothing to render: drop the empty placeholder so it leaves no // invisible gap in the published article. el.remove(); continue; } // `throwOnError: false` makes KaTeX emit a red error node instead of // throwing, mirroring the editor's behaviour and keeping publish // resilient to a single malformed expression. el.innerHTML = katex.renderToString(latex, { displayMode, throwOnError: false, output: "htmlAndMathml", }); } }, };