Skip to content

fix(katex): convert aligned→align when \tag is present#3847

Merged
esengine merged 1 commit into
esengine:main-v2from
lightfront:fix/katex-tag-stripping
Jun 11, 2026
Merged

fix(katex): convert aligned→align when \tag is present#3847
esengine merged 1 commit into
esengine:main-v2from
lightfront:fix/katex-tag-stripping

Conversation

@lightfront

@lightfront lightfront commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Problem

KaTeXs aligned/gatheredenvironments treat the entire block as one equation and only permit a single\tagper block (parse error "Multiple \tag"). When LLMs emit\tag{...}insidealigned` — as in:

$$
\boxed{\begin{aligned}
r_A E_\pi(k;0) &= B(k^2) \tag{10}\\
F_R(k;0) + 2r_A F_\pi(k;0) &= A(k^2) \tag{11}
\end{aligned}}
$$

KaTeX throws KaTeX parse error: Multiple \tag, which rehype-katex
renders as <span class="katex-error" style="color:#cc0000">
showing red error text in the web UI.

Fix

Instead of stripping \tag commands (which loses equation numbers),
convert the environments when \tag is present:

  • \begin{aligned}\begin{align}
  • \begin{gathered}\begin{gather}
  • \begin{alignedat}{N}\begin{alignat}{N}

KaTeX's align/gather/alignat support \tag on every row
natively. Plain aligned blocks without \tag are left unchanged
so they keep their un-numbered behaviour. The conversion is only
applied when \tag is detected in the math source.

if (/\\tag\*?\s*\{/.test(source)) {
  source = source
    .replace(/\\begin\{alignedat\}\{(\d+)\}/g, "\\begin{alignat}{$1}")
    .replace(/\\end\{alignedat\}/g, "\\end{alignat}")
    .replace(/\\begin\{aligned\}/g, "\\begin{align}")
    .replace(/\\end\{aligned\}/g, "\\end{align}")
    .replace(/\\begin\{gathered\}/g, "\\begin{gather}")
    .replace(/\\end\{gathered\}/g, "\\end{gather}");
}

Files changed

  • desktop/frontend/src/components/latexNormalize.ts — aligned→align
    conversion when \tag is present
  • desktop/frontend/src/__tests__/math-golden.test.ts — 6 new unit
    tests + 1 updated e2e test

Testing

All 99 golden tests pass (npx tsx src/__tests__/math-golden.test.ts).

@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development desktop Wails desktop app (desktop/**) and removed v2 Go rewrite (1.x) — main-v2 branch, active development labels Jun 10, 2026
KaTeX's aligned/gathered environments treat the entire block as one
equation and only permit a single \tag per block (parse error "Multiple
\tag"), while align/gather support \tag on every row natively.

Instead of stripping \tag commands (which loses equation numbers),
convert aligned→align, gathered→gather, and alignedat→alignat when
\tag is detected in the math source.  Plain aligned blocks without
\tag are left unchanged so they keep their un-numbered behaviour.

6 new unit tests + 1 updated e2e test (99 total, all pass).
@lightfront lightfront force-pushed the fix/katex-tag-stripping branch from 0562163 to 2bafd91 Compare June 10, 2026 12:04
@github-actions github-actions Bot added the v2 Go rewrite (1.x) — main-v2 branch, active development label Jun 10, 2026
@lightfront lightfront changed the title fix(katex): strip \tag{...} to prevent KaTeX "Multiple \tag" errors fix(katex): convert aligned→align when \tag is present Jun 10, 2026

@esengine esengine left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice fix — converting to align/gather/alignat instead of stripping \tag keeps the equation numbers, and gating on \tag presence means plain aligned blocks keep their semantics. The e2e tests actually rendering through KaTeX (including the boxed nesting) is exactly the verification this needed. Thanks!

@esengine esengine enabled auto-merge (squash) June 11, 2026 02:10
@esengine esengine merged commit 8f91f82 into esengine:main-v2 Jun 11, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

desktop Wails desktop app (desktop/**) v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants