mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-11-09 13:44:53 +08:00
add mermaidjs support (#816)
This commit is contained in:
parent
bfbdc4602c
commit
45175b2a6f
4 changed files with 1468 additions and 6 deletions
|
|
@ -7,12 +7,16 @@ import remarkMath from "remark-math";
|
|||
import remarkRehype from "remark-rehype";
|
||||
import rehypeRaw from "rehype-raw";
|
||||
import rehypeKatex from "rehype-katex";
|
||||
import rehypeParse from "rehype-parse";
|
||||
import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
|
||||
import rehypeStringify from "rehype-stringify";
|
||||
|
||||
import { visit } from "unist-util-visit";
|
||||
import { toText } from "hast-util-to-text";
|
||||
import { removePosition } from "unist-util-remove-position";
|
||||
|
||||
import { highlight } from "./live_editor/monaco";
|
||||
import { renderMermaid } from "../mermaid";
|
||||
|
||||
/**
|
||||
* Renders markdown content in the given container.
|
||||
|
|
@ -47,6 +51,7 @@ class Markdown {
|
|||
.use(remarkParse)
|
||||
.use(remarkGfm)
|
||||
.use(remarkMath)
|
||||
.use(remarkPrepareMermaid)
|
||||
.use(remarkSyntaxHiglight, { highlight })
|
||||
.use(remarkExpandUrls, { baseUrl: this.baseUrl })
|
||||
// We keep the HTML nodes, parse with rehype-raw and then sanitize
|
||||
|
|
@ -54,6 +59,7 @@ class Markdown {
|
|||
.use(rehypeRaw)
|
||||
.use(rehypeSanitize, sanitizeSchema())
|
||||
.use(rehypeKatex)
|
||||
.use(rehypeMermaid)
|
||||
.use(rehypeExternalLinks)
|
||||
.use(rehypeStringify)
|
||||
.process(this.content)
|
||||
|
|
@ -150,6 +156,47 @@ function remarkExpandUrls(options) {
|
|||
};
|
||||
}
|
||||
|
||||
const parseHtml = unified().use(rehypeParse, { fragment: true });
|
||||
|
||||
function remarkPrepareMermaid(options) {
|
||||
return (ast) => {
|
||||
visit(ast, "code", (node, index, parent) => {
|
||||
if (node.lang === "mermaid") {
|
||||
node.type = "html";
|
||||
node.value = `<div class="mermaid">${node.value}</div>`;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function rehypeMermaid(options) {
|
||||
return (ast) => {
|
||||
const promises = [];
|
||||
|
||||
visit(ast, "element", (element) => {
|
||||
const classes =
|
||||
element.properties && Array.isArray(element.properties.className)
|
||||
? element.properties.className
|
||||
: [];
|
||||
|
||||
if (classes.includes("mermaid")) {
|
||||
function updateNode(html) {
|
||||
element.children = removePosition(
|
||||
parseHtml.parse(html),
|
||||
true
|
||||
).children;
|
||||
}
|
||||
|
||||
const value = toText(element, { whitespace: "pre" });
|
||||
const promise = renderMermaid(value).then(updateNode);
|
||||
promises.push(promise);
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(() => null);
|
||||
};
|
||||
}
|
||||
|
||||
// Modifies external links, so that they open in a new tab
|
||||
function rehypeExternalLinks(options) {
|
||||
return (ast) => {
|
||||
|
|
|
|||
27
assets/js/cell/markdown/mermaid.js
Normal file
27
assets/js/cell/markdown/mermaid.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
let idCount = 0;
|
||||
let getId = () => `mermaid-graph-${idCount++}`;
|
||||
|
||||
let mermaidInitialized = false;
|
||||
|
||||
function importMermaid() {
|
||||
return import(
|
||||
/* webpackChunkName: "mermaid" */
|
||||
"mermaid"
|
||||
).then(({ default: mermaid }) => {
|
||||
if (!mermaidInitialized) {
|
||||
mermaid.initialize({ startOnLoad: false });
|
||||
mermaidInitialized = true;
|
||||
}
|
||||
return mermaid;
|
||||
});
|
||||
}
|
||||
|
||||
export function renderMermaid(value) {
|
||||
return importMermaid().then((mermaid) => {
|
||||
try {
|
||||
return mermaid.render(getId(), value);
|
||||
} catch (e) {
|
||||
return `<pre><code>${e.message}</code></pre>`;
|
||||
}
|
||||
});
|
||||
}
|
||||
1396
assets/package-lock.json
generated
1396
assets/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -14,7 +14,9 @@
|
|||
"@fontsource/jetbrains-mono": "^4.2.2",
|
||||
"assert": "^2.0.0",
|
||||
"crypto-js": "^4.0.0",
|
||||
"hast-util-to-text": "^3.1.1",
|
||||
"hyperlist": "^1.0.0",
|
||||
"mermaid": "^8.13.6",
|
||||
"monaco-editor": "^0.31.1",
|
||||
"morphdom": "^2.6.1",
|
||||
"phoenix": "file:../deps/phoenix",
|
||||
|
|
@ -22,6 +24,7 @@
|
|||
"phoenix_live_view": "file:../deps/phoenix_live_view",
|
||||
"process": "^0.11.10",
|
||||
"rehype-katex": "^6.0.0",
|
||||
"rehype-parse": "^8.0.3",
|
||||
"rehype-raw": "^6.0.0",
|
||||
"rehype-sanitize": "^5.0.0",
|
||||
"rehype-stringify": "^9.0.1",
|
||||
|
|
@ -34,6 +37,7 @@
|
|||
"tailwindcss": "^3.0.8",
|
||||
"topbar": "^1.0.1",
|
||||
"unified": "^10.1.0",
|
||||
"unist-util-remove-position": "^4.0.1",
|
||||
"unist-util-visit": "^4.0.0",
|
||||
"vega": "^5.20.2",
|
||||
"vega-embed": "^6.18.1",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue