@haklex/rich-renderer-mermaid 0.15.1 → 0.15.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MermaidEditRenderer.d.ts.map +1 -1
- package/dist/MermaidRenderer-BGh5KLUU.js +148 -0
- package/dist/MermaidRenderer.d.ts.map +1 -1
- package/dist/index.mjs +3 -18
- package/dist/static.mjs +1 -1
- package/dist/useMermaidRender.d.ts +1 -1
- package/dist/useMermaidRender.d.ts.map +1 -1
- package/dist/utils.d.ts +1 -3
- package/dist/utils.d.ts.map +1 -1
- package/package.json +5 -5
- package/dist/MermaidRenderer-DnxSrFxY.js +0 -614
- package/dist/mermaid-theme.d.ts +0 -34
- package/dist/mermaid-theme.d.ts.map +0 -1
- package/dist/svg-post-process.d.ts +0 -3
- package/dist/svg-post-process.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MermaidEditRenderer.d.ts","sourceRoot":"","sources":["../src/MermaidEditRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAiB1E,OAAO,KAAK,EAAe,EAAE,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"MermaidEditRenderer.d.ts","sourceRoot":"","sources":["../src/MermaidEditRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAiB1E,OAAO,KAAK,EAAe,EAAE,EAAE,MAAM,OAAO,CAAC;AAqT7C,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAAC,oBAAoB,CAyDxD,CAAC"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { useColorScheme } from "@haklex/rich-editor/static";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { renderMermaidSVG } from "beautiful-mermaid";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/styles.css.ts
|
|
6
|
+
var mermaidContainer = "_36yqie0";
|
|
7
|
+
var mermaidEditHint = "_36yqie1";
|
|
8
|
+
var zoomControls = "_36yqie2";
|
|
9
|
+
var zoomBtn = "_36yqie3";
|
|
10
|
+
var mermaidError = "_36yqie7";
|
|
11
|
+
var editorPopup = "_36yqie8";
|
|
12
|
+
var editorHeader = "_36yqie9";
|
|
13
|
+
var editorHeaderLeft = "_36yqiea";
|
|
14
|
+
var editorHeaderRight = "_36yqieb";
|
|
15
|
+
var editorSep = "_36yqiec";
|
|
16
|
+
var editorTitle = "_36yqied";
|
|
17
|
+
var editorTplBtn = "_36yqiee";
|
|
18
|
+
var editorViewToggle = "_36yqief";
|
|
19
|
+
var editorViewItem = "_36yqieg";
|
|
20
|
+
var editorViewItemActive = "_36yqieh";
|
|
21
|
+
var editorIconBtn = "_36yqiei";
|
|
22
|
+
var editorBody = "_36yqiej";
|
|
23
|
+
var editorPane = "_36yqiek";
|
|
24
|
+
var editorPaneHalf = "_36yqiel";
|
|
25
|
+
var editorPaneFull = "_36yqiem";
|
|
26
|
+
var editorPaneLabel = "_36yqien";
|
|
27
|
+
var editorPreviewPane = "_36yqieo";
|
|
28
|
+
var editorPreviewWrap = "_36yqiep";
|
|
29
|
+
var editorPreviewEmpty = "_36yqieq";
|
|
30
|
+
var editorPreviewErrorWrap = "_36yqier";
|
|
31
|
+
var editorPreviewErrorIcon = "_36yqies";
|
|
32
|
+
var editorPreviewErrorTitle = "_36yqiet";
|
|
33
|
+
var editorPreviewErrorMsg = "_36yqieu";
|
|
34
|
+
var codeEditor = "_36yqiev";
|
|
35
|
+
var codeGutter = "_36yqiew";
|
|
36
|
+
var codeGutterLine = "_36yqiex";
|
|
37
|
+
var codeArea = "_36yqiey";
|
|
38
|
+
var editorFooter = "_36yqiez";
|
|
39
|
+
var footerActions = "_36yqie13";
|
|
40
|
+
var footerBtnCancel = "_36yqie15 _36yqie14";
|
|
41
|
+
var footerBtnSave = "_36yqie16 _36yqie14";
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/useMermaidRender.ts
|
|
44
|
+
var LIGHT_PALETTE = {
|
|
45
|
+
bg: "#ffffff",
|
|
46
|
+
fg: "#262626"
|
|
47
|
+
};
|
|
48
|
+
var DARK_PALETTE = {
|
|
49
|
+
bg: "#171717",
|
|
50
|
+
fg: "#fafafa"
|
|
51
|
+
};
|
|
52
|
+
function svgToDataUrl(svg) {
|
|
53
|
+
const bytes = new TextEncoder().encode(svg);
|
|
54
|
+
let binary = "";
|
|
55
|
+
for (const byte of bytes) binary += String.fromCodePoint(byte);
|
|
56
|
+
return `data:image/svg+xml;base64,${btoa(binary)}`;
|
|
57
|
+
}
|
|
58
|
+
function readDimensions(svg) {
|
|
59
|
+
const match = svg.match(/viewBox="\s*(?:[\d.-]+\s+){2}([\d.]+)\s+([\d.]+)/);
|
|
60
|
+
if (!match) return {};
|
|
61
|
+
return {
|
|
62
|
+
width: Number.parseFloat(match[1]),
|
|
63
|
+
height: Number.parseFloat(match[2])
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function useMermaidRender(content, preferredColorScheme) {
|
|
67
|
+
const colorScheme = useColorScheme();
|
|
68
|
+
const effectiveColorScheme = preferredColorScheme ?? colorScheme;
|
|
69
|
+
return useMemo(() => {
|
|
70
|
+
if (!content) return {
|
|
71
|
+
loading: false,
|
|
72
|
+
error: "",
|
|
73
|
+
svg: "",
|
|
74
|
+
imgSrc: "",
|
|
75
|
+
width: void 0,
|
|
76
|
+
height: void 0
|
|
77
|
+
};
|
|
78
|
+
try {
|
|
79
|
+
const palette = effectiveColorScheme === "dark" ? DARK_PALETTE : LIGHT_PALETTE;
|
|
80
|
+
const svg = renderMermaidSVG(content, {
|
|
81
|
+
bg: palette.bg,
|
|
82
|
+
fg: palette.fg
|
|
83
|
+
});
|
|
84
|
+
const { width, height } = readDimensions(svg);
|
|
85
|
+
return {
|
|
86
|
+
loading: false,
|
|
87
|
+
error: "",
|
|
88
|
+
svg,
|
|
89
|
+
imgSrc: svgToDataUrl(svg),
|
|
90
|
+
width,
|
|
91
|
+
height
|
|
92
|
+
};
|
|
93
|
+
} catch (err) {
|
|
94
|
+
return {
|
|
95
|
+
loading: false,
|
|
96
|
+
error: err instanceof Error ? err.message : String(err),
|
|
97
|
+
svg: "",
|
|
98
|
+
imgSrc: "",
|
|
99
|
+
width: void 0,
|
|
100
|
+
height: void 0
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}, [content, effectiveColorScheme]);
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region src/estimate-height.ts
|
|
107
|
+
function estimateMermaidHeight(content) {
|
|
108
|
+
const lines = content.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("%%"));
|
|
109
|
+
const first = (lines[0] ?? "").toLowerCase();
|
|
110
|
+
let h;
|
|
111
|
+
if (first.startsWith("sequencediagram")) h = lines.length * 50 + 60;
|
|
112
|
+
else if (first.startsWith("gantt")) h = lines.length * 36 + 80;
|
|
113
|
+
else if (first.startsWith("pie")) h = 320;
|
|
114
|
+
else if (first.startsWith("flowchart lr") || first.startsWith("graph lr") || first.startsWith("flowchart rl") || first.startsWith("graph rl")) h = lines.length * 30 + 100;
|
|
115
|
+
else if (first.startsWith("classdiagram")) h = lines.length * 40 + 100;
|
|
116
|
+
else if (first.startsWith("statediagram")) h = lines.length * 50 + 80;
|
|
117
|
+
else if (first.startsWith("erdiagram")) h = lines.length * 60 + 80;
|
|
118
|
+
else if (first.startsWith("journey")) h = lines.length * 40 + 80;
|
|
119
|
+
else if (first.startsWith("mindmap")) h = lines.length * 50 + 100;
|
|
120
|
+
else h = lines.length * 60 + 80;
|
|
121
|
+
return Math.min(Math.max(Math.round(h), 200), 800);
|
|
122
|
+
}
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/MermaidRenderer.tsx
|
|
125
|
+
var MermaidRenderer = ({ content, colorScheme }) => {
|
|
126
|
+
const { error, imgSrc, width, height } = useMermaidRender(content, colorScheme);
|
|
127
|
+
const wrapperStyle = { minHeight: estimateMermaidHeight(content) };
|
|
128
|
+
if (!imgSrc) return /* @__PURE__ */ jsx("div", {
|
|
129
|
+
className: mermaidError,
|
|
130
|
+
style: wrapperStyle,
|
|
131
|
+
children: error || "Render failed"
|
|
132
|
+
});
|
|
133
|
+
return /* @__PURE__ */ jsx("div", {
|
|
134
|
+
className: mermaidContainer,
|
|
135
|
+
style: {
|
|
136
|
+
...wrapperStyle,
|
|
137
|
+
cursor: "default"
|
|
138
|
+
},
|
|
139
|
+
children: /* @__PURE__ */ jsx("img", {
|
|
140
|
+
alt: "Mermaid diagram",
|
|
141
|
+
height,
|
|
142
|
+
src: imgSrc,
|
|
143
|
+
width
|
|
144
|
+
})
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
//#endregion
|
|
148
|
+
export { editorViewToggle as A, editorPreviewPane as C, editorTplBtn as D, editorTitle as E, mermaidEditHint as F, mermaidError as I, zoomBtn as L, footerBtnCancel as M, footerBtnSave as N, editorViewItem as O, mermaidContainer as P, zoomControls as R, editorPreviewErrorWrap as S, editorSep as T, editorPopup as _, codeGutter as a, editorPreviewErrorMsg as b, editorFooter as c, editorHeaderRight as d, editorIconBtn as f, editorPaneLabel as g, editorPaneHalf as h, codeEditor as i, footerActions as j, editorViewItemActive as k, editorHeader as l, editorPaneFull as m, useMermaidRender as n, codeGutterLine as o, editorPane as p, codeArea as r, editorBody as s, MermaidRenderer as t, editorHeaderLeft as u, editorPreviewEmpty as v, editorPreviewWrap as w, editorPreviewErrorTitle as x, editorPreviewErrorIcon as y };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MermaidRenderer.d.ts","sourceRoot":"","sources":["../src/MermaidRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAMhC,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,oBAAoB,GAAG;IAAE,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"MermaidRenderer.d.ts","sourceRoot":"","sources":["../src/MermaidRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAMhC,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,oBAAoB,GAAG;IAAE,WAAW,CAAC,EAAE,WAAW,CAAA;CAAE,CAqBpF,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as editorViewToggle, D as editorTplBtn, E as editorTitle, I as mermaidError, L as
|
|
1
|
+
import { A as editorViewToggle, D as editorTplBtn, E as editorTitle, I as mermaidError, L as zoomBtn, M as footerBtnCancel, N as footerBtnSave, O as editorViewItem, P as mermaidContainer, R as zoomControls, S as editorPreviewErrorWrap, T as editorSep, _ as editorPopup, a as codeGutter, b as editorPreviewErrorMsg, c as editorFooter, d as editorHeaderRight, f as editorIconBtn, i as codeEditor, j as footerActions, k as editorViewItemActive, l as editorHeader, n as useMermaidRender, o as codeGutterLine, r as codeArea, s as editorBody, t as MermaidRenderer, u as editorHeaderLeft, v as editorPreviewEmpty, w as editorPreviewWrap, x as editorPreviewErrorTitle, y as editorPreviewErrorIcon } from "./MermaidRenderer-BGh5KLUU.js";
|
|
2
2
|
import { useColorScheme } from "@haklex/rich-editor/static";
|
|
3
3
|
import { presentDialog, usePortalTheme } from "@haklex/rich-editor-ui";
|
|
4
4
|
import { CircleAlert, Code2, Columns2, Copy, Download, Eye, FishSymbol, Maximize2, RotateCcw, X, ZoomIn, ZoomOut } from "lucide-react";
|
|
@@ -22,10 +22,6 @@ var TEMPLATES = [
|
|
|
22
22
|
{
|
|
23
23
|
label: "State",
|
|
24
24
|
code: "stateDiagram-v2\n [*] --> Idle\n Idle --> Processing: Submit\n Processing --> Success: Complete\n Processing --> Error: Fail\n Error --> Idle: Retry\n Success --> [*]"
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
label: "Git",
|
|
28
|
-
code: "gitGraph\n commit\n branch develop\n checkout develop\n commit\n checkout main\n merge develop\n commit"
|
|
29
25
|
}
|
|
30
26
|
];
|
|
31
27
|
var MermaidLivePreview = ({ code, svgRef, colorScheme }) => {
|
|
@@ -34,7 +30,7 @@ var MermaidLivePreview = ({ code, svgRef, colorScheme }) => {
|
|
|
34
30
|
const t = setTimeout(() => setDebounced(code), 300);
|
|
35
31
|
return () => clearTimeout(t);
|
|
36
32
|
}, [code]);
|
|
37
|
-
const {
|
|
33
|
+
const { error, imgSrc, svg, width, height } = useMermaidRender(debounced, colorScheme);
|
|
38
34
|
useEffect(() => {
|
|
39
35
|
svgRef.current = svg;
|
|
40
36
|
}, [svg, svgRef]);
|
|
@@ -45,13 +41,6 @@ var MermaidLivePreview = ({ code, svgRef, colorScheme }) => {
|
|
|
45
41
|
children: "Enter Mermaid code to see the preview"
|
|
46
42
|
})
|
|
47
43
|
});
|
|
48
|
-
if (loading && !imgSrc) return /* @__PURE__ */ jsx("div", {
|
|
49
|
-
className: editorPreviewWrap,
|
|
50
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
51
|
-
className: mermaidLoading,
|
|
52
|
-
children: "Rendering"
|
|
53
|
-
})
|
|
54
|
-
});
|
|
55
44
|
if (error && !imgSrc) return /* @__PURE__ */ jsx("div", {
|
|
56
45
|
className: editorPreviewWrap,
|
|
57
46
|
children: /* @__PURE__ */ jsxs("div", {
|
|
@@ -312,7 +301,7 @@ var ZoomControls = () => {
|
|
|
312
301
|
};
|
|
313
302
|
var MermaidEditRenderer = ({ content, onContentChange }) => {
|
|
314
303
|
const colorScheme = useColorScheme();
|
|
315
|
-
const {
|
|
304
|
+
const { error, imgSrc, width, height } = useMermaidRender(content);
|
|
316
305
|
const { className: portalClassName } = usePortalTheme();
|
|
317
306
|
const handleClick = useCallback(() => {
|
|
318
307
|
if (!onContentChange) return;
|
|
@@ -335,10 +324,6 @@ var MermaidEditRenderer = ({ content, onContentChange }) => {
|
|
|
335
324
|
portalClassName,
|
|
336
325
|
colorScheme
|
|
337
326
|
]);
|
|
338
|
-
if (loading) return /* @__PURE__ */ jsx("div", {
|
|
339
|
-
className: mermaidLoading,
|
|
340
|
-
children: "Mermaid Loading"
|
|
341
|
-
});
|
|
342
327
|
if (!imgSrc) return /* @__PURE__ */ jsx("div", {
|
|
343
328
|
className: mermaidError,
|
|
344
329
|
children: error || "Render failed"
|
package/dist/static.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as MermaidRenderer } from "./MermaidRenderer-
|
|
1
|
+
import { t as MermaidRenderer } from "./MermaidRenderer-BGh5KLUU.js";
|
|
2
2
|
export { MermaidRenderer };
|
|
@@ -2,8 +2,8 @@ import { ColorScheme } from '@haklex/rich-editor/static';
|
|
|
2
2
|
export declare function useMermaidRender(content: string, preferredColorScheme?: ColorScheme): {
|
|
3
3
|
loading: boolean;
|
|
4
4
|
error: string;
|
|
5
|
-
imgSrc: string;
|
|
6
5
|
svg: string;
|
|
6
|
+
imgSrc: string;
|
|
7
7
|
width: number | undefined;
|
|
8
8
|
height: number | undefined;
|
|
9
9
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMermaidRender.d.ts","sourceRoot":"","sources":["../src/useMermaidRender.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"useMermaidRender.d.ts","sourceRoot":"","sources":["../src/useMermaidRender.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAwB9D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,WAAW;;;;;WAWxD,MAAM,GAAG,SAAS;YACjB,MAAM,GAAG,SAAS;EA8B9C"}
|
package/dist/utils.d.ts
CHANGED
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haklex/rich-renderer-mermaid",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.4",
|
|
4
4
|
"description": "Mermaid diagram renderer",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"dist"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"mermaid": "^
|
|
32
|
+
"beautiful-mermaid": "^1.1.3",
|
|
33
33
|
"react-zoom-pan-pinch": "^4.0.3"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
"lucide-react": "^1.0.0",
|
|
48
48
|
"react": ">=19",
|
|
49
49
|
"react-dom": ">=19",
|
|
50
|
-
"@haklex/rich-editor": "0.15.
|
|
51
|
-
"@haklex/rich-
|
|
52
|
-
"@haklex/rich-
|
|
50
|
+
"@haklex/rich-editor": "0.15.4",
|
|
51
|
+
"@haklex/rich-editor-ui": "0.15.4",
|
|
52
|
+
"@haklex/rich-style-token": "0.15.4"
|
|
53
53
|
},
|
|
54
54
|
"publishConfig": {
|
|
55
55
|
"access": "public"
|
|
@@ -1,614 +0,0 @@
|
|
|
1
|
-
import { useColorScheme } from "@haklex/rich-editor/static";
|
|
2
|
-
import { useEffect, useId, useState } from "react";
|
|
3
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
-
//#region src/styles.css.ts
|
|
5
|
-
var mermaidContainer = "_36yqie0";
|
|
6
|
-
var mermaidEditHint = "_36yqie1";
|
|
7
|
-
var zoomControls = "_36yqie2";
|
|
8
|
-
var zoomBtn = "_36yqie3";
|
|
9
|
-
var mermaidLoading = "_36yqie4";
|
|
10
|
-
var mermaidSpinner = "_36yqie6";
|
|
11
|
-
var mermaidError = "_36yqie7";
|
|
12
|
-
var editorPopup = "_36yqie8";
|
|
13
|
-
var editorHeader = "_36yqie9";
|
|
14
|
-
var editorHeaderLeft = "_36yqiea";
|
|
15
|
-
var editorHeaderRight = "_36yqieb";
|
|
16
|
-
var editorSep = "_36yqiec";
|
|
17
|
-
var editorTitle = "_36yqied";
|
|
18
|
-
var editorTplBtn = "_36yqiee";
|
|
19
|
-
var editorViewToggle = "_36yqief";
|
|
20
|
-
var editorViewItem = "_36yqieg";
|
|
21
|
-
var editorViewItemActive = "_36yqieh";
|
|
22
|
-
var editorIconBtn = "_36yqiei";
|
|
23
|
-
var editorBody = "_36yqiej";
|
|
24
|
-
var editorPane = "_36yqiek";
|
|
25
|
-
var editorPaneHalf = "_36yqiel";
|
|
26
|
-
var editorPaneFull = "_36yqiem";
|
|
27
|
-
var editorPaneLabel = "_36yqien";
|
|
28
|
-
var editorPreviewPane = "_36yqieo";
|
|
29
|
-
var editorPreviewWrap = "_36yqiep";
|
|
30
|
-
var editorPreviewEmpty = "_36yqieq";
|
|
31
|
-
var editorPreviewErrorWrap = "_36yqier";
|
|
32
|
-
var editorPreviewErrorIcon = "_36yqies";
|
|
33
|
-
var editorPreviewErrorTitle = "_36yqiet";
|
|
34
|
-
var editorPreviewErrorMsg = "_36yqieu";
|
|
35
|
-
var codeEditor = "_36yqiev";
|
|
36
|
-
var codeGutter = "_36yqiew";
|
|
37
|
-
var codeGutterLine = "_36yqiex";
|
|
38
|
-
var codeArea = "_36yqiey";
|
|
39
|
-
var editorFooter = "_36yqiez";
|
|
40
|
-
var footerActions = "_36yqie13";
|
|
41
|
-
var footerBtnCancel = "_36yqie15 _36yqie14";
|
|
42
|
-
var footerBtnSave = "_36yqie16 _36yqie14";
|
|
43
|
-
//#endregion
|
|
44
|
-
//#region src/mermaid-theme.ts
|
|
45
|
-
var MIX = {
|
|
46
|
-
text: 100,
|
|
47
|
-
textSec: 60,
|
|
48
|
-
textMuted: 40,
|
|
49
|
-
textFaint: 25,
|
|
50
|
-
line: 50,
|
|
51
|
-
arrow: 85,
|
|
52
|
-
nodeFill: 3,
|
|
53
|
-
nodeStroke: 20,
|
|
54
|
-
groupHeader: 5,
|
|
55
|
-
innerStroke: 12
|
|
56
|
-
};
|
|
57
|
-
function parseHex(hex) {
|
|
58
|
-
return [
|
|
59
|
-
Number.parseInt(hex.slice(1, 3), 16),
|
|
60
|
-
Number.parseInt(hex.slice(3, 5), 16),
|
|
61
|
-
Number.parseInt(hex.slice(5, 7), 16)
|
|
62
|
-
];
|
|
63
|
-
}
|
|
64
|
-
function toHex(r, g, b) {
|
|
65
|
-
const clamp = (v) => Math.round(Math.max(0, Math.min(255, v)));
|
|
66
|
-
return `#${clamp(r).toString(16).padStart(2, "0")}${clamp(g).toString(16).padStart(2, "0")}${clamp(b).toString(16).padStart(2, "0")}`;
|
|
67
|
-
}
|
|
68
|
-
function mix(fg, bg, percent) {
|
|
69
|
-
const [fR, fG, fB] = parseHex(fg);
|
|
70
|
-
const [bR, bG, bB] = parseHex(bg);
|
|
71
|
-
const p = percent / 100;
|
|
72
|
-
return toHex(fR * p + bR * (1 - p), fG * p + bG * (1 - p), fB * p + bB * (1 - p));
|
|
73
|
-
}
|
|
74
|
-
function deriveTokens(bg, fg) {
|
|
75
|
-
return {
|
|
76
|
-
bg,
|
|
77
|
-
fg,
|
|
78
|
-
line: mix(fg, bg, MIX.line),
|
|
79
|
-
arrow: mix(fg, bg, MIX.arrow),
|
|
80
|
-
nodeFill: mix(fg, bg, MIX.nodeFill),
|
|
81
|
-
nodeStroke: mix(fg, bg, MIX.nodeStroke),
|
|
82
|
-
groupHeader: mix(fg, bg, MIX.groupHeader),
|
|
83
|
-
innerStroke: mix(fg, bg, MIX.innerStroke),
|
|
84
|
-
textSec: mix(fg, bg, MIX.textSec),
|
|
85
|
-
textMuted: mix(fg, bg, MIX.textMuted),
|
|
86
|
-
textFaint: mix(fg, bg, MIX.textFaint)
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
function buildTheme(bg, fg) {
|
|
90
|
-
const t = deriveTokens(bg, fg);
|
|
91
|
-
return {
|
|
92
|
-
theme: "base",
|
|
93
|
-
themeVariables: {
|
|
94
|
-
background: t.bg,
|
|
95
|
-
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
96
|
-
fontSize: "14px",
|
|
97
|
-
primaryColor: t.nodeFill,
|
|
98
|
-
primaryTextColor: t.fg,
|
|
99
|
-
primaryBorderColor: t.nodeStroke,
|
|
100
|
-
secondaryColor: t.nodeFill,
|
|
101
|
-
secondaryTextColor: t.fg,
|
|
102
|
-
secondaryBorderColor: t.innerStroke,
|
|
103
|
-
tertiaryColor: t.groupHeader,
|
|
104
|
-
tertiaryTextColor: t.fg,
|
|
105
|
-
tertiaryBorderColor: t.innerStroke,
|
|
106
|
-
noteBkgColor: t.nodeFill,
|
|
107
|
-
noteTextColor: t.fg,
|
|
108
|
-
noteBorderColor: t.innerStroke,
|
|
109
|
-
lineColor: t.line,
|
|
110
|
-
textColor: t.fg,
|
|
111
|
-
mainBkg: t.nodeFill,
|
|
112
|
-
nodeBorder: t.nodeStroke,
|
|
113
|
-
nodeTextColor: t.fg,
|
|
114
|
-
clusterBkg: t.bg,
|
|
115
|
-
clusterBorder: t.nodeStroke,
|
|
116
|
-
titleColor: t.fg,
|
|
117
|
-
labelColor: t.fg,
|
|
118
|
-
altBackground: t.nodeFill,
|
|
119
|
-
fillType0: t.nodeFill,
|
|
120
|
-
fillType1: t.groupHeader,
|
|
121
|
-
fillType2: mix(fg, bg, 7),
|
|
122
|
-
fillType3: t.innerStroke,
|
|
123
|
-
fillType4: t.nodeStroke,
|
|
124
|
-
fillType5: t.groupHeader,
|
|
125
|
-
fillType6: t.nodeFill,
|
|
126
|
-
fillType7: mix(fg, bg, 7),
|
|
127
|
-
actorBkg: t.nodeFill,
|
|
128
|
-
actorBorder: t.nodeStroke,
|
|
129
|
-
actorTextColor: t.fg,
|
|
130
|
-
actorLineColor: t.line,
|
|
131
|
-
signalColor: t.fg,
|
|
132
|
-
signalTextColor: t.fg,
|
|
133
|
-
labelBoxBkgColor: t.nodeFill,
|
|
134
|
-
labelBoxBorderColor: t.nodeStroke,
|
|
135
|
-
labelTextColor: t.fg,
|
|
136
|
-
loopTextColor: t.fg,
|
|
137
|
-
activationBorderColor: t.line,
|
|
138
|
-
activationBkgColor: t.innerStroke,
|
|
139
|
-
sequenceNumberColor: t.bg,
|
|
140
|
-
git0: t.fg,
|
|
141
|
-
git1: t.line,
|
|
142
|
-
git2: t.textMuted,
|
|
143
|
-
git3: t.textFaint,
|
|
144
|
-
git4: t.nodeStroke,
|
|
145
|
-
git5: t.innerStroke,
|
|
146
|
-
git6: t.groupHeader,
|
|
147
|
-
git7: t.nodeFill,
|
|
148
|
-
gitBranchLabel0: t.bg,
|
|
149
|
-
gitBranchLabel1: t.bg,
|
|
150
|
-
gitBranchLabel2: t.bg,
|
|
151
|
-
gitBranchLabel3: t.fg,
|
|
152
|
-
gitInv0: t.bg,
|
|
153
|
-
pie1: t.fg,
|
|
154
|
-
pie2: mix(fg, bg, 80),
|
|
155
|
-
pie3: t.line,
|
|
156
|
-
pie4: t.textMuted,
|
|
157
|
-
pie5: t.nodeStroke,
|
|
158
|
-
pie6: t.innerStroke,
|
|
159
|
-
pie7: mix(fg, bg, 7),
|
|
160
|
-
pie8: t.groupHeader,
|
|
161
|
-
pie9: t.nodeFill,
|
|
162
|
-
pie10: t.bg,
|
|
163
|
-
pie11: t.textSec,
|
|
164
|
-
pie12: t.arrow,
|
|
165
|
-
pieTitleTextColor: t.fg,
|
|
166
|
-
pieSectionTextColor: t.bg,
|
|
167
|
-
pieLegendTextColor: t.fg,
|
|
168
|
-
pieLegendTextSize: "14px",
|
|
169
|
-
pieStrokeColor: t.bg,
|
|
170
|
-
pieStrokeWidth: "2px",
|
|
171
|
-
classText: t.fg,
|
|
172
|
-
sectionBkgColor: t.nodeFill,
|
|
173
|
-
altSectionBkgColor: t.groupHeader,
|
|
174
|
-
sectionBkgColor2: mix(fg, bg, 7),
|
|
175
|
-
taskBkgColor: t.innerStroke,
|
|
176
|
-
taskTextColor: t.fg,
|
|
177
|
-
taskTextLightColor: t.fg,
|
|
178
|
-
taskTextOutsideColor: t.fg,
|
|
179
|
-
activeTaskBkgColor: t.nodeStroke,
|
|
180
|
-
activeTaskBorderColor: t.line,
|
|
181
|
-
gridColor: t.innerStroke,
|
|
182
|
-
doneTaskBkgColor: t.nodeStroke,
|
|
183
|
-
doneTaskBorderColor: t.line,
|
|
184
|
-
critBkgColor: t.fg,
|
|
185
|
-
critBorderColor: t.fg,
|
|
186
|
-
todayLineColor: t.fg,
|
|
187
|
-
requirementBackground: t.nodeFill,
|
|
188
|
-
requirementBorderColor: t.nodeStroke,
|
|
189
|
-
requirementBorderSize: "1px",
|
|
190
|
-
requirementTextColor: t.fg,
|
|
191
|
-
relationColor: t.line,
|
|
192
|
-
relationLabelBackground: t.bg,
|
|
193
|
-
relationLabelColor: t.fg,
|
|
194
|
-
edgeLabelBackground: t.bg,
|
|
195
|
-
cScale0: t.nodeFill,
|
|
196
|
-
cScale1: t.innerStroke,
|
|
197
|
-
cScale2: t.nodeStroke,
|
|
198
|
-
cScale3: t.textMuted,
|
|
199
|
-
cScale4: t.line,
|
|
200
|
-
cScale5: t.textSec,
|
|
201
|
-
cScale6: mix(fg, bg, 70),
|
|
202
|
-
cScale7: mix(fg, bg, 80),
|
|
203
|
-
cScale8: t.arrow,
|
|
204
|
-
cScale9: t.fg,
|
|
205
|
-
cScaleLabel0: t.fg,
|
|
206
|
-
cScaleLabel2: t.fg
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
var lightTheme = buildTheme("#ffffff", "#262626");
|
|
211
|
-
var darkTheme = buildTheme("#171717", "#fafafa");
|
|
212
|
-
var lightTokens = deriveTokens("#ffffff", "#262626");
|
|
213
|
-
var darkTokens = deriveTokens("#171717", "#fafafa");
|
|
214
|
-
//#endregion
|
|
215
|
-
//#region src/svg-post-process.ts
|
|
216
|
-
var CORNER_RADIUS = {
|
|
217
|
-
node: 5,
|
|
218
|
-
classNode: 4,
|
|
219
|
-
entity: 5,
|
|
220
|
-
subgraphOuter: 7,
|
|
221
|
-
subgraphHeader: 6,
|
|
222
|
-
actor: 6,
|
|
223
|
-
activation: 4,
|
|
224
|
-
diamond: 4
|
|
225
|
-
};
|
|
226
|
-
/**
|
|
227
|
-
* Convert node <polygon> elements to <path> with rounded corners.
|
|
228
|
-
* Handles diamonds (4pt), hexagons (6pt), asymmetric (5pt), etc.
|
|
229
|
-
* Each corner is replaced by a quadratic bezier curve.
|
|
230
|
-
*/
|
|
231
|
-
function roundNodePolygons(doc, radius) {
|
|
232
|
-
const polygons = doc.querySelectorAll(".node > polygon, .node polygon");
|
|
233
|
-
for (const polygon of polygons) {
|
|
234
|
-
const points = polygon.points;
|
|
235
|
-
if (points.numberOfItems < 3) continue;
|
|
236
|
-
const pts = [];
|
|
237
|
-
for (let i = 0; i < points.numberOfItems; i++) {
|
|
238
|
-
const p = points.getItem(i);
|
|
239
|
-
pts.push([p.x, p.y]);
|
|
240
|
-
}
|
|
241
|
-
const d = pts.map((pt, i) => {
|
|
242
|
-
const prev = pts[(i + pts.length - 1) % pts.length];
|
|
243
|
-
const next = pts[(i + 1) % pts.length];
|
|
244
|
-
const dx1 = prev[0] - pt[0];
|
|
245
|
-
const dy1 = prev[1] - pt[1];
|
|
246
|
-
const len1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
|
|
247
|
-
const dx2 = next[0] - pt[0];
|
|
248
|
-
const dy2 = next[1] - pt[1];
|
|
249
|
-
const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
|
|
250
|
-
const r = Math.min(radius, len1 / 2, len2 / 2);
|
|
251
|
-
const startX = pt[0] + dx1 / len1 * r;
|
|
252
|
-
const startY = pt[1] + dy1 / len1 * r;
|
|
253
|
-
const endX = pt[0] + dx2 / len2 * r;
|
|
254
|
-
const endY = pt[1] + dy2 / len2 * r;
|
|
255
|
-
return `${i === 0 ? "M" : "L"}${startX},${startY} Q${pt[0]},${pt[1]} ${endX},${endY}`;
|
|
256
|
-
}).join(" ");
|
|
257
|
-
const path = doc.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
258
|
-
path.setAttribute("d", `${d} Z`);
|
|
259
|
-
for (const attr of Array.from(polygon.attributes)) if (attr.name !== "points") path.setAttribute(attr.name, attr.value);
|
|
260
|
-
polygon.replaceWith(path);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
function applyCornerRounding(doc) {
|
|
264
|
-
const applyRadius = (selector, radius) => {
|
|
265
|
-
const rects = doc.querySelectorAll(selector);
|
|
266
|
-
for (const rect of rects) {
|
|
267
|
-
rect.setAttribute("rx", String(radius));
|
|
268
|
-
rect.setAttribute("ry", String(radius));
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
applyRadius(".node > rect", CORNER_RADIUS.node);
|
|
272
|
-
applyRadius(".node > .basic", CORNER_RADIUS.node);
|
|
273
|
-
applyRadius(".classGroup > rect", CORNER_RADIUS.classNode);
|
|
274
|
-
applyRadius(".er > rect", CORNER_RADIUS.entity);
|
|
275
|
-
applyRadius(".cluster > rect", CORNER_RADIUS.subgraphOuter);
|
|
276
|
-
applyRadius(".actor", CORNER_RADIUS.actor);
|
|
277
|
-
applyRadius(".activation0, .activation1, .activation2", CORNER_RADIUS.activation);
|
|
278
|
-
roundNodePolygons(doc, CORNER_RADIUS.diamond);
|
|
279
|
-
}
|
|
280
|
-
function buildVisualCss(tokens) {
|
|
281
|
-
return `
|
|
282
|
-
/* beautiful-mermaid inspired visual overrides */
|
|
283
|
-
|
|
284
|
-
/* Edge styling: rounded linecaps for clean connections */
|
|
285
|
-
.edgePath path.path,
|
|
286
|
-
.flowchart-link,
|
|
287
|
-
line[class*="messageLine"] {
|
|
288
|
-
stroke-linecap: round !important;
|
|
289
|
-
stroke-linejoin: round !important;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/* Cluster/subgraph "soft" styling */
|
|
293
|
-
.cluster > rect {
|
|
294
|
-
fill: ${tokens.nodeFill} !important;
|
|
295
|
-
fill-opacity: 0.96 !important;
|
|
296
|
-
stroke: ${tokens.nodeStroke} !important;
|
|
297
|
-
stroke-width: 1px !important;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/* Cluster title */
|
|
301
|
-
.cluster text,
|
|
302
|
-
.cluster .nodeLabel {
|
|
303
|
-
fill: ${tokens.textSec} !important;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/* Node stroke consistency */
|
|
307
|
-
.node rect,
|
|
308
|
-
.node circle,
|
|
309
|
-
.node ellipse,
|
|
310
|
-
.node polygon,
|
|
311
|
-
.node .basic {
|
|
312
|
-
stroke: ${tokens.nodeStroke} !important;
|
|
313
|
-
stroke-width: 1px !important;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
/* Node fill */
|
|
317
|
-
.node rect,
|
|
318
|
-
.node .basic {
|
|
319
|
-
fill: ${tokens.nodeFill} !important;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/* Edge label "subtle" styling */
|
|
323
|
-
.edgeLabel rect,
|
|
324
|
-
.labelBkg {
|
|
325
|
-
rx: 5 !important;
|
|
326
|
-
ry: 5 !important;
|
|
327
|
-
fill: ${tokens.bg} !important;
|
|
328
|
-
stroke: ${tokens.innerStroke} !important;
|
|
329
|
-
stroke-width: 1px !important;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
.edgeLabel text,
|
|
333
|
-
.edgeLabel .edgeLabel {
|
|
334
|
-
fill: ${tokens.textMuted} !important;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/* Arrow heads */
|
|
338
|
-
marker path {
|
|
339
|
-
fill: ${tokens.arrow} !important;
|
|
340
|
-
stroke: ${tokens.arrow} !important;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/* Edge paths */
|
|
344
|
-
.edgePath path.path {
|
|
345
|
-
stroke: ${tokens.line} !important;
|
|
346
|
-
stroke-width: 1px !important;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
/* Sequence diagram refinements */
|
|
350
|
-
.actor {
|
|
351
|
-
fill: ${tokens.nodeFill} !important;
|
|
352
|
-
stroke: ${tokens.nodeStroke} !important;
|
|
353
|
-
stroke-width: 1px !important;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
.messageLine0,
|
|
357
|
-
.messageLine1 {
|
|
358
|
-
stroke: ${tokens.line} !important;
|
|
359
|
-
stroke-width: 1px !important;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
.messageText {
|
|
363
|
-
fill: ${tokens.fg} !important;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
.loopLine {
|
|
367
|
-
stroke: ${tokens.innerStroke} !important;
|
|
368
|
-
stroke-width: 1px !important;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
.labelBox {
|
|
372
|
-
fill: ${tokens.nodeFill} !important;
|
|
373
|
-
stroke: ${tokens.nodeStroke} !important;
|
|
374
|
-
stroke-width: 1px !important;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
.loopText tspan,
|
|
378
|
-
.loopText {
|
|
379
|
-
fill: ${tokens.textSec} !important;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
/* Activation bars */
|
|
383
|
-
.activation0,
|
|
384
|
-
.activation1,
|
|
385
|
-
.activation2 {
|
|
386
|
-
fill: ${tokens.innerStroke} !important;
|
|
387
|
-
stroke: ${tokens.line} !important;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/* Note styling */
|
|
391
|
-
.note {
|
|
392
|
-
fill: ${tokens.nodeFill} !important;
|
|
393
|
-
stroke: ${tokens.innerStroke} !important;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
.noteText {
|
|
397
|
-
fill: ${tokens.fg} !important;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/* Inner divider lines */
|
|
401
|
-
.divider {
|
|
402
|
-
stroke: ${tokens.innerStroke} !important;
|
|
403
|
-
stroke-width: 0.75px !important;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
/* Class diagram */
|
|
407
|
-
.classGroup rect {
|
|
408
|
-
fill: ${tokens.nodeFill} !important;
|
|
409
|
-
stroke: ${tokens.nodeStroke} !important;
|
|
410
|
-
stroke-width: 1px !important;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
.classGroup line {
|
|
414
|
-
stroke: ${tokens.innerStroke} !important;
|
|
415
|
-
stroke-width: 0.75px !important;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
.classGroup text {
|
|
419
|
-
fill: ${tokens.fg} !important;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
.classLabel .box {
|
|
423
|
-
fill: ${tokens.groupHeader} !important;
|
|
424
|
-
stroke: ${tokens.nodeStroke} !important;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
.relation {
|
|
428
|
-
stroke: ${tokens.line} !important;
|
|
429
|
-
stroke-width: 1px !important;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
/* State diagram */
|
|
433
|
-
.stateGroup rect,
|
|
434
|
-
.statediagram-state rect {
|
|
435
|
-
fill: ${tokens.nodeFill} !important;
|
|
436
|
-
stroke: ${tokens.nodeStroke} !important;
|
|
437
|
-
stroke-width: 1px !important;
|
|
438
|
-
rx: 5 !important;
|
|
439
|
-
ry: 5 !important;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
.stateGroup text {
|
|
443
|
-
fill: ${tokens.fg} !important;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
/* Git graph */
|
|
447
|
-
.commit-id text {
|
|
448
|
-
fill: ${tokens.textMuted} !important;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
`;
|
|
452
|
-
}
|
|
453
|
-
function postProcessMermaidSvg(svg, tokens) {
|
|
454
|
-
const normalizedSvg = svg.replaceAll(/<br\s*>/gi, "<br/>");
|
|
455
|
-
const doc = new DOMParser().parseFromString(normalizedSvg, "image/svg+xml");
|
|
456
|
-
if (doc.querySelector("parsererror")) return normalizedSvg;
|
|
457
|
-
const root = doc.documentElement;
|
|
458
|
-
if (!root || root.tagName.toLowerCase() !== "svg") return normalizedSvg;
|
|
459
|
-
applyCornerRounding(doc);
|
|
460
|
-
const viewBox = root.getAttribute("viewBox");
|
|
461
|
-
if (viewBox) {
|
|
462
|
-
const parts = viewBox.split(/\s+/).map(Number);
|
|
463
|
-
if (parts.length === 4 && parts[2] > 0 && parts[3] > 0) {
|
|
464
|
-
root.setAttribute("width", String(parts[2]));
|
|
465
|
-
root.setAttribute("height", String(parts[3]));
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
root.querySelector("style[data-visual-overrides]")?.remove();
|
|
469
|
-
const styleEl = doc.createElementNS("http://www.w3.org/2000/svg", "style");
|
|
470
|
-
styleEl.dataset.visualOverrides = "";
|
|
471
|
-
styleEl.textContent = buildVisualCss(tokens);
|
|
472
|
-
if (root.firstChild) root.insertBefore(styleEl, root.firstChild);
|
|
473
|
-
else root.append(styleEl);
|
|
474
|
-
return new XMLSerializer().serializeToString(root);
|
|
475
|
-
}
|
|
476
|
-
//#endregion
|
|
477
|
-
//#region src/useMermaidRender.ts
|
|
478
|
-
function useMermaidRender(content, preferredColorScheme) {
|
|
479
|
-
const [loading, setLoading] = useState(true);
|
|
480
|
-
const [error, setError] = useState("");
|
|
481
|
-
const [svg, setSvg] = useState("");
|
|
482
|
-
const [width, setWidth] = useState();
|
|
483
|
-
const [height, setHeight] = useState();
|
|
484
|
-
const colorScheme = useColorScheme();
|
|
485
|
-
const effectiveColorScheme = preferredColorScheme ?? colorScheme;
|
|
486
|
-
const id = useId().split(":").join("");
|
|
487
|
-
useEffect(() => {
|
|
488
|
-
if (!content) return;
|
|
489
|
-
setError("");
|
|
490
|
-
setLoading(true);
|
|
491
|
-
let cancelled = false;
|
|
492
|
-
import("mermaid").then(async (mo) => {
|
|
493
|
-
const mermaid = mo.default;
|
|
494
|
-
const themeConfig = effectiveColorScheme === "dark" ? darkTheme : lightTheme;
|
|
495
|
-
const tokens = effectiveColorScheme === "dark" ? darkTokens : lightTokens;
|
|
496
|
-
mermaid.initialize({
|
|
497
|
-
startOnLoad: false,
|
|
498
|
-
theme: themeConfig.theme,
|
|
499
|
-
themeVariables: themeConfig.themeVariables,
|
|
500
|
-
darkMode: effectiveColorScheme === "dark",
|
|
501
|
-
flowchart: {
|
|
502
|
-
htmlLabels: true,
|
|
503
|
-
curve: "basis",
|
|
504
|
-
padding: 20,
|
|
505
|
-
nodeSpacing: 24,
|
|
506
|
-
rankSpacing: 48
|
|
507
|
-
},
|
|
508
|
-
sequence: {
|
|
509
|
-
actorMargin: 80,
|
|
510
|
-
messageMargin: 40
|
|
511
|
-
},
|
|
512
|
-
gantt: {
|
|
513
|
-
titleTopMargin: 16,
|
|
514
|
-
barHeight: 24,
|
|
515
|
-
barGap: 6
|
|
516
|
-
}
|
|
517
|
-
});
|
|
518
|
-
let result;
|
|
519
|
-
try {
|
|
520
|
-
result = await mermaid.render(`mermaid-${id}`, content);
|
|
521
|
-
} catch (err) {
|
|
522
|
-
document.getElementById(`dmermaid-${id}`)?.remove();
|
|
523
|
-
if (err instanceof Error) setError(err.message);
|
|
524
|
-
setSvg("");
|
|
525
|
-
setWidth(void 0);
|
|
526
|
-
setHeight(void 0);
|
|
527
|
-
}
|
|
528
|
-
if (cancelled) return;
|
|
529
|
-
if (result) {
|
|
530
|
-
const processedSvg = postProcessMermaidSvg(result.svg, tokens);
|
|
531
|
-
setSvg(processedSvg);
|
|
532
|
-
const match = processedSvg.match(/viewBox="[^"]*\s([\d.]+)\s([\d.]+)"/);
|
|
533
|
-
if (match?.[1] && match?.[2]) {
|
|
534
|
-
setWidth(Number.parseInt(match[1]));
|
|
535
|
-
setHeight(Number.parseInt(match[2]));
|
|
536
|
-
}
|
|
537
|
-
setError("");
|
|
538
|
-
}
|
|
539
|
-
setLoading(false);
|
|
540
|
-
});
|
|
541
|
-
return () => {
|
|
542
|
-
cancelled = true;
|
|
543
|
-
};
|
|
544
|
-
}, [
|
|
545
|
-
id,
|
|
546
|
-
content,
|
|
547
|
-
effectiveColorScheme
|
|
548
|
-
]);
|
|
549
|
-
let imgSrc = "";
|
|
550
|
-
if (svg) {
|
|
551
|
-
const data = new TextEncoder().encode(svg);
|
|
552
|
-
imgSrc = `data:image/svg+xml;base64,${btoa(String.fromCodePoint(...new Uint8Array(data)))}`;
|
|
553
|
-
}
|
|
554
|
-
return {
|
|
555
|
-
loading,
|
|
556
|
-
error,
|
|
557
|
-
imgSrc,
|
|
558
|
-
svg,
|
|
559
|
-
width,
|
|
560
|
-
height
|
|
561
|
-
};
|
|
562
|
-
}
|
|
563
|
-
//#endregion
|
|
564
|
-
//#region src/estimate-height.ts
|
|
565
|
-
function estimateMermaidHeight(content) {
|
|
566
|
-
const lines = content.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("%%"));
|
|
567
|
-
const first = (lines[0] ?? "").toLowerCase();
|
|
568
|
-
let h;
|
|
569
|
-
if (first.startsWith("sequencediagram")) h = lines.length * 50 + 60;
|
|
570
|
-
else if (first.startsWith("gantt")) h = lines.length * 36 + 80;
|
|
571
|
-
else if (first.startsWith("pie")) h = 320;
|
|
572
|
-
else if (first.startsWith("flowchart lr") || first.startsWith("graph lr") || first.startsWith("flowchart rl") || first.startsWith("graph rl")) h = lines.length * 30 + 100;
|
|
573
|
-
else if (first.startsWith("classdiagram")) h = lines.length * 40 + 100;
|
|
574
|
-
else if (first.startsWith("statediagram")) h = lines.length * 50 + 80;
|
|
575
|
-
else if (first.startsWith("erdiagram")) h = lines.length * 60 + 80;
|
|
576
|
-
else if (first.startsWith("journey")) h = lines.length * 40 + 80;
|
|
577
|
-
else if (first.startsWith("mindmap")) h = lines.length * 50 + 100;
|
|
578
|
-
else h = lines.length * 60 + 80;
|
|
579
|
-
return Math.min(Math.max(Math.round(h), 200), 800);
|
|
580
|
-
}
|
|
581
|
-
//#endregion
|
|
582
|
-
//#region src/MermaidRenderer.tsx
|
|
583
|
-
var MermaidRenderer = ({ content, colorScheme }) => {
|
|
584
|
-
const { loading, error, imgSrc, width, height } = useMermaidRender(content, colorScheme);
|
|
585
|
-
const wrapperStyle = { minHeight: estimateMermaidHeight(content) };
|
|
586
|
-
if (loading) return /* @__PURE__ */ jsxs("div", {
|
|
587
|
-
className: mermaidLoading,
|
|
588
|
-
style: wrapperStyle,
|
|
589
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
590
|
-
"aria-hidden": "true",
|
|
591
|
-
className: mermaidSpinner
|
|
592
|
-
}), /* @__PURE__ */ jsx("span", { children: "Rendering diagram…" })]
|
|
593
|
-
});
|
|
594
|
-
if (!imgSrc) return /* @__PURE__ */ jsx("div", {
|
|
595
|
-
className: mermaidError,
|
|
596
|
-
style: wrapperStyle,
|
|
597
|
-
children: error || "Render failed"
|
|
598
|
-
});
|
|
599
|
-
return /* @__PURE__ */ jsx("div", {
|
|
600
|
-
className: mermaidContainer,
|
|
601
|
-
style: {
|
|
602
|
-
...wrapperStyle,
|
|
603
|
-
cursor: "default"
|
|
604
|
-
},
|
|
605
|
-
children: /* @__PURE__ */ jsx("img", {
|
|
606
|
-
alt: "Mermaid diagram",
|
|
607
|
-
height,
|
|
608
|
-
src: imgSrc,
|
|
609
|
-
width
|
|
610
|
-
})
|
|
611
|
-
});
|
|
612
|
-
};
|
|
613
|
-
//#endregion
|
|
614
|
-
export { editorViewToggle as A, editorPreviewPane as C, editorTplBtn as D, editorTitle as E, mermaidEditHint as F, mermaidError as I, mermaidLoading as L, footerBtnCancel as M, footerBtnSave as N, editorViewItem as O, mermaidContainer as P, zoomBtn as R, editorPreviewErrorWrap as S, editorSep as T, editorPopup as _, codeGutter as a, editorPreviewErrorMsg as b, editorFooter as c, editorHeaderRight as d, editorIconBtn as f, editorPaneLabel as g, editorPaneHalf as h, codeEditor as i, footerActions as j, editorViewItemActive as k, editorHeader as l, editorPaneFull as m, useMermaidRender as n, codeGutterLine as o, editorPane as p, codeArea as r, editorBody as s, MermaidRenderer as t, editorHeaderLeft as u, editorPreviewEmpty as v, editorPreviewWrap as w, editorPreviewErrorTitle as x, editorPreviewErrorIcon as y, zoomControls as z };
|
package/dist/mermaid-theme.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mermaid theme system inspired by beautiful-mermaid (lukilabs/beautiful-mermaid).
|
|
3
|
-
*
|
|
4
|
-
* Architecture:
|
|
5
|
-
* - Two base colors: bg (background) + fg (foreground)
|
|
6
|
-
* - All derived colors computed via color-mix ratios from bg + fg
|
|
7
|
-
* - Produces a coherent mono hierarchy on any bg/fg combination
|
|
8
|
-
*
|
|
9
|
-
* @see https://github.com/lukilabs/beautiful-mermaid/blob/main/src/theme.ts
|
|
10
|
-
*/
|
|
11
|
-
interface MermaidThemeConfig {
|
|
12
|
-
theme: 'base';
|
|
13
|
-
themeVariables: Record<string, string>;
|
|
14
|
-
}
|
|
15
|
-
export interface ThemeTokens {
|
|
16
|
-
arrow: string;
|
|
17
|
-
bg: string;
|
|
18
|
-
fg: string;
|
|
19
|
-
groupHeader: string;
|
|
20
|
-
innerStroke: string;
|
|
21
|
-
line: string;
|
|
22
|
-
nodeFill: string;
|
|
23
|
-
nodeStroke: string;
|
|
24
|
-
textFaint: string;
|
|
25
|
-
textMuted: string;
|
|
26
|
-
textSec: string;
|
|
27
|
-
}
|
|
28
|
-
export declare function deriveTokens(bg: string, fg: string): ThemeTokens;
|
|
29
|
-
export declare const lightTheme: MermaidThemeConfig;
|
|
30
|
-
export declare const darkTheme: MermaidThemeConfig;
|
|
31
|
-
export declare const lightTokens: ThemeTokens;
|
|
32
|
-
export declare const darkTokens: ThemeTokens;
|
|
33
|
-
export {};
|
|
34
|
-
//# sourceMappingURL=mermaid-theme.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mermaid-theme.d.ts","sourceRoot":"","sources":["../src/mermaid-theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,UAAU,kBAAkB;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAoCD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,WAAW,CAchE;AAqJD,eAAO,MAAM,UAAU,oBAAmC,CAAC;AAG3D,eAAO,MAAM,SAAS,oBAAmC,CAAC;AAE1D,eAAO,MAAM,WAAW,aAAqC,CAAC;AAC9D,eAAO,MAAM,UAAU,aAAqC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"svg-post-process.d.ts","sourceRoot":"","sources":["../src/svg-post-process.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAmRnD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAmD9E"}
|