Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions scripts/katexContribFlavour.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* KaTeX publishes every contrib file twice: `contrib/*.mjs` behind the
* `import` condition, `contrib/*.js` (CommonJS, `require("katex")`) behind
* `require`. Only the `.mjs` shares the preview's KaTeX instance; the `.js`
* gets the bundler's CommonJS copy, and a macro mhchem registers there never
* reaches `renderToString` (#745). vitest and node both dedupe the two, so the
* only runtime that shows the split is a production build — which is why this
* is asserted on the source: the loader may not name the CommonJS flavour.
*/
import assert from 'node:assert/strict';
import test from 'node:test';

import { readSource } from './sourceTree.ts';

test('the rich-content loader imports KaTeX contribs through the exports map', () => {
const source = readSource('src/lib/utils/richContent.ts');
assert.doesNotMatch(source, /import\('katex\/dist\/contrib\//);
assert.match(source, /import\('katex\/contrib\/mhchem'\)/);
});
4 changes: 2 additions & 2 deletions src/globals.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
declare module 'katex/dist/contrib/auto-render.js';
declare module 'katex/dist/contrib/mhchem.js';
declare module 'katex/contrib/auto-render';
declare module 'katex/contrib/mhchem';
declare module 'highlightjs-svelte';
14 changes: 10 additions & 4 deletions src/lib/utils/richContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ export function loadRichContentLibraries(): Promise<RichContentLibraries> {
}

const katex = (katexMainModule as any).default;
// mhchem is a KaTeX extension that binds to the global.
(window as any).katex = katex;

// `copy-tex` used to be loaded here too. It installs its own document
// `copy` listener, which fires only when the selection contains math and
Expand All @@ -100,9 +98,17 @@ export function loadRichContentLibraries(): Promise<RichContentLibraries> {
// Its two worthwhile behaviours, whole-formula expansion and TeX as the
// plain text, are implemented in `utils/previewCopy.ts` instead, where
// they apply to one copy path rather than a second one.
// The bare `katex/contrib/…` subpaths, not `katex/dist/contrib/….js`:
// KaTeX publishes every file twice, `.mjs` behind the `import` condition
// and `.js` (CommonJS, `require("katex")`) behind `require`. Ask for the
// `.js` and the bundler hands it the CommonJS copy of KaTeX — a second
// parser with its own macro table — so mhchem registered `\ce` on a
// KaTeX the preview never calls, and `$$\ce{…}$$` came out as a parse
// error (#745). The subpath resolves to the `.mjs`, which imports
// `../katex.mjs`: the same module `import('katex')` above returned.
const [autoRenderModule] = await Promise.all([
import('katex/dist/contrib/auto-render.js'),
import('katex/dist/contrib/mhchem.js'),
import('katex/contrib/auto-render'),
import('katex/contrib/mhchem'),
]);

return {
Expand Down
Loading