From 21ac99abdc3c31e396c314fe9f08f8fa2c5fa188 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Wed, 8 Nov 2023 17:32:49 -0800 Subject: [PATCH 1/7] unfork katex --- docs/tex.md | 14 ++++++++++++++ public/client.js | 33 ++++++++++++++++++++++++++++----- src/render.ts | 1 + 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/docs/tex.md b/docs/tex.md index 1c49abe12..851ae6167 100644 --- a/docs/tex.md +++ b/docs/tex.md @@ -1,5 +1,19 @@ # TeX +${tex`\TeX`} is a language for typesetting mathematical formulae. Observable Markdown’s implementation is powered by ${tex`\KaTeX`}. + +There are two ways to use TeX. The first is a `tex` fenced code block: + ```tex show E = mc^2 ``` + +The second is an inline expression using the `tex` tagged template literal provided by the Observable standard library: + +````md +My favorite equation is ${tex`E = mc^2`}. +```` + +This produces: + +My favorite equation is ${tex`E = mc^2`}. diff --git a/public/client.js b/public/client.js index 70afb0d48..0b6bcf6e1 100644 --- a/public/client.js +++ b/public/client.js @@ -75,11 +75,36 @@ function recommendedLibraries() { document.head.append(link); return inputs; }, + tex, dot, mermaid }; } +// TODO Incorporate this into the standard library. +async function tex() { + const {default: katex} = await import("https://cdn.jsdelivr.net/npm/katex/+esm"); + const tex = renderer(); + + const link = document.createElement("link"); + link.rel = "stylesheet"; + link.href = "https://cdn.jsdelivr.net/npm/katex/dist/katex.min.css"; + link.crossOrigin = "anonymous"; + document.head.appendChild(link); + + function renderer(options) { + return function () { + const root = document.createElement("div"); + katex.render(String.raw.apply(String, arguments), root, options); + return root.removeChild(root.firstChild); + }; + } + + tex.options = renderer; + tex.block = renderer({displayMode: true}); + return tex; +} + // TODO Incorporate this into the standard library. async function dot() { const {instance} = await import("https://cdn.jsdelivr.net/npm/@viz-js/viz/+esm"); @@ -123,11 +148,9 @@ async function mermaid() { const {default: mer} = await import("https://cdn.jsdelivr.net/npm/mermaid/+esm"); mer.initialize({startOnLoad: false, securityLevel: "loose", theme: "neutral"}); return async function mermaid() { - const div = document.createElement("div"); - div.innerHTML = (await mer.render(`mermaid-${++nextId}`, String.raw.apply(String, arguments))).svg; - const svg = div.firstChild; - svg.remove(); - return svg; + const root = document.createElement("div"); + root.innerHTML = (await mer.render(`mermaid-${++nextId}`, String.raw.apply(String, arguments))).svg; + return root.removeChild(root.firstChild); }; } diff --git a/src/render.ts b/src/render.ts index c4b3f5b45..240c62286 100644 --- a/src/render.ts +++ b/src/render.ts @@ -118,6 +118,7 @@ function getImportPreloads(parseResult: ParseResult): Iterable { if (inputs.has("Inputs")) specifiers.add("npm:@observablehq/inputs"); if (inputs.has("dot")) specifiers.add("npm:@viz-js/viz"); if (inputs.has("mermaid")) specifiers.add("npm:mermaid").add("npm:d3"); + if (inputs.has("tex")) specifiers.add("npm:katex"); const preloads: string[] = []; for (const specifier of specifiers) { preloads.push(resolveImport(specifier)); From 759413424dc0903ccbaafb3a7fade0902d1fdc80 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Wed, 8 Nov 2023 19:31:19 -0800 Subject: [PATCH 2/7] more examples --- docs/tex.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/tex.md b/docs/tex.md index 851ae6167..8a7122c01 100644 --- a/docs/tex.md +++ b/docs/tex.md @@ -17,3 +17,26 @@ My favorite equation is ${tex`E = mc^2`}. This produces: My favorite equation is ${tex`E = mc^2`}. + +Here are some more examples. + +```tex show +c = \pm\sqrt{a^2 + b^2} +``` + +```tex show +\Delta E^*_{00} = \sqrt{ + \Big(\frac{\Delta L'}{k_LS_L}\Big)^2 + + \Big(\frac{\Delta C'}{k_CS_C}\Big)^2 + + \Big(\frac{\Delta H'}{k_HS_H}\Big)^2 + + R_T + \frac{\Delta C'}{k_CS_C} + \frac{\Delta H'}{k_HS_H}} +``` + +```tex show +\def\f#1#2{#1f(#2)} +\f\relax{x} = \int_{-\infty}^\infty + \f\hat\xi\,e^{2 \pi i \xi x} + \,d\xi +``` From 6ca62f2f5aedeacf03a72de532807413d3313edf Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Wed, 8 Nov 2023 19:36:09 -0800 Subject: [PATCH 3/7] show tex language --- docs/tex.md | 14 +++++++++++++- public/style.css | 25 ++++++++++--------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/docs/tex.md b/docs/tex.md index 8a7122c01..e2b49387e 100644 --- a/docs/tex.md +++ b/docs/tex.md @@ -4,7 +4,15 @@ ${tex`\TeX`} is a language for typesetting mathematical formulae. Observable Mar There are two ways to use TeX. The first is a `tex` fenced code block: -```tex show +````md +```tex +E = mc^2 +``` +```` + +This produces a centered block: + +```tex E = mc^2 ``` @@ -16,6 +24,10 @@ My favorite equation is ${tex`E = mc^2`}. This produces: +```tex +E = \prod_{i=1}^n{\text{Owen}^\pi} +``` + My favorite equation is ${tex`E = mc^2`}. Here are some more examples. diff --git a/public/style.css b/public/style.css index 823d25245..0225196c9 100644 --- a/public/style.css +++ b/public/style.css @@ -308,6 +308,9 @@ pre { } pre .language-md::after, +pre .language-tex::after, +pre .language-dot::after, +pre .language-mermaid::after, pre .language-js::after, pre .language-sh::after, pre .language-sql::after { @@ -321,21 +324,13 @@ pre .language-sql::after { padding: 0.5rem 0.5rem 0.5rem 1rem; } -pre .language-md::after { - content: "md"; -} - -pre .language-js::after { - content: "js"; -} - -pre .language-sh::after { - content: "sh"; -} - -pre .language-sql::after { - content: "sql"; -} +pre .language-md::after { content: "md"; } +pre .language-js::after { content: "js"; } +pre .language-sh::after { content: "sh"; } +pre .language-sql::after { content: "sql"; } +pre .language-tex::after { content: "tex"; } +pre .language-dot::after { content: "dot"; } +pre .language-mermaid::after { content: "mermaid"; } input:not([type]), input[type="email"], From 91c9e64fec3da8855468274c587f514b04034db3 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Wed, 8 Nov 2023 19:37:00 -0800 Subject: [PATCH 4/7] doc edits --- docs/tex.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/tex.md b/docs/tex.md index e2b49387e..07c970f15 100644 --- a/docs/tex.md +++ b/docs/tex.md @@ -24,10 +24,6 @@ My favorite equation is ${tex`E = mc^2`}. This produces: -```tex -E = \prod_{i=1}^n{\text{Owen}^\pi} -``` - My favorite equation is ${tex`E = mc^2`}. Here are some more examples. From 112f57c1f0b6f561e53a45f67457b09efd703d07 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Wed, 8 Nov 2023 19:39:34 -0800 Subject: [PATCH 5/7] only html output --- public/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/client.js b/public/client.js index 0b6bcf6e1..465f66f0f 100644 --- a/public/client.js +++ b/public/client.js @@ -95,7 +95,7 @@ async function tex() { function renderer(options) { return function () { const root = document.createElement("div"); - katex.render(String.raw.apply(String, arguments), root, options); + katex.render(String.raw.apply(String, arguments), root, {...options, output: "html"}); return root.removeChild(root.firstChild); }; } From f5d406c7cb35f71b35b60f091f7801127fbcebc9 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Wed, 8 Nov 2023 20:11:24 -0800 Subject: [PATCH 6/7] parallel load --- public/client.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/client.js b/public/client.js index 465f66f0f..776387227 100644 --- a/public/client.js +++ b/public/client.js @@ -83,15 +83,15 @@ function recommendedLibraries() { // TODO Incorporate this into the standard library. async function tex() { - const {default: katex} = await import("https://cdn.jsdelivr.net/npm/katex/+esm"); - const tex = renderer(); - const link = document.createElement("link"); link.rel = "stylesheet"; link.href = "https://cdn.jsdelivr.net/npm/katex/dist/katex.min.css"; link.crossOrigin = "anonymous"; document.head.appendChild(link); + const {default: katex} = await import("https://cdn.jsdelivr.net/npm/katex/+esm"); + const tex = renderer(); + function renderer(options) { return function () { const root = document.createElement("div"); From 9bfe56c74480dbd677dbe19372f8fc0a4dbe3d72 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Thu, 9 Nov 2023 10:01:02 -0500 Subject: [PATCH 7/7] Update docs/tex.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Philippe Rivière --- docs/tex.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tex.md b/docs/tex.md index 07c970f15..d5bde354f 100644 --- a/docs/tex.md +++ b/docs/tex.md @@ -18,9 +18,9 @@ E = mc^2 The second is an inline expression using the `tex` tagged template literal provided by the Observable standard library: -````md +```md My favorite equation is ${tex`E = mc^2`}. -```` +``` This produces: