@statelyai/graph 0.4.0 → 0.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/dist/{algorithms-CnTmuX9t.mjs → algorithms-DldwenLt.mjs} +1 -1
- package/dist/algorithms.d.mts +1 -1
- package/dist/algorithms.mjs +1 -1
- package/dist/{converter-C5DlzzHs.mjs → converter-B5CUD0r9.mjs} +2 -2
- package/dist/formats/adjacency-list/index.d.mts +1 -1
- package/dist/formats/adjacency-list/index.mjs +1 -1
- package/dist/formats/converter/index.d.mts +2 -2
- package/dist/formats/converter/index.mjs +1 -1
- package/dist/formats/cytoscape/index.d.mts +1 -1
- package/dist/formats/cytoscape/index.mjs +1 -1
- package/dist/formats/d3/index.d.mts +1 -1
- package/dist/formats/d3/index.mjs +1 -1
- package/dist/formats/dot/index.d.mts +1 -1
- package/dist/formats/dot/index.mjs +1 -1
- package/dist/formats/edge-list/index.d.mts +1 -1
- package/dist/formats/edge-list/index.mjs +1 -1
- package/dist/formats/elk/index.d.mts +61 -0
- package/dist/formats/elk/index.mjs +176 -0
- package/dist/formats/gexf/index.d.mts +1 -1
- package/dist/formats/gexf/index.mjs +1 -1
- package/dist/formats/gml/index.d.mts +1 -1
- package/dist/formats/gml/index.mjs +1 -1
- package/dist/formats/graphml/index.d.mts +1 -1
- package/dist/formats/graphml/index.mjs +1 -1
- package/dist/formats/jgf/index.d.mts +1 -1
- package/dist/formats/jgf/index.mjs +1 -1
- package/dist/formats/mermaid/index.d.mts +46 -33
- package/dist/formats/mermaid/index.mjs +315 -31
- package/dist/formats/tgf/index.d.mts +1 -1
- package/dist/formats/tgf/index.mjs +1 -1
- package/dist/formats/xyflow/index.d.mts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +3 -3
- package/dist/queries.d.mts +1 -1
- package/dist/queries.mjs +1 -1
- package/dist/schemas.d.mts +37 -4
- package/dist/schemas.mjs +26 -5
- package/dist/{types-Bq_fmLwW.d.mts → types-FBZCrmnG.d.mts} +6 -6
- package/package.json +7 -1
- package/schemas/edge.schema.json +32 -1
- package/schemas/graph.schema.json +114 -4
- package/schemas/node.schema.json +45 -2
- /package/dist/{adjacency-list-Bv4tfiM3.mjs → adjacency-list-fldj-QAL.mjs} +0 -0
- /package/dist/{edge-list-R1SUbHwe.mjs → edge-list-Br05wXMg.mjs} +0 -0
- /package/dist/{indexing-DitHphT7.mjs → indexing-DyfgLuzw.mjs} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as createFormatConverter } from "../../converter-
|
|
1
|
+
import { n as createFormatConverter } from "../../converter-B5CUD0r9.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/formats/mermaid/shared.ts
|
|
4
4
|
const MERMAID_TO_DIRECTION = {
|
|
@@ -146,6 +146,7 @@ function fromMermaidSequence(input) {
|
|
|
146
146
|
let autonumber = false;
|
|
147
147
|
let edgeCounter = 0;
|
|
148
148
|
let seqNum = 0;
|
|
149
|
+
let currentBox = null;
|
|
149
150
|
const blockStack = [];
|
|
150
151
|
function ensureNode(id, actorType = "participant") {
|
|
151
152
|
if (!nodeMap.has(id)) nodeMap.set(id, {
|
|
@@ -173,7 +174,7 @@ function fromMermaidSequence(input) {
|
|
|
173
174
|
autonumber = true;
|
|
174
175
|
continue;
|
|
175
176
|
}
|
|
176
|
-
const participantMatch = line.match(/^(participant|actor)\s+(\S+?)(?:\s+as\s+(.+))?$/);
|
|
177
|
+
const participantMatch = line.match(/^(participant|actor|boundary|control|entity|database|collections|queue)\s+(\S+?)(?:\s+as\s+(.+))?$/);
|
|
177
178
|
if (participantMatch) {
|
|
178
179
|
const actorType = participantMatch[1];
|
|
179
180
|
const id = participantMatch[2];
|
|
@@ -185,9 +186,10 @@ function fromMermaidSequence(input) {
|
|
|
185
186
|
node.data.alias = alias;
|
|
186
187
|
node.label = alias;
|
|
187
188
|
}
|
|
189
|
+
if (currentBox) node.data.box = { ...currentBox };
|
|
188
190
|
continue;
|
|
189
191
|
}
|
|
190
|
-
const createMatch = line.match(/^create\s+(participant|actor)\s+(\S+?)(?:\s+as\s+(.+))?$/);
|
|
192
|
+
const createMatch = line.match(/^create\s+(participant|actor|boundary|control|entity|database|collections|queue)\s+(\S+?)(?:\s+as\s+(.+))?$/);
|
|
191
193
|
if (createMatch) {
|
|
192
194
|
const actorType = createMatch[1];
|
|
193
195
|
const id = createMatch[2];
|
|
@@ -226,6 +228,22 @@ function fromMermaidSequence(input) {
|
|
|
226
228
|
});
|
|
227
229
|
continue;
|
|
228
230
|
}
|
|
231
|
+
const boxMatch = line.match(/^box\s*(.*)?$/);
|
|
232
|
+
if (boxMatch) {
|
|
233
|
+
const rest = (boxMatch[1] ?? "").trim();
|
|
234
|
+
let color;
|
|
235
|
+
let title;
|
|
236
|
+
const colorTitleMatch = rest.match(/^(rgb\([^)]*\)|#[a-fA-F0-9]+|[a-zA-Z]+)?\s*(.*)$/);
|
|
237
|
+
if (colorTitleMatch) {
|
|
238
|
+
color = colorTitleMatch[1]?.trim() || void 0;
|
|
239
|
+
title = colorTitleMatch[2]?.trim() || void 0;
|
|
240
|
+
}
|
|
241
|
+
currentBox = {
|
|
242
|
+
...color && { color },
|
|
243
|
+
...title && { title }
|
|
244
|
+
};
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
229
247
|
if (/^(loop|alt|opt|par|critical|break)\s+/.test(line) || line.startsWith("rect ")) {
|
|
230
248
|
const spaceIdx = line.indexOf(" ");
|
|
231
249
|
const keyword = line.slice(0, spaceIdx);
|
|
@@ -290,6 +308,10 @@ function fromMermaidSequence(input) {
|
|
|
290
308
|
continue;
|
|
291
309
|
}
|
|
292
310
|
if (line === "end") {
|
|
311
|
+
if (currentBox && blockStack.length === 0) {
|
|
312
|
+
currentBox = null;
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
293
315
|
if (blockStack.length > 0) {
|
|
294
316
|
const finished = blockStack.pop();
|
|
295
317
|
const block = buildBlock(finished);
|
|
@@ -300,6 +322,25 @@ function fromMermaidSequence(input) {
|
|
|
300
322
|
}
|
|
301
323
|
continue;
|
|
302
324
|
}
|
|
325
|
+
const noteMatch = line.match(/^Note\s+(left of|right of|over)\s+([^:]+):\s*(.*)$/i);
|
|
326
|
+
if (noteMatch) {
|
|
327
|
+
const posRaw = noteMatch[1].toLowerCase();
|
|
328
|
+
const position = posRaw === "left of" ? "left" : posRaw === "right of" ? "right" : "over";
|
|
329
|
+
const actorsPart = noteMatch[2].trim();
|
|
330
|
+
const text = noteMatch[3].trim();
|
|
331
|
+
const actorIds = actorsPart.split(",").map((s) => s.trim());
|
|
332
|
+
for (const actorId of actorIds) {
|
|
333
|
+
ensureNode(actorId);
|
|
334
|
+
const node = nodeMap.get(actorId);
|
|
335
|
+
if (!node.data.notes) node.data.notes = [];
|
|
336
|
+
node.data.notes.push({
|
|
337
|
+
position,
|
|
338
|
+
text,
|
|
339
|
+
...position === "over" && actorIds.length > 1 ? { over: actorIds } : {}
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
303
344
|
if (/^Note\s+(left|right|over)\s+/i.test(line)) continue;
|
|
304
345
|
const msgMatch = line.match(MESSAGE_RE);
|
|
305
346
|
if (msgMatch) {
|
|
@@ -443,12 +484,38 @@ function toMermaidSequence(graph) {
|
|
|
443
484
|
const lines = ["sequenceDiagram"];
|
|
444
485
|
const gd = graph.data;
|
|
445
486
|
if (gd?.autonumber) lines.push(" autonumber");
|
|
487
|
+
const boxGroups = /* @__PURE__ */ new Map();
|
|
488
|
+
const noBoxNodes = [];
|
|
446
489
|
for (const node of graph.nodes) {
|
|
490
|
+
const box = node.data?.box;
|
|
491
|
+
if (box) {
|
|
492
|
+
const key = JSON.stringify(box);
|
|
493
|
+
if (!boxGroups.has(key)) boxGroups.set(key, {
|
|
494
|
+
box,
|
|
495
|
+
nodes: []
|
|
496
|
+
});
|
|
497
|
+
boxGroups.get(key).nodes.push(node);
|
|
498
|
+
} else noBoxNodes.push(node);
|
|
499
|
+
}
|
|
500
|
+
function emitParticipant(node, indent$1) {
|
|
447
501
|
const d = node.data;
|
|
448
|
-
const keyword = d?.actorType
|
|
502
|
+
const keyword = d?.actorType ?? "participant";
|
|
449
503
|
const alias = d?.alias ? ` as ${escapeMermaidLabel(d.alias)}` : "";
|
|
450
|
-
if (d?.created) lines.push(
|
|
451
|
-
else lines.push(
|
|
504
|
+
if (d?.created) lines.push(`${indent$1}create ${keyword} ${node.id}${alias}`);
|
|
505
|
+
else lines.push(`${indent$1}${keyword} ${node.id}${alias}`);
|
|
506
|
+
}
|
|
507
|
+
for (const { box, nodes: boxNodes } of boxGroups.values()) {
|
|
508
|
+
const colorStr = box.color ? ` ${box.color}` : "";
|
|
509
|
+
const titleStr = box.title ? ` ${box.title}` : "";
|
|
510
|
+
lines.push(` box${colorStr}${titleStr}`);
|
|
511
|
+
for (const node of boxNodes) emitParticipant(node, " ");
|
|
512
|
+
lines.push(" end");
|
|
513
|
+
}
|
|
514
|
+
for (const node of noBoxNodes) emitParticipant(node, " ");
|
|
515
|
+
for (const node of graph.nodes) if (node.data?.notes) for (const note of node.data.notes) if (note.position === "over" && note.over && note.over.length > 1) lines.push(` Note over ${note.over.join(",")}: ${escapeMermaidLabel(note.text)}`);
|
|
516
|
+
else {
|
|
517
|
+
const posStr = note.position === "left" ? "left of" : note.position === "right" ? "right of" : "over";
|
|
518
|
+
lines.push(` Note ${posStr} ${node.id}: ${escapeMermaidLabel(note.text)}`);
|
|
452
519
|
}
|
|
453
520
|
const blocks = gd?.blocks ?? [];
|
|
454
521
|
const edgeIdSet = new Set(graph.edges.map((e) => e.id));
|
|
@@ -705,6 +772,32 @@ const SHAPE_OPENERS = [
|
|
|
705
772
|
const SHAPE_TO_BRACKETS$1 = {};
|
|
706
773
|
for (const [opener, closer, name] of SHAPE_OPENERS) SHAPE_TO_BRACKETS$1[name] = [opener, closer];
|
|
707
774
|
function parseNodeDecl(text) {
|
|
775
|
+
let className;
|
|
776
|
+
const classIdx = text.indexOf(":::");
|
|
777
|
+
if (classIdx >= 0) {
|
|
778
|
+
className = text.slice(classIdx + 3).trim();
|
|
779
|
+
text = text.slice(0, classIdx);
|
|
780
|
+
}
|
|
781
|
+
const atMatch = text.match(/^([a-zA-Z_][\w]*)@\{(.+)\}$/s);
|
|
782
|
+
if (atMatch) {
|
|
783
|
+
const id = atMatch[1];
|
|
784
|
+
const body = atMatch[2].trim();
|
|
785
|
+
let shape = "rectangle";
|
|
786
|
+
let label = "";
|
|
787
|
+
for (const line of body.split(",")) {
|
|
788
|
+
const kv = line.match(/^\s*(\w+)\s*:\s*"?([^"]*)"?\s*$/);
|
|
789
|
+
if (kv) {
|
|
790
|
+
if (kv[1] === "shape") shape = kv[2].trim();
|
|
791
|
+
else if (kv[1] === "label") label = kv[2].trim();
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
return {
|
|
795
|
+
id,
|
|
796
|
+
label,
|
|
797
|
+
shape,
|
|
798
|
+
...className && { className }
|
|
799
|
+
};
|
|
800
|
+
}
|
|
708
801
|
for (const [opener, closer, shapeName] of SHAPE_OPENERS) {
|
|
709
802
|
const opIdx = text.indexOf(opener);
|
|
710
803
|
if (opIdx < 0) continue;
|
|
@@ -714,13 +807,15 @@ function parseNodeDecl(text) {
|
|
|
714
807
|
return {
|
|
715
808
|
id,
|
|
716
809
|
label: text.slice(opIdx + opener.length, text.length - closer.length).trim(),
|
|
717
|
-
shape: shapeName
|
|
810
|
+
shape: shapeName,
|
|
811
|
+
...className && { className }
|
|
718
812
|
};
|
|
719
813
|
}
|
|
720
814
|
if (/^[a-zA-Z_][\w]*$/.test(text)) return {
|
|
721
815
|
id: text,
|
|
722
816
|
label: "",
|
|
723
|
-
shape: "rectangle"
|
|
817
|
+
shape: "rectangle",
|
|
818
|
+
...className && { className }
|
|
724
819
|
};
|
|
725
820
|
return null;
|
|
726
821
|
}
|
|
@@ -836,6 +931,12 @@ const EDGE_ARROWS = [
|
|
|
836
931
|
arrowType: "none",
|
|
837
932
|
endMarker: "arrow",
|
|
838
933
|
bidirectional: false
|
|
934
|
+
}],
|
|
935
|
+
[/^~~~$/, {
|
|
936
|
+
stroke: "invisible",
|
|
937
|
+
arrowType: "none",
|
|
938
|
+
endMarker: "arrow",
|
|
939
|
+
bidirectional: false
|
|
839
940
|
}]
|
|
840
941
|
];
|
|
841
942
|
function findEdge(line) {
|
|
@@ -903,7 +1004,7 @@ function fromMermaidFlowchart(input) {
|
|
|
903
1004
|
const classAssignments = {};
|
|
904
1005
|
let edgeCounter = 0;
|
|
905
1006
|
const parentStack = [null];
|
|
906
|
-
function ensureNode(id, label, shape) {
|
|
1007
|
+
function ensureNode(id, label, shape, className) {
|
|
907
1008
|
if (!nodeMap.has(id)) nodeMap.set(id, {
|
|
908
1009
|
type: "node",
|
|
909
1010
|
id,
|
|
@@ -916,6 +1017,10 @@ function fromMermaidFlowchart(input) {
|
|
|
916
1017
|
const node = nodeMap.get(id);
|
|
917
1018
|
if (label && !node.label) node.label = label;
|
|
918
1019
|
if (shape && shape !== "rectangle" && !node.shape) node.shape = shape;
|
|
1020
|
+
if (className) {
|
|
1021
|
+
if (!classAssignments[id]) classAssignments[id] = [];
|
|
1022
|
+
if (!classAssignments[id].includes(className)) classAssignments[id].push(className);
|
|
1023
|
+
}
|
|
919
1024
|
return node;
|
|
920
1025
|
}
|
|
921
1026
|
for (let i = 1; i < lines.length; i++) {
|
|
@@ -928,7 +1033,15 @@ function fromMermaidFlowchart(input) {
|
|
|
928
1033
|
parentStack.push(subId);
|
|
929
1034
|
continue;
|
|
930
1035
|
}
|
|
931
|
-
|
|
1036
|
+
const dirMatch = line.match(/^direction\s+(TD|TB|BT|LR|RL)\s*$/);
|
|
1037
|
+
if (dirMatch) {
|
|
1038
|
+
const parentId = parentStack[parentStack.length - 1];
|
|
1039
|
+
if (parentId) {
|
|
1040
|
+
const parentNode = nodeMap.get(parentId);
|
|
1041
|
+
if (parentNode) parentNode.data.direction = MERMAID_TO_DIRECTION[dirMatch[1]];
|
|
1042
|
+
}
|
|
1043
|
+
continue;
|
|
1044
|
+
}
|
|
932
1045
|
if (line === "end") {
|
|
933
1046
|
if (parentStack.length > 1) parentStack.pop();
|
|
934
1047
|
continue;
|
|
@@ -992,11 +1105,11 @@ function fromMermaidFlowchart(input) {
|
|
|
992
1105
|
if (!edgeResult) break;
|
|
993
1106
|
foundEdge = true;
|
|
994
1107
|
const sourceDecl = parseNodeDecl(edgeResult.sourceText);
|
|
995
|
-
if (sourceDecl) ensureNode(sourceDecl.id, sourceDecl.label, sourceDecl.shape);
|
|
1108
|
+
if (sourceDecl) ensureNode(sourceDecl.id, sourceDecl.label, sourceDecl.shape, sourceDecl.className);
|
|
996
1109
|
const targetDecl = parseNodeDecl(edgeResult.targetText);
|
|
997
1110
|
let targetId;
|
|
998
1111
|
if (targetDecl) {
|
|
999
|
-
ensureNode(targetDecl.id, targetDecl.label, targetDecl.shape);
|
|
1112
|
+
ensureNode(targetDecl.id, targetDecl.label, targetDecl.shape, targetDecl.className);
|
|
1000
1113
|
targetId = targetDecl.id;
|
|
1001
1114
|
remaining = "";
|
|
1002
1115
|
} else {
|
|
@@ -1004,7 +1117,7 @@ function fromMermaidFlowchart(input) {
|
|
|
1004
1117
|
if (nextEdge) {
|
|
1005
1118
|
const tDecl = parseNodeDecl(nextEdge.sourceText);
|
|
1006
1119
|
if (tDecl) {
|
|
1007
|
-
ensureNode(tDecl.id, tDecl.label, tDecl.shape);
|
|
1120
|
+
ensureNode(tDecl.id, tDecl.label, tDecl.shape, tDecl.className);
|
|
1008
1121
|
targetId = tDecl.id;
|
|
1009
1122
|
} else {
|
|
1010
1123
|
targetId = nextEdge.sourceText;
|
|
@@ -1039,7 +1152,7 @@ function fromMermaidFlowchart(input) {
|
|
|
1039
1152
|
if (foundEdge) continue;
|
|
1040
1153
|
const nodeDecl = parseNodeDecl(line);
|
|
1041
1154
|
if (nodeDecl) {
|
|
1042
|
-
ensureNode(nodeDecl.id, nodeDecl.label, nodeDecl.shape);
|
|
1155
|
+
ensureNode(nodeDecl.id, nodeDecl.label, nodeDecl.shape, nodeDecl.className);
|
|
1043
1156
|
continue;
|
|
1044
1157
|
}
|
|
1045
1158
|
if (line.includes(";")) {
|
|
@@ -1108,6 +1221,10 @@ function toMermaidFlowchart(graph) {
|
|
|
1108
1221
|
for (const node of children) if (isParent.has(node.id)) {
|
|
1109
1222
|
const label = node.label ? `[${escapeMermaidLabel(node.label)}]` : "";
|
|
1110
1223
|
lines.push(`${indent}subgraph ${node.id}${label}`);
|
|
1224
|
+
if (node.data?.direction) {
|
|
1225
|
+
const subDir = DIRECTION_TO_MERMAID[node.data.direction] ?? "TD";
|
|
1226
|
+
lines.push(`${indent} direction ${subDir}`);
|
|
1227
|
+
}
|
|
1111
1228
|
writeNodes(node.id, indent + " ");
|
|
1112
1229
|
lines.push(`${indent}end`);
|
|
1113
1230
|
} else {
|
|
@@ -1120,12 +1237,18 @@ function toMermaidFlowchart(graph) {
|
|
|
1120
1237
|
for (const edge of graph.edges) {
|
|
1121
1238
|
const d = edge.data;
|
|
1122
1239
|
let arrow;
|
|
1123
|
-
if (d?.
|
|
1240
|
+
if (d?.stroke === "invisible") arrow = "~~~";
|
|
1241
|
+
else if (d?.bidirectional) arrow = d.stroke === "thick" ? "<==>" : d.stroke === "dotted" ? "<-.->" : "<-->";
|
|
1124
1242
|
else if (d?.stroke === "thick") arrow = d.arrowType === "none" ? "===" : "==>";
|
|
1125
1243
|
else if (d?.stroke === "dotted") arrow = d.arrowType === "none" ? "-.-" : "-.->";
|
|
1126
|
-
else
|
|
1127
|
-
|
|
1128
|
-
|
|
1244
|
+
else {
|
|
1245
|
+
let prefix = "";
|
|
1246
|
+
if (d?.startMarker === "circle") prefix = "o";
|
|
1247
|
+
else if (d?.startMarker === "cross") prefix = "x";
|
|
1248
|
+
if (d?.endMarker === "circle") arrow = `${prefix}--o`;
|
|
1249
|
+
else if (d?.endMarker === "cross") arrow = `${prefix}--x`;
|
|
1250
|
+
else arrow = d?.arrowType === "none" ? `${prefix}---` : `${prefix}-->`;
|
|
1251
|
+
}
|
|
1129
1252
|
let labelStr = "";
|
|
1130
1253
|
if (edge.label) labelStr = `|${escapeMermaidLabel(edge.label)}|`;
|
|
1131
1254
|
lines.push(` ${edge.sourceId} ${arrow}${labelStr} ${edge.targetId}`);
|
|
@@ -1177,7 +1300,11 @@ function fromMermaidState(input) {
|
|
|
1177
1300
|
let edgeCounter = 0;
|
|
1178
1301
|
let startCounter = 0;
|
|
1179
1302
|
let endCounter = 0;
|
|
1303
|
+
let graphDirection;
|
|
1304
|
+
const classDefs = {};
|
|
1305
|
+
const classAssignments = {};
|
|
1180
1306
|
const parentStack = [null];
|
|
1307
|
+
const regionCounters = /* @__PURE__ */ new Map();
|
|
1181
1308
|
function ensureNode(id) {
|
|
1182
1309
|
if (!nodeMap.has(id)) nodeMap.set(id, {
|
|
1183
1310
|
type: "node",
|
|
@@ -1209,7 +1336,16 @@ function fromMermaidState(input) {
|
|
|
1209
1336
|
for (let i = 1; i < lines.length; i++) {
|
|
1210
1337
|
const line = lines[i].trim();
|
|
1211
1338
|
if (!line) continue;
|
|
1212
|
-
|
|
1339
|
+
const dirMatch = line.match(/^direction\s+(TD|TB|BT|LR|RL)\s*$/);
|
|
1340
|
+
if (dirMatch) {
|
|
1341
|
+
const dir = MERMAID_TO_DIRECTION[dirMatch[1]];
|
|
1342
|
+
const currentParent = parentStack[parentStack.length - 1];
|
|
1343
|
+
if (currentParent) {
|
|
1344
|
+
const parentNode = nodeMap.get(currentParent);
|
|
1345
|
+
if (parentNode) parentNode.data.direction = dir;
|
|
1346
|
+
} else graphDirection = dir;
|
|
1347
|
+
continue;
|
|
1348
|
+
}
|
|
1213
1349
|
const compositeMatch = line.match(/^state\s+(\S+)\s*\{?\s*$/);
|
|
1214
1350
|
if (compositeMatch && line.includes("{")) {
|
|
1215
1351
|
const stateId = compositeMatch[1];
|
|
@@ -1235,7 +1371,66 @@ function fromMermaidState(input) {
|
|
|
1235
1371
|
continue;
|
|
1236
1372
|
}
|
|
1237
1373
|
if (line === "}" || line === "end") {
|
|
1238
|
-
if (parentStack.length > 1)
|
|
1374
|
+
if (parentStack.length > 1) {
|
|
1375
|
+
const top = parentStack[parentStack.length - 1];
|
|
1376
|
+
if (top && top.includes("_region_")) parentStack.pop();
|
|
1377
|
+
parentStack.pop();
|
|
1378
|
+
}
|
|
1379
|
+
continue;
|
|
1380
|
+
}
|
|
1381
|
+
if (/^-{2,}$/.test(line)) {
|
|
1382
|
+
const compositeParent = (() => {
|
|
1383
|
+
for (let s = parentStack.length - 1; s >= 0; s--) {
|
|
1384
|
+
const id = parentStack[s];
|
|
1385
|
+
if (id && !id.includes("_region_")) return id;
|
|
1386
|
+
}
|
|
1387
|
+
return null;
|
|
1388
|
+
})();
|
|
1389
|
+
if (compositeParent) {
|
|
1390
|
+
const parentNode = nodeMap.get(compositeParent);
|
|
1391
|
+
parentNode.data.stateType = "parallel";
|
|
1392
|
+
const regionIndex = regionCounters.get(compositeParent) ?? 0;
|
|
1393
|
+
if (regionIndex === 0) {
|
|
1394
|
+
const region0Id = `${compositeParent}_region_0`;
|
|
1395
|
+
const region0 = {
|
|
1396
|
+
type: "node",
|
|
1397
|
+
id: region0Id,
|
|
1398
|
+
parentId: compositeParent,
|
|
1399
|
+
initialNodeId: null,
|
|
1400
|
+
label: region0Id,
|
|
1401
|
+
data: {}
|
|
1402
|
+
};
|
|
1403
|
+
nodeMap.set(region0Id, region0);
|
|
1404
|
+
for (const node of nodeMap.values()) if (node.parentId === compositeParent && node.id !== region0Id) node.parentId = region0Id;
|
|
1405
|
+
const region1Id = `${compositeParent}_region_1`;
|
|
1406
|
+
const region1 = {
|
|
1407
|
+
type: "node",
|
|
1408
|
+
id: region1Id,
|
|
1409
|
+
parentId: compositeParent,
|
|
1410
|
+
initialNodeId: null,
|
|
1411
|
+
label: region1Id,
|
|
1412
|
+
data: {}
|
|
1413
|
+
};
|
|
1414
|
+
nodeMap.set(region1Id, region1);
|
|
1415
|
+
if (parentStack[parentStack.length - 1] === compositeParent) parentStack.push(region1Id);
|
|
1416
|
+
regionCounters.set(compositeParent, 2);
|
|
1417
|
+
} else {
|
|
1418
|
+
const top = parentStack[parentStack.length - 1];
|
|
1419
|
+
if (top && top.includes("_region_")) parentStack.pop();
|
|
1420
|
+
const nextRegionId = `${compositeParent}_region_${regionIndex}`;
|
|
1421
|
+
const nextRegion = {
|
|
1422
|
+
type: "node",
|
|
1423
|
+
id: nextRegionId,
|
|
1424
|
+
parentId: compositeParent,
|
|
1425
|
+
initialNodeId: null,
|
|
1426
|
+
label: nextRegionId,
|
|
1427
|
+
data: {}
|
|
1428
|
+
};
|
|
1429
|
+
nodeMap.set(nextRegionId, nextRegion);
|
|
1430
|
+
parentStack.push(nextRegionId);
|
|
1431
|
+
regionCounters.set(compositeParent, regionIndex + 1);
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1239
1434
|
continue;
|
|
1240
1435
|
}
|
|
1241
1436
|
const noteMatch = line.match(/^note\s+(left|right)\s+of\s+(\S+)\s*:\s*(.+)$/i);
|
|
@@ -1251,15 +1446,29 @@ function fromMermaidState(input) {
|
|
|
1251
1446
|
});
|
|
1252
1447
|
continue;
|
|
1253
1448
|
}
|
|
1254
|
-
const transMatch = line.match(/^(\S+)
|
|
1449
|
+
const transMatch = line.match(/^(\S+?)(?::::([\w]+))?\s*-->\s*(\S+?)(?::::([\w]+))?\s*(?::\s*(.+))?$/);
|
|
1255
1450
|
if (transMatch) {
|
|
1256
1451
|
let sourceId = transMatch[1];
|
|
1257
|
-
|
|
1258
|
-
|
|
1452
|
+
const sourceClass = transMatch[2];
|
|
1453
|
+
let targetId = transMatch[3];
|
|
1454
|
+
const targetClass = transMatch[4];
|
|
1455
|
+
const label = transMatch[5]?.trim() ?? "";
|
|
1259
1456
|
if (sourceId === "[*]") sourceId = resolveStarNode("source");
|
|
1260
|
-
else
|
|
1457
|
+
else {
|
|
1458
|
+
ensureNode(sourceId);
|
|
1459
|
+
if (sourceClass) {
|
|
1460
|
+
if (!classAssignments[sourceId]) classAssignments[sourceId] = [];
|
|
1461
|
+
classAssignments[sourceId].push(sourceClass);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1261
1464
|
if (targetId === "[*]") targetId = resolveStarNode("target");
|
|
1262
|
-
else
|
|
1465
|
+
else {
|
|
1466
|
+
ensureNode(targetId);
|
|
1467
|
+
if (targetClass) {
|
|
1468
|
+
if (!classAssignments[targetId]) classAssignments[targetId] = [];
|
|
1469
|
+
classAssignments[targetId].push(targetClass);
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1263
1472
|
const edgeId = generateEdgeId(sourceId, targetId, edgeCounter++);
|
|
1264
1473
|
edges.push({
|
|
1265
1474
|
type: "edge",
|
|
@@ -1271,7 +1480,7 @@ function fromMermaidState(input) {
|
|
|
1271
1480
|
});
|
|
1272
1481
|
continue;
|
|
1273
1482
|
}
|
|
1274
|
-
const descMatch = line.match(/^(\
|
|
1483
|
+
const descMatch = line.match(/^([a-zA-Z_][\w]*)\s*:\s*([^:].*)$/);
|
|
1275
1484
|
if (descMatch) {
|
|
1276
1485
|
const stateId = descMatch[1];
|
|
1277
1486
|
const description = descMatch[2].trim();
|
|
@@ -1279,18 +1488,67 @@ function fromMermaidState(input) {
|
|
|
1279
1488
|
node.data.description = description;
|
|
1280
1489
|
continue;
|
|
1281
1490
|
}
|
|
1282
|
-
|
|
1283
|
-
|
|
1491
|
+
const classDefMatch = line.match(/^classDef\s+(\S+)\s+(.+)$/);
|
|
1492
|
+
if (classDefMatch) {
|
|
1493
|
+
const className = classDefMatch[1];
|
|
1494
|
+
const propsStr = classDefMatch[2];
|
|
1495
|
+
const props = {};
|
|
1496
|
+
for (const pair of propsStr.split(",")) {
|
|
1497
|
+
const [k, v] = pair.split(":").map((s) => s.trim());
|
|
1498
|
+
if (k && v) props[k] = v;
|
|
1499
|
+
}
|
|
1500
|
+
classDefs[className] = props;
|
|
1501
|
+
continue;
|
|
1502
|
+
}
|
|
1503
|
+
const classAssignMatch = line.match(/^class\s+(.+)\s+(\S+)\s*$/);
|
|
1504
|
+
if (classAssignMatch) {
|
|
1505
|
+
const nodeIds = classAssignMatch[1].split(",").map((s) => s.trim());
|
|
1506
|
+
const className = classAssignMatch[2];
|
|
1507
|
+
for (const nid of nodeIds) {
|
|
1508
|
+
if (!classAssignments[nid]) classAssignments[nid] = [];
|
|
1509
|
+
classAssignments[nid].push(className);
|
|
1510
|
+
}
|
|
1511
|
+
continue;
|
|
1512
|
+
}
|
|
1513
|
+
const bareMatch = line.match(/^([a-zA-Z_][\w]*)(?::::([\w]+))?$/);
|
|
1514
|
+
if (bareMatch) {
|
|
1515
|
+
const node = ensureNode(bareMatch[1]);
|
|
1516
|
+
if (bareMatch[2]) {
|
|
1517
|
+
if (!classAssignments[node.id]) classAssignments[node.id] = [];
|
|
1518
|
+
classAssignments[node.id].push(bareMatch[2]);
|
|
1519
|
+
}
|
|
1284
1520
|
continue;
|
|
1285
1521
|
}
|
|
1286
1522
|
}
|
|
1523
|
+
for (const [nodeId, classes] of Object.entries(classAssignments)) {
|
|
1524
|
+
const node = nodeMap.get(nodeId);
|
|
1525
|
+
if (node) {
|
|
1526
|
+
node.data.classes = classes;
|
|
1527
|
+
for (const cls of classes) {
|
|
1528
|
+
const def = classDefs[cls];
|
|
1529
|
+
if (def) {
|
|
1530
|
+
if (def.fill) node.color = def.fill;
|
|
1531
|
+
const style = {};
|
|
1532
|
+
for (const [k, v] of Object.entries(def)) style[k] = v;
|
|
1533
|
+
if (Object.keys(style).length > 0) node.style = {
|
|
1534
|
+
...node.style ?? {},
|
|
1535
|
+
...style
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1287
1541
|
return {
|
|
1288
1542
|
id: "",
|
|
1289
1543
|
type: "directed",
|
|
1290
1544
|
initialNodeId: null,
|
|
1291
1545
|
nodes: Array.from(nodeMap.values()),
|
|
1292
1546
|
edges,
|
|
1293
|
-
data: {
|
|
1547
|
+
data: {
|
|
1548
|
+
diagramType: "stateDiagram",
|
|
1549
|
+
...Object.keys(classDefs).length > 0 && { classDefs }
|
|
1550
|
+
},
|
|
1551
|
+
direction: graphDirection
|
|
1294
1552
|
};
|
|
1295
1553
|
}
|
|
1296
1554
|
/**
|
|
@@ -1302,6 +1560,10 @@ function fromMermaidState(input) {
|
|
|
1302
1560
|
*/
|
|
1303
1561
|
function toMermaidState(graph) {
|
|
1304
1562
|
const lines = ["stateDiagram-v2"];
|
|
1563
|
+
if (graph.direction) {
|
|
1564
|
+
const mDir = DIRECTION_TO_MERMAID[graph.direction];
|
|
1565
|
+
if (mDir) lines.push(` direction ${mDir}`);
|
|
1566
|
+
}
|
|
1305
1567
|
const childrenMap = /* @__PURE__ */ new Map();
|
|
1306
1568
|
for (const node of graph.nodes) {
|
|
1307
1569
|
const pid = node.parentId ?? null;
|
|
@@ -1314,11 +1576,22 @@ function toMermaidState(graph) {
|
|
|
1314
1576
|
const children = childrenMap.get(parentId) ?? [];
|
|
1315
1577
|
for (const node of children) {
|
|
1316
1578
|
if (node.data?.isStart || node.data?.isEnd) continue;
|
|
1317
|
-
if (node.
|
|
1579
|
+
if (node.id.includes("_region_")) continue;
|
|
1580
|
+
if (node.data?.stateType && node.data.stateType !== "parallel") lines.push(`${indent}state ${node.id} <<${node.data.stateType}>>`);
|
|
1318
1581
|
if (node.data?.description) lines.push(`${indent}state "${escapeMermaidLabel(node.data.description)}" as ${node.id}`);
|
|
1319
1582
|
if (isParent.has(node.id)) {
|
|
1320
1583
|
lines.push(`${indent}state ${node.id} {`);
|
|
1321
|
-
|
|
1584
|
+
if (node.data?.direction) {
|
|
1585
|
+
const mDir = DIRECTION_TO_MERMAID[node.data.direction];
|
|
1586
|
+
if (mDir) lines.push(`${indent} direction ${mDir}`);
|
|
1587
|
+
}
|
|
1588
|
+
if (node.data?.stateType === "parallel") {
|
|
1589
|
+
const regions = (childrenMap.get(node.id) ?? []).filter((r) => r.id.includes("_region_"));
|
|
1590
|
+
for (let ri = 0; ri < regions.length; ri++) {
|
|
1591
|
+
if (ri > 0) lines.push(`${indent} --`);
|
|
1592
|
+
writeNodes(regions[ri].id, indent + " ");
|
|
1593
|
+
}
|
|
1594
|
+
} else writeNodes(node.id, indent + " ");
|
|
1322
1595
|
lines.push(`${indent}}`);
|
|
1323
1596
|
}
|
|
1324
1597
|
if (node.data?.notes) for (const note of node.data.notes) lines.push(`${indent}note ${note.position} of ${node.id} : ${escapeMermaidLabel(note.text)}`);
|
|
@@ -1335,6 +1608,17 @@ function toMermaidState(graph) {
|
|
|
1335
1608
|
const label = edge.label ? ` : ${escapeMermaidLabel(edge.label)}` : "";
|
|
1336
1609
|
lines.push(` ${sourceId} --> ${targetId}${label}`);
|
|
1337
1610
|
}
|
|
1611
|
+
const gd = graph.data;
|
|
1612
|
+
if (gd?.classDefs) for (const [name, props] of Object.entries(gd.classDefs)) {
|
|
1613
|
+
const propsStr = Object.entries(props).map(([k, v]) => `${k}:${v}`).join(",");
|
|
1614
|
+
lines.push(` classDef ${name} ${propsStr}`);
|
|
1615
|
+
}
|
|
1616
|
+
const classMap = /* @__PURE__ */ new Map();
|
|
1617
|
+
for (const node of graph.nodes) if (node.data?.classes?.length) for (const cls of node.data.classes) {
|
|
1618
|
+
if (!classMap.has(cls)) classMap.set(cls, []);
|
|
1619
|
+
classMap.get(cls).push(node.id);
|
|
1620
|
+
}
|
|
1621
|
+
for (const [cls, nodeIds] of classMap) lines.push(` class ${nodeIds.join(",")} ${cls}`);
|
|
1338
1622
|
return lines.join("\n");
|
|
1339
1623
|
}
|
|
1340
1624
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as VisualGraphFormatConverter, T as VisualGraph } from "../../types-
|
|
1
|
+
import { D as VisualGraphFormatConverter, T as VisualGraph } from "../../types-FBZCrmnG.mjs";
|
|
2
2
|
import { EdgeBase, NodeBase } from "@xyflow/system";
|
|
3
3
|
|
|
4
4
|
//#region src/formats/xyflow/index.d.ts
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as TraversalOptions, E as VisualGraphConfig, O as VisualNode, S as TransitionOptions, T as VisualGraph, _ as MSTOptions, a as EntitiesConfig, b as PathOptions, c as Graph, d as GraphEdge, f as GraphFormatConverter, g as GraphStep, h as GraphPath, i as EdgeConfig, l as GraphConfig, m as GraphPatch, n as DeleteNodeOptions, o as EntitiesUpdate, p as GraphNode, r as EdgeChange, s as EntityRect, t as AllPairsShortestPathsOptions, u as GraphDiff, v as NodeChange, w as VisualEdge, x as SinglePathOptions, y as NodeConfig } from "./types-
|
|
1
|
+
import { C as TraversalOptions, E as VisualGraphConfig, O as VisualNode, S as TransitionOptions, T as VisualGraph, _ as MSTOptions, a as EntitiesConfig, b as PathOptions, c as Graph, d as GraphEdge, f as GraphFormatConverter, g as GraphStep, h as GraphPath, i as EdgeConfig, l as GraphConfig, m as GraphPatch, n as DeleteNodeOptions, o as EntitiesUpdate, p as GraphNode, r as EdgeChange, s as EntityRect, t as AllPairsShortestPathsOptions, u as GraphDiff, v as NodeChange, w as VisualEdge, x as SinglePathOptions, y as NodeConfig } from "./types-FBZCrmnG.mjs";
|
|
2
2
|
import { bfs, dfs, genCycles, genPostorders, genPreorders, genShortestPaths, genSimplePaths, getAllPairsShortestPaths, getConnectedComponents, getCycles, getMinimumSpanningTree, getPostorder, getPostorders, getPreorder, getPreorders, getShortestPath, getShortestPaths, getSimplePath, getSimplePaths, getStronglyConnectedComponents, getTopologicalSort, hasPath, isAcyclic, isConnected, isTree, joinPaths } from "./algorithms.mjs";
|
|
3
3
|
import { createFormatConverter } from "./formats/converter/index.mjs";
|
|
4
4
|
import { getAncestors, getChildren, getDegree, getDepth, getDescendants, getEdgeBetween, getEdgesOf, getInDegree, getInEdges, getLCA, getNeighbors, getOutDegree, getOutEdges, getParent, getPredecessors, getRelativeDistance, getRelativeDistanceMap, getRoots, getSiblings, getSinks, getSources, getSuccessors, isCompound, isLeaf } from "./queries.mjs";
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { o as invalidateIndex, t as getIndex } from "./indexing-
|
|
2
|
-
import { A as addNode, B as hasNode, C as isAcyclic, D as GraphInstance, E as joinPaths, F as deleteEntities, H as updateEntities, I as deleteNode, L as getEdge, M as createGraphFromTransition, N as createVisualGraph, O as addEdge, P as deleteEdge, R as getNode, S as hasPath, T as isTree, U as updateNode, V as updateEdge, _ as getShortestPaths, a as genPreorders, b as getStronglyConnectedComponents, c as getAllPairsShortestPaths, d as getMinimumSpanningTree, f as getPostorder, g as getShortestPath, h as getPreorders, i as genPostorders, j as createGraph, k as addEntities, l as getConnectedComponents, m as getPreorder, n as dfs, o as genShortestPaths, p as getPostorders, r as genCycles, s as genSimplePaths, t as bfs, u as getCycles, v as getSimplePath, w as isConnected, x as getTopologicalSort, y as getSimplePaths, z as hasEdge } from "./algorithms-
|
|
1
|
+
import { o as invalidateIndex, t as getIndex } from "./indexing-DyfgLuzw.mjs";
|
|
2
|
+
import { A as addNode, B as hasNode, C as isAcyclic, D as GraphInstance, E as joinPaths, F as deleteEntities, H as updateEntities, I as deleteNode, L as getEdge, M as createGraphFromTransition, N as createVisualGraph, O as addEdge, P as deleteEdge, R as getNode, S as hasPath, T as isTree, U as updateNode, V as updateEdge, _ as getShortestPaths, a as genPreorders, b as getStronglyConnectedComponents, c as getAllPairsShortestPaths, d as getMinimumSpanningTree, f as getPostorder, g as getShortestPath, h as getPreorders, i as genPostorders, j as createGraph, k as addEntities, l as getConnectedComponents, m as getPreorder, n as dfs, o as genShortestPaths, p as getPostorders, r as genCycles, s as genSimplePaths, t as bfs, u as getCycles, v as getSimplePath, w as isConnected, x as getTopologicalSort, y as getSimplePaths, z as hasEdge } from "./algorithms-DldwenLt.mjs";
|
|
3
3
|
import { getAncestors, getChildren, getDegree, getDepth, getDescendants, getEdgeBetween, getEdgesOf, getInDegree, getInEdges, getLCA, getNeighbors, getOutDegree, getOutEdges, getParent, getPredecessors, getRelativeDistance, getRelativeDistanceMap, getRoots, getSiblings, getSinks, getSources, getSuccessors, isCompound, isLeaf } from "./queries.mjs";
|
|
4
|
-
import { n as createFormatConverter } from "./converter-
|
|
4
|
+
import { n as createFormatConverter } from "./converter-B5CUD0r9.mjs";
|
|
5
5
|
|
|
6
6
|
//#region src/diff.ts
|
|
7
7
|
function nodeToConfig(node) {
|
package/dist/queries.d.mts
CHANGED
package/dist/queries.mjs
CHANGED