zombie-mermaid 1.4.0 → 1.5.0
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/README.md +5 -10
- package/dist/cli.js +265 -43
- package/dist/index.cjs +461 -239
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -1
- package/dist/index.d.ts +83 -1
- package/dist/index.js +461 -239
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
- package/src/__tests__/ascii-combining-mark-width.test.ts +70 -0
- package/src/__tests__/ascii-display-width-unit.test.ts +129 -0
- package/src/__tests__/ascii-edge-cross-style-overlap.test.ts +212 -0
- package/src/__tests__/ascii-emoji-cluster-width.test.ts +101 -0
- package/src/__tests__/edge-cell-styles.test.ts +177 -0
- package/src/__tests__/grid-occupancy.test.ts +160 -0
- package/src/__tests__/helpers/terminal-display-width.ts +41 -13
- package/src/__tests__/interactivity-config.test.ts +64 -0
- package/src/__tests__/interactivity-option.test.ts +141 -0
- package/src/__tests__/svg-accessible-name.test.ts +392 -0
- package/src/ascii/display-width.ts +92 -26
- package/src/ascii/edge-cell-styles.ts +81 -0
- package/src/ascii/grid-occupancy.ts +98 -0
- package/src/ascii/grid.ts +102 -3
- package/src/class/renderer.ts +13 -1
- package/src/er/renderer.ts +13 -1
- package/src/index.ts +62 -1
- package/src/parser.ts +52 -16
- package/src/renderer.ts +47 -10
- package/src/sequence/renderer.ts +13 -1
- package/src/theme.ts +104 -1
- package/src/types.ts +74 -1
- package/src/xychart/renderer.ts +13 -4
package/README.md
CHANGED
|
@@ -6,11 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
Ultra-fast, fully themeable, zero DOM dependencies. A maintained fork of [`beautiful-mermaid`](https://github.com/lukilabs/beautiful-mermaid).
|
|
8
8
|
|
|
9
|
-

|
|
10
10
|
|
|
11
|
-
[
|
|
11
|
+
[](https://dfadler.github.io/zombie-mermaid/)
|
|
12
12
|
|
|
13
13
|
[](https://www.npmjs.com/package/zombie-mermaid)
|
|
14
|
+
[](https://github.com/dfadler/zombie-mermaid/actions/workflows/ci.yml)
|
|
15
|
+
[](https://codecov.io/gh/dfadler/zombie-mermaid)
|
|
16
|
+
[](https://socket.dev/npm/package/zombie-mermaid)
|
|
14
17
|
[](LICENSE)
|
|
15
18
|
|
|
16
19
|
</div>
|
|
@@ -145,11 +148,3 @@ Thank you Alexander for the excellent foundation!
|
|
|
145
148
|
## License
|
|
146
149
|
|
|
147
150
|
MIT — see [LICENSE](LICENSE) for details.
|
|
148
|
-
|
|
149
|
-
---
|
|
150
|
-
|
|
151
|
-
<div align="center">
|
|
152
|
-
|
|
153
|
-
Built with care by the team at [Craft](https://craft.do)
|
|
154
|
-
|
|
155
|
-
</div>
|
package/dist/cli.js
CHANGED
|
@@ -800,13 +800,8 @@ function parseFlowchart(lines) {
|
|
|
800
800
|
applyClickStatement(line, graph);
|
|
801
801
|
continue;
|
|
802
802
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
const block = matchExpandedBlock(line.slice(edgeMetaMatch[1].length));
|
|
806
|
-
if (block) {
|
|
807
|
-
applyEdgeMeta(graph, edgeMetaMatch[1], parseExpandedMeta(block.body));
|
|
808
|
-
continue;
|
|
809
|
-
}
|
|
803
|
+
if (tryApplyEdgeMetaLine(line, graph)) {
|
|
804
|
+
continue;
|
|
810
805
|
}
|
|
811
806
|
const linkStyleMatch = line.match(/^linkStyle\s+(default|[\d,\s]+)\s+(.+)$/);
|
|
812
807
|
if (linkStyleMatch) {
|
|
@@ -920,6 +915,9 @@ function parseStateDiagram(lines) {
|
|
|
920
915
|
}
|
|
921
916
|
continue;
|
|
922
917
|
}
|
|
918
|
+
if (tryApplyEdgeMetaLine(line, graph)) {
|
|
919
|
+
continue;
|
|
920
|
+
}
|
|
923
921
|
const compositeMatch = line.match(
|
|
924
922
|
/^state\s+(?:"([^"]+)"\s+as\s+)?([\w\p{L}]+)\s*\{$/u
|
|
925
923
|
);
|
|
@@ -953,10 +951,11 @@ function parseStateDiagram(lines) {
|
|
|
953
951
|
continue;
|
|
954
952
|
}
|
|
955
953
|
const transitionMatch = line.match(
|
|
956
|
-
/^(\[\*\]|[\w\p{L}-]+)\s*(
|
|
954
|
+
/^(\[\*\]|[\w\p{L}-]+)\s*(?:([\w-]+)@)?-->\s*(\[\*\]|[\w\p{L}-]+)(?:\s*:\s*(.+))?$/u
|
|
957
955
|
);
|
|
958
956
|
if (transitionMatch) {
|
|
959
957
|
let sourceId = transitionMatch[1];
|
|
958
|
+
const edgeId = transitionMatch[2];
|
|
960
959
|
let targetId = transitionMatch[3];
|
|
961
960
|
const rawTransitionLabel = transitionMatch[4]?.trim();
|
|
962
961
|
const edgeLabel = rawTransitionLabel ? normalizeBrTags(rawTransitionLabel) : void 0;
|
|
@@ -988,7 +987,8 @@ function parseStateDiagram(lines) {
|
|
|
988
987
|
label: edgeLabel,
|
|
989
988
|
style: "solid",
|
|
990
989
|
hasArrowStart: false,
|
|
991
|
-
hasArrowEnd: true
|
|
990
|
+
hasArrowEnd: true,
|
|
991
|
+
...edgeId !== void 0 ? { id: edgeId } : {}
|
|
992
992
|
});
|
|
993
993
|
continue;
|
|
994
994
|
}
|
|
@@ -1162,6 +1162,17 @@ function applyClickStatement(line, graph) {
|
|
|
1162
1162
|
graph.interactions.set(nodeId, interaction);
|
|
1163
1163
|
}
|
|
1164
1164
|
}
|
|
1165
|
+
var EDGE_META_ID_REGEX = /^([\w-]+)(?=@\{)/;
|
|
1166
|
+
function tryApplyEdgeMetaLine(line, graph) {
|
|
1167
|
+
const edgeMetaMatch = line.match(EDGE_META_ID_REGEX);
|
|
1168
|
+
if (!edgeMetaMatch || !graph.edges.some((e) => e.id === edgeMetaMatch[1])) {
|
|
1169
|
+
return false;
|
|
1170
|
+
}
|
|
1171
|
+
const block = matchExpandedBlock(line.slice(edgeMetaMatch[1].length));
|
|
1172
|
+
if (!block) return false;
|
|
1173
|
+
applyEdgeMeta(graph, edgeMetaMatch[1], parseExpandedMeta(block.body));
|
|
1174
|
+
return true;
|
|
1175
|
+
}
|
|
1165
1176
|
function applyEdgeMeta(graph, edgeId, meta) {
|
|
1166
1177
|
for (const edge of graph.edges) {
|
|
1167
1178
|
if (edge.id !== edgeId) continue;
|
|
@@ -1623,7 +1634,12 @@ function getReadableTextColor(fill, fallback) {
|
|
|
1623
1634
|
const luminance = perceptualLuminance(...rgb);
|
|
1624
1635
|
return luminance > 0.5 ? "#000000" : "#FFFFFF";
|
|
1625
1636
|
}
|
|
1626
|
-
|
|
1637
|
+
var titleIdCounter = 0;
|
|
1638
|
+
function nextTitleId() {
|
|
1639
|
+
titleIdCounter += 1;
|
|
1640
|
+
return `zm-title-${titleIdCounter}`;
|
|
1641
|
+
}
|
|
1642
|
+
function svgOpenTag(width, height, colors, transparent, title, decorative, hasInteractiveLinks) {
|
|
1627
1643
|
const vars = [
|
|
1628
1644
|
`--bg:${colors.bg}`,
|
|
1629
1645
|
`--fg:${colors.fg}`,
|
|
@@ -1634,7 +1650,27 @@ function svgOpenTag(width, height, colors, transparent) {
|
|
|
1634
1650
|
colors.border ? `--border:${colors.border}` : ""
|
|
1635
1651
|
].filter(Boolean).join(";");
|
|
1636
1652
|
const bgStyle = transparent ? "" : ";background:var(--bg)";
|
|
1637
|
-
|
|
1653
|
+
let a11yAttrs = "";
|
|
1654
|
+
let titleEl = "";
|
|
1655
|
+
if (hasInteractiveLinks) {
|
|
1656
|
+
if (title) {
|
|
1657
|
+
const id = nextTitleId();
|
|
1658
|
+
a11yAttrs = ` aria-labelledby="${id}"`;
|
|
1659
|
+
titleEl = `
|
|
1660
|
+
<title id="${id}">${escapeXml(title)}</title>`;
|
|
1661
|
+
}
|
|
1662
|
+
} else if (decorative) {
|
|
1663
|
+
a11yAttrs = ' aria-hidden="true"';
|
|
1664
|
+
} else {
|
|
1665
|
+
a11yAttrs = ' role="img"';
|
|
1666
|
+
if (title) {
|
|
1667
|
+
const id = nextTitleId();
|
|
1668
|
+
a11yAttrs += ` aria-labelledby="${id}"`;
|
|
1669
|
+
titleEl = `
|
|
1670
|
+
<title id="${id}">${escapeXml(title)}</title>`;
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}"${a11yAttrs} style="${vars}${bgStyle}">` + titleEl;
|
|
1638
1674
|
}
|
|
1639
1675
|
|
|
1640
1676
|
// src/ascii/ansi.ts
|
|
@@ -1908,19 +1944,44 @@ function colorizeText(text, hex, mode) {
|
|
|
1908
1944
|
|
|
1909
1945
|
// src/ascii/display-width.ts
|
|
1910
1946
|
var WIDE_CHAR_PLACEHOLDER = "";
|
|
1911
|
-
|
|
1912
|
-
|
|
1947
|
+
var COMBINING_MARK_REGEX = /\p{Mn}|\p{Me}/u;
|
|
1948
|
+
function isCombiningMark2(char) {
|
|
1949
|
+
return COMBINING_MARK_REGEX.test(char);
|
|
1950
|
+
}
|
|
1951
|
+
var graphemeSegmenter = new Intl.Segmenter(void 0, {
|
|
1952
|
+
granularity: "grapheme"
|
|
1953
|
+
});
|
|
1954
|
+
function graphemeClusters(text) {
|
|
1955
|
+
const clusters = [];
|
|
1956
|
+
for (const { segment } of graphemeSegmenter.segment(text)) {
|
|
1957
|
+
clusters.push(segment);
|
|
1958
|
+
}
|
|
1959
|
+
return clusters;
|
|
1960
|
+
}
|
|
1961
|
+
function charDisplayWidth(cluster) {
|
|
1962
|
+
let sawWide = false;
|
|
1963
|
+
let sawNonMark = false;
|
|
1964
|
+
for (const ch of cluster) {
|
|
1965
|
+
if (isWideChar(ch)) sawWide = true;
|
|
1966
|
+
if (!isCombiningMark2(ch)) sawNonMark = true;
|
|
1967
|
+
}
|
|
1968
|
+
if (sawWide) return 2;
|
|
1969
|
+
return sawNonMark ? 1 : 0;
|
|
1913
1970
|
}
|
|
1914
1971
|
function displayWidth(text) {
|
|
1915
1972
|
let width = 0;
|
|
1916
|
-
for (const
|
|
1973
|
+
for (const cluster of graphemeClusters(text)) {
|
|
1974
|
+
width += charDisplayWidth(cluster);
|
|
1975
|
+
}
|
|
1917
1976
|
return width;
|
|
1918
1977
|
}
|
|
1919
1978
|
function toDisplayCells(text) {
|
|
1920
1979
|
const cells = [];
|
|
1921
|
-
for (const
|
|
1922
|
-
|
|
1923
|
-
if (
|
|
1980
|
+
for (const cluster of graphemeClusters(text)) {
|
|
1981
|
+
const width = charDisplayWidth(cluster);
|
|
1982
|
+
if (width === 0) continue;
|
|
1983
|
+
cells.push(cluster);
|
|
1984
|
+
if (width === 2) cells.push(WIDE_CHAR_PLACEHOLDER);
|
|
1924
1985
|
}
|
|
1925
1986
|
return cells;
|
|
1926
1987
|
}
|
|
@@ -2278,10 +2339,28 @@ var Grid = class {
|
|
|
2278
2339
|
add(key) {
|
|
2279
2340
|
this.#cells.add(key);
|
|
2280
2341
|
}
|
|
2342
|
+
/**
|
|
2343
|
+
* Release a single cell. For temporary reservations only (see
|
|
2344
|
+
* `rerouteAroundStyleConflicts` in grid.ts) — every other reservation in
|
|
2345
|
+
* this module (node blocks, in particular) is permanent for the life of
|
|
2346
|
+
* a render, so a real caller should rarely need this.
|
|
2347
|
+
*/
|
|
2348
|
+
delete(key) {
|
|
2349
|
+
this.#cells.delete(key);
|
|
2350
|
+
}
|
|
2351
|
+
/** Iterate the reserved cell keys. Read-only — see `cloneGrid`. */
|
|
2352
|
+
keys() {
|
|
2353
|
+
return this.#cells.keys();
|
|
2354
|
+
}
|
|
2281
2355
|
};
|
|
2282
2356
|
function createGrid() {
|
|
2283
2357
|
return new Grid();
|
|
2284
2358
|
}
|
|
2359
|
+
function cloneGrid(grid) {
|
|
2360
|
+
const clone = createGrid();
|
|
2361
|
+
for (const key of grid.keys()) clone.add(key);
|
|
2362
|
+
return clone;
|
|
2363
|
+
}
|
|
2285
2364
|
var NODE_BLOCK_SIZE = 3;
|
|
2286
2365
|
function isOccupied(grid, coord) {
|
|
2287
2366
|
return grid.has(gridKey(coord));
|
|
@@ -2313,6 +2392,42 @@ function placeBlock(grid, origin, size = NODE_BLOCK_SIZE) {
|
|
|
2313
2392
|
}
|
|
2314
2393
|
}
|
|
2315
2394
|
}
|
|
2395
|
+
var MAX_WALK_STEPS = 1e5;
|
|
2396
|
+
function pathCells(path) {
|
|
2397
|
+
if (path.length === 0) return [];
|
|
2398
|
+
const cells = [path[0]];
|
|
2399
|
+
for (let i = 1; i < path.length; i++) {
|
|
2400
|
+
const from = path[i - 1];
|
|
2401
|
+
const to = path[i];
|
|
2402
|
+
let x = from.x;
|
|
2403
|
+
let y = from.y;
|
|
2404
|
+
const absDx = Math.abs(to.x - from.x);
|
|
2405
|
+
const absDy = Math.abs(to.y - from.y);
|
|
2406
|
+
const sx = from.x < to.x ? 1 : -1;
|
|
2407
|
+
const sy = from.y < to.y ? 1 : -1;
|
|
2408
|
+
let err = absDx - absDy;
|
|
2409
|
+
let steps = 0;
|
|
2410
|
+
while (x !== to.x || y !== to.y) {
|
|
2411
|
+
if (steps >= MAX_WALK_STEPS) {
|
|
2412
|
+
throw new Error(
|
|
2413
|
+
`pathCells: segment from (${from.x},${from.y}) to (${to.x},${to.y}) did not reach its endpoint within ${MAX_WALK_STEPS} steps`
|
|
2414
|
+
);
|
|
2415
|
+
}
|
|
2416
|
+
const e2 = 2 * err;
|
|
2417
|
+
if (e2 > -absDy) {
|
|
2418
|
+
err -= absDy;
|
|
2419
|
+
x += sx;
|
|
2420
|
+
}
|
|
2421
|
+
if (e2 < absDx) {
|
|
2422
|
+
err += absDx;
|
|
2423
|
+
y += sy;
|
|
2424
|
+
}
|
|
2425
|
+
cells.push({ x, y });
|
|
2426
|
+
steps++;
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
return cells;
|
|
2430
|
+
}
|
|
2316
2431
|
|
|
2317
2432
|
// src/ascii/converter.ts
|
|
2318
2433
|
function convertToAsciiGraph(parsed, config) {
|
|
@@ -3128,6 +3243,26 @@ function processBundles(graph) {
|
|
|
3128
3243
|
}
|
|
3129
3244
|
}
|
|
3130
3245
|
|
|
3246
|
+
// src/ascii/edge-cell-styles.ts
|
|
3247
|
+
function createEdgeCellStyles() {
|
|
3248
|
+
return /* @__PURE__ */ new Map();
|
|
3249
|
+
}
|
|
3250
|
+
function findStyleConflict(grid, cellStyles, path, style) {
|
|
3251
|
+
for (const cell of pathCells(path)) {
|
|
3252
|
+
if (isOccupied(grid, cell)) continue;
|
|
3253
|
+
const existing = cellStyles.get(gridKey(cell));
|
|
3254
|
+
if (existing !== void 0 && existing !== style) return cell;
|
|
3255
|
+
}
|
|
3256
|
+
return null;
|
|
3257
|
+
}
|
|
3258
|
+
function claimPathCells(grid, cellStyles, path, style) {
|
|
3259
|
+
for (const cell of pathCells(path)) {
|
|
3260
|
+
if (isOccupied(grid, cell)) continue;
|
|
3261
|
+
const key = gridKey(cell);
|
|
3262
|
+
if (!cellStyles.has(key)) cellStyles.set(key, style);
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3265
|
+
|
|
3131
3266
|
// src/ascii/multiline-utils.ts
|
|
3132
3267
|
function splitLines(label) {
|
|
3133
3268
|
return label.split("\n");
|
|
@@ -4903,6 +5038,26 @@ function increaseGridSizeForPath(graph, path) {
|
|
|
4903
5038
|
}
|
|
4904
5039
|
}
|
|
4905
5040
|
}
|
|
5041
|
+
var MAX_STYLE_CONFLICT_REROUTES = 8;
|
|
5042
|
+
function rerouteAroundStyleConflicts(graph, edge, cellStyles, nodeOnlyGrid) {
|
|
5043
|
+
const temporarilyBlocked = [];
|
|
5044
|
+
try {
|
|
5045
|
+
for (let i = 0; i < MAX_STYLE_CONFLICT_REROUTES; i++) {
|
|
5046
|
+
const conflict = findStyleConflict(
|
|
5047
|
+
nodeOnlyGrid,
|
|
5048
|
+
cellStyles,
|
|
5049
|
+
edge.path,
|
|
5050
|
+
edge.style
|
|
5051
|
+
);
|
|
5052
|
+
if (!conflict) return;
|
|
5053
|
+
graph.grid.add(gridKey(conflict));
|
|
5054
|
+
temporarilyBlocked.push(conflict);
|
|
5055
|
+
determinePath(graph, edge);
|
|
5056
|
+
}
|
|
5057
|
+
} finally {
|
|
5058
|
+
for (const cell of temporarilyBlocked) graph.grid.delete(gridKey(cell));
|
|
5059
|
+
}
|
|
5060
|
+
}
|
|
4906
5061
|
function isNodeInAnySubgraph(graph, node) {
|
|
4907
5062
|
return graph.subgraphs.some((sg) => sg.nodes.includes(node));
|
|
4908
5063
|
}
|
|
@@ -5257,14 +5412,19 @@ function createMapping(graph) {
|
|
|
5257
5412
|
graph.pathBudget = createPathBudget();
|
|
5258
5413
|
graph.bundles = analyzeEdgeBundles(graph);
|
|
5259
5414
|
processBundles(graph);
|
|
5415
|
+
const cellStyles = createEdgeCellStyles();
|
|
5416
|
+
const nodeOnlyGrid = cloneGrid(graph.grid);
|
|
5260
5417
|
for (const edge of graph.edges) {
|
|
5261
5418
|
if (edge.bundle && edge.path.length > 0) {
|
|
5262
5419
|
increaseGridSizeForPath(graph, edge.path);
|
|
5420
|
+
claimPathCells(nodeOnlyGrid, cellStyles, edge.path, edge.style);
|
|
5263
5421
|
determineLabelLine(graph, edge);
|
|
5264
5422
|
continue;
|
|
5265
5423
|
}
|
|
5266
5424
|
determinePath(graph, edge);
|
|
5425
|
+
rerouteAroundStyleConflicts(graph, edge, cellStyles, nodeOnlyGrid);
|
|
5267
5426
|
increaseGridSizeForPath(graph, edge.path);
|
|
5427
|
+
claimPathCells(nodeOnlyGrid, cellStyles, edge.path, edge.style);
|
|
5268
5428
|
determineLabelLine(graph, edge);
|
|
5269
5429
|
}
|
|
5270
5430
|
for (const node of graph.nodes) {
|
|
@@ -9232,16 +9392,27 @@ function pointsToPath(points, curve = "linear") {
|
|
|
9232
9392
|
}
|
|
9233
9393
|
|
|
9234
9394
|
// src/renderer.ts
|
|
9235
|
-
function renderSvg(graph, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, curve = "linear", embedSource) {
|
|
9395
|
+
function renderSvg(graph, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, curve = "linear", embedSource, animationEnabled = true, title, decorative) {
|
|
9236
9396
|
const parts = [];
|
|
9397
|
+
const hasInteractiveLinks = graph.nodes.some(
|
|
9398
|
+
(n) => Boolean(safeHref(n.interaction?.href))
|
|
9399
|
+
);
|
|
9237
9400
|
parts.push(
|
|
9238
9401
|
withDataSrc(
|
|
9239
|
-
svgOpenTag(
|
|
9402
|
+
svgOpenTag(
|
|
9403
|
+
graph.width,
|
|
9404
|
+
graph.height,
|
|
9405
|
+
colors,
|
|
9406
|
+
transparent,
|
|
9407
|
+
title,
|
|
9408
|
+
decorative,
|
|
9409
|
+
hasInteractiveLinks
|
|
9410
|
+
),
|
|
9240
9411
|
embedSource
|
|
9241
9412
|
)
|
|
9242
9413
|
);
|
|
9243
9414
|
parts.push(buildStyleBlock(font, false));
|
|
9244
|
-
if (graph.edges.some((e) => e.animate)) {
|
|
9415
|
+
if (animationEnabled && graph.edges.some((e) => e.animate)) {
|
|
9245
9416
|
parts.push(edgeAnimationStyle());
|
|
9246
9417
|
}
|
|
9247
9418
|
parts.push("<defs>");
|
|
@@ -9260,7 +9431,7 @@ function renderSvg(graph, colors, font = "Inter", transparent = false, fontSizes
|
|
|
9260
9431
|
parts.push(renderGroup(group, font, fontSizes));
|
|
9261
9432
|
}
|
|
9262
9433
|
for (const edge of graph.edges) {
|
|
9263
|
-
parts.push(renderEdge(edge, curve));
|
|
9434
|
+
parts.push(renderEdge(edge, curve, animationEnabled));
|
|
9264
9435
|
}
|
|
9265
9436
|
for (const edge of graph.edges) {
|
|
9266
9437
|
if (edge.label) {
|
|
@@ -9331,8 +9502,9 @@ function renderGroup(group, font, fontSizes) {
|
|
|
9331
9502
|
parts.push("</g>");
|
|
9332
9503
|
return parts.join("\n");
|
|
9333
9504
|
}
|
|
9334
|
-
function renderEdge(edge, curve) {
|
|
9505
|
+
function renderEdge(edge, curve, animationEnabled = true) {
|
|
9335
9506
|
if (edge.points.length < 2) return "";
|
|
9507
|
+
const animate = animationEnabled && (edge.animate ?? false);
|
|
9336
9508
|
const curved = curve !== "linear";
|
|
9337
9509
|
const invisible = edge.style === "invisible";
|
|
9338
9510
|
const dashArray = edge.style === "dotted" ? ' stroke-dasharray="4 4"' : "";
|
|
@@ -9349,9 +9521,9 @@ function renderEdge(edge, curve) {
|
|
|
9349
9521
|
markers += ` marker-start="url(#arrowhead-start${suffix})"`;
|
|
9350
9522
|
}
|
|
9351
9523
|
const dataAttrs = [
|
|
9352
|
-
// An animated edge (`e1@{ animate: true }
|
|
9353
|
-
// keyframes live in the shared style block.
|
|
9354
|
-
`class="edge${
|
|
9524
|
+
// An animated edge (`e1@{ animate: true }`, with animation enabled)
|
|
9525
|
+
// carries an extra class; its keyframes live in the shared style block.
|
|
9526
|
+
`class="edge${animate ? " edge-animated" : ""}"`,
|
|
9355
9527
|
`data-from="${escapeAttr(edge.source)}"`,
|
|
9356
9528
|
`data-to="${escapeAttr(edge.target)}"`,
|
|
9357
9529
|
`data-style="${edge.style}"`,
|
|
@@ -9364,7 +9536,7 @@ function renderEdge(edge, curve) {
|
|
|
9364
9536
|
if (edge.id) {
|
|
9365
9537
|
dataAttrs.push(`data-id="${escapeAttr(edge.id)}"`);
|
|
9366
9538
|
}
|
|
9367
|
-
const animatedDash =
|
|
9539
|
+
const animatedDash = animate && !dashArray ? ' stroke-dasharray="8 6"' : "";
|
|
9368
9540
|
const geometry = curved ? `d="${pointsToPath(edge.points, curve)}"` : `points="${pointsToPolylinePath(edge.points)}"`;
|
|
9369
9541
|
return `<${curved ? "path" : "polyline"} ${dataAttrs.join(" ")} ${geometry} fill="none" stroke="${strokeColor}" stroke-width="${strokeWidth}"${dashArray}${animatedDash}${markers} />`;
|
|
9370
9542
|
}
|
|
@@ -10279,11 +10451,18 @@ function layoutSequenceDiagram(diagram, options = {}) {
|
|
|
10279
10451
|
}
|
|
10280
10452
|
|
|
10281
10453
|
// src/sequence/renderer.ts
|
|
10282
|
-
function renderSequenceSvg(diagram, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, embedSource) {
|
|
10454
|
+
function renderSequenceSvg(diagram, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, embedSource, title, decorative) {
|
|
10283
10455
|
const parts = [];
|
|
10284
10456
|
parts.push(
|
|
10285
10457
|
withDataSrc(
|
|
10286
|
-
svgOpenTag(
|
|
10458
|
+
svgOpenTag(
|
|
10459
|
+
diagram.width,
|
|
10460
|
+
diagram.height,
|
|
10461
|
+
colors,
|
|
10462
|
+
transparent,
|
|
10463
|
+
title,
|
|
10464
|
+
decorative
|
|
10465
|
+
),
|
|
10287
10466
|
embedSource
|
|
10288
10467
|
)
|
|
10289
10468
|
);
|
|
@@ -10680,11 +10859,18 @@ var CLS_FONT = {
|
|
|
10680
10859
|
annotationSize: 10,
|
|
10681
10860
|
annotationWeight: 500
|
|
10682
10861
|
};
|
|
10683
|
-
function renderClassSvg(diagram, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, embedSource) {
|
|
10862
|
+
function renderClassSvg(diagram, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, embedSource, title, decorative) {
|
|
10684
10863
|
const parts = [];
|
|
10685
10864
|
parts.push(
|
|
10686
10865
|
withDataSrc(
|
|
10687
|
-
svgOpenTag(
|
|
10866
|
+
svgOpenTag(
|
|
10867
|
+
diagram.width,
|
|
10868
|
+
diagram.height,
|
|
10869
|
+
colors,
|
|
10870
|
+
transparent,
|
|
10871
|
+
title,
|
|
10872
|
+
decorative
|
|
10873
|
+
),
|
|
10688
10874
|
embedSource
|
|
10689
10875
|
)
|
|
10690
10876
|
);
|
|
@@ -11068,11 +11254,18 @@ var ER_FONT = {
|
|
|
11068
11254
|
keySize: 9,
|
|
11069
11255
|
keyWeight: 600
|
|
11070
11256
|
};
|
|
11071
|
-
function renderErSvg(diagram, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, embedSource) {
|
|
11257
|
+
function renderErSvg(diagram, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, embedSource, title, decorative) {
|
|
11072
11258
|
const parts = [];
|
|
11073
11259
|
parts.push(
|
|
11074
11260
|
withDataSrc(
|
|
11075
|
-
svgOpenTag(
|
|
11261
|
+
svgOpenTag(
|
|
11262
|
+
diagram.width,
|
|
11263
|
+
diagram.height,
|
|
11264
|
+
colors,
|
|
11265
|
+
transparent,
|
|
11266
|
+
title,
|
|
11267
|
+
decorative
|
|
11268
|
+
),
|
|
11076
11269
|
embedSource
|
|
11077
11270
|
)
|
|
11078
11271
|
);
|
|
@@ -11807,7 +12000,7 @@ var TIP = {
|
|
|
11807
12000
|
minY: 4,
|
|
11808
12001
|
pointerSize: 6
|
|
11809
12002
|
};
|
|
11810
|
-
function renderXYChartSvg(chart, colors, font = "Inter", transparent = false, interactive = false, embedSource) {
|
|
12003
|
+
function renderXYChartSvg(chart, colors, font = "Inter", transparent = false, interactive = false, embedSource, title, decorative) {
|
|
11811
12004
|
const parts = [];
|
|
11812
12005
|
const maxColorIdx = Math.max(
|
|
11813
12006
|
0,
|
|
@@ -11815,10 +12008,14 @@ function renderXYChartSvg(chart, colors, font = "Inter", transparent = false, in
|
|
|
11815
12008
|
...chart.lines.map((l) => l.colorIndex)
|
|
11816
12009
|
);
|
|
11817
12010
|
const svgTag = withDataSrc(
|
|
11818
|
-
svgOpenTag(
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
|
|
12011
|
+
svgOpenTag(
|
|
12012
|
+
chart.width,
|
|
12013
|
+
chart.height,
|
|
12014
|
+
colors,
|
|
12015
|
+
transparent,
|
|
12016
|
+
title,
|
|
12017
|
+
decorative
|
|
12018
|
+
).replace("<svg ", `<svg data-xychart-colors="${maxColorIdx}" `),
|
|
11822
12019
|
embedSource
|
|
11823
12020
|
);
|
|
11824
12021
|
parts.push(svgTag);
|
|
@@ -12234,6 +12431,18 @@ function buildColors(options) {
|
|
|
12234
12431
|
border: options.border
|
|
12235
12432
|
};
|
|
12236
12433
|
}
|
|
12434
|
+
function resolveInteractivity(options) {
|
|
12435
|
+
return options.interactivity ?? "static";
|
|
12436
|
+
}
|
|
12437
|
+
function resolveAnimationEnabled(options) {
|
|
12438
|
+
return resolveInteractivity(options) !== "none";
|
|
12439
|
+
}
|
|
12440
|
+
function resolveXYChartInteractive(options) {
|
|
12441
|
+
if (options.interactivity !== void 0) {
|
|
12442
|
+
return options.interactivity === "full";
|
|
12443
|
+
}
|
|
12444
|
+
return options.interactive ?? false;
|
|
12445
|
+
}
|
|
12237
12446
|
function renderMermaidSVG(text, options = {}) {
|
|
12238
12447
|
const originalText = text;
|
|
12239
12448
|
text = decodeXML(text);
|
|
@@ -12243,6 +12452,8 @@ function renderMermaidSVG(text, options = {}) {
|
|
|
12243
12452
|
const fontSizes = resolveFontSizes(options.fontSizes);
|
|
12244
12453
|
const diagramType = detectDiagramType(text);
|
|
12245
12454
|
const embedSource = options.embedSource ? originalText : void 0;
|
|
12455
|
+
const title = options.title;
|
|
12456
|
+
const decorative = options.decorative;
|
|
12246
12457
|
const lines = splitStatements(text);
|
|
12247
12458
|
switch (diagramType) {
|
|
12248
12459
|
case "sequence": {
|
|
@@ -12254,7 +12465,9 @@ function renderMermaidSVG(text, options = {}) {
|
|
|
12254
12465
|
font,
|
|
12255
12466
|
transparent,
|
|
12256
12467
|
fontSizes,
|
|
12257
|
-
embedSource
|
|
12468
|
+
embedSource,
|
|
12469
|
+
title,
|
|
12470
|
+
decorative
|
|
12258
12471
|
);
|
|
12259
12472
|
}
|
|
12260
12473
|
case "class": {
|
|
@@ -12266,7 +12479,9 @@ function renderMermaidSVG(text, options = {}) {
|
|
|
12266
12479
|
font,
|
|
12267
12480
|
transparent,
|
|
12268
12481
|
fontSizes,
|
|
12269
|
-
embedSource
|
|
12482
|
+
embedSource,
|
|
12483
|
+
title,
|
|
12484
|
+
decorative
|
|
12270
12485
|
);
|
|
12271
12486
|
}
|
|
12272
12487
|
case "er": {
|
|
@@ -12278,7 +12493,9 @@ function renderMermaidSVG(text, options = {}) {
|
|
|
12278
12493
|
font,
|
|
12279
12494
|
transparent,
|
|
12280
12495
|
fontSizes,
|
|
12281
|
-
embedSource
|
|
12496
|
+
embedSource,
|
|
12497
|
+
title,
|
|
12498
|
+
decorative
|
|
12282
12499
|
);
|
|
12283
12500
|
}
|
|
12284
12501
|
case "xychart": {
|
|
@@ -12289,8 +12506,10 @@ function renderMermaidSVG(text, options = {}) {
|
|
|
12289
12506
|
colors,
|
|
12290
12507
|
font,
|
|
12291
12508
|
transparent,
|
|
12292
|
-
options
|
|
12293
|
-
embedSource
|
|
12509
|
+
resolveXYChartInteractive(options),
|
|
12510
|
+
embedSource,
|
|
12511
|
+
title,
|
|
12512
|
+
decorative
|
|
12294
12513
|
);
|
|
12295
12514
|
}
|
|
12296
12515
|
case "flowchart":
|
|
@@ -12305,7 +12524,10 @@ function renderMermaidSVG(text, options = {}) {
|
|
|
12305
12524
|
transparent,
|
|
12306
12525
|
fontSizes,
|
|
12307
12526
|
effective.curve ?? "linear",
|
|
12308
|
-
embedSource
|
|
12527
|
+
embedSource,
|
|
12528
|
+
resolveAnimationEnabled(options),
|
|
12529
|
+
title,
|
|
12530
|
+
decorative
|
|
12309
12531
|
);
|
|
12310
12532
|
}
|
|
12311
12533
|
}
|