Skip to content

Commit 36e704c

Browse files
authored
Merge pull request #12493 from quarto-dev/katex-jupyter-embed
Fix conflict in with KaTeX and Require.js
2 parents e67ce56 + 1be52af commit 36e704c

File tree

6 files changed

+86
-11
lines changed

6 files changed

+86
-11
lines changed

news/changelog-1.7.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ All changes included in 1.7:
120120
### `jupyter`
121121

122122
- ([#9089](https://github.com/quarto-dev/quarto-cli/issues/9089)): Serialize compound `jupyter` metadata into a special key-value attribute to not break Pandoc's fenced div parsing.
123+
- ([#10113](https://github.com/quarto-dev/quarto-cli/issues/10113)): KaTeX will now load correctly in `engine: jupyter` documents using `emebed-resources: true`.
123124
- ([#12114](https://github.com/quarto-dev/quarto-cli/issues/12114)): `JUPYTERCACHE` environment variable from [Jupyter cache CLI](https://jupyter-cache.readthedocs.io/en/latest/using/cli.html) is now respected by Quarto when `cache: true` is used. This environment variable allows to change the path of the cache directory.
124125
- ([#12228](https://github.com/quarto-dev/quarto-cli/issues/12228)): `quarto render` will now fails if errors are detected at IPython display level. Setting `error: true` globally or at cell level will keep the error to show in output and not stop the rendering.
125126
- ([#12374](https://github.com/quarto-dev/quarto-cli/issues/12374)): Detect language properly in Jupyter notebooks that lack the `language` field in their `kernelspec`s.

src/command/render/template.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -270,26 +270,47 @@ function katexScript(url: string) {
270270
link.rel = "stylesheet";
271271
link.href = "${url}katex.min.css";
272272
head.appendChild(link);
273-
274-
var script = document.createElement("script");
275-
script.type = "text/javascript";
276-
script.src = "${url}katex.min.js";
277-
script.async = false;
278-
script.addEventListener('load', function() {
273+
274+
function renderMathElements() {
279275
var mathElements = document.getElementsByClassName("math");
280-
var macros = [];
281-
for (var i = 0; i < mathElements.length; i++) {
282-
var texText = mathElements[i].firstChild;
283-
if (mathElements[i].tagName == "SPAN") {
276+
var macros = [];
277+
for (var i = 0; i < mathElements.length; i++) {
278+
var texText = mathElements[i].firstChild;
279+
if (mathElements[i].tagName == "SPAN") {
280+
if (window.katex) {
284281
window.katex.render(texText.data, mathElements[i], {
285282
displayMode: mathElements[i].classList.contains('display'),
286283
throwOnError: false,
287284
macros: macros,
288285
fleqn: false
289286
});
287+
} else {
288+
console.error("KaTeX has not been loaded correctly, as not found globally.");
290289
}
291290
}
292-
});
291+
}
292+
}
293+
294+
var script = document.createElement("script");
295+
script.src = "${url}katex.min.js";
296+
script.onload = renderMathElements;
297+
298+
// Check for RequireJS and AMD detection as it conflicts with KaTeX loading.
299+
if (typeof require === 'function' && typeof define === 'function' && define.amd) {
300+
// Disable require.js AMD detection temporarily, as it conflicts with KaTeX loading using CommonJS
301+
var disableAmdScript = document.createElement("script");
302+
disableAmdScript.textContent = 'window._amd_backup = window.define.amd; window.define.amd = false;';
303+
head.appendChild(disableAmdScript);
304+
305+
// overwrite onload to restore Require.js AMD detection
306+
script.onload = function() {
307+
// Restore Require.js AMD detection
308+
window.define.amd = window._amd_backup;
309+
delete window._amd_backup;
310+
renderMathElements();
311+
};
312+
}
313+
293314
head.appendChild(script);
294315
});
295316
</script>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
format: html
3+
html-math-method: katex
4+
embed-resources: true
5+
---
6+
7+
$\alpha$
8+
9+
```{python}
10+
import pandas as pd
11+
pd.DataFrame([1])
12+
```
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
format: html
3+
html-math-method: katex
4+
embed-resources: true
5+
self-contained-math: true
6+
---
7+
8+
$\alpha$
9+
10+
```{python}
11+
import pandas as pd
12+
pd.DataFrame([1])
13+
```
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
format: html
3+
html-math-method: katex
4+
---
5+
6+
$\alpha$
7+
8+
```{python}
9+
import pandas as pd
10+
pd.DataFrame([1])
11+
```
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { test, expect } from '@playwright/test';
2+
3+
test.describe('KaTeX math rendering in Jupyter engine document', () => {
4+
const testCases = [
5+
{ url: 'html/math/katex/not-embed.html', description: 'not embedding resources' },
6+
{ url: 'html/math/katex/embed-with-math.html', description: 'embedding resources including Math' },
7+
{ url: 'html/math/katex/embed-except-math.html', description: 'embedding resources except Math' }
8+
];
9+
10+
for (const { url, description } of testCases) {
11+
test(`KaTeX math is rendered while ${description}`, async ({ page }) => {
12+
await page.goto(url);
13+
// Check that math is rendered
14+
await expect(page.locator("span.katex")).toContainText('α');
15+
});
16+
}
17+
});

0 commit comments

Comments
 (0)