import MathJax from "mathjax"; import process from "node:process"; const MAX_MESSAGE_LENGTH = 500; function errorMessage(error) { const message = error && typeof error.message === "string" ? error.message : String(error); return message.slice(0, MAX_MESSAGE_LENGTH); } function renderError(serialized) { const match = serialized.match(/data-mjx-error="([^"]+)"/); return match ? match[1].slice(0, MAX_MESSAGE_LENGTH) : ""; } async function readStdin() { let input = ""; for await (const chunk of process.stdin) { input += chunk; } return input; } function parsePayload(input) { const payload = JSON.parse(input || "{}"); if (!payload || !Array.isArray(payload.expressions)) { throw new Error("Input JSON must contain an expressions array."); } return payload; } async function checkExpression(expression) { const index = Number(expression.index); const body = String(expression.body ?? ""); const display = Boolean(expression.display); try { const svg = await MathJax.tex2svgPromise(body, { display }); const serialized = MathJax.startup.adaptor.serializeXML(svg); const message = renderError(serialized); if (message) { return { index, ok: false, message }; } return { index, ok: true }; } catch (error) { return { index, ok: false, message: errorMessage(error) }; } } async function main() { await MathJax.init({ loader: { load: ["input/tex", "output/svg"] }, }); if (process.argv.includes("--health")) { await MathJax.tex2svgPromise("x", { display: false }); process.stdout.write(`${JSON.stringify({ ok: true })}\n`); return; } const payload = parsePayload(await readStdin()); const results = []; for (const expression of payload.expressions) { results.push(await checkExpression(expression)); } process.stdout.write(`${JSON.stringify({ results })}\n`); } main().catch((error) => { process.stderr.write(`${errorMessage(error)}\n`); process.exitCode = 1; });