@haklex/rich-renderer-mermaid 0.0.80 → 0.0.82
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/MermaidRenderer-DTf6tYSw.js +577 -0
- package/dist/index.mjs +368 -287
- package/dist/rich-renderer-mermaid.css +2 -1
- package/dist/static.mjs +2 -4
- package/package.json +4 -4
- package/dist/MermaidRenderer-v-jwdXd2.js +0 -606
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
import { useColorScheme } from "@haklex/rich-editor";
|
|
2
|
+
import { useEffect, useId, useState } from "react";
|
|
3
|
+
import { jsx } 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 mermaidError = "_36yqie6";
|
|
11
|
+
var editorPopup = "_36yqie7";
|
|
12
|
+
var editorHeader = "_36yqie8";
|
|
13
|
+
var editorHeaderLeft = "_36yqie9";
|
|
14
|
+
var editorHeaderRight = "_36yqiea";
|
|
15
|
+
var editorSep = "_36yqieb";
|
|
16
|
+
var editorTitle = "_36yqiec";
|
|
17
|
+
var editorTplBtn = "_36yqied";
|
|
18
|
+
var editorViewToggle = "_36yqiee";
|
|
19
|
+
var editorViewItem = "_36yqief";
|
|
20
|
+
var editorViewItemActive = "_36yqieg";
|
|
21
|
+
var editorIconBtn = "_36yqieh";
|
|
22
|
+
var editorBody = "_36yqiei";
|
|
23
|
+
var editorPane = "_36yqiej";
|
|
24
|
+
var editorPaneHalf = "_36yqiek";
|
|
25
|
+
var editorPaneFull = "_36yqiel";
|
|
26
|
+
var editorPaneLabel = "_36yqiem";
|
|
27
|
+
var editorPreviewPane = "_36yqien";
|
|
28
|
+
var editorPreviewWrap = "_36yqieo";
|
|
29
|
+
var editorPreviewEmpty = "_36yqiep";
|
|
30
|
+
var editorPreviewErrorWrap = "_36yqieq";
|
|
31
|
+
var editorPreviewErrorIcon = "_36yqier";
|
|
32
|
+
var editorPreviewErrorTitle = "_36yqies";
|
|
33
|
+
var editorPreviewErrorMsg = "_36yqiet";
|
|
34
|
+
var codeEditor = "_36yqieu";
|
|
35
|
+
var codeGutter = "_36yqiev";
|
|
36
|
+
var codeGutterLine = "_36yqiew";
|
|
37
|
+
var codeArea = "_36yqiex";
|
|
38
|
+
var editorFooter = "_36yqiey";
|
|
39
|
+
var footerActions = "_36yqie12";
|
|
40
|
+
var footerBtnCancel = "_36yqie14 _36yqie13";
|
|
41
|
+
var footerBtnSave = "_36yqie15 _36yqie13";
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/mermaid-theme.ts
|
|
44
|
+
var MIX = {
|
|
45
|
+
text: 100,
|
|
46
|
+
textSec: 60,
|
|
47
|
+
textMuted: 40,
|
|
48
|
+
textFaint: 25,
|
|
49
|
+
line: 50,
|
|
50
|
+
arrow: 85,
|
|
51
|
+
nodeFill: 3,
|
|
52
|
+
nodeStroke: 20,
|
|
53
|
+
groupHeader: 5,
|
|
54
|
+
innerStroke: 12
|
|
55
|
+
};
|
|
56
|
+
function parseHex(hex) {
|
|
57
|
+
return [
|
|
58
|
+
Number.parseInt(hex.slice(1, 3), 16),
|
|
59
|
+
Number.parseInt(hex.slice(3, 5), 16),
|
|
60
|
+
Number.parseInt(hex.slice(5, 7), 16)
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
function toHex(r, g, b) {
|
|
64
|
+
const clamp = (v) => Math.round(Math.max(0, Math.min(255, v)));
|
|
65
|
+
return `#${clamp(r).toString(16).padStart(2, "0")}${clamp(g).toString(16).padStart(2, "0")}${clamp(b).toString(16).padStart(2, "0")}`;
|
|
66
|
+
}
|
|
67
|
+
function mix(fg, bg, percent) {
|
|
68
|
+
const [fR, fG, fB] = parseHex(fg);
|
|
69
|
+
const [bR, bG, bB] = parseHex(bg);
|
|
70
|
+
const p = percent / 100;
|
|
71
|
+
return toHex(fR * p + bR * (1 - p), fG * p + bG * (1 - p), fB * p + bB * (1 - p));
|
|
72
|
+
}
|
|
73
|
+
function deriveTokens(bg, fg) {
|
|
74
|
+
return {
|
|
75
|
+
bg,
|
|
76
|
+
fg,
|
|
77
|
+
line: mix(fg, bg, MIX.line),
|
|
78
|
+
arrow: mix(fg, bg, MIX.arrow),
|
|
79
|
+
nodeFill: mix(fg, bg, MIX.nodeFill),
|
|
80
|
+
nodeStroke: mix(fg, bg, MIX.nodeStroke),
|
|
81
|
+
groupHeader: mix(fg, bg, MIX.groupHeader),
|
|
82
|
+
innerStroke: mix(fg, bg, MIX.innerStroke),
|
|
83
|
+
textSec: mix(fg, bg, MIX.textSec),
|
|
84
|
+
textMuted: mix(fg, bg, MIX.textMuted),
|
|
85
|
+
textFaint: mix(fg, bg, MIX.textFaint)
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function buildTheme(bg, fg) {
|
|
89
|
+
const t = deriveTokens(bg, fg);
|
|
90
|
+
return {
|
|
91
|
+
theme: "base",
|
|
92
|
+
themeVariables: {
|
|
93
|
+
background: t.bg,
|
|
94
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
95
|
+
fontSize: "14px",
|
|
96
|
+
primaryColor: t.nodeFill,
|
|
97
|
+
primaryTextColor: t.fg,
|
|
98
|
+
primaryBorderColor: t.nodeStroke,
|
|
99
|
+
secondaryColor: t.nodeFill,
|
|
100
|
+
secondaryTextColor: t.fg,
|
|
101
|
+
secondaryBorderColor: t.innerStroke,
|
|
102
|
+
tertiaryColor: t.groupHeader,
|
|
103
|
+
tertiaryTextColor: t.fg,
|
|
104
|
+
tertiaryBorderColor: t.innerStroke,
|
|
105
|
+
noteBkgColor: t.nodeFill,
|
|
106
|
+
noteTextColor: t.fg,
|
|
107
|
+
noteBorderColor: t.innerStroke,
|
|
108
|
+
lineColor: t.line,
|
|
109
|
+
textColor: t.fg,
|
|
110
|
+
mainBkg: t.nodeFill,
|
|
111
|
+
nodeBorder: t.nodeStroke,
|
|
112
|
+
nodeTextColor: t.fg,
|
|
113
|
+
clusterBkg: t.bg,
|
|
114
|
+
clusterBorder: t.nodeStroke,
|
|
115
|
+
titleColor: t.fg,
|
|
116
|
+
labelColor: t.fg,
|
|
117
|
+
altBackground: t.nodeFill,
|
|
118
|
+
fillType0: t.nodeFill,
|
|
119
|
+
fillType1: t.groupHeader,
|
|
120
|
+
fillType2: mix(fg, bg, 7),
|
|
121
|
+
fillType3: t.innerStroke,
|
|
122
|
+
fillType4: t.nodeStroke,
|
|
123
|
+
fillType5: t.groupHeader,
|
|
124
|
+
fillType6: t.nodeFill,
|
|
125
|
+
fillType7: mix(fg, bg, 7),
|
|
126
|
+
actorBkg: t.nodeFill,
|
|
127
|
+
actorBorder: t.nodeStroke,
|
|
128
|
+
actorTextColor: t.fg,
|
|
129
|
+
actorLineColor: t.line,
|
|
130
|
+
signalColor: t.fg,
|
|
131
|
+
signalTextColor: t.fg,
|
|
132
|
+
labelBoxBkgColor: t.nodeFill,
|
|
133
|
+
labelBoxBorderColor: t.nodeStroke,
|
|
134
|
+
labelTextColor: t.fg,
|
|
135
|
+
loopTextColor: t.fg,
|
|
136
|
+
activationBorderColor: t.line,
|
|
137
|
+
activationBkgColor: t.innerStroke,
|
|
138
|
+
sequenceNumberColor: t.bg,
|
|
139
|
+
git0: t.fg,
|
|
140
|
+
git1: t.line,
|
|
141
|
+
git2: t.textMuted,
|
|
142
|
+
git3: t.textFaint,
|
|
143
|
+
git4: t.nodeStroke,
|
|
144
|
+
git5: t.innerStroke,
|
|
145
|
+
git6: t.groupHeader,
|
|
146
|
+
git7: t.nodeFill,
|
|
147
|
+
gitBranchLabel0: t.bg,
|
|
148
|
+
gitBranchLabel1: t.bg,
|
|
149
|
+
gitBranchLabel2: t.bg,
|
|
150
|
+
gitBranchLabel3: t.fg,
|
|
151
|
+
gitInv0: t.bg,
|
|
152
|
+
pie1: t.fg,
|
|
153
|
+
pie2: mix(fg, bg, 80),
|
|
154
|
+
pie3: t.line,
|
|
155
|
+
pie4: t.textMuted,
|
|
156
|
+
pie5: t.nodeStroke,
|
|
157
|
+
pie6: t.innerStroke,
|
|
158
|
+
pie7: mix(fg, bg, 7),
|
|
159
|
+
pie8: t.groupHeader,
|
|
160
|
+
pie9: t.nodeFill,
|
|
161
|
+
pie10: t.bg,
|
|
162
|
+
pie11: t.textSec,
|
|
163
|
+
pie12: t.arrow,
|
|
164
|
+
pieTitleTextColor: t.fg,
|
|
165
|
+
pieSectionTextColor: t.bg,
|
|
166
|
+
pieLegendTextColor: t.fg,
|
|
167
|
+
pieLegendTextSize: "14px",
|
|
168
|
+
pieStrokeColor: t.bg,
|
|
169
|
+
pieStrokeWidth: "2px",
|
|
170
|
+
classText: t.fg,
|
|
171
|
+
sectionBkgColor: t.nodeFill,
|
|
172
|
+
altSectionBkgColor: t.groupHeader,
|
|
173
|
+
sectionBkgColor2: mix(fg, bg, 7),
|
|
174
|
+
taskBkgColor: t.innerStroke,
|
|
175
|
+
taskTextColor: t.fg,
|
|
176
|
+
taskTextLightColor: t.fg,
|
|
177
|
+
taskTextOutsideColor: t.fg,
|
|
178
|
+
activeTaskBkgColor: t.nodeStroke,
|
|
179
|
+
activeTaskBorderColor: t.line,
|
|
180
|
+
gridColor: t.innerStroke,
|
|
181
|
+
doneTaskBkgColor: t.nodeStroke,
|
|
182
|
+
doneTaskBorderColor: t.line,
|
|
183
|
+
critBkgColor: t.fg,
|
|
184
|
+
critBorderColor: t.fg,
|
|
185
|
+
todayLineColor: t.fg,
|
|
186
|
+
requirementBackground: t.nodeFill,
|
|
187
|
+
requirementBorderColor: t.nodeStroke,
|
|
188
|
+
requirementBorderSize: "1px",
|
|
189
|
+
requirementTextColor: t.fg,
|
|
190
|
+
relationColor: t.line,
|
|
191
|
+
relationLabelBackground: t.bg,
|
|
192
|
+
relationLabelColor: t.fg,
|
|
193
|
+
edgeLabelBackground: t.bg,
|
|
194
|
+
cScale0: t.nodeFill,
|
|
195
|
+
cScale1: t.innerStroke,
|
|
196
|
+
cScale2: t.nodeStroke,
|
|
197
|
+
cScale3: t.textMuted,
|
|
198
|
+
cScale4: t.line,
|
|
199
|
+
cScale5: t.textSec,
|
|
200
|
+
cScale6: mix(fg, bg, 70),
|
|
201
|
+
cScale7: mix(fg, bg, 80),
|
|
202
|
+
cScale8: t.arrow,
|
|
203
|
+
cScale9: t.fg,
|
|
204
|
+
cScaleLabel0: t.fg,
|
|
205
|
+
cScaleLabel2: t.fg
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
var lightTheme = buildTheme("#ffffff", "#27272a");
|
|
210
|
+
var darkTheme = buildTheme("#18181b", "#fafafa");
|
|
211
|
+
var lightTokens = deriveTokens("#ffffff", "#27272a");
|
|
212
|
+
var darkTokens = deriveTokens("#18181b", "#fafafa");
|
|
213
|
+
//#endregion
|
|
214
|
+
//#region src/svg-post-process.ts
|
|
215
|
+
var CORNER_RADIUS = {
|
|
216
|
+
node: 5,
|
|
217
|
+
classNode: 4,
|
|
218
|
+
entity: 5,
|
|
219
|
+
subgraphOuter: 7,
|
|
220
|
+
subgraphHeader: 6,
|
|
221
|
+
actor: 6,
|
|
222
|
+
activation: 4,
|
|
223
|
+
diamond: 4
|
|
224
|
+
};
|
|
225
|
+
/**
|
|
226
|
+
* Convert node <polygon> elements to <path> with rounded corners.
|
|
227
|
+
* Handles diamonds (4pt), hexagons (6pt), asymmetric (5pt), etc.
|
|
228
|
+
* Each corner is replaced by a quadratic bezier curve.
|
|
229
|
+
*/
|
|
230
|
+
function roundNodePolygons(doc, radius) {
|
|
231
|
+
const polygons = doc.querySelectorAll(".node > polygon, .node polygon");
|
|
232
|
+
for (const polygon of polygons) {
|
|
233
|
+
const points = polygon.points;
|
|
234
|
+
if (points.numberOfItems < 3) continue;
|
|
235
|
+
const pts = [];
|
|
236
|
+
for (let i = 0; i < points.numberOfItems; i++) {
|
|
237
|
+
const p = points.getItem(i);
|
|
238
|
+
pts.push([p.x, p.y]);
|
|
239
|
+
}
|
|
240
|
+
const d = pts.map((pt, i) => {
|
|
241
|
+
const prev = pts[(i + pts.length - 1) % pts.length];
|
|
242
|
+
const next = pts[(i + 1) % pts.length];
|
|
243
|
+
const dx1 = prev[0] - pt[0];
|
|
244
|
+
const dy1 = prev[1] - pt[1];
|
|
245
|
+
const len1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
|
|
246
|
+
const dx2 = next[0] - pt[0];
|
|
247
|
+
const dy2 = next[1] - pt[1];
|
|
248
|
+
const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
|
|
249
|
+
const r = Math.min(radius, len1 / 2, len2 / 2);
|
|
250
|
+
const startX = pt[0] + dx1 / len1 * r;
|
|
251
|
+
const startY = pt[1] + dy1 / len1 * r;
|
|
252
|
+
const endX = pt[0] + dx2 / len2 * r;
|
|
253
|
+
const endY = pt[1] + dy2 / len2 * r;
|
|
254
|
+
return `${i === 0 ? "M" : "L"}${startX},${startY} Q${pt[0]},${pt[1]} ${endX},${endY}`;
|
|
255
|
+
}).join(" ");
|
|
256
|
+
const path = doc.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
257
|
+
path.setAttribute("d", `${d} Z`);
|
|
258
|
+
for (const attr of Array.from(polygon.attributes)) if (attr.name !== "points") path.setAttribute(attr.name, attr.value);
|
|
259
|
+
polygon.replaceWith(path);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function applyCornerRounding(doc) {
|
|
263
|
+
const applyRadius = (selector, radius) => {
|
|
264
|
+
const rects = doc.querySelectorAll(selector);
|
|
265
|
+
for (const rect of rects) {
|
|
266
|
+
rect.setAttribute("rx", String(radius));
|
|
267
|
+
rect.setAttribute("ry", String(radius));
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
applyRadius(".node > rect", CORNER_RADIUS.node);
|
|
271
|
+
applyRadius(".node > .basic", CORNER_RADIUS.node);
|
|
272
|
+
applyRadius(".classGroup > rect", CORNER_RADIUS.classNode);
|
|
273
|
+
applyRadius(".er > rect", CORNER_RADIUS.entity);
|
|
274
|
+
applyRadius(".cluster > rect", CORNER_RADIUS.subgraphOuter);
|
|
275
|
+
applyRadius(".actor", CORNER_RADIUS.actor);
|
|
276
|
+
applyRadius(".activation0, .activation1, .activation2", CORNER_RADIUS.activation);
|
|
277
|
+
roundNodePolygons(doc, CORNER_RADIUS.diamond);
|
|
278
|
+
}
|
|
279
|
+
function buildVisualCss(tokens) {
|
|
280
|
+
return `
|
|
281
|
+
/* beautiful-mermaid inspired visual overrides */
|
|
282
|
+
|
|
283
|
+
/* Edge styling: rounded linecaps for clean connections */
|
|
284
|
+
.edgePath path.path,
|
|
285
|
+
.flowchart-link,
|
|
286
|
+
line[class*="messageLine"] {
|
|
287
|
+
stroke-linecap: round !important;
|
|
288
|
+
stroke-linejoin: round !important;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/* Cluster/subgraph "soft" styling */
|
|
292
|
+
.cluster > rect {
|
|
293
|
+
fill: ${tokens.nodeFill} !important;
|
|
294
|
+
fill-opacity: 0.96 !important;
|
|
295
|
+
stroke: ${tokens.nodeStroke} !important;
|
|
296
|
+
stroke-width: 1px !important;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/* Cluster title */
|
|
300
|
+
.cluster text,
|
|
301
|
+
.cluster .nodeLabel {
|
|
302
|
+
fill: ${tokens.textSec} !important;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/* Node stroke consistency */
|
|
306
|
+
.node rect,
|
|
307
|
+
.node circle,
|
|
308
|
+
.node ellipse,
|
|
309
|
+
.node polygon,
|
|
310
|
+
.node .basic {
|
|
311
|
+
stroke: ${tokens.nodeStroke} !important;
|
|
312
|
+
stroke-width: 1px !important;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/* Node fill */
|
|
316
|
+
.node rect,
|
|
317
|
+
.node .basic {
|
|
318
|
+
fill: ${tokens.nodeFill} !important;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* Edge label "subtle" styling */
|
|
322
|
+
.edgeLabel rect,
|
|
323
|
+
.labelBkg {
|
|
324
|
+
rx: 5 !important;
|
|
325
|
+
ry: 5 !important;
|
|
326
|
+
fill: ${tokens.bg} !important;
|
|
327
|
+
stroke: ${tokens.innerStroke} !important;
|
|
328
|
+
stroke-width: 1px !important;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.edgeLabel text,
|
|
332
|
+
.edgeLabel .edgeLabel {
|
|
333
|
+
fill: ${tokens.textMuted} !important;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/* Arrow heads */
|
|
337
|
+
marker path {
|
|
338
|
+
fill: ${tokens.arrow} !important;
|
|
339
|
+
stroke: ${tokens.arrow} !important;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/* Edge paths */
|
|
343
|
+
.edgePath path.path {
|
|
344
|
+
stroke: ${tokens.line} !important;
|
|
345
|
+
stroke-width: 1px !important;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/* Sequence diagram refinements */
|
|
349
|
+
.actor {
|
|
350
|
+
fill: ${tokens.nodeFill} !important;
|
|
351
|
+
stroke: ${tokens.nodeStroke} !important;
|
|
352
|
+
stroke-width: 1px !important;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.messageLine0,
|
|
356
|
+
.messageLine1 {
|
|
357
|
+
stroke: ${tokens.line} !important;
|
|
358
|
+
stroke-width: 1px !important;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.messageText {
|
|
362
|
+
fill: ${tokens.fg} !important;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.loopLine {
|
|
366
|
+
stroke: ${tokens.innerStroke} !important;
|
|
367
|
+
stroke-width: 1px !important;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.labelBox {
|
|
371
|
+
fill: ${tokens.nodeFill} !important;
|
|
372
|
+
stroke: ${tokens.nodeStroke} !important;
|
|
373
|
+
stroke-width: 1px !important;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.loopText tspan,
|
|
377
|
+
.loopText {
|
|
378
|
+
fill: ${tokens.textSec} !important;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/* Activation bars */
|
|
382
|
+
.activation0,
|
|
383
|
+
.activation1,
|
|
384
|
+
.activation2 {
|
|
385
|
+
fill: ${tokens.innerStroke} !important;
|
|
386
|
+
stroke: ${tokens.line} !important;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/* Note styling */
|
|
390
|
+
.note {
|
|
391
|
+
fill: ${tokens.nodeFill} !important;
|
|
392
|
+
stroke: ${tokens.innerStroke} !important;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.noteText {
|
|
396
|
+
fill: ${tokens.fg} !important;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/* Inner divider lines */
|
|
400
|
+
.divider {
|
|
401
|
+
stroke: ${tokens.innerStroke} !important;
|
|
402
|
+
stroke-width: 0.75px !important;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/* Class diagram */
|
|
406
|
+
.classGroup rect {
|
|
407
|
+
fill: ${tokens.nodeFill} !important;
|
|
408
|
+
stroke: ${tokens.nodeStroke} !important;
|
|
409
|
+
stroke-width: 1px !important;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
.classGroup line {
|
|
413
|
+
stroke: ${tokens.innerStroke} !important;
|
|
414
|
+
stroke-width: 0.75px !important;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.classGroup text {
|
|
418
|
+
fill: ${tokens.fg} !important;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.classLabel .box {
|
|
422
|
+
fill: ${tokens.groupHeader} !important;
|
|
423
|
+
stroke: ${tokens.nodeStroke} !important;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.relation {
|
|
427
|
+
stroke: ${tokens.line} !important;
|
|
428
|
+
stroke-width: 1px !important;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/* State diagram */
|
|
432
|
+
.stateGroup rect,
|
|
433
|
+
.statediagram-state rect {
|
|
434
|
+
fill: ${tokens.nodeFill} !important;
|
|
435
|
+
stroke: ${tokens.nodeStroke} !important;
|
|
436
|
+
stroke-width: 1px !important;
|
|
437
|
+
rx: 5 !important;
|
|
438
|
+
ry: 5 !important;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.stateGroup text {
|
|
442
|
+
fill: ${tokens.fg} !important;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/* Git graph */
|
|
446
|
+
.commit-id text {
|
|
447
|
+
fill: ${tokens.textMuted} !important;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
`;
|
|
451
|
+
}
|
|
452
|
+
function postProcessMermaidSvg(svg, tokens) {
|
|
453
|
+
const doc = new DOMParser().parseFromString(svg, "image/svg+xml");
|
|
454
|
+
if (doc.querySelector("parsererror")) return svg;
|
|
455
|
+
const root = doc.documentElement;
|
|
456
|
+
if (!root || root.tagName.toLowerCase() !== "svg") return svg;
|
|
457
|
+
applyCornerRounding(doc);
|
|
458
|
+
root.querySelector("style[data-visual-overrides]")?.remove();
|
|
459
|
+
const styleEl = doc.createElementNS("http://www.w3.org/2000/svg", "style");
|
|
460
|
+
styleEl.dataset.visualOverrides = "";
|
|
461
|
+
styleEl.textContent = buildVisualCss(tokens);
|
|
462
|
+
if (root.firstChild) root.insertBefore(styleEl, root.firstChild);
|
|
463
|
+
else root.append(styleEl);
|
|
464
|
+
return new XMLSerializer().serializeToString(root);
|
|
465
|
+
}
|
|
466
|
+
//#endregion
|
|
467
|
+
//#region src/useMermaidRender.ts
|
|
468
|
+
function useMermaidRender(content, preferredColorScheme) {
|
|
469
|
+
const [loading, setLoading] = useState(true);
|
|
470
|
+
const [error, setError] = useState("");
|
|
471
|
+
const [svg, setSvg] = useState("");
|
|
472
|
+
const [width, setWidth] = useState();
|
|
473
|
+
const [height, setHeight] = useState();
|
|
474
|
+
const colorScheme = useColorScheme();
|
|
475
|
+
const effectiveColorScheme = preferredColorScheme ?? colorScheme;
|
|
476
|
+
const id = useId().split(":").join("");
|
|
477
|
+
useEffect(() => {
|
|
478
|
+
if (!content) return;
|
|
479
|
+
setError("");
|
|
480
|
+
setLoading(true);
|
|
481
|
+
let cancelled = false;
|
|
482
|
+
import("mermaid").then(async (mo) => {
|
|
483
|
+
const mermaid = mo.default;
|
|
484
|
+
const themeConfig = effectiveColorScheme === "dark" ? darkTheme : lightTheme;
|
|
485
|
+
const tokens = effectiveColorScheme === "dark" ? darkTokens : lightTokens;
|
|
486
|
+
mermaid.initialize({
|
|
487
|
+
startOnLoad: false,
|
|
488
|
+
theme: themeConfig.theme,
|
|
489
|
+
themeVariables: themeConfig.themeVariables,
|
|
490
|
+
darkMode: effectiveColorScheme === "dark",
|
|
491
|
+
flowchart: {
|
|
492
|
+
htmlLabels: true,
|
|
493
|
+
curve: "basis",
|
|
494
|
+
padding: 20,
|
|
495
|
+
nodeSpacing: 24,
|
|
496
|
+
rankSpacing: 48
|
|
497
|
+
},
|
|
498
|
+
sequence: {
|
|
499
|
+
actorMargin: 80,
|
|
500
|
+
messageMargin: 40
|
|
501
|
+
},
|
|
502
|
+
gantt: {
|
|
503
|
+
titleTopMargin: 16,
|
|
504
|
+
barHeight: 24,
|
|
505
|
+
barGap: 6
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
let result;
|
|
509
|
+
try {
|
|
510
|
+
result = await mermaid.render(`mermaid-${id}`, content);
|
|
511
|
+
} catch (err) {
|
|
512
|
+
document.getElementById(`dmermaid-${id}`)?.remove();
|
|
513
|
+
if (err instanceof Error) setError(err.message);
|
|
514
|
+
setSvg("");
|
|
515
|
+
setWidth(void 0);
|
|
516
|
+
setHeight(void 0);
|
|
517
|
+
}
|
|
518
|
+
if (cancelled) return;
|
|
519
|
+
if (result) {
|
|
520
|
+
const processedSvg = postProcessMermaidSvg(result.svg, tokens);
|
|
521
|
+
setSvg(processedSvg);
|
|
522
|
+
const match = processedSvg.match(/viewBox="[^"]*\s([\d.]+)\s([\d.]+)"/);
|
|
523
|
+
if (match?.[1] && match?.[2]) {
|
|
524
|
+
setWidth(Number.parseInt(match[1]));
|
|
525
|
+
setHeight(Number.parseInt(match[2]));
|
|
526
|
+
}
|
|
527
|
+
setError("");
|
|
528
|
+
}
|
|
529
|
+
setLoading(false);
|
|
530
|
+
});
|
|
531
|
+
return () => {
|
|
532
|
+
cancelled = true;
|
|
533
|
+
};
|
|
534
|
+
}, [
|
|
535
|
+
id,
|
|
536
|
+
content,
|
|
537
|
+
effectiveColorScheme
|
|
538
|
+
]);
|
|
539
|
+
let imgSrc = "";
|
|
540
|
+
if (svg) {
|
|
541
|
+
const data = new TextEncoder().encode(svg);
|
|
542
|
+
imgSrc = `data:image/svg+xml;base64,${btoa(String.fromCodePoint(...new Uint8Array(data)))}`;
|
|
543
|
+
}
|
|
544
|
+
return {
|
|
545
|
+
loading,
|
|
546
|
+
error,
|
|
547
|
+
imgSrc,
|
|
548
|
+
svg,
|
|
549
|
+
width,
|
|
550
|
+
height
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
//#endregion
|
|
554
|
+
//#region src/MermaidRenderer.tsx
|
|
555
|
+
var MermaidRenderer = ({ content, colorScheme }) => {
|
|
556
|
+
const { loading, error, imgSrc, width, height } = useMermaidRender(content, colorScheme);
|
|
557
|
+
if (loading) return /* @__PURE__ */ jsx("pre", {
|
|
558
|
+
className: mermaidLoading,
|
|
559
|
+
children: /* @__PURE__ */ jsx("code", { children: content })
|
|
560
|
+
});
|
|
561
|
+
if (!imgSrc) return /* @__PURE__ */ jsx("div", {
|
|
562
|
+
className: mermaidError,
|
|
563
|
+
children: error || "Render failed"
|
|
564
|
+
});
|
|
565
|
+
return /* @__PURE__ */ jsx("div", {
|
|
566
|
+
className: mermaidContainer,
|
|
567
|
+
style: { cursor: "default" },
|
|
568
|
+
children: /* @__PURE__ */ jsx("img", {
|
|
569
|
+
alt: "Mermaid diagram",
|
|
570
|
+
height,
|
|
571
|
+
src: imgSrc,
|
|
572
|
+
width
|
|
573
|
+
})
|
|
574
|
+
});
|
|
575
|
+
};
|
|
576
|
+
//#endregion
|
|
577
|
+
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 };
|