semajsx 0.7.0 → 0.9.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/dist/{client-BrupjhG0.mjs → client-CEJQ4fit.mjs} +3 -3
- package/dist/{client-BrupjhG0.mjs.map → client-CEJQ4fit.mjs.map} +1 -1
- package/dist/{document-DsiJO2jG.mjs → document-Cbz4084O.mjs} +2 -2
- package/dist/{document-XKyAs62C.mjs → document-Cfdhi7vG.mjs} +2 -2
- package/dist/{document-XKyAs62C.mjs.map → document-Cfdhi7vG.mjs.map} +1 -1
- package/dist/dom/index.mjs +2 -2
- package/dist/dom/jsx-dev-runtime.mjs +1 -1
- package/dist/dom/jsx-runtime.mjs +1 -1
- package/dist/index.d.mts +11 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{jsx-runtime-Dc77fsnM.d.mts → jsx-runtime-tdaY-P9K.d.mts} +2 -2
- package/dist/{jsx-runtime-Dc77fsnM.d.mts.map → jsx-runtime-tdaY-P9K.d.mts.map} +1 -1
- package/dist/{lucide-Ddt_N9dJ.mjs → lucide-DWk3itzO.mjs} +3 -3
- package/dist/{lucide-Ddt_N9dJ.mjs.map → lucide-DWk3itzO.mjs.map} +1 -1
- package/dist/{resource-pm7qP-jV.mjs → resource-BU0Po0ez.mjs} +2 -2
- package/dist/{resource-pm7qP-jV.mjs.map → resource-BU0Po0ez.mjs.map} +1 -1
- package/dist/{src-Cv4rRVzv.mjs → src--YS4EvMz.mjs} +9 -6
- package/dist/src--YS4EvMz.mjs.map +1 -0
- package/dist/{src-CXY-7FC3.mjs → src-77V1Plyd.mjs} +665 -129
- package/dist/src-77V1Plyd.mjs.map +1 -0
- package/dist/{src-SqJ6k7Xv.mjs → src-BTG08Qnh.mjs} +4 -4
- package/dist/{src-SqJ6k7Xv.mjs.map → src-BTG08Qnh.mjs.map} +1 -1
- package/dist/{src-C_aFsFJ3.mjs → src-Cm12Y2XV.mjs} +2 -2
- package/dist/{src-C_aFsFJ3.mjs.map → src-Cm12Y2XV.mjs.map} +1 -1
- package/dist/{src-CAyv9Uf9.mjs → src-Mucdq4zw.mjs} +6 -6
- package/dist/{src-CAyv9Uf9.mjs.map → src-Mucdq4zw.mjs.map} +1 -1
- package/dist/ssg/index.mjs +6 -6
- package/dist/ssg/plugins/docs-theme.d.mts +8 -0
- package/dist/ssg/plugins/docs-theme.d.mts.map +1 -1
- package/dist/ssg/plugins/docs-theme.mjs +1039 -222
- package/dist/ssg/plugins/docs-theme.mjs.map +1 -1
- package/dist/ssg/plugins/lucide.mjs +3 -3
- package/dist/ssr/client.mjs +4 -4
- package/dist/ssr/index.mjs +5 -5
- package/dist/terminal/index.d.mts +248 -4
- package/dist/terminal/index.d.mts.map +1 -1
- package/dist/terminal/index.mjs +3 -3
- package/dist/terminal/jsx-dev-runtime.d.mts +2 -2
- package/dist/terminal/jsx-dev-runtime.mjs +1 -1
- package/dist/terminal/jsx-runtime.d.mts +2 -2
- package/dist/terminal/jsx-runtime.mjs +1 -1
- package/dist/{types-Bj5q5x2Q.d.mts → types-Bm8rZGKW.d.mts} +2 -2
- package/dist/{types-Bj5q5x2Q.d.mts.map → types-Bm8rZGKW.d.mts.map} +1 -1
- package/package.json +1 -1
- package/dist/src-CXY-7FC3.mjs.map +0 -1
- package/dist/src-Cv4rRVzv.mjs.map +0 -1
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { t as signal } from "../../signal-4PgGfydw.mjs";
|
|
2
2
|
import { n as unwrap } from "../../utils-BrGmTgfG.mjs";
|
|
3
|
-
import { a as jsxs, i as jsx, u as context, v as Fragment } from "../../src
|
|
4
|
-
import "../../src-
|
|
3
|
+
import { a as jsxs, i as jsx, u as context, v as Fragment } from "../../src--YS4EvMz.mjs";
|
|
4
|
+
import "../../src-Cm12Y2XV.mjs";
|
|
5
5
|
import { G as rules, K as classes, M as createTheme, N as defineTokens, W as rule } from "../../src-DV9uwtE5.mjs";
|
|
6
6
|
import "../../jsx-runtime-BFs1c0xz.mjs";
|
|
7
|
-
import "../../src-
|
|
7
|
+
import "../../src-77V1Plyd.mjs";
|
|
8
8
|
import "../../jsx-runtime-kv_6vBiR.mjs";
|
|
9
|
-
import { d as island } from "../../resource-
|
|
10
|
-
import "../../src-
|
|
11
|
-
import "../../document-
|
|
12
|
-
import "../../client-
|
|
13
|
-
import { d as defineCollection } from "../../src-
|
|
14
|
-
import { n as Icon, t as lucide } from "../../lucide-
|
|
9
|
+
import { d as island } from "../../resource-BU0Po0ez.mjs";
|
|
10
|
+
import "../../src-Mucdq4zw.mjs";
|
|
11
|
+
import "../../document-Cfdhi7vG.mjs";
|
|
12
|
+
import "../../client-CEJQ4fit.mjs";
|
|
13
|
+
import { d as defineCollection } from "../../src-BTG08Qnh.mjs";
|
|
14
|
+
import { n as Icon, t as lucide } from "../../lucide-DWk3itzO.mjs";
|
|
15
15
|
import { dirname, join } from "path";
|
|
16
16
|
import { mkdir, writeFile } from "fs/promises";
|
|
17
17
|
import { z } from "zod";
|
|
@@ -464,6 +464,7 @@ function parseNodeRef(state) {
|
|
|
464
464
|
const shape = parseNodeShape(state, id);
|
|
465
465
|
if (shape) {
|
|
466
466
|
if (!state.nodes.has(id)) state.nodes.set(id, shape);
|
|
467
|
+
state.nodeRefCollector?.push(id);
|
|
467
468
|
return id;
|
|
468
469
|
}
|
|
469
470
|
}
|
|
@@ -472,6 +473,7 @@ function parseNodeRef(state) {
|
|
|
472
473
|
label: id,
|
|
473
474
|
shape: "rect"
|
|
474
475
|
});
|
|
476
|
+
state.nodeRefCollector?.push(id);
|
|
475
477
|
return id;
|
|
476
478
|
}
|
|
477
479
|
function parseNodeShape(state, id) {
|
|
@@ -607,7 +609,8 @@ function parseSubgraph(state) {
|
|
|
607
609
|
}
|
|
608
610
|
skipSemicolon(state);
|
|
609
611
|
}
|
|
610
|
-
const
|
|
612
|
+
const childSubgraphs = [];
|
|
613
|
+
const childNodeIds = /* @__PURE__ */ new Set();
|
|
611
614
|
const nodeIds = [];
|
|
612
615
|
while (!isEof$1(state)) {
|
|
613
616
|
skipNewlines$1(state);
|
|
@@ -617,18 +620,39 @@ function parseSubgraph(state) {
|
|
|
617
620
|
advance$1(state);
|
|
618
621
|
break;
|
|
619
622
|
}
|
|
623
|
+
if (token.type === "keyword" && token.value === "subgraph") {
|
|
624
|
+
const sgCountBefore = state.subgraphs.length;
|
|
625
|
+
const result = parseSubgraph(state);
|
|
626
|
+
if ("message" in result) return result;
|
|
627
|
+
if (state.subgraphs.length > sgCountBefore) {
|
|
628
|
+
const child = state.subgraphs.pop();
|
|
629
|
+
childSubgraphs.push(child);
|
|
630
|
+
collectAllNodes(child, childNodeIds);
|
|
631
|
+
}
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
state.nodeRefCollector = [];
|
|
620
635
|
const result = parseStatement(state);
|
|
636
|
+
const refs = state.nodeRefCollector;
|
|
637
|
+
state.nodeRefCollector = void 0;
|
|
621
638
|
if (result && "message" in result) return result;
|
|
622
|
-
for (const
|
|
639
|
+
for (const nodeId of refs) if (!childNodeIds.has(nodeId) && !nodeIds.includes(nodeId)) nodeIds.push(nodeId);
|
|
623
640
|
}
|
|
624
|
-
|
|
641
|
+
const sg = {
|
|
625
642
|
id: id || `subgraph_${state.subgraphs.length}`,
|
|
626
643
|
label,
|
|
627
644
|
nodes: nodeIds,
|
|
628
645
|
direction
|
|
629
|
-
}
|
|
646
|
+
};
|
|
647
|
+
if (childSubgraphs.length > 0) sg.subgraphs = childSubgraphs;
|
|
648
|
+
state.subgraphs.push(sg);
|
|
630
649
|
return { ok: true };
|
|
631
650
|
}
|
|
651
|
+
/** Recursively collect all node IDs owned by a subgraph and its children. */
|
|
652
|
+
function collectAllNodes(sg, out) {
|
|
653
|
+
for (const id of sg.nodes) out.add(id);
|
|
654
|
+
for (const child of sg.subgraphs ?? []) collectAllNodes(child, out);
|
|
655
|
+
}
|
|
632
656
|
function parseArrow(arrow) {
|
|
633
657
|
const raw = arrow.endsWith("|") ? arrow.slice(0, -1) : arrow;
|
|
634
658
|
let sourceMarker = "none";
|
|
@@ -713,7 +737,8 @@ function parseSequence(input) {
|
|
|
713
737
|
participants: /* @__PURE__ */ new Map(),
|
|
714
738
|
messages: [],
|
|
715
739
|
blocks: [],
|
|
716
|
-
notes: []
|
|
740
|
+
notes: [],
|
|
741
|
+
noteMessageCounts: []
|
|
717
742
|
};
|
|
718
743
|
skipNewlines(state);
|
|
719
744
|
const header = peek(state);
|
|
@@ -762,7 +787,8 @@ function parseSequence(input) {
|
|
|
762
787
|
participants: Array.from(state.participants.values()),
|
|
763
788
|
messages: state.messages,
|
|
764
789
|
blocks: state.blocks,
|
|
765
|
-
notes: state.notes
|
|
790
|
+
notes: state.notes,
|
|
791
|
+
_noteMessageCounts: state.noteMessageCounts
|
|
766
792
|
};
|
|
767
793
|
}
|
|
768
794
|
function parseParticipant(state, type) {
|
|
@@ -851,6 +877,7 @@ function parseNote(state) {
|
|
|
851
877
|
advance(state);
|
|
852
878
|
text = readRestOfLine(state);
|
|
853
879
|
}
|
|
880
|
+
state.noteMessageCounts.push(state.messages.length);
|
|
854
881
|
state.notes.push({
|
|
855
882
|
position,
|
|
856
883
|
participants,
|
|
@@ -900,11 +927,16 @@ function parseBlock(state) {
|
|
|
900
927
|
parseNote(state);
|
|
901
928
|
continue;
|
|
902
929
|
}
|
|
930
|
+
if (token.type === "keyword" && isBlockKeyword(token.value)) {
|
|
931
|
+
const result = parseBlock(state);
|
|
932
|
+
if ("message" in result) return result;
|
|
933
|
+
continue;
|
|
934
|
+
}
|
|
903
935
|
if (token.type === "identifier" || token.type === "keyword") {
|
|
904
936
|
const beforeLen = state.messages.length;
|
|
905
937
|
parseMessage(state);
|
|
906
938
|
if (state.messages.length > beforeLen) {
|
|
907
|
-
const msg = state.messages.
|
|
939
|
+
const msg = state.messages[state.messages.length - 1];
|
|
908
940
|
if (currentSection) currentSection.messages.push(msg);
|
|
909
941
|
else messages.push(msg);
|
|
910
942
|
}
|
|
@@ -1057,6 +1089,30 @@ const tokens$1 = defineTokens(tokenDefinition$1);
|
|
|
1057
1089
|
*/
|
|
1058
1090
|
const defaultTheme = createTheme(tokens$1);
|
|
1059
1091
|
|
|
1092
|
+
//#endregion
|
|
1093
|
+
//#region ../mermaid/src/base.style.ts
|
|
1094
|
+
/**
|
|
1095
|
+
* Common SVG text label properties.
|
|
1096
|
+
* Produces: fill, stroke:none, font-family, font-size, text-anchor, dominant-baseline.
|
|
1097
|
+
*/
|
|
1098
|
+
function textLabel(fill, fontSize) {
|
|
1099
|
+
return `fill: ${fill};
|
|
1100
|
+
stroke: none;
|
|
1101
|
+
font-family: ${tokens$1.fontFamily};
|
|
1102
|
+
font-size: ${fontSize};
|
|
1103
|
+
text-anchor: middle;
|
|
1104
|
+
dominant-baseline: central;`;
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Common SVG box/container properties.
|
|
1108
|
+
* Produces: fill, stroke, stroke-width.
|
|
1109
|
+
*/
|
|
1110
|
+
function boxShape(fill, stroke, strokeWidth = 1) {
|
|
1111
|
+
return `fill: ${fill};
|
|
1112
|
+
stroke: ${stroke};
|
|
1113
|
+
stroke-width: ${strokeWidth};`;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1060
1116
|
//#endregion
|
|
1061
1117
|
//#region ../mermaid/src/edge.style.ts
|
|
1062
1118
|
const c$14 = classes([
|
|
@@ -1103,12 +1159,7 @@ const edgeThick = rule`${c$14.edgeThick} {
|
|
|
1103
1159
|
stroke-width: 3;
|
|
1104
1160
|
}`;
|
|
1105
1161
|
const edgeLabel = rule`${c$14.edgeLabel} {
|
|
1106
|
-
|
|
1107
|
-
stroke: none;
|
|
1108
|
-
font-family: ${tokens$1.fontFamily};
|
|
1109
|
-
font-size: 12px;
|
|
1110
|
-
text-anchor: middle;
|
|
1111
|
-
dominant-baseline: central;
|
|
1162
|
+
${textLabel(tokens$1.edgeLabelText, "12px")}
|
|
1112
1163
|
}`;
|
|
1113
1164
|
const edgeLabelBg = rule`${c$14.edgeLabelBg} {
|
|
1114
1165
|
fill: ${tokens$1.edgeLabelBg};
|
|
@@ -1267,9 +1318,7 @@ const c$13 = classes([
|
|
|
1267
1318
|
"nodeLabel"
|
|
1268
1319
|
]);
|
|
1269
1320
|
const nodeShape = rule`${c$13.nodeShape} {
|
|
1270
|
-
|
|
1271
|
-
stroke: ${tokens$1.nodeStroke};
|
|
1272
|
-
stroke-width: ${tokens$1.edgeWidth};
|
|
1321
|
+
${boxShape(tokens$1.nodeFill, tokens$1.nodeStroke, tokens$1.edgeWidth)}
|
|
1273
1322
|
}`;
|
|
1274
1323
|
const nodeShapeHover = rule`${c$13.nodeShape} {
|
|
1275
1324
|
transition: filter 0.15s ease;
|
|
@@ -1279,12 +1328,7 @@ ${c$13.nodeShape}:hover {
|
|
|
1279
1328
|
filter: brightness(0.93);
|
|
1280
1329
|
}`;
|
|
1281
1330
|
const nodeLabel = rule`${c$13.nodeLabel} {
|
|
1282
|
-
|
|
1283
|
-
stroke: none;
|
|
1284
|
-
font-family: ${tokens$1.fontFamily};
|
|
1285
|
-
font-size: ${tokens$1.fontSize}px;
|
|
1286
|
-
text-anchor: middle;
|
|
1287
|
-
dominant-baseline: central;
|
|
1331
|
+
${textLabel(tokens$1.nodeText, `${tokens$1.fontSize}px`)}
|
|
1288
1332
|
pointer-events: none;
|
|
1289
1333
|
}`;
|
|
1290
1334
|
|
|
@@ -1583,18 +1627,42 @@ const shapeMap = {
|
|
|
1583
1627
|
};
|
|
1584
1628
|
|
|
1585
1629
|
//#endregion
|
|
1586
|
-
//#region ../mermaid/src/components/
|
|
1587
|
-
|
|
1588
|
-
solid: void 0,
|
|
1589
|
-
dotted: edgeDotted,
|
|
1590
|
-
thick: edgeThick
|
|
1591
|
-
};
|
|
1630
|
+
//#region ../mermaid/src/components/markers.ts
|
|
1631
|
+
/** SVG marker URL by EdgeMarker type (used by flowchart edges). */
|
|
1592
1632
|
const MARKER_URL = {
|
|
1593
1633
|
arrow: "url(#mmd-arrow)",
|
|
1594
1634
|
dot: "url(#mmd-dot)",
|
|
1595
1635
|
cross: "url(#mmd-cross)",
|
|
1596
1636
|
none: void 0
|
|
1597
1637
|
};
|
|
1638
|
+
/**
|
|
1639
|
+
* Resolve an ArrowType (sequence diagram) to a marker URL.
|
|
1640
|
+
* This bridges the sequence-specific enum to the shared marker definitions in defs.tsx.
|
|
1641
|
+
*/
|
|
1642
|
+
const SEQUENCE_MARKER = {
|
|
1643
|
+
solid: "url(#mmd-arrow)",
|
|
1644
|
+
dotted: "url(#mmd-arrow)",
|
|
1645
|
+
solidCross: "url(#mmd-cross)",
|
|
1646
|
+
dottedCross: "url(#mmd-cross)",
|
|
1647
|
+
solidOpen: "url(#mmd-arrow-open)",
|
|
1648
|
+
dottedOpen: "url(#mmd-arrow-open)"
|
|
1649
|
+
};
|
|
1650
|
+
/** Get marker-end URL for a sequence message arrow type. */
|
|
1651
|
+
function sequenceMarker(arrow) {
|
|
1652
|
+
return SEQUENCE_MARKER[arrow];
|
|
1653
|
+
}
|
|
1654
|
+
/** Check if an ArrowType renders with a dashed stroke. */
|
|
1655
|
+
function isDottedArrow(arrow) {
|
|
1656
|
+
return arrow === "dotted" || arrow === "dottedCross" || arrow === "dottedOpen";
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
//#endregion
|
|
1660
|
+
//#region ../mermaid/src/components/edge.tsx
|
|
1661
|
+
const LINE_STYLE = {
|
|
1662
|
+
solid: void 0,
|
|
1663
|
+
dotted: edgeDotted,
|
|
1664
|
+
thick: edgeThick
|
|
1665
|
+
};
|
|
1598
1666
|
function Edge(props) {
|
|
1599
1667
|
const { edge, path, labelPosition, labelSize } = props.positioned;
|
|
1600
1668
|
const lineStyle = LINE_STYLE[edge.lineStyle];
|
|
@@ -1634,9 +1702,7 @@ function Edge(props) {
|
|
|
1634
1702
|
//#region ../mermaid/src/subgraph.style.ts
|
|
1635
1703
|
const c$12 = classes(["subgraphBg", "subgraphTitle"]);
|
|
1636
1704
|
const subgraphBg = rule`${c$12.subgraphBg} {
|
|
1637
|
-
|
|
1638
|
-
stroke: ${tokens$1.subgraphStroke};
|
|
1639
|
-
stroke-width: 1;
|
|
1705
|
+
${boxShape(tokens$1.subgraphFill, tokens$1.subgraphStroke, 1)}
|
|
1640
1706
|
}`;
|
|
1641
1707
|
const subgraphTitle = rule`${c$12.subgraphTitle} {
|
|
1642
1708
|
fill: ${tokens$1.subgraphTitleText};
|
|
@@ -1666,6 +1732,171 @@ function SubgraphBox(props) {
|
|
|
1666
1732
|
});
|
|
1667
1733
|
}
|
|
1668
1734
|
|
|
1735
|
+
//#endregion
|
|
1736
|
+
//#region ../mermaid/src/layout/measure.ts
|
|
1737
|
+
/**
|
|
1738
|
+
* Per-character width multipliers relative to fontSize, derived from
|
|
1739
|
+
* font metrics of common sans-serif typefaces (Helvetica / Arial).
|
|
1740
|
+
* Covers ASCII printable range; anything outside falls back to a
|
|
1741
|
+
* sensible default (0.55 for Latin, 1.0 for CJK / fullwidth).
|
|
1742
|
+
*/
|
|
1743
|
+
const CHAR_WIDTH = {
|
|
1744
|
+
" ": .28,
|
|
1745
|
+
"!": .28,
|
|
1746
|
+
"'": .19,
|
|
1747
|
+
",": .28,
|
|
1748
|
+
".": .28,
|
|
1749
|
+
":": .28,
|
|
1750
|
+
";": .28,
|
|
1751
|
+
i: .22,
|
|
1752
|
+
j: .22,
|
|
1753
|
+
l: .22,
|
|
1754
|
+
f: .28,
|
|
1755
|
+
r: .33,
|
|
1756
|
+
t: .33,
|
|
1757
|
+
I: .22,
|
|
1758
|
+
"|": .22,
|
|
1759
|
+
a: .5,
|
|
1760
|
+
b: .55,
|
|
1761
|
+
c: .5,
|
|
1762
|
+
d: .55,
|
|
1763
|
+
e: .5,
|
|
1764
|
+
g: .55,
|
|
1765
|
+
h: .55,
|
|
1766
|
+
k: .5,
|
|
1767
|
+
n: .55,
|
|
1768
|
+
o: .55,
|
|
1769
|
+
p: .55,
|
|
1770
|
+
q: .55,
|
|
1771
|
+
s: .5,
|
|
1772
|
+
u: .55,
|
|
1773
|
+
v: .5,
|
|
1774
|
+
x: .5,
|
|
1775
|
+
y: .5,
|
|
1776
|
+
z: .5,
|
|
1777
|
+
"0": .55,
|
|
1778
|
+
"1": .55,
|
|
1779
|
+
"2": .55,
|
|
1780
|
+
"3": .55,
|
|
1781
|
+
"4": .55,
|
|
1782
|
+
"5": .55,
|
|
1783
|
+
"6": .55,
|
|
1784
|
+
"7": .55,
|
|
1785
|
+
"8": .55,
|
|
1786
|
+
"9": .55,
|
|
1787
|
+
"-": .33,
|
|
1788
|
+
"(": .33,
|
|
1789
|
+
")": .33,
|
|
1790
|
+
"/": .28,
|
|
1791
|
+
m: .83,
|
|
1792
|
+
w: .72,
|
|
1793
|
+
M: .72,
|
|
1794
|
+
W: .83,
|
|
1795
|
+
A: .67,
|
|
1796
|
+
B: .67,
|
|
1797
|
+
C: .67,
|
|
1798
|
+
D: .72,
|
|
1799
|
+
E: .61,
|
|
1800
|
+
F: .56,
|
|
1801
|
+
G: .72,
|
|
1802
|
+
H: .72,
|
|
1803
|
+
J: .5,
|
|
1804
|
+
K: .67,
|
|
1805
|
+
L: .56,
|
|
1806
|
+
N: .72,
|
|
1807
|
+
O: .72,
|
|
1808
|
+
P: .67,
|
|
1809
|
+
Q: .72,
|
|
1810
|
+
R: .67,
|
|
1811
|
+
S: .67,
|
|
1812
|
+
T: .61,
|
|
1813
|
+
U: .72,
|
|
1814
|
+
V: .67,
|
|
1815
|
+
X: .67,
|
|
1816
|
+
Y: .67,
|
|
1817
|
+
Z: .61,
|
|
1818
|
+
"@": .92,
|
|
1819
|
+
"#": .55,
|
|
1820
|
+
$: .55,
|
|
1821
|
+
"%": .89,
|
|
1822
|
+
"&": .67,
|
|
1823
|
+
"+": .58,
|
|
1824
|
+
"=": .58,
|
|
1825
|
+
"<": .58,
|
|
1826
|
+
">": .58,
|
|
1827
|
+
_: .55,
|
|
1828
|
+
"{": .33,
|
|
1829
|
+
"}": .33,
|
|
1830
|
+
"[": .28,
|
|
1831
|
+
"]": .28,
|
|
1832
|
+
"\"": .35,
|
|
1833
|
+
"~": .58,
|
|
1834
|
+
"^": .47,
|
|
1835
|
+
"*": .39,
|
|
1836
|
+
"\\": .28,
|
|
1837
|
+
"`": .33,
|
|
1838
|
+
"?": .56
|
|
1839
|
+
};
|
|
1840
|
+
/** Default multiplier for unlisted Latin / symbol characters. */
|
|
1841
|
+
const DEFAULT_CHAR_WIDTH = .55;
|
|
1842
|
+
/**
|
|
1843
|
+
* Check whether a code point is in a CJK / fullwidth Unicode range.
|
|
1844
|
+
* These characters are typically rendered at roughly 1em width.
|
|
1845
|
+
*/
|
|
1846
|
+
function isCJKOrFullwidth(code) {
|
|
1847
|
+
return code >= 11904 && code <= 40959 || code >= 63744 && code <= 64255 || code >= 65072 && code <= 65103 || code >= 65280 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 131072 && code <= 195103 || code >= 12288 && code <= 12351 || code >= 12352 && code <= 12543 || code >= 44032 && code <= 55215;
|
|
1848
|
+
}
|
|
1849
|
+
/**
|
|
1850
|
+
* Estimate text dimensions using per-character width tables.
|
|
1851
|
+
* Falls back to this when no Canvas / DOM measurement is available.
|
|
1852
|
+
*/
|
|
1853
|
+
function estimateTextSize(text, fontSize) {
|
|
1854
|
+
let totalWidth = 0;
|
|
1855
|
+
for (let i = 0; i < text.length; i++) {
|
|
1856
|
+
const ch = text[i];
|
|
1857
|
+
const known = CHAR_WIDTH[ch];
|
|
1858
|
+
if (known !== void 0) totalWidth += known;
|
|
1859
|
+
else {
|
|
1860
|
+
const code = ch.charCodeAt(0);
|
|
1861
|
+
totalWidth += isCJKOrFullwidth(code) ? 1 : DEFAULT_CHAR_WIDTH;
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
return {
|
|
1865
|
+
width: totalWidth * fontSize,
|
|
1866
|
+
height: fontSize * 1.4
|
|
1867
|
+
};
|
|
1868
|
+
}
|
|
1869
|
+
let _ctx;
|
|
1870
|
+
function canvasMeasureText(text, fontSize) {
|
|
1871
|
+
if (_ctx === void 0) {
|
|
1872
|
+
_ctx = null;
|
|
1873
|
+
try {
|
|
1874
|
+
if (typeof OffscreenCanvas !== "undefined") _ctx = new OffscreenCanvas(1, 1).getContext("2d");
|
|
1875
|
+
else if (typeof document !== "undefined") _ctx = document.createElement("canvas").getContext("2d");
|
|
1876
|
+
} catch {}
|
|
1877
|
+
}
|
|
1878
|
+
if (_ctx) {
|
|
1879
|
+
_ctx.font = `${fontSize}px sans-serif`;
|
|
1880
|
+
return {
|
|
1881
|
+
width: _ctx.measureText(text).width,
|
|
1882
|
+
height: fontSize * 1.2
|
|
1883
|
+
};
|
|
1884
|
+
}
|
|
1885
|
+
return estimateTextSize(text, fontSize);
|
|
1886
|
+
}
|
|
1887
|
+
/** Measure a node label (default 14px). */
|
|
1888
|
+
function measureNode(label, opts) {
|
|
1889
|
+
const textSize = (opts.measureText ?? canvasMeasureText)(label, 14);
|
|
1890
|
+
return {
|
|
1891
|
+
width: Math.max(textSize.width + opts.nodePadding * 2, opts.nodeWidth),
|
|
1892
|
+
height: Math.max(textSize.height + opts.nodePadding * 2, opts.nodeHeight)
|
|
1893
|
+
};
|
|
1894
|
+
}
|
|
1895
|
+
/** Measure an edge / message label (default 12px). */
|
|
1896
|
+
function measureLabel(text, opts) {
|
|
1897
|
+
return (opts.measureText ?? canvasMeasureText)(text, 12);
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1669
1900
|
//#endregion
|
|
1670
1901
|
//#region ../mermaid/src/layout/flowchart.ts
|
|
1671
1902
|
const DEFAULT_OPTIONS$1 = {
|
|
@@ -1692,31 +1923,37 @@ function flowchartLayout(diagram, options) {
|
|
|
1692
1923
|
subgraphs: []
|
|
1693
1924
|
};
|
|
1694
1925
|
const nodeSizes = /* @__PURE__ */ new Map();
|
|
1695
|
-
for (const node of nodes) nodeSizes.set(node.id, measureNode(node, opts));
|
|
1926
|
+
for (const node of nodes) nodeSizes.set(node.id, measureNode(node.label, opts));
|
|
1927
|
+
const selfLoops = [];
|
|
1928
|
+
const nonSelfEdges = [];
|
|
1929
|
+
for (const edge of edges) if (edge.source === edge.target) selfLoops.push(edge);
|
|
1930
|
+
else nonSelfEdges.push(edge);
|
|
1931
|
+
const backEdgeSet = /* @__PURE__ */ new Set();
|
|
1696
1932
|
const adj = /* @__PURE__ */ new Map();
|
|
1697
|
-
const safeEdges = [];
|
|
1698
1933
|
const visited = /* @__PURE__ */ new Set();
|
|
1699
1934
|
const inStack = /* @__PURE__ */ new Set();
|
|
1700
1935
|
for (const node of nodes) adj.set(node.id, []);
|
|
1701
|
-
for (const edge of
|
|
1702
|
-
const targets = adj.get(edge.source);
|
|
1703
|
-
if (targets) targets.push(edge.target);
|
|
1704
|
-
}
|
|
1936
|
+
for (const edge of nonSelfEdges) adj.get(edge.source)?.push(edge.target);
|
|
1705
1937
|
function dfs(node) {
|
|
1706
1938
|
visited.add(node);
|
|
1707
1939
|
inStack.add(node);
|
|
1708
1940
|
for (const neighbor of adj.get(node) ?? []) if (inStack.has(neighbor)) {
|
|
1709
|
-
const edge =
|
|
1710
|
-
if (edge)
|
|
1711
|
-
...edge,
|
|
1712
|
-
source: neighbor,
|
|
1713
|
-
target: node
|
|
1714
|
-
});
|
|
1941
|
+
const edge = nonSelfEdges.find((e) => e.source === node && e.target === neighbor);
|
|
1942
|
+
if (edge) backEdgeSet.add(edge);
|
|
1715
1943
|
} else if (!visited.has(neighbor)) dfs(neighbor);
|
|
1716
1944
|
inStack.delete(node);
|
|
1717
1945
|
}
|
|
1718
1946
|
for (const node of nodes) if (!visited.has(node.id)) dfs(node.id);
|
|
1719
|
-
|
|
1947
|
+
const origToSafe = /* @__PURE__ */ new Map();
|
|
1948
|
+
const safeEdges = nonSelfEdges.map((edge) => {
|
|
1949
|
+
const safe = backEdgeSet.has(edge) ? {
|
|
1950
|
+
...edge,
|
|
1951
|
+
source: edge.target,
|
|
1952
|
+
target: edge.source
|
|
1953
|
+
} : edge;
|
|
1954
|
+
origToSafe.set(edge, safe);
|
|
1955
|
+
return safe;
|
|
1956
|
+
});
|
|
1720
1957
|
const layers = /* @__PURE__ */ new Map();
|
|
1721
1958
|
const safeAdj = /* @__PURE__ */ new Map();
|
|
1722
1959
|
const inDegree = /* @__PURE__ */ new Map();
|
|
@@ -1744,87 +1981,276 @@ function flowchartLayout(diagram, options) {
|
|
|
1744
1981
|
}
|
|
1745
1982
|
}
|
|
1746
1983
|
for (const node of nodes) if (!layers.has(node.id)) layers.set(node.id, 0);
|
|
1984
|
+
const DUMMY_DIM = 8;
|
|
1985
|
+
const dummySet = /* @__PURE__ */ new Set();
|
|
1986
|
+
const dummySize = {
|
|
1987
|
+
width: DUMMY_DIM,
|
|
1988
|
+
height: DUMMY_DIM
|
|
1989
|
+
};
|
|
1990
|
+
const edgeDummies = /* @__PURE__ */ new Map();
|
|
1991
|
+
let workEdges = [...safeEdges];
|
|
1992
|
+
{
|
|
1993
|
+
const newEdges = [];
|
|
1994
|
+
for (const edge of workEdges) {
|
|
1995
|
+
const srcLayer = layers.get(edge.source) ?? 0;
|
|
1996
|
+
const tgtLayer = layers.get(edge.target) ?? 0;
|
|
1997
|
+
if (tgtLayer - srcLayer <= 1) {
|
|
1998
|
+
newEdges.push(edge);
|
|
1999
|
+
continue;
|
|
2000
|
+
}
|
|
2001
|
+
const dummies = [];
|
|
2002
|
+
let prev = edge.source;
|
|
2003
|
+
for (let l = srcLayer + 1; l < tgtLayer; l++) {
|
|
2004
|
+
const dummyId = `__dummy_${edge.source}_${edge.target}_${l}`;
|
|
2005
|
+
dummies.push(dummyId);
|
|
2006
|
+
dummySet.add(dummyId);
|
|
2007
|
+
layers.set(dummyId, l);
|
|
2008
|
+
nodeSizes.set(dummyId, dummySize);
|
|
2009
|
+
newEdges.push({
|
|
2010
|
+
source: prev,
|
|
2011
|
+
target: dummyId,
|
|
2012
|
+
lineStyle: edge.lineStyle,
|
|
2013
|
+
sourceMarker: "none",
|
|
2014
|
+
targetMarker: "none"
|
|
2015
|
+
});
|
|
2016
|
+
prev = dummyId;
|
|
2017
|
+
}
|
|
2018
|
+
newEdges.push({
|
|
2019
|
+
source: prev,
|
|
2020
|
+
target: edge.target,
|
|
2021
|
+
lineStyle: edge.lineStyle,
|
|
2022
|
+
sourceMarker: "none",
|
|
2023
|
+
targetMarker: "none"
|
|
2024
|
+
});
|
|
2025
|
+
edgeDummies.set(edge, dummies);
|
|
2026
|
+
}
|
|
2027
|
+
workEdges = newEdges;
|
|
2028
|
+
}
|
|
1747
2029
|
const maxLayer = Math.max(...Array.from(layers.values()), 0);
|
|
1748
2030
|
const layerGroups = Array.from({ length: maxLayer + 1 }, () => []);
|
|
1749
2031
|
for (const node of nodes) layerGroups[layers.get(node.id) ?? 0].push(node.id);
|
|
1750
|
-
for (
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
2032
|
+
for (const dummyId of dummySet) layerGroups[layers.get(dummyId) ?? 0].push(dummyId);
|
|
2033
|
+
const nodeSubgraph = /* @__PURE__ */ new Map();
|
|
2034
|
+
for (const sg of subgraphs) mapNodesToSubgraph(sg, nodeSubgraph);
|
|
2035
|
+
const allNodeIds = [...nodes.map((n) => n.id), ...dummySet];
|
|
2036
|
+
const parents = /* @__PURE__ */ new Map();
|
|
2037
|
+
const children = /* @__PURE__ */ new Map();
|
|
2038
|
+
for (const id of allNodeIds) {
|
|
2039
|
+
parents.set(id, []);
|
|
2040
|
+
children.set(id, []);
|
|
2041
|
+
}
|
|
2042
|
+
for (const edge of workEdges) {
|
|
2043
|
+
children.get(edge.source)?.push(edge.target);
|
|
2044
|
+
parents.get(edge.target)?.push(edge.source);
|
|
2045
|
+
}
|
|
2046
|
+
for (let pass = 0; pass < 4; pass++) if (pass % 2 === 0) for (let l = 1; l <= maxLayer; l++) orderLayerByBarycenter(layerGroups[l], layerGroups[l - 1], parents, nodeSubgraph);
|
|
2047
|
+
else for (let l = maxLayer - 1; l >= 0; l--) orderLayerByBarycenter(layerGroups[l], layerGroups[l + 1], children, nodeSubgraph);
|
|
2048
|
+
for (let pass = 0; pass < 3; pass++) {
|
|
2049
|
+
let improved = false;
|
|
2050
|
+
for (let l = 0; l < maxLayer; l++) {
|
|
2051
|
+
const layer = layerGroups[l];
|
|
2052
|
+
const nextLayer = layerGroups[l + 1];
|
|
2053
|
+
for (let i = 0; i < layer.length - 1; i++) {
|
|
2054
|
+
const crossBefore = countCrossings(layer, nextLayer, children);
|
|
2055
|
+
const tmp = layer[i];
|
|
2056
|
+
layer[i] = layer[i + 1];
|
|
2057
|
+
layer[i + 1] = tmp;
|
|
2058
|
+
if (countCrossings(layer, nextLayer, children) < crossBefore) improved = true;
|
|
2059
|
+
else {
|
|
2060
|
+
layer[i + 1] = layer[i];
|
|
2061
|
+
layer[i] = tmp;
|
|
2062
|
+
}
|
|
1760
2063
|
}
|
|
1761
|
-
barycenters.set(nodeId, count > 0 ? sum / count : prevLayer.length / 2);
|
|
1762
2064
|
}
|
|
1763
|
-
|
|
2065
|
+
if (!improved) break;
|
|
1764
2066
|
}
|
|
1765
2067
|
const isVertical = direction === "TB" || direction === "TD" || direction === "BT";
|
|
1766
|
-
const
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
for (const
|
|
1774
|
-
const
|
|
1775
|
-
|
|
1776
|
-
if (
|
|
1777
|
-
|
|
1778
|
-
y: l * (opts.nodeHeight + opts.rankSpacing)
|
|
1779
|
-
});
|
|
1780
|
-
else positions.set(nodeId, {
|
|
1781
|
-
x: l * (opts.nodeWidth + opts.rankSpacing),
|
|
1782
|
-
y: offset + primaryDim / 2
|
|
1783
|
-
});
|
|
1784
|
-
offset += primaryDim + opts.nodeSpacing;
|
|
2068
|
+
const sgLayerRanges = computeSubgraphLayerRanges(subgraphs, layers);
|
|
2069
|
+
const allSubgraphs = flattenSubgraphs(subgraphs);
|
|
2070
|
+
const rankNodeDim = isVertical ? opts.nodeHeight : opts.nodeWidth;
|
|
2071
|
+
const sgTitleHeight = 20;
|
|
2072
|
+
const rankPos = [0];
|
|
2073
|
+
for (let l = 0; l < maxLayer; l++) {
|
|
2074
|
+
let overhead = 0;
|
|
2075
|
+
for (const sg of allSubgraphs) {
|
|
2076
|
+
const range = sgLayerRanges.get(sg.id);
|
|
2077
|
+
if (!range || range.minLayer > range.maxLayer) continue;
|
|
2078
|
+
if (range.maxLayer === l) overhead += opts.nodePadding;
|
|
2079
|
+
if (range.minLayer === l + 1) overhead += opts.nodePadding + sgTitleHeight;
|
|
1785
2080
|
}
|
|
2081
|
+
const extra = overhead > 0 ? Math.max(0, overhead - opts.rankSpacing + opts.nodePadding) : 0;
|
|
2082
|
+
rankPos.push(rankPos[l] + rankNodeDim + opts.rankSpacing + extra);
|
|
2083
|
+
}
|
|
2084
|
+
const dim = (id) => {
|
|
2085
|
+
if (dummySet.has(id)) return DUMMY_DIM;
|
|
2086
|
+
const size = nodeSizes.get(id);
|
|
2087
|
+
return isVertical ? size.width : size.height;
|
|
2088
|
+
};
|
|
2089
|
+
const gap = (a, b) => {
|
|
2090
|
+
if (nodeSubgraph.get(a) !== nodeSubgraph.get(b)) return opts.nodeSpacing + opts.nodePadding * 2;
|
|
2091
|
+
return opts.nodeSpacing;
|
|
2092
|
+
};
|
|
2093
|
+
const bkResults = [];
|
|
2094
|
+
for (let dir = 0; dir < 4; dir++) {
|
|
2095
|
+
const isDown = dir < 2;
|
|
2096
|
+
const isLeft = dir % 2 === 0;
|
|
2097
|
+
const alignment = isDown ? parents : children;
|
|
2098
|
+
const p = /* @__PURE__ */ new Map();
|
|
2099
|
+
for (let l = 0; l <= maxLayer; l++) packLayerCentered(layerGroups[l], p, dim, gap);
|
|
2100
|
+
const sweeps = 4;
|
|
2101
|
+
for (let s = 0; s < sweeps; s++) if (isDown) for (let l = 1; l <= maxLayer; l++) alignLayerBK(layerGroups[l], alignment, p, dim, gap, isLeft);
|
|
2102
|
+
else for (let l = maxLayer - 1; l >= 0; l--) alignLayerBK(layerGroups[l], alignment, p, dim, gap, isLeft);
|
|
2103
|
+
bkResults.push(p);
|
|
2104
|
+
}
|
|
2105
|
+
const pos = /* @__PURE__ */ new Map();
|
|
2106
|
+
for (const id of allNodeIds) {
|
|
2107
|
+
const vals = bkResults.map((r) => r.get(id) ?? 0).sort((a, b) => a - b);
|
|
2108
|
+
pos.set(id, (vals[1] + vals[2]) / 2);
|
|
2109
|
+
}
|
|
2110
|
+
for (const [, dummies] of edgeDummies) {
|
|
2111
|
+
if (dummies.length === 0) continue;
|
|
2112
|
+
let sum = 0;
|
|
2113
|
+
for (const id of dummies) sum += pos.get(id) ?? 0;
|
|
2114
|
+
const avg = sum / dummies.length;
|
|
2115
|
+
for (const id of dummies) pos.set(id, avg);
|
|
2116
|
+
}
|
|
2117
|
+
const nodeLayer = /* @__PURE__ */ new Map();
|
|
2118
|
+
for (let l = 0; l <= maxLayer; l++) for (const id of layerGroups[l]) nodeLayer.set(id, l);
|
|
2119
|
+
const positions = /* @__PURE__ */ new Map();
|
|
2120
|
+
for (const id of allNodeIds) {
|
|
2121
|
+
const p = pos.get(id) ?? 0;
|
|
2122
|
+
const l = nodeLayer.get(id) ?? 0;
|
|
2123
|
+
if (isVertical) positions.set(id, {
|
|
2124
|
+
x: p,
|
|
2125
|
+
y: rankPos[l]
|
|
2126
|
+
});
|
|
2127
|
+
else positions.set(id, {
|
|
2128
|
+
x: rankPos[l],
|
|
2129
|
+
y: p
|
|
2130
|
+
});
|
|
1786
2131
|
}
|
|
1787
2132
|
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
1788
|
-
for (const [id,
|
|
2133
|
+
for (const [id, p] of positions) {
|
|
2134
|
+
if (dummySet.has(id)) continue;
|
|
1789
2135
|
const size = nodeSizes.get(id);
|
|
1790
|
-
minX = Math.min(minX,
|
|
1791
|
-
minY = Math.min(minY,
|
|
1792
|
-
maxX = Math.max(maxX,
|
|
1793
|
-
maxY = Math.max(maxY,
|
|
2136
|
+
minX = Math.min(minX, p.x - size.width / 2);
|
|
2137
|
+
minY = Math.min(minY, p.y - size.height / 2);
|
|
2138
|
+
maxX = Math.max(maxX, p.x + size.width / 2);
|
|
2139
|
+
maxY = Math.max(maxY, p.y + size.height / 2);
|
|
1794
2140
|
}
|
|
1795
2141
|
const offsetX = opts.diagramPadding - minX;
|
|
1796
2142
|
const offsetY = opts.diagramPadding - minY;
|
|
1797
|
-
for (const [,
|
|
1798
|
-
|
|
1799
|
-
|
|
2143
|
+
for (const [, p] of positions) {
|
|
2144
|
+
p.x += offsetX;
|
|
2145
|
+
p.y += offsetY;
|
|
1800
2146
|
}
|
|
1801
2147
|
if (direction === "BT") {
|
|
1802
2148
|
const totalHeight = maxY - minY;
|
|
1803
|
-
for (const [,
|
|
2149
|
+
for (const [, p] of positions) p.y = totalHeight - (p.y - opts.diagramPadding) + opts.diagramPadding;
|
|
1804
2150
|
}
|
|
1805
2151
|
if (direction === "RL") {
|
|
1806
2152
|
const totalWidth = maxX - minX;
|
|
1807
|
-
for (const [,
|
|
2153
|
+
for (const [, p] of positions) p.x = totalWidth - (p.x - opts.diagramPadding) + opts.diagramPadding;
|
|
2154
|
+
}
|
|
2155
|
+
if (subgraphs.length > 0) {
|
|
2156
|
+
let extraShiftX = 0;
|
|
2157
|
+
let extraShiftY = 0;
|
|
2158
|
+
for (const sg of subgraphs) {
|
|
2159
|
+
const sgMin = precomputeSgMin(sg, positions, nodeSizes, opts);
|
|
2160
|
+
extraShiftX = Math.max(extraShiftX, opts.diagramPadding - sgMin.minX);
|
|
2161
|
+
extraShiftY = Math.max(extraShiftY, opts.diagramPadding - sgMin.minY);
|
|
2162
|
+
}
|
|
2163
|
+
if (extraShiftX > 0 || extraShiftY > 0) for (const [, p] of positions) {
|
|
2164
|
+
p.x += extraShiftX;
|
|
2165
|
+
p.y += extraShiftY;
|
|
2166
|
+
}
|
|
1808
2167
|
}
|
|
1809
2168
|
const positionedNodes = nodes.map((node) => {
|
|
1810
|
-
const
|
|
2169
|
+
const p = positions.get(node.id);
|
|
1811
2170
|
const size = nodeSizes.get(node.id);
|
|
1812
2171
|
return {
|
|
1813
2172
|
node,
|
|
1814
|
-
x:
|
|
1815
|
-
y:
|
|
2173
|
+
x: p.x,
|
|
2174
|
+
y: p.y,
|
|
1816
2175
|
width: size.width,
|
|
1817
2176
|
height: size.height
|
|
1818
2177
|
};
|
|
1819
2178
|
});
|
|
1820
2179
|
const positionedEdges = edges.map((edge) => {
|
|
2180
|
+
if (edge.source === edge.target) {
|
|
2181
|
+
const p = positions.get(edge.source);
|
|
2182
|
+
const size = nodeSizes.get(edge.source);
|
|
2183
|
+
if (!p || !size) return {
|
|
2184
|
+
edge,
|
|
2185
|
+
path: "M 0 0"
|
|
2186
|
+
};
|
|
2187
|
+
const loopSize = 30;
|
|
2188
|
+
const rx = size.width / 2;
|
|
2189
|
+
const ry = size.height / 2;
|
|
2190
|
+
let path;
|
|
2191
|
+
let labelMid;
|
|
2192
|
+
if (isVertical) {
|
|
2193
|
+
const sx = p.x + rx;
|
|
2194
|
+
const sy = p.y - ry * .3;
|
|
2195
|
+
const tx = p.x + rx;
|
|
2196
|
+
const ty = p.y + ry * .3;
|
|
2197
|
+
const cx = p.x + rx + loopSize;
|
|
2198
|
+
path = `M ${sx} ${sy} C ${cx} ${sy - loopSize} ${cx} ${ty + loopSize} ${tx} ${ty}`;
|
|
2199
|
+
labelMid = {
|
|
2200
|
+
x: cx + 4,
|
|
2201
|
+
y: p.y
|
|
2202
|
+
};
|
|
2203
|
+
} else {
|
|
2204
|
+
const sx = p.x - rx * .3;
|
|
2205
|
+
const sy = p.y + ry;
|
|
2206
|
+
const tx = p.x + rx * .3;
|
|
2207
|
+
const ty = p.y + ry;
|
|
2208
|
+
const cy = p.y + ry + loopSize;
|
|
2209
|
+
path = `M ${sx} ${sy} C ${sx - loopSize} ${cy} ${tx + loopSize} ${cy} ${tx} ${ty}`;
|
|
2210
|
+
labelMid = {
|
|
2211
|
+
x: p.x,
|
|
2212
|
+
y: cy + 4
|
|
2213
|
+
};
|
|
2214
|
+
}
|
|
2215
|
+
let labelPosition;
|
|
2216
|
+
let labelSize;
|
|
2217
|
+
if (edge.label) {
|
|
2218
|
+
labelPosition = labelMid;
|
|
2219
|
+
labelSize = measureLabel(edge.label, opts);
|
|
2220
|
+
}
|
|
2221
|
+
return {
|
|
2222
|
+
edge,
|
|
2223
|
+
path,
|
|
2224
|
+
labelPosition,
|
|
2225
|
+
labelSize
|
|
2226
|
+
};
|
|
2227
|
+
}
|
|
1821
2228
|
const sourcePos = positions.get(edge.source);
|
|
1822
2229
|
const targetPos = positions.get(edge.target);
|
|
1823
2230
|
if (!sourcePos || !targetPos) return {
|
|
1824
2231
|
edge,
|
|
1825
2232
|
path: "M 0 0"
|
|
1826
2233
|
};
|
|
1827
|
-
const
|
|
2234
|
+
const sourceSize = nodeSizes.get(edge.source);
|
|
2235
|
+
const targetSize = nodeSizes.get(edge.target);
|
|
2236
|
+
const safeEdge = origToSafe.get(edge);
|
|
2237
|
+
const dummies = safeEdge ? edgeDummies.get(safeEdge) : void 0;
|
|
2238
|
+
if (dummies && dummies.length > 0) {
|
|
2239
|
+
const result = buildLongEdgePath(sourcePos, targetPos, sourceSize, targetSize, dummies.map((id) => positions.get(id)), isVertical, opts);
|
|
2240
|
+
let labelPosition;
|
|
2241
|
+
let labelSize;
|
|
2242
|
+
if (edge.label) {
|
|
2243
|
+
labelPosition = result.labelMid;
|
|
2244
|
+
labelSize = measureLabel(edge.label, opts);
|
|
2245
|
+
}
|
|
2246
|
+
return {
|
|
2247
|
+
edge,
|
|
2248
|
+
path: result.path,
|
|
2249
|
+
labelPosition,
|
|
2250
|
+
labelSize
|
|
2251
|
+
};
|
|
2252
|
+
}
|
|
2253
|
+
const result = buildEdgePath(sourcePos, targetPos, sourceSize, targetSize, isVertical, opts);
|
|
1828
2254
|
let labelPosition;
|
|
1829
2255
|
let labelSize;
|
|
1830
2256
|
if (edge.label) {
|
|
@@ -1838,29 +2264,51 @@ function flowchartLayout(diagram, options) {
|
|
|
1838
2264
|
labelSize
|
|
1839
2265
|
};
|
|
1840
2266
|
});
|
|
1841
|
-
const positionedSubgraphs =
|
|
2267
|
+
const positionedSubgraphs = [];
|
|
2268
|
+
function layoutSubgraph(sg) {
|
|
2269
|
+
const childPositioned = [];
|
|
2270
|
+
for (const child of sg.subgraphs ?? []) childPositioned.push(layoutSubgraph(child));
|
|
1842
2271
|
let sgMinX = Infinity, sgMinY = Infinity, sgMaxX = -Infinity, sgMaxY = -Infinity;
|
|
1843
2272
|
for (const nodeId of sg.nodes) {
|
|
1844
|
-
const
|
|
2273
|
+
const p = positions.get(nodeId);
|
|
1845
2274
|
const size = nodeSizes.get(nodeId);
|
|
1846
|
-
if (
|
|
1847
|
-
sgMinX = Math.min(sgMinX,
|
|
1848
|
-
sgMinY = Math.min(sgMinY,
|
|
1849
|
-
sgMaxX = Math.max(sgMaxX,
|
|
1850
|
-
sgMaxY = Math.max(sgMaxY,
|
|
2275
|
+
if (p && size) {
|
|
2276
|
+
sgMinX = Math.min(sgMinX, p.x - size.width / 2);
|
|
2277
|
+
sgMinY = Math.min(sgMinY, p.y - size.height / 2);
|
|
2278
|
+
sgMaxX = Math.max(sgMaxX, p.x + size.width / 2);
|
|
2279
|
+
sgMaxY = Math.max(sgMaxY, p.y + size.height / 2);
|
|
1851
2280
|
}
|
|
1852
2281
|
}
|
|
2282
|
+
for (const child of childPositioned) {
|
|
2283
|
+
sgMinX = Math.min(sgMinX, child.x);
|
|
2284
|
+
sgMinY = Math.min(sgMinY, child.y);
|
|
2285
|
+
sgMaxX = Math.max(sgMaxX, child.x + child.width);
|
|
2286
|
+
sgMaxY = Math.max(sgMaxY, child.y + child.height);
|
|
2287
|
+
}
|
|
1853
2288
|
const padding = opts.nodePadding;
|
|
1854
|
-
|
|
2289
|
+
const positioned = {
|
|
1855
2290
|
subgraph: sg,
|
|
1856
2291
|
x: sgMinX - padding,
|
|
1857
2292
|
y: sgMinY - padding - 20,
|
|
1858
2293
|
width: sgMaxX - sgMinX + padding * 2,
|
|
1859
2294
|
height: sgMaxY - sgMinY + padding * 2 + 20
|
|
1860
2295
|
};
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
2296
|
+
positionedSubgraphs.push(positioned);
|
|
2297
|
+
return positioned;
|
|
2298
|
+
}
|
|
2299
|
+
for (const sg of subgraphs) layoutSubgraph(sg);
|
|
2300
|
+
let extMaxX = -Infinity;
|
|
2301
|
+
let extMaxY = -Infinity;
|
|
2302
|
+
for (const pn of positionedNodes) {
|
|
2303
|
+
extMaxX = Math.max(extMaxX, pn.x + pn.width / 2);
|
|
2304
|
+
extMaxY = Math.max(extMaxY, pn.y + pn.height / 2);
|
|
2305
|
+
}
|
|
2306
|
+
for (const psg of positionedSubgraphs) {
|
|
2307
|
+
extMaxX = Math.max(extMaxX, psg.x + psg.width);
|
|
2308
|
+
extMaxY = Math.max(extMaxY, psg.y + psg.height);
|
|
2309
|
+
}
|
|
2310
|
+
const diagramWidth = extMaxX + opts.diagramPadding;
|
|
2311
|
+
const diagramHeight = extMaxY + opts.diagramPadding;
|
|
1864
2312
|
return {
|
|
1865
2313
|
width: diagramWidth,
|
|
1866
2314
|
height: diagramHeight,
|
|
@@ -1870,6 +2318,136 @@ function flowchartLayout(diagram, options) {
|
|
|
1870
2318
|
subgraphs: positionedSubgraphs
|
|
1871
2319
|
};
|
|
1872
2320
|
}
|
|
2321
|
+
/** Map each node to its most immediate (deepest) containing subgraph. */
|
|
2322
|
+
function mapNodesToSubgraph(sg, out) {
|
|
2323
|
+
for (const nodeId of sg.nodes) out.set(nodeId, sg.id);
|
|
2324
|
+
for (const child of sg.subgraphs ?? []) mapNodesToSubgraph(child, out);
|
|
2325
|
+
}
|
|
2326
|
+
/**
|
|
2327
|
+
* Order a layer using barycenter heuristic with subgraph clustering.
|
|
2328
|
+
* `neighbors` maps each node to its connected nodes in the reference layer.
|
|
2329
|
+
* Nodes in the same subgraph are kept adjacent.
|
|
2330
|
+
*/
|
|
2331
|
+
function orderLayerByBarycenter(layer, refLayer, neighborMap, nodeSubgraph) {
|
|
2332
|
+
const barycenters = /* @__PURE__ */ new Map();
|
|
2333
|
+
const refIndex = /* @__PURE__ */ new Map();
|
|
2334
|
+
for (let i = 0; i < refLayer.length; i++) refIndex.set(refLayer[i], i);
|
|
2335
|
+
for (const nodeId of layer) {
|
|
2336
|
+
const nbrs = neighborMap.get(nodeId) ?? [];
|
|
2337
|
+
let sum = 0;
|
|
2338
|
+
let count = 0;
|
|
2339
|
+
for (const n of nbrs) {
|
|
2340
|
+
const idx = refIndex.get(n);
|
|
2341
|
+
if (idx !== void 0) {
|
|
2342
|
+
sum += idx;
|
|
2343
|
+
count++;
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
if (count > 0) barycenters.set(nodeId, sum / count);
|
|
2347
|
+
}
|
|
2348
|
+
const groupBary = /* @__PURE__ */ new Map();
|
|
2349
|
+
for (const nodeId of layer) {
|
|
2350
|
+
const sgId = nodeSubgraph.get(nodeId) ?? "";
|
|
2351
|
+
if (!groupBary.has(sgId)) {
|
|
2352
|
+
const connected = layer.filter((n) => (nodeSubgraph.get(n) ?? "") === sgId).filter((n) => barycenters.has(n));
|
|
2353
|
+
if (connected.length > 0) {
|
|
2354
|
+
const avg = connected.reduce((s, n) => s + barycenters.get(n), 0) / connected.length;
|
|
2355
|
+
groupBary.set(sgId, avg);
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
const original = [...layer];
|
|
2360
|
+
layer.sort((a, b) => {
|
|
2361
|
+
const sgA = nodeSubgraph.get(a) ?? "";
|
|
2362
|
+
const sgB = nodeSubgraph.get(b) ?? "";
|
|
2363
|
+
if (sgA !== sgB) {
|
|
2364
|
+
const ga = groupBary.get(sgA);
|
|
2365
|
+
const gb = groupBary.get(sgB);
|
|
2366
|
+
if (ga !== void 0 && gb !== void 0 && ga !== gb) return ga - gb;
|
|
2367
|
+
if (ga !== void 0 && gb === void 0) return -1;
|
|
2368
|
+
if (ga === void 0 && gb !== void 0) return 1;
|
|
2369
|
+
}
|
|
2370
|
+
const ba = barycenters.get(a);
|
|
2371
|
+
const bb = barycenters.get(b);
|
|
2372
|
+
if (ba !== void 0 && bb !== void 0 && ba !== bb) return ba - bb;
|
|
2373
|
+
if (ba !== void 0 && bb === void 0) return -1;
|
|
2374
|
+
if (ba === void 0 && bb !== void 0) return 1;
|
|
2375
|
+
return original.indexOf(a) - original.indexOf(b);
|
|
2376
|
+
});
|
|
2377
|
+
}
|
|
2378
|
+
/**
|
|
2379
|
+
* Count edge crossings between two adjacent layers.
|
|
2380
|
+
* Two edges (u1→v1) and (u2→v2) cross iff u1 < u2 and v1 > v2 (or vice versa).
|
|
2381
|
+
*/
|
|
2382
|
+
function countCrossings(upperLayer, lowerLayer, children) {
|
|
2383
|
+
const lowerIdx = /* @__PURE__ */ new Map();
|
|
2384
|
+
for (let i = 0; i < lowerLayer.length; i++) lowerIdx.set(lowerLayer[i], i);
|
|
2385
|
+
const edgePairs = [];
|
|
2386
|
+
for (let ui = 0; ui < upperLayer.length; ui++) for (const child of children.get(upperLayer[ui]) ?? []) {
|
|
2387
|
+
const li = lowerIdx.get(child);
|
|
2388
|
+
if (li !== void 0) edgePairs.push([ui, li]);
|
|
2389
|
+
}
|
|
2390
|
+
let crossings = 0;
|
|
2391
|
+
for (let i = 0; i < edgePairs.length; i++) for (let j = i + 1; j < edgePairs.length; j++) {
|
|
2392
|
+
const [u1, v1] = edgePairs[i];
|
|
2393
|
+
const [u2, v2] = edgePairs[j];
|
|
2394
|
+
if (u1 < u2 && v1 > v2 || u1 > u2 && v1 < v2) crossings++;
|
|
2395
|
+
}
|
|
2396
|
+
return crossings;
|
|
2397
|
+
}
|
|
2398
|
+
/** Pack a layer centered at x=0 with minimum spacing. */
|
|
2399
|
+
function packLayerCentered(layer, pos, dim, gap) {
|
|
2400
|
+
if (layer.length === 0) return;
|
|
2401
|
+
let totalWidth = dim(layer[0]);
|
|
2402
|
+
for (let i = 1; i < layer.length; i++) totalWidth += gap(layer[i - 1], layer[i]) + dim(layer[i]);
|
|
2403
|
+
let offset = -totalWidth / 2;
|
|
2404
|
+
for (let i = 0; i < layer.length; i++) {
|
|
2405
|
+
const id = layer[i];
|
|
2406
|
+
const d = dim(id);
|
|
2407
|
+
if (i > 0) offset += gap(layer[i - 1], id);
|
|
2408
|
+
pos.set(id, offset + d / 2);
|
|
2409
|
+
offset += d;
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
/**
|
|
2413
|
+
* Brandes-Köpf style single-direction alignment.
|
|
2414
|
+
* `isLeft`: when true, prefer the left (lower-index) median neighbor;
|
|
2415
|
+
* when false, prefer the right (higher-index) median neighbor.
|
|
2416
|
+
* This produces 4 distinct alignments that are then merged via median.
|
|
2417
|
+
*/
|
|
2418
|
+
function alignLayerBK(layer, neighborMap, pos, dim, gap, isLeft) {
|
|
2419
|
+
if (layer.length === 0) return;
|
|
2420
|
+
const ideal = /* @__PURE__ */ new Map();
|
|
2421
|
+
for (const id of layer) {
|
|
2422
|
+
const nbrs = neighborMap.get(id) ?? [];
|
|
2423
|
+
if (nbrs.length > 0) {
|
|
2424
|
+
const xs = nbrs.map((n) => pos.get(n)).sort((a, b) => a - b);
|
|
2425
|
+
const mid = Math.floor(xs.length / 2);
|
|
2426
|
+
if (xs.length % 2 === 1) ideal.set(id, xs[mid]);
|
|
2427
|
+
else ideal.set(id, isLeft ? xs[mid - 1] : xs[mid]);
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
if (ideal.size === 0) return;
|
|
2431
|
+
const indices = layer.map((_, i) => i);
|
|
2432
|
+
if (!isLeft) indices.reverse();
|
|
2433
|
+
for (const i of indices) {
|
|
2434
|
+
const id = layer[i];
|
|
2435
|
+
const target = ideal.get(id);
|
|
2436
|
+
if (target === void 0) continue;
|
|
2437
|
+
const halfDim = dim(id) / 2;
|
|
2438
|
+
let minPos = -Infinity;
|
|
2439
|
+
if (i > 0) {
|
|
2440
|
+
const leftId = layer[i - 1];
|
|
2441
|
+
minPos = pos.get(leftId) + dim(leftId) / 2 + gap(leftId, id) + halfDim;
|
|
2442
|
+
}
|
|
2443
|
+
let maxPos = Infinity;
|
|
2444
|
+
if (i < layer.length - 1) {
|
|
2445
|
+
const rightId = layer[i + 1];
|
|
2446
|
+
maxPos = pos.get(rightId) - dim(rightId) / 2 - gap(id, rightId) - halfDim;
|
|
2447
|
+
}
|
|
2448
|
+
pos.set(id, Math.max(minPos, Math.min(maxPos, target)));
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
1873
2451
|
/** Default curvature factor (matches xyflow) */
|
|
1874
2452
|
const DEFAULT_CURVATURE = .25;
|
|
1875
2453
|
/**
|
|
@@ -1931,6 +2509,25 @@ function buildEdgePath(source, target, sourceSize, targetSize, isVertical, opts)
|
|
|
1931
2509
|
labelMid: mid
|
|
1932
2510
|
};
|
|
1933
2511
|
}
|
|
2512
|
+
if (opts.edgeRouting === "orthogonal") if (isVertical) {
|
|
2513
|
+
const midY = (sy + ty) / 2;
|
|
2514
|
+
return {
|
|
2515
|
+
path: `M ${sx} ${sy} L ${sx} ${midY} L ${tx} ${midY} L ${tx} ${ty}`,
|
|
2516
|
+
labelMid: {
|
|
2517
|
+
x: (sx + tx) / 2,
|
|
2518
|
+
y: midY
|
|
2519
|
+
}
|
|
2520
|
+
};
|
|
2521
|
+
} else {
|
|
2522
|
+
const midX = (sx + tx) / 2;
|
|
2523
|
+
return {
|
|
2524
|
+
path: `M ${sx} ${sy} L ${midX} ${sy} L ${midX} ${ty} L ${tx} ${ty}`,
|
|
2525
|
+
labelMid: {
|
|
2526
|
+
x: midX,
|
|
2527
|
+
y: (sy + ty) / 2
|
|
2528
|
+
}
|
|
2529
|
+
};
|
|
2530
|
+
}
|
|
1934
2531
|
return {
|
|
1935
2532
|
path: `M ${sx} ${sy} L ${tx} ${ty}`,
|
|
1936
2533
|
labelMid: {
|
|
@@ -1939,21 +2536,146 @@ function buildEdgePath(source, target, sourceSize, targetSize, isVertical, opts)
|
|
|
1939
2536
|
}
|
|
1940
2537
|
};
|
|
1941
2538
|
}
|
|
1942
|
-
|
|
1943
|
-
|
|
2539
|
+
/**
|
|
2540
|
+
* Build a smooth path through dummy waypoints for edges spanning multiple layers.
|
|
2541
|
+
* Uses cubic Bezier spline fitting through the waypoints for bezier mode,
|
|
2542
|
+
* or polyline/orthogonal segments through the waypoints for other modes.
|
|
2543
|
+
*/
|
|
2544
|
+
function buildLongEdgePath(source, target, sourceSize, targetSize, waypoints, isVertical, opts) {
|
|
2545
|
+
let sx, sy, tx, ty;
|
|
2546
|
+
if (isVertical) {
|
|
2547
|
+
sx = source.x;
|
|
2548
|
+
sy = source.y + sourceSize.height / 2;
|
|
2549
|
+
tx = target.x;
|
|
2550
|
+
ty = target.y - targetSize.height / 2;
|
|
2551
|
+
if (source.y > target.y) {
|
|
2552
|
+
sy = source.y - sourceSize.height / 2;
|
|
2553
|
+
ty = target.y + targetSize.height / 2;
|
|
2554
|
+
}
|
|
2555
|
+
} else {
|
|
2556
|
+
sx = source.x + sourceSize.width / 2;
|
|
2557
|
+
sy = source.y;
|
|
2558
|
+
tx = target.x - targetSize.width / 2;
|
|
2559
|
+
ty = target.y;
|
|
2560
|
+
if (source.x > target.x) {
|
|
2561
|
+
sx = source.x - sourceSize.width / 2;
|
|
2562
|
+
tx = target.x + targetSize.width / 2;
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
const points = [
|
|
2566
|
+
{
|
|
2567
|
+
x: sx,
|
|
2568
|
+
y: sy
|
|
2569
|
+
},
|
|
2570
|
+
...waypoints,
|
|
2571
|
+
{
|
|
2572
|
+
x: tx,
|
|
2573
|
+
y: ty
|
|
2574
|
+
}
|
|
2575
|
+
];
|
|
2576
|
+
const labelMid = points[Math.floor(points.length / 2)];
|
|
2577
|
+
if (opts.edgeRouting === "bezier" && points.length >= 3) {
|
|
2578
|
+
let d = `M ${points[0].x} ${points[0].y}`;
|
|
2579
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
2580
|
+
const p0 = points[Math.max(0, i - 1)];
|
|
2581
|
+
const p1 = points[i];
|
|
2582
|
+
const p2 = points[i + 1];
|
|
2583
|
+
const p3 = points[Math.min(points.length - 1, i + 2)];
|
|
2584
|
+
const cp1x = p1.x + (p2.x - p0.x) / 6;
|
|
2585
|
+
const cp1y = p1.y + (p2.y - p0.y) / 6;
|
|
2586
|
+
const cp2x = p2.x - (p3.x - p1.x) / 6;
|
|
2587
|
+
const cp2y = p2.y - (p3.y - p1.y) / 6;
|
|
2588
|
+
d += ` C ${cp1x} ${cp1y} ${cp2x} ${cp2y} ${p2.x} ${p2.y}`;
|
|
2589
|
+
}
|
|
2590
|
+
return {
|
|
2591
|
+
path: d,
|
|
2592
|
+
labelMid
|
|
2593
|
+
};
|
|
2594
|
+
}
|
|
2595
|
+
if (opts.edgeRouting === "orthogonal") {
|
|
2596
|
+
let d = `M ${points[0].x} ${points[0].y}`;
|
|
2597
|
+
for (let i = 1; i < points.length; i++) {
|
|
2598
|
+
const prev = points[i - 1];
|
|
2599
|
+
const curr = points[i];
|
|
2600
|
+
if (isVertical) {
|
|
2601
|
+
const midY = (prev.y + curr.y) / 2;
|
|
2602
|
+
d += ` L ${prev.x} ${midY} L ${curr.x} ${midY} L ${curr.x} ${curr.y}`;
|
|
2603
|
+
} else {
|
|
2604
|
+
const midX = (prev.x + curr.x) / 2;
|
|
2605
|
+
d += ` L ${midX} ${prev.y} L ${midX} ${curr.y} L ${curr.x} ${curr.y}`;
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
return {
|
|
2609
|
+
path: d,
|
|
2610
|
+
labelMid
|
|
2611
|
+
};
|
|
2612
|
+
}
|
|
2613
|
+
let d = `M ${points[0].x} ${points[0].y}`;
|
|
2614
|
+
for (let i = 1; i < points.length; i++) d += ` L ${points[i].x} ${points[i].y}`;
|
|
1944
2615
|
return {
|
|
1945
|
-
|
|
1946
|
-
|
|
2616
|
+
path: d,
|
|
2617
|
+
labelMid
|
|
1947
2618
|
};
|
|
1948
2619
|
}
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
function
|
|
1953
|
-
|
|
2620
|
+
/** Compute the layer range (min, max) for each subgraph including nested children. */
|
|
2621
|
+
function computeSubgraphLayerRanges(subgraphs, layers) {
|
|
2622
|
+
const ranges = /* @__PURE__ */ new Map();
|
|
2623
|
+
function compute(sg) {
|
|
2624
|
+
let minL = Infinity;
|
|
2625
|
+
let maxL = -Infinity;
|
|
2626
|
+
for (const nodeId of sg.nodes) {
|
|
2627
|
+
const l = layers.get(nodeId);
|
|
2628
|
+
if (l !== void 0) {
|
|
2629
|
+
minL = Math.min(minL, l);
|
|
2630
|
+
maxL = Math.max(maxL, l);
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
for (const child of sg.subgraphs ?? []) {
|
|
2634
|
+
const childRange = compute(child);
|
|
2635
|
+
minL = Math.min(minL, childRange.minLayer);
|
|
2636
|
+
maxL = Math.max(maxL, childRange.maxLayer);
|
|
2637
|
+
}
|
|
2638
|
+
const range = {
|
|
2639
|
+
minLayer: minL,
|
|
2640
|
+
maxLayer: maxL
|
|
2641
|
+
};
|
|
2642
|
+
ranges.set(sg.id, range);
|
|
2643
|
+
return range;
|
|
2644
|
+
}
|
|
2645
|
+
for (const sg of subgraphs) compute(sg);
|
|
2646
|
+
return ranges;
|
|
2647
|
+
}
|
|
2648
|
+
/** Flatten a subgraph tree into a flat array of all subgraphs. */
|
|
2649
|
+
function flattenSubgraphs(subgraphs) {
|
|
2650
|
+
const result = [];
|
|
2651
|
+
function collect(sg) {
|
|
2652
|
+
result.push(sg);
|
|
2653
|
+
for (const child of sg.subgraphs ?? []) collect(child);
|
|
2654
|
+
}
|
|
2655
|
+
for (const sg of subgraphs) collect(sg);
|
|
2656
|
+
return result;
|
|
2657
|
+
}
|
|
2658
|
+
/** Pre-compute the minimum x/y bounds of a subgraph (including nested children). */
|
|
2659
|
+
function precomputeSgMin(sg, positions, nodeSizes, opts) {
|
|
2660
|
+
const titleHeight = 20;
|
|
2661
|
+
let minX = Infinity;
|
|
2662
|
+
let minY = Infinity;
|
|
2663
|
+
for (const nodeId of sg.nodes) {
|
|
2664
|
+
const p = positions.get(nodeId);
|
|
2665
|
+
const size = nodeSizes.get(nodeId);
|
|
2666
|
+
if (p && size) {
|
|
2667
|
+
minX = Math.min(minX, p.x - size.width / 2);
|
|
2668
|
+
minY = Math.min(minY, p.y - size.height / 2);
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
for (const child of sg.subgraphs ?? []) {
|
|
2672
|
+
const childMin = precomputeSgMin(child, positions, nodeSizes, opts);
|
|
2673
|
+
minX = Math.min(minX, childMin.minX);
|
|
2674
|
+
minY = Math.min(minY, childMin.minY);
|
|
2675
|
+
}
|
|
1954
2676
|
return {
|
|
1955
|
-
|
|
1956
|
-
|
|
2677
|
+
minX: minX - opts.nodePadding,
|
|
2678
|
+
minY: minY - opts.nodePadding - titleHeight
|
|
1957
2679
|
};
|
|
1958
2680
|
}
|
|
1959
2681
|
|
|
@@ -1985,20 +2707,72 @@ function sequenceLayout(diagram, options) {
|
|
|
1985
2707
|
blocks: [],
|
|
1986
2708
|
notes: []
|
|
1987
2709
|
};
|
|
2710
|
+
const participantIndex = /* @__PURE__ */ new Map();
|
|
2711
|
+
const participantSizes = /* @__PURE__ */ new Map();
|
|
2712
|
+
for (let i = 0; i < participants.length; i++) {
|
|
2713
|
+
const p = participants[i];
|
|
2714
|
+
participantIndex.set(p.id, i);
|
|
2715
|
+
participantSizes.set(p.id, measureNode(p.label, opts));
|
|
2716
|
+
}
|
|
2717
|
+
const pairSpacing = [];
|
|
2718
|
+
for (let i = 0; i < participants.length - 1; i++) {
|
|
2719
|
+
const left = participants[i];
|
|
2720
|
+
const right = participants[i + 1];
|
|
2721
|
+
const leftSize = participantSizes.get(left.id);
|
|
2722
|
+
const rightSize = participantSizes.get(right.id);
|
|
2723
|
+
let minDist = leftSize.width / 2 + rightSize.width / 2 + opts.nodePadding * 2;
|
|
2724
|
+
for (const msg of messages) {
|
|
2725
|
+
const fi = participantIndex.get(msg.from);
|
|
2726
|
+
const ti = participantIndex.get(msg.to);
|
|
2727
|
+
if (fi === void 0 || ti === void 0) continue;
|
|
2728
|
+
const lo = Math.min(fi, ti);
|
|
2729
|
+
const hi = Math.max(fi, ti);
|
|
2730
|
+
if (lo <= i && hi >= i + 1 && msg.text) {
|
|
2731
|
+
const labelSize = measureLabel(msg.text, opts);
|
|
2732
|
+
const spanCols = hi - lo;
|
|
2733
|
+
const perGap = (labelSize.width + opts.nodePadding * 2) / spanCols;
|
|
2734
|
+
minDist = Math.max(minDist, perGap);
|
|
2735
|
+
}
|
|
2736
|
+
}
|
|
2737
|
+
pairSpacing.push(Math.max(minDist, opts.nodeSpacing));
|
|
2738
|
+
}
|
|
1988
2739
|
const participantX = /* @__PURE__ */ new Map();
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2740
|
+
let currentX = opts.diagramPadding + (participantSizes.get(participants[0].id)?.width ?? opts.nodeWidth) / 2;
|
|
2741
|
+
participantX.set(participants[0].id, currentX);
|
|
2742
|
+
for (let i = 1; i < participants.length; i++) {
|
|
2743
|
+
currentX += pairSpacing[i - 1];
|
|
2744
|
+
participantX.set(participants[i].id, currentX);
|
|
2745
|
+
}
|
|
1992
2746
|
const headerY = opts.diagramPadding + opts.nodeHeight / 2;
|
|
1993
2747
|
const headerBottom = headerY + opts.nodeHeight / 2 + 20;
|
|
1994
|
-
const
|
|
1995
|
-
|
|
2748
|
+
const selfMessageWidth = 40;
|
|
2749
|
+
const selfMessageHeight = 30;
|
|
2750
|
+
const positionedMessages = [];
|
|
2751
|
+
const positionedNotes = [];
|
|
2752
|
+
let currentY = headerBottom;
|
|
2753
|
+
const noteMessageCounts = diagram._noteMessageCounts ?? notes.map(() => messages.length);
|
|
2754
|
+
let nextNoteIdx = 0;
|
|
2755
|
+
for (let msgIdx = 0; msgIdx < messages.length; msgIdx++) {
|
|
2756
|
+
while (nextNoteIdx < notes.length && (noteMessageCounts[nextNoteIdx] ?? messages.length) <= msgIdx) {
|
|
2757
|
+
currentY = positionNote(notes[nextNoteIdx], nextNoteIdx, currentY, positionedNotes, participantX, opts);
|
|
2758
|
+
nextNoteIdx++;
|
|
2759
|
+
}
|
|
2760
|
+
const msg = messages[msgIdx];
|
|
2761
|
+
const fromX = participantX.get(msg.from) ?? 0;
|
|
2762
|
+
const toX = participantX.get(msg.to) ?? 0;
|
|
2763
|
+
const isSelf = msg.from === msg.to;
|
|
2764
|
+
positionedMessages.push({
|
|
1996
2765
|
message: msg,
|
|
1997
|
-
fromX
|
|
1998
|
-
toX:
|
|
1999
|
-
y:
|
|
2000
|
-
};
|
|
2001
|
-
|
|
2766
|
+
fromX,
|
|
2767
|
+
toX: isSelf ? fromX + selfMessageWidth : toX,
|
|
2768
|
+
y: currentY
|
|
2769
|
+
});
|
|
2770
|
+
currentY += isSelf ? selfMessageHeight + opts.rankSpacing * .5 : opts.rankSpacing;
|
|
2771
|
+
}
|
|
2772
|
+
while (nextNoteIdx < notes.length) {
|
|
2773
|
+
currentY = positionNote(notes[nextNoteIdx], nextNoteIdx, currentY, positionedNotes, participantX, opts);
|
|
2774
|
+
nextNoteIdx++;
|
|
2775
|
+
}
|
|
2002
2776
|
const activationStarts = /* @__PURE__ */ new Map();
|
|
2003
2777
|
const positionedActivations = [];
|
|
2004
2778
|
for (const pmsg of positionedMessages) {
|
|
@@ -2021,7 +2795,10 @@ function sequenceLayout(diagram, options) {
|
|
|
2021
2795
|
}
|
|
2022
2796
|
}
|
|
2023
2797
|
const lastMsg = positionedMessages[positionedMessages.length - 1];
|
|
2024
|
-
const
|
|
2798
|
+
const lastNote = positionedNotes[positionedNotes.length - 1];
|
|
2799
|
+
const lastMessageY = lastMsg ? lastMsg.y : headerBottom;
|
|
2800
|
+
const lastNoteY = lastNote ? lastNote.y + lastNote.height : headerBottom;
|
|
2801
|
+
const diagramBottom = Math.max(lastMessageY, lastNoteY) + opts.rankSpacing;
|
|
2025
2802
|
const positionedLifelines = participants.map((p) => {
|
|
2026
2803
|
return {
|
|
2027
2804
|
participant: p,
|
|
@@ -2030,6 +2807,8 @@ function sequenceLayout(diagram, options) {
|
|
|
2030
2807
|
y2: diagramBottom
|
|
2031
2808
|
};
|
|
2032
2809
|
});
|
|
2810
|
+
const msgIndexMap = /* @__PURE__ */ new Map();
|
|
2811
|
+
for (let i = 0; i < messages.length; i++) msgIndexMap.set(messages[i], i);
|
|
2033
2812
|
const positionedBlocks = blocks.map((block) => {
|
|
2034
2813
|
const allMsgs = [...block.messages, ...block.sections?.flatMap((s) => s.messages) ?? []];
|
|
2035
2814
|
let minX = Infinity;
|
|
@@ -2040,48 +2819,48 @@ function sequenceLayout(diagram, options) {
|
|
|
2040
2819
|
minX = Math.min(minX, fromX, toX);
|
|
2041
2820
|
maxX = Math.max(maxX, fromX, toX);
|
|
2042
2821
|
}
|
|
2043
|
-
const msgIndices = allMsgs.map((m) =>
|
|
2822
|
+
const msgIndices = allMsgs.map((m) => msgIndexMap.get(m) ?? -1).filter((i) => i >= 0);
|
|
2044
2823
|
const firstBlockMsg = msgIndices.length > 0 ? positionedMessages[Math.min(...msgIndices)] : void 0;
|
|
2045
2824
|
const lastBlockMsg = msgIndices.length > 0 ? positionedMessages[Math.max(...msgIndices)] : void 0;
|
|
2046
2825
|
const startY = firstBlockMsg ? firstBlockMsg.y - 20 : headerBottom;
|
|
2047
2826
|
const endY = lastBlockMsg ? lastBlockMsg.y + 20 : headerBottom + opts.rankSpacing;
|
|
2827
|
+
let sectionDividers;
|
|
2828
|
+
if (block.sections && block.sections.length > 0) {
|
|
2829
|
+
sectionDividers = [];
|
|
2830
|
+
for (const section of block.sections) {
|
|
2831
|
+
const sectionMsgIndices = section.messages.map((m) => msgIndexMap.get(m) ?? -1).filter((i) => i >= 0);
|
|
2832
|
+
if (sectionMsgIndices.length > 0) {
|
|
2833
|
+
const firstSectionMsg = positionedMessages[Math.min(...sectionMsgIndices)];
|
|
2834
|
+
if (firstSectionMsg) sectionDividers.push({
|
|
2835
|
+
y: firstSectionMsg.y - 15,
|
|
2836
|
+
label: section.label
|
|
2837
|
+
});
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2048
2841
|
const padding = opts.nodePadding;
|
|
2049
2842
|
return {
|
|
2050
2843
|
block,
|
|
2051
2844
|
x: minX - padding - opts.nodeWidth / 2,
|
|
2052
2845
|
y: startY,
|
|
2053
2846
|
width: maxX - minX + opts.nodeWidth + padding * 2,
|
|
2054
|
-
height: endY - startY
|
|
2055
|
-
|
|
2056
|
-
});
|
|
2057
|
-
const positionedNotes = notes.map((note, i) => {
|
|
2058
|
-
const xs = note.participants.map((id) => participantX.get(id) ?? 0).filter((x) => x > 0);
|
|
2059
|
-
let x;
|
|
2060
|
-
if (note.position === "left of") x = (xs[0] ?? opts.diagramPadding) - opts.nodeWidth;
|
|
2061
|
-
else if (note.position === "right of") x = (xs[0] ?? opts.diagramPadding) + opts.nodeWidth;
|
|
2062
|
-
else x = xs.length > 0 ? xs.reduce((a, b) => a + b, 0) / xs.length : opts.diagramPadding;
|
|
2063
|
-
const y = headerBottom + (messages.length + i) * opts.rankSpacing * .5;
|
|
2064
|
-
const size = estimateTextSize(note.text, 12);
|
|
2065
|
-
return {
|
|
2066
|
-
note,
|
|
2067
|
-
x,
|
|
2068
|
-
y,
|
|
2069
|
-
width: Math.max(size.width + opts.nodePadding * 2, 80),
|
|
2070
|
-
height: Math.max(size.height + opts.nodePadding, 30)
|
|
2847
|
+
height: endY - startY,
|
|
2848
|
+
sectionDividers
|
|
2071
2849
|
};
|
|
2072
2850
|
});
|
|
2073
2851
|
const positionedParticipants = participants.map((p) => {
|
|
2074
|
-
const x = participantX.get(p.id) ?? 0;
|
|
2075
|
-
const size = estimateTextSize(p.label, 14);
|
|
2076
2852
|
return {
|
|
2077
2853
|
participant: p,
|
|
2078
|
-
x,
|
|
2854
|
+
x: participantX.get(p.id) ?? 0,
|
|
2079
2855
|
y: headerY,
|
|
2080
|
-
width:
|
|
2856
|
+
width: participantSizes.get(p.id).width,
|
|
2081
2857
|
height: opts.nodeHeight
|
|
2082
2858
|
};
|
|
2083
2859
|
});
|
|
2084
|
-
const
|
|
2860
|
+
const firstX = participantX.get(participants[0].id);
|
|
2861
|
+
const lastX = participantX.get(participants[participants.length - 1].id);
|
|
2862
|
+
const firstHalf = (participantSizes.get(participants[0].id)?.width ?? opts.nodeWidth) / 2;
|
|
2863
|
+
const diagramWidth = lastX + (participantSizes.get(participants[participants.length - 1].id)?.width ?? opts.nodeWidth) / 2 + opts.diagramPadding - (firstX - firstHalf - opts.diagramPadding);
|
|
2085
2864
|
const diagramHeight = diagramBottom + opts.diagramPadding;
|
|
2086
2865
|
return {
|
|
2087
2866
|
width: diagramWidth,
|
|
@@ -2095,12 +2874,23 @@ function sequenceLayout(diagram, options) {
|
|
|
2095
2874
|
notes: positionedNotes
|
|
2096
2875
|
};
|
|
2097
2876
|
}
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2877
|
+
/** Position a single note and advance currentY, returning the new currentY */
|
|
2878
|
+
function positionNote(note, _index, currentY, out, participantX, opts) {
|
|
2879
|
+
const xs = note.participants.map((id) => participantX.get(id) ?? 0).filter((x) => x > 0);
|
|
2880
|
+
let x;
|
|
2881
|
+
if (note.position === "left of") x = (xs[0] ?? opts.diagramPadding) - opts.nodeWidth;
|
|
2882
|
+
else if (note.position === "right of") x = (xs[0] ?? opts.diagramPadding) + opts.nodeWidth;
|
|
2883
|
+
else x = xs.length > 0 ? xs.reduce((a, b) => a + b, 0) / xs.length : opts.diagramPadding;
|
|
2884
|
+
const size = estimateTextSize(note.text, 12);
|
|
2885
|
+
const noteHeight = Math.max(size.height + opts.nodePadding, 30);
|
|
2886
|
+
out.push({
|
|
2887
|
+
note,
|
|
2888
|
+
x,
|
|
2889
|
+
y: currentY,
|
|
2890
|
+
width: Math.max(size.width + opts.nodePadding * 2, 80),
|
|
2891
|
+
height: noteHeight
|
|
2892
|
+
});
|
|
2893
|
+
return currentY + noteHeight + opts.rankSpacing * .3;
|
|
2104
2894
|
}
|
|
2105
2895
|
|
|
2106
2896
|
//#endregion
|
|
@@ -2169,21 +2959,16 @@ const c$11 = classes([
|
|
|
2169
2959
|
"blockBg",
|
|
2170
2960
|
"blockLabel",
|
|
2171
2961
|
"blockLabelText",
|
|
2962
|
+
"blockSectionLine",
|
|
2963
|
+
"blockSectionLabel",
|
|
2172
2964
|
"noteBg",
|
|
2173
2965
|
"noteText"
|
|
2174
2966
|
]);
|
|
2175
2967
|
const participantBox = rule`${c$11.participantBox} {
|
|
2176
|
-
|
|
2177
|
-
stroke: ${tokens$1.actorStroke};
|
|
2178
|
-
stroke-width: 2;
|
|
2968
|
+
${boxShape(tokens$1.actorFill, tokens$1.actorStroke, 2)}
|
|
2179
2969
|
}`;
|
|
2180
2970
|
const participantLabel = rule`${c$11.participantLabel} {
|
|
2181
|
-
|
|
2182
|
-
stroke: none;
|
|
2183
|
-
font-family: ${tokens$1.fontFamily};
|
|
2184
|
-
font-size: ${tokens$1.fontSize}px;
|
|
2185
|
-
text-anchor: middle;
|
|
2186
|
-
dominant-baseline: central;
|
|
2971
|
+
${textLabel(tokens$1.nodeText, `${tokens$1.fontSize}px`)}
|
|
2187
2972
|
}`;
|
|
2188
2973
|
const lifeline = rule`${c$11.lifeline} {
|
|
2189
2974
|
stroke: ${tokens$1.lifelineStroke};
|
|
@@ -2191,9 +2976,7 @@ const lifeline = rule`${c$11.lifeline} {
|
|
|
2191
2976
|
stroke-dasharray: 6, 4;
|
|
2192
2977
|
}`;
|
|
2193
2978
|
const activation = rule`${c$11.activation} {
|
|
2194
|
-
|
|
2195
|
-
stroke: ${tokens$1.actorStroke};
|
|
2196
|
-
stroke-width: 1;
|
|
2979
|
+
${boxShape(tokens$1.activationFill, tokens$1.actorStroke, 1)}
|
|
2197
2980
|
}`;
|
|
2198
2981
|
const messageLine = rule`${c$11.messageLine} {
|
|
2199
2982
|
stroke: ${tokens$1.messageStroke};
|
|
@@ -2204,39 +2987,33 @@ const messageDotted = rule`${c$11.messageDotted} {
|
|
|
2204
2987
|
stroke-dasharray: 6, 4;
|
|
2205
2988
|
}`;
|
|
2206
2989
|
const messageText = rule`${c$11.messageText} {
|
|
2207
|
-
|
|
2208
|
-
stroke: none;
|
|
2209
|
-
font-family: ${tokens$1.fontFamily};
|
|
2210
|
-
font-size: 12px;
|
|
2211
|
-
text-anchor: middle;
|
|
2990
|
+
${textLabel(tokens$1.nodeText, "12px")}
|
|
2212
2991
|
}`;
|
|
2213
2992
|
const blockBg = rule`${c$11.blockBg} {
|
|
2214
|
-
|
|
2215
|
-
stroke: ${tokens$1.blockStroke};
|
|
2216
|
-
stroke-width: 1;
|
|
2993
|
+
${boxShape(tokens$1.blockFill, tokens$1.blockStroke, 1)}
|
|
2217
2994
|
}`;
|
|
2218
2995
|
const blockLabel = rule`${c$11.blockLabel} {
|
|
2219
2996
|
fill: ${tokens$1.blockStroke};
|
|
2220
2997
|
}`;
|
|
2221
2998
|
const blockLabelText = rule`${c$11.blockLabelText} {
|
|
2222
|
-
|
|
2223
|
-
stroke: none;
|
|
2224
|
-
font-family: ${tokens$1.fontFamily};
|
|
2225
|
-
font-size: 11px;
|
|
2999
|
+
${textLabel(tokens$1.nodeText, "11px")}
|
|
2226
3000
|
font-weight: 600;
|
|
2227
3001
|
}`;
|
|
2228
|
-
const
|
|
2229
|
-
|
|
2230
|
-
stroke: ${tokens$1.noteStroke};
|
|
3002
|
+
const blockSectionLine = rule`${c$11.blockSectionLine} {
|
|
3003
|
+
stroke: ${tokens$1.blockStroke};
|
|
2231
3004
|
stroke-width: 1;
|
|
3005
|
+
stroke-dasharray: 6, 4;
|
|
3006
|
+
}`;
|
|
3007
|
+
const blockSectionLabel = rule`${c$11.blockSectionLabel} {
|
|
3008
|
+
${textLabel(tokens$1.nodeText, "11px")}
|
|
3009
|
+
font-weight: 600;
|
|
3010
|
+
font-style: italic;
|
|
3011
|
+
}`;
|
|
3012
|
+
const noteBg = rule`${c$11.noteBg} {
|
|
3013
|
+
${boxShape(tokens$1.noteBg, tokens$1.noteStroke, 1)}
|
|
2232
3014
|
}`;
|
|
2233
3015
|
const noteText = rule`${c$11.noteText} {
|
|
2234
|
-
|
|
2235
|
-
stroke: none;
|
|
2236
|
-
font-family: ${tokens$1.fontFamily};
|
|
2237
|
-
font-size: 12px;
|
|
2238
|
-
text-anchor: middle;
|
|
2239
|
-
dominant-baseline: central;
|
|
3016
|
+
${textLabel(tokens$1.noteText, "12px")}
|
|
2240
3017
|
}`;
|
|
2241
3018
|
|
|
2242
3019
|
//#endregion
|
|
@@ -2262,19 +3039,36 @@ function Participant(props) {
|
|
|
2262
3039
|
|
|
2263
3040
|
//#endregion
|
|
2264
3041
|
//#region ../mermaid/src/components/sequence/message.tsx
|
|
2265
|
-
const MARKER = {
|
|
2266
|
-
solid: "url(#mmd-arrow)",
|
|
2267
|
-
dotted: "url(#mmd-arrow)",
|
|
2268
|
-
solidCross: "url(#mmd-cross)",
|
|
2269
|
-
dottedCross: "url(#mmd-cross)",
|
|
2270
|
-
solidOpen: "url(#mmd-arrow-open)",
|
|
2271
|
-
dottedOpen: "url(#mmd-arrow-open)"
|
|
2272
|
-
};
|
|
2273
3042
|
function Message(props) {
|
|
2274
3043
|
const { message, fromX, toX, y } = props;
|
|
2275
|
-
const isDotted = message.arrow
|
|
3044
|
+
const isDotted = isDottedArrow(message.arrow);
|
|
3045
|
+
const markerEnd = sequenceMarker(message.arrow);
|
|
3046
|
+
if (message.from === message.to) {
|
|
3047
|
+
const loopWidth = toX - fromX;
|
|
3048
|
+
const loopHeight = 30;
|
|
3049
|
+
const path = [
|
|
3050
|
+
`M ${fromX} ${y}`,
|
|
3051
|
+
`L ${fromX + loopWidth} ${y}`,
|
|
3052
|
+
`L ${fromX + loopWidth} ${y + loopHeight}`,
|
|
3053
|
+
`L ${fromX} ${y + loopHeight}`
|
|
3054
|
+
].join(" ");
|
|
3055
|
+
return /* @__PURE__ */ jsxs("g", {
|
|
3056
|
+
class: props.class,
|
|
3057
|
+
children: [/* @__PURE__ */ jsx("path", {
|
|
3058
|
+
class: [messageLine, isDotted ? messageDotted : void 0],
|
|
3059
|
+
d: path,
|
|
3060
|
+
fill: "none",
|
|
3061
|
+
"marker-end": markerEnd
|
|
3062
|
+
}), /* @__PURE__ */ jsx("text", {
|
|
3063
|
+
class: messageText,
|
|
3064
|
+
x: fromX + loopWidth / 2 + loopWidth / 2 + 6,
|
|
3065
|
+
y: y + loopHeight / 2,
|
|
3066
|
+
"text-anchor": "start",
|
|
3067
|
+
children: message.text
|
|
3068
|
+
})]
|
|
3069
|
+
});
|
|
3070
|
+
}
|
|
2276
3071
|
const midX = (fromX + toX) / 2;
|
|
2277
|
-
const markerEnd = MARKER[message.arrow];
|
|
2278
3072
|
return /* @__PURE__ */ jsxs("g", {
|
|
2279
3073
|
class: props.class,
|
|
2280
3074
|
children: [/* @__PURE__ */ jsx("line", {
|
|
@@ -2320,7 +3114,10 @@ function Activation(props) {
|
|
|
2320
3114
|
//#endregion
|
|
2321
3115
|
//#region ../mermaid/src/components/sequence/block.tsx
|
|
2322
3116
|
function Block(props) {
|
|
2323
|
-
const { block, x, y, width, height } = props;
|
|
3117
|
+
const { block, x, y, width, height, sectionDividers } = props;
|
|
3118
|
+
const typeText = block.type;
|
|
3119
|
+
const labelText = block.label ? `${typeText} [${block.label}]` : typeText;
|
|
3120
|
+
const labelWidth = Math.max(labelText.length * 7 + 10, 50);
|
|
2324
3121
|
return /* @__PURE__ */ jsxs("g", {
|
|
2325
3122
|
class: props.class,
|
|
2326
3123
|
children: [
|
|
@@ -2336,16 +3133,33 @@ function Block(props) {
|
|
|
2336
3133
|
class: blockLabel,
|
|
2337
3134
|
x,
|
|
2338
3135
|
y,
|
|
2339
|
-
width:
|
|
3136
|
+
width: labelWidth,
|
|
2340
3137
|
height: 20,
|
|
2341
3138
|
rx: 4
|
|
2342
3139
|
}),
|
|
2343
3140
|
/* @__PURE__ */ jsx("text", {
|
|
2344
3141
|
class: blockLabelText,
|
|
2345
|
-
x: x +
|
|
2346
|
-
y: y +
|
|
2347
|
-
children:
|
|
2348
|
-
})
|
|
3142
|
+
x: x + labelWidth / 2,
|
|
3143
|
+
y: y + 10,
|
|
3144
|
+
children: labelText
|
|
3145
|
+
}),
|
|
3146
|
+
sectionDividers?.map((div) => /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("line", {
|
|
3147
|
+
class: blockSectionLine,
|
|
3148
|
+
x1: x,
|
|
3149
|
+
y1: div.y,
|
|
3150
|
+
x2: x + width,
|
|
3151
|
+
y2: div.y
|
|
3152
|
+
}), div.label && /* @__PURE__ */ jsxs("text", {
|
|
3153
|
+
class: blockSectionLabel,
|
|
3154
|
+
x: x + 8,
|
|
3155
|
+
y: div.y + 14,
|
|
3156
|
+
"text-anchor": "start",
|
|
3157
|
+
children: [
|
|
3158
|
+
"[",
|
|
3159
|
+
div.label,
|
|
3160
|
+
"]"
|
|
3161
|
+
]
|
|
3162
|
+
})] }))
|
|
2349
3163
|
]
|
|
2350
3164
|
});
|
|
2351
3165
|
}
|
|
@@ -2451,7 +3265,8 @@ function Sequence(props, ctx) {
|
|
|
2451
3265
|
x: b.x,
|
|
2452
3266
|
y: b.y,
|
|
2453
3267
|
width: b.width,
|
|
2454
|
-
height: b.height
|
|
3268
|
+
height: b.height,
|
|
3269
|
+
sectionDividers: b.sectionDividers
|
|
2455
3270
|
})),
|
|
2456
3271
|
positioned.activations.map((a) => /* @__PURE__ */ jsx(ActivationComp, {
|
|
2457
3272
|
participant: a.participant,
|
|
@@ -2509,18 +3324,20 @@ function walk(node) {
|
|
|
2509
3324
|
if (!node.children) return;
|
|
2510
3325
|
for (let i = 0; i < node.children.length; i++) {
|
|
2511
3326
|
const child = node.children[i];
|
|
2512
|
-
if (child.type === "code" && child.lang === "mermaid")
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
3327
|
+
if (child.type === "code" && child.lang === "mermaid") {
|
|
3328
|
+
if (child.meta && /\braw\b/.test(child.meta)) continue;
|
|
3329
|
+
node.children[i] = {
|
|
3330
|
+
type: "mdxJsxFlowElement",
|
|
3331
|
+
name: "Mermaid",
|
|
3332
|
+
attributes: [{
|
|
3333
|
+
type: "mdxJsxAttribute",
|
|
3334
|
+
name: "code",
|
|
3335
|
+
value: child.value ?? ""
|
|
3336
|
+
}],
|
|
3337
|
+
children: [],
|
|
3338
|
+
data: { _mdxExplicitJsx: true }
|
|
3339
|
+
};
|
|
3340
|
+
} else walk(child);
|
|
2524
3341
|
}
|
|
2525
3342
|
}
|
|
2526
3343
|
function remarkMermaid() {
|