Skip to content

Commit 7d6f337

Browse files
committed
mermaid
1 parent 043f615 commit 7d6f337

File tree

6 files changed

+92
-36
lines changed

6 files changed

+92
-36
lines changed

public/client.js

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -64,41 +64,6 @@ function recommendedLibraries() {
6464
html: () => import("https://cdn.jsdelivr.net/npm/htl/+esm").then((htl) => htl.html),
6565
svg: () => import("https://cdn.jsdelivr.net/npm/htl/+esm").then((htl) => htl.svg),
6666
Plot: () => import("https://cdn.jsdelivr.net/npm/@observablehq/plot/+esm"),
67-
dot: async () => {
68-
// TODO Incorporate this into the standard library.
69-
const viz = await import("https://cdn.jsdelivr.net/npm/@viz-js/viz/+esm").then(({instance}) => instance());
70-
return function dot(strings) {
71-
let string = strings[0] + "";
72-
let i = 0;
73-
let n = arguments.length;
74-
while (++i < n) string += arguments[i] + "" + strings[i];
75-
const svg = viz.renderSVGElement(string, {
76-
graphAttributes: {
77-
bgcolor: "none"
78-
},
79-
nodeAttributes: {
80-
color: "#00000101",
81-
fontcolor: "#00000101",
82-
fontname: "var(--sans-serif)",
83-
fontsize: "12"
84-
},
85-
edgeAttributes: {
86-
color: "#00000101"
87-
}
88-
});
89-
for (const e of svg.querySelectorAll("[stroke='#000001'][stroke-opacity='0.003922']")) {
90-
e.setAttribute("stroke", "currentColor");
91-
e.removeAttribute("stroke-opacity");
92-
}
93-
for (const e of svg.querySelectorAll("[fill='#000001'][fill-opacity='0.003922']")) {
94-
e.setAttribute("fill", "currentColor");
95-
e.removeAttribute("fill-opacity");
96-
}
97-
svg.remove();
98-
svg.style = "max-width: 100%; height: auto;";
99-
return svg;
100-
};
101-
},
10267
Inputs: () => {
10368
// TODO Observable Inputs needs to include the CSS in the dist folder
10469
// published to npm, and we should replace the __ns__ namespace with
@@ -109,7 +74,60 @@ function recommendedLibraries() {
10974
link.href = "https://cdn.jsdelivr.net/gh/observablehq/inputs/src/style.css";
11075
document.head.append(link);
11176
return inputs;
77+
},
78+
dot,
79+
mermaid
80+
};
81+
}
82+
83+
// TODO Incorporate this into the standard library.
84+
async function dot() {
85+
const {instance} = await import("https://cdn.jsdelivr.net/npm/@viz-js/viz/+esm");
86+
const viz = await instance();
87+
return function dot(strings) {
88+
let string = strings[0] + "";
89+
let i = 0;
90+
let n = arguments.length;
91+
while (++i < n) string += arguments[i] + "" + strings[i];
92+
const svg = viz.renderSVGElement(string, {
93+
graphAttributes: {
94+
bgcolor: "none"
95+
},
96+
nodeAttributes: {
97+
color: "#00000101",
98+
fontcolor: "#00000101",
99+
fontname: "var(--sans-serif)",
100+
fontsize: "12"
101+
},
102+
edgeAttributes: {
103+
color: "#00000101"
104+
}
105+
});
106+
for (const e of svg.querySelectorAll("[stroke='#000001'][stroke-opacity='0.003922']")) {
107+
e.setAttribute("stroke", "currentColor");
108+
e.removeAttribute("stroke-opacity");
112109
}
110+
for (const e of svg.querySelectorAll("[fill='#000001'][fill-opacity='0.003922']")) {
111+
e.setAttribute("fill", "currentColor");
112+
e.removeAttribute("fill-opacity");
113+
}
114+
svg.remove();
115+
svg.style = "max-width: 100%; height: auto;";
116+
return svg;
117+
};
118+
}
119+
120+
// TODO Incorporate this into the standard library.
121+
async function mermaid() {
122+
let nextId = 0;
123+
const {default: mer} = await import("https://cdn.jsdelivr.net/npm/mermaid/+esm");
124+
mer.initialize({startOnLoad: false, securityLevel: "loose", theme: "neutral"});
125+
return async function mermaid() {
126+
const div = document.createElement("div");
127+
div.innerHTML = (await mer.render(`mermaid-${++nextId}`, String.raw.apply(String, arguments))).svg;
128+
const svg = div.firstChild;
129+
svg.remove();
130+
return svg;
113131
};
114132
}
115133

src/markdown.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ function getLiveSource(content, language, option) {
8787
? transpileTag(content, "tex.block", true)
8888
: language === "dot"
8989
? transpileTag(content, "dot", false)
90+
: language === "mermaid"
91+
? transpileTag(content, "await mermaid", false)
9092
: undefined;
9193
}
9294

src/render.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,12 @@ function getImportPreloads(parseResult: ParseResult): Iterable<string> {
115115
const specifiers = new Set<string>(["npm:@observablehq/runtime"]);
116116
for (const {name} of parseResult.imports) specifiers.add(name);
117117
const inputs = new Set(parseResult.cells.flatMap((cell) => cell.inputs ?? []));
118-
if (inputs.has("dot")) specifiers.add("npm:@viz-js/viz");
119118
if (inputs.has("d3") || inputs.has("Plot")) specifiers.add("npm:d3");
120119
if (inputs.has("Plot")) specifiers.add("npm:@observablehq/plot");
121120
if (inputs.has("htl") || inputs.has("html") || inputs.has("svg") || inputs.has("Inputs")) specifiers.add("npm:htl");
122121
if (inputs.has("Inputs")) specifiers.add("npm:@observablehq/inputs");
122+
if (inputs.has("dot")) specifiers.add("npm:@viz-js/viz");
123+
if (inputs.has("mermaid")) specifiers.add("npm:mermaid").add("npm:d3");
123124
const preloads: string[] = [];
124125
for (const specifier of specifiers) {
125126
const resolved = resolveImport(specifier);

test/input/mermaid.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```mermaid
2+
graph TD;
3+
A-->B;
4+
A-->C;
5+
B-->D;
6+
C-->D;
7+
```

test/output/mermaid.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<div id="cell-1ffa6d4f" class="observablehq observablehq--block"></div>

test/output/mermaid.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"data": null,
3+
"title": null,
4+
"files": [],
5+
"imports": [],
6+
"pieces": [
7+
{
8+
"type": "html",
9+
"id": "",
10+
"cellIds": [
11+
"1ffa6d4f"
12+
],
13+
"html": "<div id=\"cell-1ffa6d4f\" class=\"observablehq observablehq--block\"></div>\n"
14+
}
15+
],
16+
"cells": [
17+
{
18+
"type": "cell",
19+
"id": "1ffa6d4f",
20+
"inputs": [
21+
"mermaid",
22+
"display"
23+
],
24+
"body": "async (mermaid,display) => {\ndisplay((\nawait mermaid`graph TD;\n A-->B;\n A-->C;\n B-->D;\n C-->D;\n`\n))\n}"
25+
}
26+
]
27+
}

0 commit comments

Comments
 (0)