@statelyai/graph 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -11
- package/dist/{adjacency-list-A4_Eiwj3.mjs → adjacency-list-Bv4tfiM3.mjs} +33 -0
- package/dist/{algorithms-DBU7nmIV.mjs → algorithms-CnTmuX9t.mjs} +682 -24
- package/dist/algorithms.d.mts +479 -10
- package/dist/algorithms.mjs +1 -1
- package/dist/converter-C5DlzzHs.mjs +67 -0
- package/dist/{edge-list-DuHMz8hf.mjs → edge-list-R1SUbHwe.mjs} +32 -0
- package/dist/formats/adjacency-list/index.d.mts +35 -1
- package/dist/formats/adjacency-list/index.mjs +1 -1
- package/dist/formats/converter/index.d.mts +37 -3
- package/dist/formats/converter/index.mjs +1 -1
- package/dist/formats/cytoscape/index.d.mts +50 -2
- package/dist/formats/cytoscape/index.mjs +53 -5
- package/dist/formats/d3/index.d.mts +48 -2
- package/dist/formats/d3/index.mjs +48 -2
- package/dist/formats/dot/index.d.mts +56 -2
- package/dist/formats/dot/index.mjs +55 -2
- package/dist/formats/edge-list/index.d.mts +34 -1
- package/dist/formats/edge-list/index.mjs +1 -1
- package/dist/formats/gexf/index.d.mts +1 -1
- package/dist/formats/gexf/index.mjs +5 -5
- package/dist/formats/gml/index.d.mts +58 -2
- package/dist/formats/gml/index.mjs +59 -4
- package/dist/formats/graphml/index.d.mts +1 -1
- package/dist/formats/graphml/index.mjs +2 -2
- package/dist/formats/jgf/index.d.mts +51 -2
- package/dist/formats/jgf/index.mjs +54 -5
- package/dist/formats/mermaid/index.d.mts +201 -8
- package/dist/formats/mermaid/index.mjs +365 -26
- package/dist/formats/tgf/index.d.mts +47 -2
- package/dist/formats/tgf/index.mjs +46 -2
- package/dist/formats/xyflow/index.d.mts +73 -0
- package/dist/formats/xyflow/index.mjs +133 -0
- package/dist/index.d.mts +320 -14
- package/dist/index.mjs +117 -9
- package/dist/{indexing-BFFVMnjF.mjs → indexing-DitHphT7.mjs} +37 -7
- package/dist/queries.d.mts +353 -8
- package/dist/queries.mjs +359 -15
- package/dist/{types-B6Tpeerk.d.mts → types-Bq_fmLwW.d.mts} +15 -4
- package/package.json +3 -1
- package/dist/converter-DnbeyE_p.mjs +0 -33
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as createFormatConverter } from "../../converter-
|
|
1
|
+
import { n as createFormatConverter } from "../../converter-C5DlzzHs.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/formats/mermaid/shared.ts
|
|
4
4
|
const MERMAID_TO_DIRECTION = {
|
|
@@ -123,6 +123,18 @@ function parseArrow(arrow) {
|
|
|
123
123
|
for (const [pattern, info] of ARROW_PATTERNS) if (arrow === pattern) return info;
|
|
124
124
|
}
|
|
125
125
|
const MESSAGE_RE = /^(\S+?)\s*(<<-->>|<<->>|-->>|-->|--x|--\)|->>|->|-x|-\))\s*(\S+?)\s*:\s*(.*)$/;
|
|
126
|
+
/**
|
|
127
|
+
* Parses a Mermaid sequence diagram string into a Graph.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* const graph = fromMermaidSequence(`
|
|
131
|
+
* sequenceDiagram
|
|
132
|
+
* participant Alice
|
|
133
|
+
* participant Bob
|
|
134
|
+
* Alice->>Bob: Hello
|
|
135
|
+
* Bob-->>Alice: Hi back
|
|
136
|
+
* `);
|
|
137
|
+
*/
|
|
126
138
|
function fromMermaidSequence(input) {
|
|
127
139
|
validateInput(input, "Mermaid sequence");
|
|
128
140
|
const { lines } = prepareLines(input);
|
|
@@ -420,9 +432,17 @@ const ARROW_MAP = {
|
|
|
420
432
|
async: "--)"
|
|
421
433
|
}
|
|
422
434
|
};
|
|
435
|
+
/**
|
|
436
|
+
* Converts a sequence diagram Graph to a Mermaid sequence diagram string.
|
|
437
|
+
*
|
|
438
|
+
* @example
|
|
439
|
+
* const mermaid = toMermaidSequence(graph);
|
|
440
|
+
* // "sequenceDiagram\n participant Alice\n ..."
|
|
441
|
+
*/
|
|
423
442
|
function toMermaidSequence(graph) {
|
|
424
443
|
const lines = ["sequenceDiagram"];
|
|
425
|
-
|
|
444
|
+
const gd = graph.data;
|
|
445
|
+
if (gd?.autonumber) lines.push(" autonumber");
|
|
426
446
|
for (const node of graph.nodes) {
|
|
427
447
|
const d = node.data;
|
|
428
448
|
const keyword = d?.actorType === "actor" ? "actor" : "participant";
|
|
@@ -430,28 +450,182 @@ function toMermaidSequence(graph) {
|
|
|
430
450
|
if (d?.created) lines.push(` create ${keyword} ${node.id}${alias}`);
|
|
431
451
|
else lines.push(` ${keyword} ${node.id}${alias}`);
|
|
432
452
|
}
|
|
453
|
+
const blocks = gd?.blocks ?? [];
|
|
454
|
+
const edgeIdSet = new Set(graph.edges.map((e) => e.id));
|
|
455
|
+
const beforeEdge = /* @__PURE__ */ new Map();
|
|
456
|
+
const afterEdge = /* @__PURE__ */ new Map();
|
|
457
|
+
for (const block of blocks) if (block.type === "alt") {
|
|
458
|
+
const firstEdge = block.branches[0]?.edgeIds[0];
|
|
459
|
+
if (firstEdge && edgeIdSet.has(firstEdge)) {
|
|
460
|
+
const events = beforeEdge.get(firstEdge) ?? [];
|
|
461
|
+
events.push({
|
|
462
|
+
type: "open",
|
|
463
|
+
block
|
|
464
|
+
});
|
|
465
|
+
beforeEdge.set(firstEdge, events);
|
|
466
|
+
}
|
|
467
|
+
for (let bi = 1; bi < block.branches.length; bi++) {
|
|
468
|
+
const branchFirstEdge = block.branches[bi]?.edgeIds[0];
|
|
469
|
+
if (branchFirstEdge && edgeIdSet.has(branchFirstEdge)) {
|
|
470
|
+
const events = beforeEdge.get(branchFirstEdge) ?? [];
|
|
471
|
+
events.push({
|
|
472
|
+
type: "branch",
|
|
473
|
+
block,
|
|
474
|
+
branchIndex: bi,
|
|
475
|
+
label: block.branches[bi].label
|
|
476
|
+
});
|
|
477
|
+
beforeEdge.set(branchFirstEdge, events);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
const lastBranch = block.branches[block.branches.length - 1];
|
|
481
|
+
const lastEdge = lastBranch?.edgeIds[lastBranch.edgeIds.length - 1];
|
|
482
|
+
if (lastEdge && edgeIdSet.has(lastEdge)) {
|
|
483
|
+
const events = afterEdge.get(lastEdge) ?? [];
|
|
484
|
+
events.push({
|
|
485
|
+
type: "close",
|
|
486
|
+
block
|
|
487
|
+
});
|
|
488
|
+
afterEdge.set(lastEdge, events);
|
|
489
|
+
}
|
|
490
|
+
} else if (block.type === "par") {
|
|
491
|
+
const firstEdge = block.branches[0]?.edgeIds[0];
|
|
492
|
+
if (firstEdge && edgeIdSet.has(firstEdge)) {
|
|
493
|
+
const events = beforeEdge.get(firstEdge) ?? [];
|
|
494
|
+
events.push({
|
|
495
|
+
type: "open",
|
|
496
|
+
block
|
|
497
|
+
});
|
|
498
|
+
beforeEdge.set(firstEdge, events);
|
|
499
|
+
}
|
|
500
|
+
for (let bi = 1; bi < block.branches.length; bi++) {
|
|
501
|
+
const branchFirstEdge = block.branches[bi]?.edgeIds[0];
|
|
502
|
+
if (branchFirstEdge && edgeIdSet.has(branchFirstEdge)) {
|
|
503
|
+
const events = beforeEdge.get(branchFirstEdge) ?? [];
|
|
504
|
+
events.push({
|
|
505
|
+
type: "branch",
|
|
506
|
+
block,
|
|
507
|
+
branchIndex: bi,
|
|
508
|
+
label: block.branches[bi].label
|
|
509
|
+
});
|
|
510
|
+
beforeEdge.set(branchFirstEdge, events);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
const lastBranch = block.branches[block.branches.length - 1];
|
|
514
|
+
const lastEdge = lastBranch?.edgeIds[lastBranch.edgeIds.length - 1];
|
|
515
|
+
if (lastEdge && edgeIdSet.has(lastEdge)) {
|
|
516
|
+
const events = afterEdge.get(lastEdge) ?? [];
|
|
517
|
+
events.push({
|
|
518
|
+
type: "close",
|
|
519
|
+
block
|
|
520
|
+
});
|
|
521
|
+
afterEdge.set(lastEdge, events);
|
|
522
|
+
}
|
|
523
|
+
} else if (block.type === "critical") {
|
|
524
|
+
const firstEdge = block.edgeIds[0];
|
|
525
|
+
if (firstEdge && edgeIdSet.has(firstEdge)) {
|
|
526
|
+
const events = beforeEdge.get(firstEdge) ?? [];
|
|
527
|
+
events.push({
|
|
528
|
+
type: "open",
|
|
529
|
+
block
|
|
530
|
+
});
|
|
531
|
+
beforeEdge.set(firstEdge, events);
|
|
532
|
+
}
|
|
533
|
+
if (block.options) for (const opt of block.options) {
|
|
534
|
+
const optFirstEdge = opt.edgeIds[0];
|
|
535
|
+
if (optFirstEdge && edgeIdSet.has(optFirstEdge)) {
|
|
536
|
+
const events = beforeEdge.get(optFirstEdge) ?? [];
|
|
537
|
+
events.push({
|
|
538
|
+
type: "branch",
|
|
539
|
+
block,
|
|
540
|
+
label: opt.label
|
|
541
|
+
});
|
|
542
|
+
beforeEdge.set(optFirstEdge, events);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
const allEdgeIds = [...block.edgeIds, ...block.options?.flatMap((o) => o.edgeIds) ?? []];
|
|
546
|
+
const lastEdge = allEdgeIds[allEdgeIds.length - 1];
|
|
547
|
+
if (lastEdge && edgeIdSet.has(lastEdge)) {
|
|
548
|
+
const events = afterEdge.get(lastEdge) ?? [];
|
|
549
|
+
events.push({
|
|
550
|
+
type: "close",
|
|
551
|
+
block
|
|
552
|
+
});
|
|
553
|
+
afterEdge.set(lastEdge, events);
|
|
554
|
+
}
|
|
555
|
+
} else {
|
|
556
|
+
const edgeIds = block.edgeIds;
|
|
557
|
+
const firstEdge = edgeIds[0];
|
|
558
|
+
const lastEdge = edgeIds[edgeIds.length - 1];
|
|
559
|
+
if (firstEdge && edgeIdSet.has(firstEdge)) {
|
|
560
|
+
const events = beforeEdge.get(firstEdge) ?? [];
|
|
561
|
+
events.push({
|
|
562
|
+
type: "open",
|
|
563
|
+
block
|
|
564
|
+
});
|
|
565
|
+
beforeEdge.set(firstEdge, events);
|
|
566
|
+
}
|
|
567
|
+
if (lastEdge && edgeIdSet.has(lastEdge)) {
|
|
568
|
+
const events = afterEdge.get(lastEdge) ?? [];
|
|
569
|
+
events.push({
|
|
570
|
+
type: "close",
|
|
571
|
+
block
|
|
572
|
+
});
|
|
573
|
+
afterEdge.set(lastEdge, events);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
let depth = 1;
|
|
577
|
+
const indent = () => " ".repeat(depth);
|
|
433
578
|
for (const edge of graph.edges) {
|
|
579
|
+
const befores = beforeEdge.get(edge.id);
|
|
580
|
+
if (befores) {
|
|
581
|
+
for (const ev of befores) if (ev.type === "open") {
|
|
582
|
+
const b = ev.block;
|
|
583
|
+
if (b.type === "alt") lines.push(`${indent()}alt ${b.label}`);
|
|
584
|
+
else if (b.type === "par") lines.push(`${indent()}par ${b.branches[0].label}`);
|
|
585
|
+
else if (b.type === "critical") lines.push(`${indent()}critical ${b.label}`);
|
|
586
|
+
else if (b.type === "rect") lines.push(`${indent()}rect ${b.color}`);
|
|
587
|
+
else if (b.type === "loop" || b.type === "opt" || b.type === "break") lines.push(`${indent()}${b.type} ${b.label}`);
|
|
588
|
+
depth++;
|
|
589
|
+
} else if (ev.type === "branch") {
|
|
590
|
+
depth--;
|
|
591
|
+
const b = ev.block;
|
|
592
|
+
if (b.type === "alt") lines.push(`${indent()}else${ev.label ? ` ${ev.label}` : ""}`);
|
|
593
|
+
else if (b.type === "par") lines.push(`${indent()}and ${ev.label ?? ""}`);
|
|
594
|
+
else if (b.type === "critical") lines.push(`${indent()}option ${ev.label ?? ""}`);
|
|
595
|
+
depth++;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
434
598
|
const d = edge.data;
|
|
435
599
|
if (!d) continue;
|
|
436
|
-
if (d.kind === "activation") {
|
|
437
|
-
|
|
438
|
-
|
|
600
|
+
if (d.kind === "activation") lines.push(`${indent()}activate ${edge.sourceId}`);
|
|
601
|
+
else if (d.kind === "deactivation") lines.push(`${indent()}deactivate ${edge.sourceId}`);
|
|
602
|
+
else {
|
|
603
|
+
const stroke = d.stroke ?? "solid";
|
|
604
|
+
const arrowType = d.arrowType ?? "filled";
|
|
605
|
+
let arrow;
|
|
606
|
+
if (d.bidirectional) arrow = stroke === "dotted" ? "<<-->>" : "<<->>";
|
|
607
|
+
else arrow = ARROW_MAP[stroke]?.[arrowType] ?? "->>";
|
|
608
|
+
const label = edge.label ? `: ${escapeMermaidLabel(edge.label)}` : ":";
|
|
609
|
+
lines.push(`${indent()}${edge.sourceId}${arrow}${edge.targetId}${label}`);
|
|
439
610
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
611
|
+
const afters = afterEdge.get(edge.id);
|
|
612
|
+
if (afters) for (const _ev of afters) {
|
|
613
|
+
depth--;
|
|
614
|
+
lines.push(`${indent()}end`);
|
|
443
615
|
}
|
|
444
|
-
const stroke = d.stroke ?? "solid";
|
|
445
|
-
const arrowType = d.arrowType ?? "filled";
|
|
446
|
-
let arrow;
|
|
447
|
-
if (d.bidirectional) arrow = stroke === "dotted" ? "<<-->>" : "<<->>";
|
|
448
|
-
else arrow = ARROW_MAP[stroke]?.[arrowType] ?? "->>";
|
|
449
|
-
const label = edge.label ? `: ${escapeMermaidLabel(edge.label)}` : ":";
|
|
450
|
-
lines.push(` ${edge.sourceId}${arrow}${edge.targetId}${label}`);
|
|
451
616
|
}
|
|
452
617
|
return lines.join("\n");
|
|
453
618
|
}
|
|
454
|
-
/**
|
|
619
|
+
/**
|
|
620
|
+
* Bidirectional converter for Mermaid sequence diagram format.
|
|
621
|
+
*
|
|
622
|
+
* @example
|
|
623
|
+
* const graph = mermaidSequenceConverter.from(`
|
|
624
|
+
* sequenceDiagram
|
|
625
|
+
* Alice->>Bob: Hello
|
|
626
|
+
* `);
|
|
627
|
+
* const str = mermaidSequenceConverter.to(graph);
|
|
628
|
+
*/
|
|
455
629
|
const mermaidSequenceConverter = createFormatConverter(toMermaidSequence, fromMermaidSequence);
|
|
456
630
|
|
|
457
631
|
//#endregion
|
|
@@ -707,6 +881,16 @@ function findEdge(line) {
|
|
|
707
881
|
}
|
|
708
882
|
return null;
|
|
709
883
|
}
|
|
884
|
+
/**
|
|
885
|
+
* Parses a Mermaid flowchart string into a Graph.
|
|
886
|
+
*
|
|
887
|
+
* @example
|
|
888
|
+
* const graph = fromMermaidFlowchart(`
|
|
889
|
+
* flowchart TD
|
|
890
|
+
* A[Start] --> B{Decision}
|
|
891
|
+
* B -->|Yes| C[End]
|
|
892
|
+
* `);
|
|
893
|
+
*/
|
|
710
894
|
function fromMermaidFlowchart(input) {
|
|
711
895
|
validateInput(input, "Mermaid flowchart");
|
|
712
896
|
const { lines } = prepareLines(input);
|
|
@@ -897,6 +1081,13 @@ function fromMermaidFlowchart(input) {
|
|
|
897
1081
|
direction
|
|
898
1082
|
};
|
|
899
1083
|
}
|
|
1084
|
+
/**
|
|
1085
|
+
* Converts a flowchart Graph to a Mermaid flowchart string.
|
|
1086
|
+
*
|
|
1087
|
+
* @example
|
|
1088
|
+
* const mermaid = toMermaidFlowchart(graph);
|
|
1089
|
+
* // "flowchart TD\n A[Start] --> B{Decision}\n ..."
|
|
1090
|
+
*/
|
|
900
1091
|
function toMermaidFlowchart(graph) {
|
|
901
1092
|
const lines = [`flowchart ${DIRECTION_TO_MERMAID[graph.direction ?? "down"] ?? "TD"}`];
|
|
902
1093
|
const gd = graph.data;
|
|
@@ -906,7 +1097,7 @@ function toMermaidFlowchart(graph) {
|
|
|
906
1097
|
}
|
|
907
1098
|
const childrenMap = /* @__PURE__ */ new Map();
|
|
908
1099
|
for (const node of graph.nodes) {
|
|
909
|
-
const pid = node.parentId;
|
|
1100
|
+
const pid = node.parentId ?? null;
|
|
910
1101
|
if (!childrenMap.has(pid)) childrenMap.set(pid, []);
|
|
911
1102
|
childrenMap.get(pid).push(node);
|
|
912
1103
|
}
|
|
@@ -951,11 +1142,31 @@ function toMermaidFlowchart(graph) {
|
|
|
951
1142
|
}
|
|
952
1143
|
return lines.join("\n");
|
|
953
1144
|
}
|
|
954
|
-
/**
|
|
1145
|
+
/**
|
|
1146
|
+
* Bidirectional converter for Mermaid flowchart format.
|
|
1147
|
+
*
|
|
1148
|
+
* @example
|
|
1149
|
+
* const graph = mermaidFlowchartConverter.from(`
|
|
1150
|
+
* flowchart TD
|
|
1151
|
+
* A --> B
|
|
1152
|
+
* `);
|
|
1153
|
+
* const str = mermaidFlowchartConverter.to(graph);
|
|
1154
|
+
*/
|
|
955
1155
|
const mermaidFlowchartConverter = createFormatConverter(toMermaidFlowchart, fromMermaidFlowchart);
|
|
956
1156
|
|
|
957
1157
|
//#endregion
|
|
958
1158
|
//#region src/formats/mermaid/state.ts
|
|
1159
|
+
/**
|
|
1160
|
+
* Parses a Mermaid state diagram string into a Graph.
|
|
1161
|
+
*
|
|
1162
|
+
* @example
|
|
1163
|
+
* const graph = fromMermaidState(`
|
|
1164
|
+
* stateDiagram-v2
|
|
1165
|
+
* [*] --> Idle
|
|
1166
|
+
* Idle --> Running : start
|
|
1167
|
+
* Running --> [*]
|
|
1168
|
+
* `);
|
|
1169
|
+
*/
|
|
959
1170
|
function fromMermaidState(input) {
|
|
960
1171
|
validateInput(input, "Mermaid state");
|
|
961
1172
|
const { lines } = prepareLines(input);
|
|
@@ -1082,11 +1293,18 @@ function fromMermaidState(input) {
|
|
|
1082
1293
|
data: { diagramType: "stateDiagram" }
|
|
1083
1294
|
};
|
|
1084
1295
|
}
|
|
1296
|
+
/**
|
|
1297
|
+
* Converts a state diagram Graph to a Mermaid state diagram string.
|
|
1298
|
+
*
|
|
1299
|
+
* @example
|
|
1300
|
+
* const mermaid = toMermaidState(graph);
|
|
1301
|
+
* // "stateDiagram-v2\n [*] --> Idle\n ..."
|
|
1302
|
+
*/
|
|
1085
1303
|
function toMermaidState(graph) {
|
|
1086
1304
|
const lines = ["stateDiagram-v2"];
|
|
1087
1305
|
const childrenMap = /* @__PURE__ */ new Map();
|
|
1088
1306
|
for (const node of graph.nodes) {
|
|
1089
|
-
const pid = node.parentId;
|
|
1307
|
+
const pid = node.parentId ?? null;
|
|
1090
1308
|
if (!childrenMap.has(pid)) childrenMap.set(pid, []);
|
|
1091
1309
|
childrenMap.get(pid).push(node);
|
|
1092
1310
|
}
|
|
@@ -1119,7 +1337,16 @@ function toMermaidState(graph) {
|
|
|
1119
1337
|
}
|
|
1120
1338
|
return lines.join("\n");
|
|
1121
1339
|
}
|
|
1122
|
-
/**
|
|
1340
|
+
/**
|
|
1341
|
+
* Bidirectional converter for Mermaid state diagram format.
|
|
1342
|
+
*
|
|
1343
|
+
* @example
|
|
1344
|
+
* const graph = mermaidStateConverter.from(`
|
|
1345
|
+
* stateDiagram-v2
|
|
1346
|
+
* [*] --> Active
|
|
1347
|
+
* `);
|
|
1348
|
+
* const str = mermaidStateConverter.to(graph);
|
|
1349
|
+
*/
|
|
1123
1350
|
const mermaidStateConverter = createFormatConverter(toMermaidState, fromMermaidState);
|
|
1124
1351
|
|
|
1125
1352
|
//#endregion
|
|
@@ -1283,6 +1510,19 @@ function parseMember(line) {
|
|
|
1283
1510
|
isMethod
|
|
1284
1511
|
};
|
|
1285
1512
|
}
|
|
1513
|
+
/**
|
|
1514
|
+
* Parses a Mermaid class diagram string into a Graph.
|
|
1515
|
+
*
|
|
1516
|
+
* @example
|
|
1517
|
+
* const graph = fromMermaidClass(`
|
|
1518
|
+
* classDiagram
|
|
1519
|
+
* class Animal {
|
|
1520
|
+
* +String name
|
|
1521
|
+
* +eat() void
|
|
1522
|
+
* }
|
|
1523
|
+
* Animal <|-- Dog
|
|
1524
|
+
* `);
|
|
1525
|
+
*/
|
|
1286
1526
|
function fromMermaidClass(input) {
|
|
1287
1527
|
validateInput(input, "Mermaid class");
|
|
1288
1528
|
const { lines } = prepareLines(input);
|
|
@@ -1402,6 +1642,13 @@ const VISIBILITY_SYMBOLS = {
|
|
|
1402
1642
|
"#": "#",
|
|
1403
1643
|
"~": "~"
|
|
1404
1644
|
};
|
|
1645
|
+
/**
|
|
1646
|
+
* Converts a class diagram Graph to a Mermaid class diagram string.
|
|
1647
|
+
*
|
|
1648
|
+
* @example
|
|
1649
|
+
* const mermaid = toMermaidClass(graph);
|
|
1650
|
+
* // "classDiagram\n class Animal {\n ..."
|
|
1651
|
+
*/
|
|
1405
1652
|
function toMermaidClass(graph) {
|
|
1406
1653
|
const lines = ["classDiagram"];
|
|
1407
1654
|
for (const node of graph.nodes) if (node.data?.members && node.data.members.length > 0) {
|
|
@@ -1429,7 +1676,16 @@ function toMermaidClass(graph) {
|
|
|
1429
1676
|
}
|
|
1430
1677
|
return lines.join("\n");
|
|
1431
1678
|
}
|
|
1432
|
-
/**
|
|
1679
|
+
/**
|
|
1680
|
+
* Bidirectional converter for Mermaid class diagram format.
|
|
1681
|
+
*
|
|
1682
|
+
* @example
|
|
1683
|
+
* const graph = mermaidClassConverter.from(`
|
|
1684
|
+
* classDiagram
|
|
1685
|
+
* Animal <|-- Dog
|
|
1686
|
+
* `);
|
|
1687
|
+
* const str = mermaidClassConverter.to(graph);
|
|
1688
|
+
*/
|
|
1433
1689
|
const mermaidClassConverter = createFormatConverter(toMermaidClass, fromMermaidClass);
|
|
1434
1690
|
|
|
1435
1691
|
//#endregion
|
|
@@ -1477,6 +1733,16 @@ function parseERRelationship(symbol) {
|
|
|
1477
1733
|
};
|
|
1478
1734
|
}
|
|
1479
1735
|
const ER_LINE_RE = /^(\S+)\s+([|}{o.][|}{o.][-.][-.][|}{o.][|}{o.])\s+(\S+)\s*:\s*"?([^"]*)"?\s*$/;
|
|
1736
|
+
/**
|
|
1737
|
+
* Parses a Mermaid ER diagram string into a Graph.
|
|
1738
|
+
*
|
|
1739
|
+
* @example
|
|
1740
|
+
* const graph = fromMermaidER(`
|
|
1741
|
+
* erDiagram
|
|
1742
|
+
* CUSTOMER ||--o{ ORDER : places
|
|
1743
|
+
* ORDER ||--|{ LINE_ITEM : contains
|
|
1744
|
+
* `);
|
|
1745
|
+
*/
|
|
1480
1746
|
function fromMermaidER(input) {
|
|
1481
1747
|
validateInput(input, "Mermaid ER");
|
|
1482
1748
|
const { lines } = prepareLines(input);
|
|
@@ -1560,6 +1826,13 @@ function fromMermaidER(input) {
|
|
|
1560
1826
|
data: { diagramType: "erDiagram" }
|
|
1561
1827
|
};
|
|
1562
1828
|
}
|
|
1829
|
+
/**
|
|
1830
|
+
* Converts an ER diagram Graph to a Mermaid ER diagram string.
|
|
1831
|
+
*
|
|
1832
|
+
* @example
|
|
1833
|
+
* const mermaid = toMermaidER(graph);
|
|
1834
|
+
* // "erDiagram\n CUSTOMER ||--o{ ORDER : \"places\"\n ..."
|
|
1835
|
+
*/
|
|
1563
1836
|
function toMermaidER(graph) {
|
|
1564
1837
|
const lines = ["erDiagram"];
|
|
1565
1838
|
for (const node of graph.nodes) if (node.data?.attributes && node.data.attributes.length > 0) {
|
|
@@ -1582,7 +1855,16 @@ function toMermaidER(graph) {
|
|
|
1582
1855
|
}
|
|
1583
1856
|
return lines.join("\n");
|
|
1584
1857
|
}
|
|
1585
|
-
/**
|
|
1858
|
+
/**
|
|
1859
|
+
* Bidirectional converter for Mermaid ER diagram format.
|
|
1860
|
+
*
|
|
1861
|
+
* @example
|
|
1862
|
+
* const graph = mermaidERConverter.from(`
|
|
1863
|
+
* erDiagram
|
|
1864
|
+
* CUSTOMER ||--o{ ORDER : places
|
|
1865
|
+
* `);
|
|
1866
|
+
* const str = mermaidERConverter.to(graph);
|
|
1867
|
+
*/
|
|
1586
1868
|
const mermaidERConverter = createFormatConverter(toMermaidER, fromMermaidER);
|
|
1587
1869
|
|
|
1588
1870
|
//#endregion
|
|
@@ -1628,6 +1910,18 @@ function parseNodeText(text) {
|
|
|
1628
1910
|
};
|
|
1629
1911
|
return { label: text.trim() };
|
|
1630
1912
|
}
|
|
1913
|
+
/**
|
|
1914
|
+
* Parses a Mermaid mindmap string into a Graph.
|
|
1915
|
+
*
|
|
1916
|
+
* @example
|
|
1917
|
+
* const graph = fromMermaidMindmap(`
|
|
1918
|
+
* mindmap
|
|
1919
|
+
* Root
|
|
1920
|
+
* Child A
|
|
1921
|
+
* Grandchild
|
|
1922
|
+
* Child B
|
|
1923
|
+
* `);
|
|
1924
|
+
*/
|
|
1631
1925
|
function fromMermaidMindmap(input) {
|
|
1632
1926
|
validateInput(input, "Mermaid mindmap");
|
|
1633
1927
|
const { lines } = prepareLines(input);
|
|
@@ -1690,11 +1984,18 @@ function fromMermaidMindmap(input) {
|
|
|
1690
1984
|
data: { diagramType: "mindmap" }
|
|
1691
1985
|
};
|
|
1692
1986
|
}
|
|
1987
|
+
/**
|
|
1988
|
+
* Converts a mindmap Graph to a Mermaid mindmap string.
|
|
1989
|
+
*
|
|
1990
|
+
* @example
|
|
1991
|
+
* const mermaid = toMermaidMindmap(graph);
|
|
1992
|
+
* // "mindmap\n Root\n Child A\n ..."
|
|
1993
|
+
*/
|
|
1693
1994
|
function toMermaidMindmap(graph) {
|
|
1694
1995
|
const lines = ["mindmap"];
|
|
1695
1996
|
const childrenMap = /* @__PURE__ */ new Map();
|
|
1696
1997
|
for (const node of graph.nodes) {
|
|
1697
|
-
const pid = node.parentId;
|
|
1998
|
+
const pid = node.parentId ?? null;
|
|
1698
1999
|
if (!childrenMap.has(pid)) childrenMap.set(pid, []);
|
|
1699
2000
|
childrenMap.get(pid).push(node);
|
|
1700
2001
|
}
|
|
@@ -1715,7 +2016,17 @@ function toMermaidMindmap(graph) {
|
|
|
1715
2016
|
writeNode(null, 0);
|
|
1716
2017
|
return lines.join("\n");
|
|
1717
2018
|
}
|
|
1718
|
-
/**
|
|
2019
|
+
/**
|
|
2020
|
+
* Bidirectional converter for Mermaid mindmap format.
|
|
2021
|
+
*
|
|
2022
|
+
* @example
|
|
2023
|
+
* const graph = mermaidMindmapConverter.from(`
|
|
2024
|
+
* mindmap
|
|
2025
|
+
* Root
|
|
2026
|
+
* Branch
|
|
2027
|
+
* `);
|
|
2028
|
+
* const str = mermaidMindmapConverter.to(graph);
|
|
2029
|
+
*/
|
|
1719
2030
|
const mermaidMindmapConverter = createFormatConverter(toMermaidMindmap, fromMermaidMindmap);
|
|
1720
2031
|
|
|
1721
2032
|
//#endregion
|
|
@@ -1772,6 +2083,17 @@ function parseBlockNode(text) {
|
|
|
1772
2083
|
};
|
|
1773
2084
|
return null;
|
|
1774
2085
|
}
|
|
2086
|
+
/**
|
|
2087
|
+
* Parses a Mermaid block diagram string into a Graph.
|
|
2088
|
+
*
|
|
2089
|
+
* @example
|
|
2090
|
+
* const graph = fromMermaidBlock(`
|
|
2091
|
+
* block-beta
|
|
2092
|
+
* columns 2
|
|
2093
|
+
* a["Task A"] b["Task B"]
|
|
2094
|
+
* a --> b
|
|
2095
|
+
* `);
|
|
2096
|
+
*/
|
|
1775
2097
|
function fromMermaidBlock(input) {
|
|
1776
2098
|
validateInput(input, "Mermaid block");
|
|
1777
2099
|
const { lines } = prepareLines(input);
|
|
@@ -1864,12 +2186,19 @@ function fromMermaidBlock(input) {
|
|
|
1864
2186
|
}
|
|
1865
2187
|
};
|
|
1866
2188
|
}
|
|
2189
|
+
/**
|
|
2190
|
+
* Converts a block diagram Graph to a Mermaid block diagram string.
|
|
2191
|
+
*
|
|
2192
|
+
* @example
|
|
2193
|
+
* const mermaid = toMermaidBlock(graph);
|
|
2194
|
+
* // "block-beta\n columns 2\n a[\"Task A\"]\n ..."
|
|
2195
|
+
*/
|
|
1867
2196
|
function toMermaidBlock(graph) {
|
|
1868
2197
|
const lines = ["block-beta"];
|
|
1869
2198
|
if (graph.data?.columns) lines.push(` columns ${graph.data.columns}`);
|
|
1870
2199
|
const childrenMap = /* @__PURE__ */ new Map();
|
|
1871
2200
|
for (const node of graph.nodes) {
|
|
1872
|
-
const pid = node.parentId;
|
|
2201
|
+
const pid = node.parentId ?? null;
|
|
1873
2202
|
if (!childrenMap.has(pid)) childrenMap.set(pid, []);
|
|
1874
2203
|
childrenMap.get(pid).push(node);
|
|
1875
2204
|
}
|
|
@@ -1891,7 +2220,17 @@ function toMermaidBlock(graph) {
|
|
|
1891
2220
|
for (const edge of graph.edges) lines.push(` ${edge.sourceId} --> ${edge.targetId}`);
|
|
1892
2221
|
return lines.join("\n");
|
|
1893
2222
|
}
|
|
1894
|
-
/**
|
|
2223
|
+
/**
|
|
2224
|
+
* Bidirectional converter for Mermaid block diagram format.
|
|
2225
|
+
*
|
|
2226
|
+
* @example
|
|
2227
|
+
* const graph = mermaidBlockConverter.from(`
|
|
2228
|
+
* block-beta
|
|
2229
|
+
* columns 2
|
|
2230
|
+
* a b
|
|
2231
|
+
* `);
|
|
2232
|
+
* const str = mermaidBlockConverter.to(graph);
|
|
2233
|
+
*/
|
|
1895
2234
|
const mermaidBlockConverter = createFormatConverter(toMermaidBlock, fromMermaidBlock);
|
|
1896
2235
|
|
|
1897
2236
|
//#endregion
|
|
@@ -1,9 +1,54 @@
|
|
|
1
|
-
import { c as Graph, f as GraphFormatConverter } from "../../types-
|
|
1
|
+
import { c as Graph, f as GraphFormatConverter } from "../../types-Bq_fmLwW.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/formats/tgf/index.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Converts a graph to TGF (Trivial Graph Format) string.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { createGraph } from '@statelyai/graph';
|
|
11
|
+
* import { toTGF } from '@statelyai/graph/formats/tgf';
|
|
12
|
+
*
|
|
13
|
+
* const graph = createGraph({
|
|
14
|
+
* nodes: [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }],
|
|
15
|
+
* edges: [{ id: 'e0', sourceId: 'a', targetId: 'b', label: 'go' }],
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* const tgf = toTGF(graph);
|
|
19
|
+
* // "a A\nb B\n#\na b go"
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
4
22
|
declare function toTGF(graph: Graph): string;
|
|
23
|
+
/**
|
|
24
|
+
* Parses a TGF (Trivial Graph Format) string into a graph.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { fromTGF } from '@statelyai/graph/formats/tgf';
|
|
29
|
+
*
|
|
30
|
+
* const graph = fromTGF('a A\nb B\n#\na b go');
|
|
31
|
+
* // graph.nodes = [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }]
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
5
34
|
declare function fromTGF(tgf: string): Graph;
|
|
6
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Bidirectional converter for TGF (Trivial Graph Format).
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { createGraph } from '@statelyai/graph';
|
|
41
|
+
* import { tgfConverter } from '@statelyai/graph/formats/tgf';
|
|
42
|
+
*
|
|
43
|
+
* const graph = createGraph({
|
|
44
|
+
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
45
|
+
* edges: [{ id: 'e0', sourceId: 'a', targetId: 'b' }],
|
|
46
|
+
* });
|
|
47
|
+
*
|
|
48
|
+
* const tgf = tgfConverter.to(graph);
|
|
49
|
+
* const roundTripped = tgfConverter.from(tgf);
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
7
52
|
declare const tgfConverter: GraphFormatConverter<string>;
|
|
8
53
|
//#endregion
|
|
9
54
|
export { fromTGF, tgfConverter, toTGF };
|
|
@@ -1,6 +1,23 @@
|
|
|
1
|
-
import { n as createFormatConverter } from "../../converter-
|
|
1
|
+
import { n as createFormatConverter } from "../../converter-C5DlzzHs.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/formats/tgf/index.ts
|
|
4
|
+
/**
|
|
5
|
+
* Converts a graph to TGF (Trivial Graph Format) string.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { createGraph } from '@statelyai/graph';
|
|
10
|
+
* import { toTGF } from '@statelyai/graph/formats/tgf';
|
|
11
|
+
*
|
|
12
|
+
* const graph = createGraph({
|
|
13
|
+
* nodes: [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }],
|
|
14
|
+
* edges: [{ id: 'e0', sourceId: 'a', targetId: 'b', label: 'go' }],
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* const tgf = toTGF(graph);
|
|
18
|
+
* // "a A\nb B\n#\na b go"
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
4
21
|
function toTGF(graph) {
|
|
5
22
|
const lines = [];
|
|
6
23
|
for (const node of graph.nodes) lines.push(node.label ? `${node.id} ${node.label}` : node.id);
|
|
@@ -12,6 +29,17 @@ function toTGF(graph) {
|
|
|
12
29
|
}
|
|
13
30
|
return lines.join("\n");
|
|
14
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Parses a TGF (Trivial Graph Format) string into a graph.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* import { fromTGF } from '@statelyai/graph/formats/tgf';
|
|
38
|
+
*
|
|
39
|
+
* const graph = fromTGF('a A\nb B\n#\na b go');
|
|
40
|
+
* // graph.nodes = [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }]
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
15
43
|
function fromTGF(tgf) {
|
|
16
44
|
if (typeof tgf !== "string") throw new Error("TGF: expected a string");
|
|
17
45
|
const lines = tgf.split("\n");
|
|
@@ -60,7 +88,23 @@ function fromTGF(tgf) {
|
|
|
60
88
|
data: void 0
|
|
61
89
|
};
|
|
62
90
|
}
|
|
63
|
-
/**
|
|
91
|
+
/**
|
|
92
|
+
* Bidirectional converter for TGF (Trivial Graph Format).
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* import { createGraph } from '@statelyai/graph';
|
|
97
|
+
* import { tgfConverter } from '@statelyai/graph/formats/tgf';
|
|
98
|
+
*
|
|
99
|
+
* const graph = createGraph({
|
|
100
|
+
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
101
|
+
* edges: [{ id: 'e0', sourceId: 'a', targetId: 'b' }],
|
|
102
|
+
* });
|
|
103
|
+
*
|
|
104
|
+
* const tgf = tgfConverter.to(graph);
|
|
105
|
+
* const roundTripped = tgfConverter.from(tgf);
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
64
108
|
const tgfConverter = createFormatConverter(toTGF, fromTGF);
|
|
65
109
|
|
|
66
110
|
//#endregion
|