SPB Git

spb/autoscholar

Public
1.3 KB · 37 lines typescript
1import katex from "katex";23/**4 * Renders $…$ / $$…$$ / \( \) / \[ \] segments of a plain-text field (abstracts, findings) to KaTeX HTML.5 * Text outside math is HTML-escaped. Used on the server only; output is trusted markup built from escaped input.6 */7export function renderMath(text: string): { html: string; hasMath: boolean } {8  const esc = (s: string) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");9  const re = /\$\$([\s\S]+?)\$\$|\\\[([\s\S]+?)\\\]|\\\(([\s\S]+?)\\\)|\$([^$\n]+?)\$/g;10  let out = "";11  let last = 0;12  let hasMath = false;13  for (const m of text.matchAll(re)) {14    const idx = m.index ?? 0;15    out += esc(text.slice(last, idx));16    const display = m[1] !== undefined || m[2] !== undefined;17    const src = (m[1] ?? m[2] ?? m[3] ?? m[4] ?? "").trim();18    try {19      const html = katex.renderToString(src, {20        displayMode: display,21        throwOnError: false,22        output: "htmlAndMathml",23        strict: "ignore",24      });25      out += display26        ? `<span class="math-display">${html}</span>`27        : `<span class="math-inline">${html}</span>`;28      hasMath = true;29    } catch {30      out += esc(m[0]);31    }32    last = idx + m[0].length;33  }34  out += esc(text.slice(last));35  return { html: out, hasMath };36}37
Files · main
Menu

Theme