Skip to content

mhchem registers on the KaTeX the preview renders with - #747

Merged
PathGao merged 1 commit into
masterfrom
fix/mhchem-katex-instance
Sep 2, 2026
Merged

mhchem registers on the KaTeX the preview renders with#747
PathGao merged 1 commit into
masterfrom
fix/mhchem-katex-instance

Conversation

@PathGao

@PathGao PathGao commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

What this is

Closes #745. $$\ce{2H2 + O2 -> 2H2O}$$ rendered as a red parse error, "Undefined control sequence: \ce", although mhchem has been loaded since #411. The screenshot in the issue is that error, not raw text. A second commit fixes what showed up once \ce worked: the label on ->[燃烧] had its top clipped.

Mechanism

Two copies of KaTeX. KaTeX publishes every file twice: dist/katex.mjs behind the import condition and dist/katex.js (CommonJS) behind require, and the contrib files come in both flavours. The loader asked for katex/dist/contrib/mhchem.js — the CommonJS one, which does require("katex") — so the production bundle carried two copies of KaTeX 0.18.4. import('katex') gave the preview the ESM copy; mhchem registered \ce on the CommonJS copy. Display math goes through katex.renderToString on the preview's copy and never saw the macro. Inline \(\ce{…}\) happened to work because auto-render, loaded the same way, ran on the copy mhchem had patched.

Counted in build/_app/immutable/chunks before and after:

before after
chunks containing KaTeX 0.18.4 2 1
KaTeX the mhchem chunk imports the CommonJS copy the chunk the preview imports

The fix is the bare katex/contrib/mhchem and katex/contrib/auto-render subpaths: the exports map resolves them to the .mjs, which imports ../katex.mjs. window.katex is dropped with it — it existed only for the CommonJS build's global fallback and nothing else read it. One copy of KaTeX 0.16.47 remains: mermaid's own nested dependency, untouched.

The clipped label. .katex-display sets overflow-y: hidden so a wide formula's horizontal scrollbar does not bring a vertical one, and hidden overflow clips at the padding edge. KaTeX sizes the block from its own font metrics and has none for CJK, so the label in ->[燃烧] — set in the fallback font — drew taller than the box and lost its top. The block now carries 0.4em of vertical padding as headroom, and the margin drops from 1.5em to 1.1em, so the distance to the neighbouring blocks is unchanged.

Scope

No change to the math pipeline, the delimiters or the renderer options. The test is a source assertion, deliberately: vitest and node both dedupe the two copies, so the split is visible only in a production build. scripts/katexContribFlavour.test.ts fails on master and passes here. The padding has no test — a layout fact, checked on a build.

Verification

npm run check       831 files, 0 errors
npm test            1029 pass
npm run test:vitest 434 pass
vite build          one KaTeX 0.18.4 chunk, imported by both the preview and mhchem

On a macOS build: both display formulas from the issue render, the arrow label is whole. The clipping was seen on the build before the second commit and is gone after it.

…745)

KaTeX publishes every contrib file twice: .mjs behind the import
condition, .js (CommonJS, require("katex")) behind require. The loader
asked for katex/dist/contrib/mhchem.js, so the bundler gave mhchem the
CommonJS copy of KaTeX and \ce landed on a parser the preview never
calls; $$\ce{...}$$ rendered as a parse error. The bare
katex/contrib/* subpaths resolve to the .mjs, which imports the same
katex.mjs the preview does. The built app now carries one KaTeX 0.18.4
instead of two.
@PathGao
PathGao merged commit 34b72b7 into master Sep 2, 2026
4 checks passed
@PathGao
PathGao deleted the fix/mhchem-katex-instance branch September 2, 2026 00:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Support mhchem syntax \ce{} for chemical equations

1 participant