Add support for math formulas (#151)

* Add support for LaTeX equations

* Mention math support in the introductory notebook
This commit is contained in:
Jonatan Kłosko 2021-04-08 15:31:46 +02:00 committed by GitHub
parent 121eec784d
commit d68c271aae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 78 additions and 1 deletions

View file

@ -124,6 +124,10 @@
@apply mb-0;
}
.markdown .katex-display {
@apply my-8;
}
/* Overrides for user-entered markdown */
[data-element="cell"] .markdown h1,

View file

@ -1,5 +1,6 @@
import "../css/app.css";
import "remixicon/fonts/remixicon.css";
import "katex/dist/katex.min.css";
import "@fontsource/inter";
import "@fontsource/inter/500.css";

View file

@ -1,6 +1,7 @@
import marked from "marked";
import morphdom from "morphdom";
import DOMPurify from "dompurify";
import katex from "katex";
import monaco from "./live_editor/monaco";
// Reuse Monaco highlighter for Markdown code blocks
@ -51,7 +52,16 @@ class Markdown {
// Marked requires a trailing slash in the base URL
const opts = { baseUrl: this.baseUrl + "/" };
marked(this.content, opts, (error, html) => {
// Render math formulas using KaTeX.
// The resulting <span> tags will pass through
// marked.js and sanitization unchanged.
//
// We render math before anything else, because passing
// TeX through markdown renderer may have undesired
// effects like rendering \\ as \.
const contentWithRenderedMath = this.__renderMathInString(this.content);
marked(contentWithRenderedMath, opts, (error, html) => {
const sanitizedHtml = DOMPurify.sanitize(html);
if (sanitizedHtml) {
@ -66,6 +76,22 @@ class Markdown {
});
});
}
// Replaces TeX formulas in string with rendered HTML using KaTeX.
__renderMathInString(string) {
const options = {
throwOnError: false,
errorColor: "inherit",
};
return string
.replace(/\$\$([\s\S]*?)\$\$/g, (match, math) => {
return katex.renderToString(math, { ...options, displayMode: true });
})
.replace(/\$([\s\S]*?)\$/g, (match, math) => {
return katex.renderToString(math, options);
});
}
}
export default Markdown;

View file

@ -10,6 +10,7 @@
"@fontsource/jetbrains-mono": "^4.2.2",
"dompurify": "^2.2.6",
"hyperlist": "^1.0.0",
"katex": "^0.13.2",
"marked": "^1.2.8",
"monaco-editor": "^0.23.0",
"morphdom": "^2.6.1",
@ -9296,6 +9297,25 @@
"verror": "1.10.0"
}
},
"node_modules/katex": {
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.13.2.tgz",
"integrity": "sha512-u/KhjFDhyPr+70aiBn9SL/9w/QlLagIXBi2NZSbNnBUp2tR8dCjQplyEMkEzniem5gOeSCBjlBUg4VaiWs1JJg==",
"dependencies": {
"commander": "^6.0.0"
},
"bin": {
"katex": "cli.js"
}
},
"node_modules/katex/node_modules/commander": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
"integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
"engines": {
"node": ">= 6"
}
},
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@ -23464,6 +23484,21 @@
"verror": "1.10.0"
}
},
"katex": {
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.13.2.tgz",
"integrity": "sha512-u/KhjFDhyPr+70aiBn9SL/9w/QlLagIXBi2NZSbNnBUp2tR8dCjQplyEMkEzniem5gOeSCBjlBUg4VaiWs1JJg==",
"requires": {
"commander": "^6.0.0"
},
"dependencies": {
"commander": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
"integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="
}
}
},
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",

View file

@ -15,6 +15,7 @@
"@fontsource/jetbrains-mono": "^4.2.2",
"dompurify": "^2.2.6",
"hyperlist": "^1.0.0",
"katex": "^0.13.2",
"marked": "^1.2.8",
"monaco-editor": "^0.23.0",
"morphdom": "^2.6.1",

View file

@ -164,6 +164,16 @@ defmodule Livebook.Notebook.Welcome do
per runtime, so if you need to modify the dependencies, you should
go to the notebook runtime configuration and **reconnect** the current runtime.
## Math
Livebook supports both inline formulas like $e^{\\pi i} + 1 = 0$, as well as block formulas:
$$
S(x) = \\frac{1}{1 + e^{-x}} = \\frac{e^{x}}{e^{x} + 1}
$$
You can explore all supported expressions [here](https://katex.org/docs/supported.html).
## Stepping up your workflow
Once you start using notebooks more, it's gonna be beneficial