tfrere's picture
tfrere HF Staff
fix(publisher): render math server-side via KaTeX
d062662
Raw
History Blame Contribute Delete
1.7 kB
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: `<span data-type="inline-math" data-latex="...">`
* - block: `<div data-type="block-math" data-latex="...">`
*
* `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",
});
}
},
};