Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/editors/slate/elements/code-block/mermaid.tsx
1698 views
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { useEffect, useRef, useState } from "react";
7
import ShowError from "@cocalc/frontend/components/error";
8
import { delay } from "awaiting";
9
import { uuid, replace_all } from "@cocalc/util/misc";
10
import { useFileContext } from "@cocalc/frontend/lib/file-context";
11
12
interface Props {
13
value: string;
14
style?;
15
}
16
17
export default function Mermaid({ value, style }: Props) {
18
const mermaidRef = useRef<any>(null);
19
const [mermaidError, setMermaidError] = useState<string>("");
20
const processingRef = useRef<boolean>(false);
21
const [id] = useState<string>("a" + replace_all(uuid(), "-", ""));
22
const { getMermaid } = useFileContext();
23
24
if (getMermaid == null) {
25
return <div style={style}>Mermaid not available</div>;
26
}
27
28
const waitUntilNotProcessing = async () => {
29
let d = 1;
30
while (processingRef.current) {
31
// value changed *while* processing.
32
await delay(d);
33
d *= 1.2;
34
}
35
};
36
37
useEffect(() => {
38
const elt = mermaidRef.current;
39
if (!elt) {
40
return;
41
}
42
if (!value.trim()) {
43
elt.innerHTML = "";
44
return;
45
}
46
(async () => {
47
try {
48
await waitUntilNotProcessing();
49
processingRef.current = true;
50
setMermaidError("");
51
const mermaid = await getMermaid();
52
const { svg } = await mermaid.render(id, value);
53
elt.innerHTML = svg;
54
} catch (err) {
55
setMermaidError(err.str ?? `${err}`);
56
} finally {
57
processingRef.current = false;
58
}
59
})();
60
}, [value]);
61
62
return (
63
<div style={style}>
64
<pre ref={mermaidRef}></pre>
65
<ShowError error={mermaidError} setError={setMermaidError} />
66
</div>
67
);
68
}
69
70