diff --git a/README.md b/README.md index 39ba98b02b..4bfc37dc95 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ Pluto.jl is open source! Specifically, it is [MIT Licensed](https://github.com/f - `observablehq/stdlib` - [license](https://github.com/observablehq/stdlib/blob/master/LICENSE) - `preact` - [license](https://github.com/preactjs/preact/blob/master/LICENSE) - `developit/htm` - [license](https://github.com/developit/htm/blob/master/LICENSE) -- `MathJax` - [license](https://github.com/mathjax/MathJax-src/blob/master/LICENSE) +- `KaTeX` - [license](https://github.com/KaTeX/KaTeX/blob/main/LICENSE) If you want to reference Pluto.jl in scientific writing, you can use our DOI: [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.4792401.svg)](https://doi.org/10.5281/zenodo.4792401) diff --git a/frontend/common/SetupMathJax.js b/frontend/common/SetupMathJax.js deleted file mode 100644 index c60709efe0..0000000000 --- a/frontend/common/SetupMathJax.js +++ /dev/null @@ -1,76 +0,0 @@ -import "https://cdn.jsdelivr.net/npm/requestidlecallback-polyfill@1.0.2/index.js" - -let setup_done = false - -export const setup_mathjax = () => { - if (setup_done) { - return - } - setup_done = true - - const deprecated = () => console.warn("Pluto uses MathJax 3, but a MathJax 2 function was called.") - - // @ts-ignore - window.MathJax = { - options: { - ignoreHtmlClass: "no-MαθJax", - processHtmlClass: "tex", - }, - startup: { - typeset: true, // because we load MathJax asynchronously - ready: () => { - // @ts-ignore - window.MathJax.startup.defaultReady() - - // plotly uses MathJax 2, so we have this shim to make it work kindof - // @ts-ignore - window.MathJax.Hub = { - Queue: function () { - for (var i = 0, m = arguments.length; i < m; i++) { - // @ts-ignore - var fn = window.MathJax.Callback(arguments[i]) - // @ts-ignore - window.MathJax.startup.promise = window.MathJax.startup.promise.then(fn) - } - // @ts-ignore - return window.MathJax.startup.promise - }, - Typeset: function (elements, callback) { - // @ts-ignore - var promise = window.MathJax.typesetPromise(elements) - if (callback) { - promise = promise.then(callback) - } - return promise - }, - Register: { - MessageHook: deprecated, - StartupHook: deprecated, - LoadHook: deprecated, - }, - Config: deprecated, - Configured: deprecated, - setRenderer: deprecated, - } - }, - }, - tex: { - inlineMath: [ - ["$", "$"], - ["\\(", "\\)"], - ], - }, - svg: { - fontCache: "global", - }, - } - - requestIdleCallback( - () => { - console.log("Loading mathjax!!") - const script = document.head.querySelector("#MathJax-script") - script.setAttribute("src", script.getAttribute("not-the-src-yet")) - }, - { timeout: 2000 } - ) -} diff --git a/frontend/components/CellOutput.js b/frontend/components/CellOutput.js index 5fe2304202..540b3347c8 100644 --- a/frontend/components/CellOutput.js +++ b/frontend/components/CellOutput.js @@ -26,6 +26,7 @@ import { pluto_syntax_colors, ENABLE_CM_MIXED_PARSER } from "./CellInput.js" import hljs from "../imports/highlightjs.js" import { julia_mixed } from "./CellInput/mixedParsers.js" import { julia_andrey } from "../imports/CodemirrorPlutoSetup.js" +import katex from "../imports/KaTeX.js" import { SafePreviewSanitizeMessage } from "./SafePreviewUI.js" export class CellOutput extends Component { @@ -562,11 +563,16 @@ export let RawHTMLContainer = ({ body, className = "", persist_js_state = false, } // Convert LaTeX to svg - // @ts-ignore - if (window.MathJax?.typeset != undefined) { + if (true) { try { // @ts-ignore - window.MathJax.typeset(container.querySelectorAll(".tex")) + container.querySelectorAll(".pluto-tex").forEach((el) => { + if (el instanceof HTMLElement) + katex.render(el.innerText, el, { + throwOnError: false, + displayMode: el.classList.contains("pluto-tex-display"), + }) + }) } catch (err) { console.info("Failed to typeset TeX:") console.info(err) diff --git a/frontend/components/Editor.js b/frontend/components/Editor.js index 0260e3acc6..fada5492b4 100644 --- a/frontend/components/Editor.js +++ b/frontend/components/Editor.js @@ -24,7 +24,6 @@ import { slice_utf8, length_utf8 } from "../common/UnicodeTools.js" import { has_ctrl_or_cmd_pressed, ctrl_or_cmd_name, is_mac_keyboard, in_textarea_or_input } from "../common/KeyboardShortcuts.js" import { PlutoActionsContext, PlutoBondsContext, PlutoJSInitializingContext, SetWithEmptyCallback } from "../common/PlutoContext.js" import { BackendLaunchPhase, count_stat } from "../common/Binder.js" -import { setup_mathjax } from "../common/SetupMathJax.js" import { slider_server_actions, nothing_actions } from "../common/SliderServerClient.js" import { ProgressBar } from "./ProgressBar.js" import { NonCellOutput } from "./NonCellOutput.js" @@ -1373,9 +1372,6 @@ patch: ${JSON.stringify( if (old_state.disable_ui !== this.state.disable_ui || old_state.connected !== this.state.connected) { this.on_disable_ui() } - if (!this.state.initializing) { - setup_mathjax() - } if (old_state.notebook.nbpkg?.restart_recommended_msg !== new_state.notebook.nbpkg?.restart_recommended_msg) { console.warn(`New restart recommended message: ${new_state.notebook.nbpkg?.restart_recommended_msg}`) diff --git a/frontend/editor.html b/frontend/editor.html index d1009de57f..6c6027fb86 100644 --- a/frontend/editor.html +++ b/frontend/editor.html @@ -43,8 +43,7 @@ - - + diff --git a/frontend/imports/KaTeX.js b/frontend/imports/KaTeX.js new file mode 100644 index 0000000000..4a093e097e --- /dev/null +++ b/frontend/imports/KaTeX.js @@ -0,0 +1,6 @@ +import katex from "https://cdn.jsdelivr.net/npm/katex@0.15.3/dist/katex.mjs" + +import "https://cdn.jsdelivr.net/npm/katex@0.15.3/dist/contrib/mhchem.mjs" +import "https://cdn.jsdelivr.net/npm/katex@0.15.3/dist/contrib/copy-tex.mjs" + +export default katex diff --git a/src/runner/PlutoRunner.jl b/src/runner/PlutoRunner.jl index fdc891be03..e33358d17f 100644 --- a/src/runner/PlutoRunner.jl +++ b/src/runner/PlutoRunner.jl @@ -963,19 +963,15 @@ end # We add a method for the Markdown -> HTML conversion that takes a LaTeX chunk from the Markdown tree and adds our custom span function htmlinline(io::IO, x::LaTeX) - withtag(io, :span, :class => "tex") do - print(io, '$') + withtag(io, :span, :class => "pluto-tex pluto-tex-inline") do htmlesc(io, x.formula) - print(io, '$') end end # this one for block equations: (double $$) function html(io::IO, x::LaTeX) - withtag(io, :p, :class => "tex") do - print(io, '$', '$') + withtag(io, :p, :class => "pluto-tex pluto-tex-display") do htmlesc(io, x.formula) - print(io, '$', '$') end end @@ -1375,7 +1371,7 @@ function show_richest(io::IO, @nospecialize(x))::Tuple{<:Any,MIME} elseif mime isa MIME"text/latex" # Some reprs include $ at the start and end. # We strip those, since Markdown.LaTeX should contain the math content. - # (It will be rendered by MathJax, which is math-first, not text-first.) + # (It will be rendered by KaTeX, which is math-first, not text-first.) texed = repr(mime, x) Markdown.html(io, Markdown.LaTeX(strip(texed, ('$', '\n', ' ')))) nothing, MIME"text/html"()