@statelyai/graph 0.5.0 → 0.7.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 +63 -144
- package/dist/{algorithms-DldwenLt.mjs → algorithms-Dw5jEwDK.mjs} +242 -36
- package/dist/algorithms.d.mts +91 -3
- package/dist/algorithms.mjs +2 -2
- package/dist/formats/adjacency-list/index.d.mts +1 -1
- package/dist/formats/converter/index.d.mts +1 -1
- package/dist/formats/cytoscape/index.d.mts +1 -1
- package/dist/formats/d3/index.d.mts +1 -1
- package/dist/formats/dot/index.d.mts +1 -1
- package/dist/formats/edge-list/index.d.mts +1 -1
- package/dist/formats/elk/index.d.mts +1 -1
- package/dist/formats/gexf/index.d.mts +1 -1
- package/dist/formats/gml/index.d.mts +1 -1
- package/dist/formats/graphml/index.d.mts +1 -1
- package/dist/formats/graphml/index.mjs +147 -55
- package/dist/formats/jgf/index.d.mts +1 -1
- package/dist/formats/mermaid/index.d.mts +6 -1
- package/dist/formats/mermaid/index.mjs +20 -6
- package/dist/formats/tgf/index.d.mts +1 -1
- package/dist/formats/xyflow/index.d.mts +1 -1
- package/dist/index.d.mts +120 -3
- package/dist/index.mjs +364 -8
- package/dist/queries.d.mts +1 -1
- package/dist/queries.mjs +1 -1
- package/dist/schemas.d.mts +7 -5
- package/dist/schemas.mjs +4 -3
- package/dist/{types-FBZCrmnG.d.mts → types-DkKjaQW3.d.mts} +61 -9
- package/package.json +1 -1
package/dist/algorithms.d.mts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { C as SinglePathOptions, S as PathOptions, T as TraversalOptions, _ as GraphPath, h as GraphNode, n as AllPairsShortestPathsOptions, t as AStarOptions, u as Graph, y as MSTOptions } from "./types-DkKjaQW3.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/algorithms.d.ts
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Breadth-first traversal generator yielding nodes level by level.
|
|
7
7
|
*
|
|
8
|
+
* **O(V + E)** time, **O(V)** space.
|
|
9
|
+
*
|
|
8
10
|
* @example
|
|
9
11
|
* ```ts
|
|
10
12
|
* import { createGraph, bfs } from '@statelyai/graph';
|
|
@@ -23,6 +25,8 @@ declare function bfs<N>(graph: Graph<N>, startId: string): Generator<GraphNode<N
|
|
|
23
25
|
/**
|
|
24
26
|
* Depth-first traversal generator yielding nodes as visited.
|
|
25
27
|
*
|
|
28
|
+
* **O(V + E)** time, **O(V)** space.
|
|
29
|
+
*
|
|
26
30
|
* @example
|
|
27
31
|
* ```ts
|
|
28
32
|
* import { createGraph, dfs } from '@statelyai/graph';
|
|
@@ -41,6 +45,8 @@ declare function dfs<N>(graph: Graph<N>, startId: string): Generator<GraphNode<N
|
|
|
41
45
|
/**
|
|
42
46
|
* Checks whether the graph contains no cycles.
|
|
43
47
|
*
|
|
48
|
+
* **O(V + E)** time.
|
|
49
|
+
*
|
|
44
50
|
* @example
|
|
45
51
|
* ```ts
|
|
46
52
|
* import { createGraph, isAcyclic } from '@statelyai/graph';
|
|
@@ -58,6 +64,8 @@ declare function isAcyclic(graph: Graph): boolean;
|
|
|
58
64
|
* Returns connected components as arrays of nodes.
|
|
59
65
|
* Treats all edges as undirected for connectivity.
|
|
60
66
|
*
|
|
67
|
+
* **O(V + E)** time.
|
|
68
|
+
*
|
|
61
69
|
* @example
|
|
62
70
|
* ```ts
|
|
63
71
|
* import { createGraph, getConnectedComponents } from '@statelyai/graph';
|
|
@@ -75,6 +83,8 @@ declare function getConnectedComponents<N>(graph: Graph<N>): GraphNode<N>[][];
|
|
|
75
83
|
/**
|
|
76
84
|
* Returns a topological ordering of nodes, or `null` if the graph is cyclic.
|
|
77
85
|
*
|
|
86
|
+
* **O(V + E)** time (Kahn's algorithm).
|
|
87
|
+
*
|
|
78
88
|
* @example
|
|
79
89
|
* ```ts
|
|
80
90
|
* import { createGraph, getTopologicalSort } from '@statelyai/graph';
|
|
@@ -95,6 +105,8 @@ declare function getTopologicalSort<N>(graph: Graph<N>): GraphNode<N>[] | null;
|
|
|
95
105
|
/**
|
|
96
106
|
* Checks whether a path exists between two nodes.
|
|
97
107
|
*
|
|
108
|
+
* **O(V + E)** time (BFS) or **O((V + E) log V)** (Dijkstra when weighted).
|
|
109
|
+
*
|
|
98
110
|
* @example
|
|
99
111
|
* ```ts
|
|
100
112
|
* import { createGraph, hasPath } from '@statelyai/graph';
|
|
@@ -112,6 +124,8 @@ declare function hasPath(graph: Graph, sourceId: string, targetId: string): bool
|
|
|
112
124
|
/**
|
|
113
125
|
* Checks whether the graph is connected (all nodes reachable from any node).
|
|
114
126
|
*
|
|
127
|
+
* **O(V + E)** time.
|
|
128
|
+
*
|
|
115
129
|
* @example
|
|
116
130
|
* ```ts
|
|
117
131
|
* import { createGraph, isConnected } from '@statelyai/graph';
|
|
@@ -128,6 +142,8 @@ declare function isConnected(graph: Graph): boolean;
|
|
|
128
142
|
/**
|
|
129
143
|
* Checks whether the graph is a tree (connected and acyclic).
|
|
130
144
|
*
|
|
145
|
+
* **O(V + E)** time.
|
|
146
|
+
*
|
|
131
147
|
* @example
|
|
132
148
|
* ```ts
|
|
133
149
|
* import { createGraph, isTree } from '@statelyai/graph';
|
|
@@ -148,6 +164,9 @@ declare function isTree(graph: Graph): boolean;
|
|
|
148
164
|
* Lazily yields all shortest paths from a source node.
|
|
149
165
|
* Use `getShortestPaths` for the full array.
|
|
150
166
|
*
|
|
167
|
+
* **O(V + E)** time (BFS) or **O((V + E) log V)** (Dijkstra when weighted),
|
|
168
|
+
* plus **O(P)** per path yielded where P is the path length.
|
|
169
|
+
*
|
|
151
170
|
* @example
|
|
152
171
|
* ```ts
|
|
153
172
|
* import { createGraph, genShortestPaths } from '@statelyai/graph';
|
|
@@ -171,6 +190,8 @@ declare function genShortestPaths<N, E>(graph: Graph<N, E>, opts?: PathOptions<E
|
|
|
171
190
|
* Returns all shortest paths from a source node as an array.
|
|
172
191
|
* Delegates to `genShortestPaths` internally.
|
|
173
192
|
*
|
|
193
|
+
* **O(V + E)** time (BFS) or **O((V + E) log V)** (Dijkstra when weighted).
|
|
194
|
+
*
|
|
174
195
|
* @example
|
|
175
196
|
* ```ts
|
|
176
197
|
* import { createGraph, getShortestPaths } from '@statelyai/graph';
|
|
@@ -192,6 +213,8 @@ declare function getShortestPaths<N, E>(graph: Graph<N, E>, opts?: PathOptions<E
|
|
|
192
213
|
/**
|
|
193
214
|
* Returns a single shortest path from source to target, or `undefined` if unreachable.
|
|
194
215
|
*
|
|
216
|
+
* **O(V + E)** time (BFS) or **O((V + E) log V)** (Dijkstra when weighted).
|
|
217
|
+
*
|
|
195
218
|
* @example
|
|
196
219
|
* ```ts
|
|
197
220
|
* import { createGraph, getShortestPath } from '@statelyai/graph';
|
|
@@ -214,6 +237,8 @@ declare function getShortestPath<N, E>(graph: Graph<N, E>, opts: SinglePathOptio
|
|
|
214
237
|
* Returns all simple (acyclic) paths from a source node as an array.
|
|
215
238
|
* Delegates to `genSimplePaths` internally.
|
|
216
239
|
*
|
|
240
|
+
* **O(V!)** worst-case (exponential in dense graphs).
|
|
241
|
+
*
|
|
217
242
|
* @example
|
|
218
243
|
* ```ts
|
|
219
244
|
* import { createGraph, getSimplePaths } from '@statelyai/graph';
|
|
@@ -237,6 +262,8 @@ declare function getSimplePaths<N, E>(graph: Graph<N, E>, opts?: PathOptions<E>)
|
|
|
237
262
|
* Lazily yields all simple (acyclic) paths from a source node via DFS backtracking.
|
|
238
263
|
* Use `getSimplePaths` for the full array.
|
|
239
264
|
*
|
|
265
|
+
* **O(V!)** worst-case (exponential in dense graphs).
|
|
266
|
+
*
|
|
240
267
|
* @example
|
|
241
268
|
* ```ts
|
|
242
269
|
* import { createGraph, genSimplePaths } from '@statelyai/graph';
|
|
@@ -261,6 +288,8 @@ declare function genSimplePaths<N, E>(graph: Graph<N, E>, opts?: PathOptions<E>)
|
|
|
261
288
|
/**
|
|
262
289
|
* Returns a single simple (acyclic) path from source to target, or `undefined` if unreachable.
|
|
263
290
|
*
|
|
291
|
+
* **O(V + E)** typical, **O(V!)** worst-case.
|
|
292
|
+
*
|
|
264
293
|
* @example
|
|
265
294
|
* ```ts
|
|
266
295
|
* import { createGraph, getSimplePath } from '@statelyai/graph';
|
|
@@ -283,6 +312,8 @@ declare function getSimplePath<N, E>(graph: Graph<N, E>, opts: SinglePathOptions
|
|
|
283
312
|
* Returns strongly connected components using Tarjan's algorithm.
|
|
284
313
|
* Only meaningful for directed graphs.
|
|
285
314
|
*
|
|
315
|
+
* **O(V + E)** time.
|
|
316
|
+
*
|
|
286
317
|
* @example
|
|
287
318
|
* ```ts
|
|
288
319
|
* import { createGraph, getStronglyConnectedComponents } from '@statelyai/graph';
|
|
@@ -305,6 +336,8 @@ declare function getStronglyConnectedComponents<N>(graph: Graph<N>): GraphNode<N
|
|
|
305
336
|
* Returns all elementary cycles as an array of paths.
|
|
306
337
|
* Delegates to `genCycles` internally.
|
|
307
338
|
*
|
|
339
|
+
* **O((V + E) · C)** where C is the number of elementary cycles (can be exponential).
|
|
340
|
+
*
|
|
308
341
|
* @example
|
|
309
342
|
* ```ts
|
|
310
343
|
* import { createGraph, getCycles } from '@statelyai/graph';
|
|
@@ -326,6 +359,8 @@ declare function getCycles<N, E>(graph: Graph<N, E>): GraphPath<N, E>[];
|
|
|
326
359
|
* Lazily yields elementary cycles one at a time.
|
|
327
360
|
* Use `getCycles` for the full array.
|
|
328
361
|
*
|
|
362
|
+
* **O((V + E) · C)** where C is the number of elementary cycles (can be exponential).
|
|
363
|
+
*
|
|
329
364
|
* @example
|
|
330
365
|
* ```ts
|
|
331
366
|
* import { createGraph, genCycles } from '@statelyai/graph';
|
|
@@ -348,6 +383,8 @@ declare function genCycles<N, E>(graph: Graph<N, E>): Generator<GraphPath<N, E>>
|
|
|
348
383
|
* Returns a single canonical preorder (DFS visit-order) sequence.
|
|
349
384
|
* Visits neighbors in the order they appear in the adjacency list.
|
|
350
385
|
*
|
|
386
|
+
* **O(V + E)** time.
|
|
387
|
+
*
|
|
351
388
|
* @example
|
|
352
389
|
* ```ts
|
|
353
390
|
* import { createGraph, getPreorder } from '@statelyai/graph';
|
|
@@ -370,6 +407,8 @@ declare function getPreorder<N>(graph: Graph<N>, opts?: TraversalOptions): Graph
|
|
|
370
407
|
* Returns a single canonical postorder (DFS finish-order) sequence.
|
|
371
408
|
* Visits neighbors in the order they appear in the adjacency list.
|
|
372
409
|
*
|
|
410
|
+
* **O(V + E)** time.
|
|
411
|
+
*
|
|
373
412
|
* @example
|
|
374
413
|
* ```ts
|
|
375
414
|
* import { createGraph, getPostorder } from '@statelyai/graph';
|
|
@@ -391,6 +430,8 @@ declare function getPostorder<N>(graph: Graph<N>, opts?: TraversalOptions): Grap
|
|
|
391
430
|
/**
|
|
392
431
|
* Returns all possible preorder sequences as an array. Can be exponential -- prefer `genPreorders`.
|
|
393
432
|
*
|
|
433
|
+
* **O(V! · V)** worst-case (exponential).
|
|
434
|
+
*
|
|
394
435
|
* @example
|
|
395
436
|
* ```ts
|
|
396
437
|
* import { createGraph, getPreorders } from '@statelyai/graph';
|
|
@@ -412,6 +453,8 @@ declare function getPreorders<N>(graph: Graph<N>, opts?: TraversalOptions): Grap
|
|
|
412
453
|
/**
|
|
413
454
|
* Returns all possible postorder sequences as an array. Can be exponential -- prefer `genPostorders`.
|
|
414
455
|
*
|
|
456
|
+
* **O(V! · V)** worst-case (exponential).
|
|
457
|
+
*
|
|
415
458
|
* @example
|
|
416
459
|
* ```ts
|
|
417
460
|
* import { createGraph, getPostorders } from '@statelyai/graph';
|
|
@@ -435,6 +478,8 @@ declare function getPostorders<N>(graph: Graph<N>, opts?: TraversalOptions): Gra
|
|
|
435
478
|
* Different neighbor exploration orders yield different sequences.
|
|
436
479
|
* Use `getPreorder()` for a single canonical ordering.
|
|
437
480
|
*
|
|
481
|
+
* **O(V! · V)** worst-case (exponential).
|
|
482
|
+
*
|
|
438
483
|
* @example
|
|
439
484
|
* ```ts
|
|
440
485
|
* import { createGraph, genPreorders } from '@statelyai/graph';
|
|
@@ -460,6 +505,8 @@ declare function genPreorders<N>(graph: Graph<N>, opts?: TraversalOptions): Gene
|
|
|
460
505
|
* Different neighbor exploration orders yield different sequences.
|
|
461
506
|
* Use `getPostorder()` for a single canonical ordering.
|
|
462
507
|
*
|
|
508
|
+
* **O(V! · V)** worst-case (exponential).
|
|
509
|
+
*
|
|
463
510
|
* @example
|
|
464
511
|
* ```ts
|
|
465
512
|
* import { createGraph, genPostorders } from '@statelyai/graph';
|
|
@@ -485,6 +532,8 @@ declare function genPostorders<N>(graph: Graph<N>, opts?: TraversalOptions): Gen
|
|
|
485
532
|
* Only meaningful for connected undirected graphs (or the component reachable
|
|
486
533
|
* from an arbitrary start node in directed graphs).
|
|
487
534
|
*
|
|
535
|
+
* **O(E log E)** using either edge sorting (Kruskal) or a min-heap (Prim).
|
|
536
|
+
*
|
|
488
537
|
* @example
|
|
489
538
|
* ```ts
|
|
490
539
|
* import { createGraph, getMinimumSpanningTree } from '@statelyai/graph';
|
|
@@ -509,7 +558,9 @@ declare function getMinimumSpanningTree<N, E>(graph: Graph<N, E>, opts?: MSTOpti
|
|
|
509
558
|
/**
|
|
510
559
|
* Returns shortest paths between all pairs of nodes.
|
|
511
560
|
* Algorithm 'dijkstra' (default): runs getShortestPaths per source node.
|
|
512
|
-
* Algorithm 'floyd-warshall': classic
|
|
561
|
+
* Algorithm 'floyd-warshall': classic dynamic programming.
|
|
562
|
+
*
|
|
563
|
+
* **O(V · (V + E) log V)** (Dijkstra) or **O(V³)** (Floyd-Warshall).
|
|
513
564
|
*
|
|
514
565
|
* @example
|
|
515
566
|
* ```ts
|
|
@@ -528,6 +579,43 @@ declare function getMinimumSpanningTree<N, E>(graph: Graph<N, E>, opts?: MSTOpti
|
|
|
528
579
|
* ```
|
|
529
580
|
*/
|
|
530
581
|
declare function getAllPairsShortestPaths<N, E>(graph: Graph<N, E>, opts?: AllPairsShortestPathsOptions<E>): GraphPath<N, E>[];
|
|
582
|
+
/**
|
|
583
|
+
* Returns a shortest path using A* search with an admissible heuristic.
|
|
584
|
+
* More efficient than Dijkstra when a good heuristic is available.
|
|
585
|
+
*
|
|
586
|
+
* **O((V + E) log V)** time with a good heuristic; degrades to Dijkstra
|
|
587
|
+
* with `heuristic: () => 0`.
|
|
588
|
+
*
|
|
589
|
+
* @example
|
|
590
|
+
* ```ts
|
|
591
|
+
* import { createGraph, getAStarPath } from '@statelyai/graph';
|
|
592
|
+
*
|
|
593
|
+
* const graph = createGraph({
|
|
594
|
+
* nodes: [
|
|
595
|
+
* { id: 'a', x: 0, y: 0 },
|
|
596
|
+
* { id: 'b', x: 1, y: 0 },
|
|
597
|
+
* { id: 'c', x: 1, y: 1 },
|
|
598
|
+
* ],
|
|
599
|
+
* edges: [
|
|
600
|
+
* { id: 'ab', sourceId: 'a', targetId: 'b', weight: 1 },
|
|
601
|
+
* { id: 'bc', sourceId: 'b', targetId: 'c', weight: 1 },
|
|
602
|
+
* { id: 'ac', sourceId: 'a', targetId: 'c', weight: 3 },
|
|
603
|
+
* ],
|
|
604
|
+
* });
|
|
605
|
+
*
|
|
606
|
+
* const path = getAStarPath(graph, {
|
|
607
|
+
* from: 'a',
|
|
608
|
+
* to: 'c',
|
|
609
|
+
* heuristic: (nodeId) => {
|
|
610
|
+
* const node = graph.nodes.find(n => n.id === nodeId)!;
|
|
611
|
+
* const target = graph.nodes.find(n => n.id === 'c')!;
|
|
612
|
+
* return Math.abs(node.x! - target.x!) + Math.abs(node.y! - target.y!);
|
|
613
|
+
* },
|
|
614
|
+
* });
|
|
615
|
+
* // path: a -> b -> c (weight 2, cheaper than direct a -> c)
|
|
616
|
+
* ```
|
|
617
|
+
*/
|
|
618
|
+
declare function getAStarPath<N, E>(graph: Graph<N, E>, opts: AStarOptions<E>): GraphPath<N, E> | undefined;
|
|
531
619
|
/**
|
|
532
620
|
* Joins two paths end-to-end. The last node of the head path must equal
|
|
533
621
|
* the source of the tail path (the overlap node).
|
|
@@ -556,4 +644,4 @@ declare function getAllPairsShortestPaths<N, E>(graph: Graph<N, E>, opts?: AllPa
|
|
|
556
644
|
*/
|
|
557
645
|
declare function joinPaths<N, E>(headPath: GraphPath<N, E>, tailPath: GraphPath<N, E>): GraphPath<N, E>;
|
|
558
646
|
//#endregion
|
|
559
|
-
export { 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 };
|
|
647
|
+
export { bfs, dfs, genCycles, genPostorders, genPreorders, genShortestPaths, genSimplePaths, getAStarPath, getAllPairsShortestPaths, getConnectedComponents, getCycles, getMinimumSpanningTree, getPostorder, getPostorders, getPreorder, getPreorders, getShortestPath, getShortestPaths, getSimplePath, getSimplePaths, getStronglyConnectedComponents, getTopologicalSort, hasPath, isAcyclic, isConnected, isTree, joinPaths };
|
package/dist/algorithms.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { C as hasPath, D as joinPaths, E as isTree, S as getTopologicalSort, T as isConnected, _ as getShortestPath, a as genPreorders, b as getSimplePaths, c as getAStarPath, d as getCycles, f as getMinimumSpanningTree, g as getPreorders, h as getPreorder, i as genPostorders, l as getAllPairsShortestPaths, m as getPostorders, n as dfs, o as genShortestPaths, p as getPostorder, r as genCycles, s as genSimplePaths, t as bfs, u as getConnectedComponents, v as getShortestPaths, w as isAcyclic, x as getStronglyConnectedComponents, y as getSimplePath } from "./algorithms-Dw5jEwDK.mjs";
|
|
2
2
|
|
|
3
|
-
export { 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 };
|
|
3
|
+
export { bfs, dfs, genCycles, genPostorders, genPreorders, genShortestPaths, genSimplePaths, getAStarPath, getAllPairsShortestPaths, getConnectedComponents, getCycles, getMinimumSpanningTree, getPostorder, getPostorders, getPreorder, getPreorders, getShortestPath, getShortestPaths, getSimplePath, getSimplePaths, getStronglyConnectedComponents, getTopologicalSort, hasPath, isAcyclic, isConnected, isTree, joinPaths };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as
|
|
1
|
+
import { D as VisualGraph, k as VisualGraphFormatConverter } from "../../types-DkKjaQW3.mjs";
|
|
2
2
|
import { ElkEdge, ElkEdgeSection, ElkExtendedEdge, ElkGraphElement, ElkLabel, ElkNode, ElkNode as ElkNode$1, ElkPoint, ElkPort, ElkPrimitiveEdge, ElkShape, LayoutOptions } from "elkjs/lib/elk-api";
|
|
3
3
|
|
|
4
4
|
//#region src/formats/elk/index.d.ts
|
|
@@ -17,6 +17,12 @@ function toGraphML(graph) {
|
|
|
17
17
|
"@_attr.name": "parentId",
|
|
18
18
|
"@_attr.type": "string"
|
|
19
19
|
},
|
|
20
|
+
{
|
|
21
|
+
"@_id": "initialNodeId",
|
|
22
|
+
"@_for": "node",
|
|
23
|
+
"@_attr.name": "initialNodeId",
|
|
24
|
+
"@_attr.type": "string"
|
|
25
|
+
},
|
|
20
26
|
{
|
|
21
27
|
"@_id": "data",
|
|
22
28
|
"@_for": "all",
|
|
@@ -29,6 +35,30 @@ function toGraphML(graph) {
|
|
|
29
35
|
"@_attr.name": "data",
|
|
30
36
|
"@_attr.type": "string"
|
|
31
37
|
},
|
|
38
|
+
{
|
|
39
|
+
"@_id": "graphInitialNodeId",
|
|
40
|
+
"@_for": "graph",
|
|
41
|
+
"@_attr.name": "initialNodeId",
|
|
42
|
+
"@_attr.type": "string"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"@_id": "direction",
|
|
46
|
+
"@_for": "graph",
|
|
47
|
+
"@_attr.name": "direction",
|
|
48
|
+
"@_attr.type": "string"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"@_id": "style",
|
|
52
|
+
"@_for": "all",
|
|
53
|
+
"@_attr.name": "style",
|
|
54
|
+
"@_attr.type": "string"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"@_id": "graphStyle",
|
|
58
|
+
"@_for": "graph",
|
|
59
|
+
"@_attr.name": "style",
|
|
60
|
+
"@_attr.type": "string"
|
|
61
|
+
},
|
|
32
62
|
{
|
|
33
63
|
"@_id": "x",
|
|
34
64
|
"@_for": "all",
|
|
@@ -64,85 +94,107 @@ function toGraphML(graph) {
|
|
|
64
94
|
"@_for": "all",
|
|
65
95
|
"@_attr.name": "color",
|
|
66
96
|
"@_attr.type": "string"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"@_id": "weight",
|
|
100
|
+
"@_for": "edge",
|
|
101
|
+
"@_attr.name": "weight",
|
|
102
|
+
"@_attr.type": "double"
|
|
67
103
|
}
|
|
68
104
|
];
|
|
69
|
-
const nodes = graph.nodes.map((
|
|
105
|
+
const nodes = graph.nodes.map((node) => {
|
|
70
106
|
const data = [];
|
|
71
|
-
if (
|
|
107
|
+
if (node.label) data.push({
|
|
72
108
|
"@_key": "label",
|
|
73
|
-
"#text":
|
|
109
|
+
"#text": node.label
|
|
74
110
|
});
|
|
75
|
-
if (
|
|
111
|
+
if (node.parentId) data.push({
|
|
76
112
|
"@_key": "parentId",
|
|
77
|
-
"#text":
|
|
113
|
+
"#text": node.parentId
|
|
78
114
|
});
|
|
79
|
-
if (
|
|
115
|
+
if (node.initialNodeId) data.push({
|
|
116
|
+
"@_key": "initialNodeId",
|
|
117
|
+
"#text": node.initialNodeId
|
|
118
|
+
});
|
|
119
|
+
if (node.data !== void 0) data.push({
|
|
80
120
|
"@_key": "data",
|
|
81
|
-
"#text": JSON.stringify(
|
|
121
|
+
"#text": JSON.stringify(node.data)
|
|
122
|
+
});
|
|
123
|
+
if (node.style !== void 0) data.push({
|
|
124
|
+
"@_key": "style",
|
|
125
|
+
"#text": JSON.stringify(node.style)
|
|
82
126
|
});
|
|
83
|
-
if (
|
|
127
|
+
if (node.x !== void 0) data.push({
|
|
84
128
|
"@_key": "x",
|
|
85
|
-
"#text":
|
|
129
|
+
"#text": node.x
|
|
86
130
|
});
|
|
87
|
-
if (
|
|
131
|
+
if (node.y !== void 0) data.push({
|
|
88
132
|
"@_key": "y",
|
|
89
|
-
"#text":
|
|
133
|
+
"#text": node.y
|
|
90
134
|
});
|
|
91
|
-
if (
|
|
135
|
+
if (node.width !== void 0) data.push({
|
|
92
136
|
"@_key": "width",
|
|
93
|
-
"#text":
|
|
137
|
+
"#text": node.width
|
|
94
138
|
});
|
|
95
|
-
if (
|
|
139
|
+
if (node.height !== void 0) data.push({
|
|
96
140
|
"@_key": "height",
|
|
97
|
-
"#text":
|
|
141
|
+
"#text": node.height
|
|
98
142
|
});
|
|
99
|
-
if (
|
|
143
|
+
if (node.shape) data.push({
|
|
100
144
|
"@_key": "shape",
|
|
101
|
-
"#text":
|
|
145
|
+
"#text": node.shape
|
|
102
146
|
});
|
|
103
|
-
if (
|
|
147
|
+
if (node.color) data.push({
|
|
104
148
|
"@_key": "color",
|
|
105
|
-
"#text":
|
|
149
|
+
"#text": node.color
|
|
106
150
|
});
|
|
107
151
|
return {
|
|
108
|
-
"@_id":
|
|
152
|
+
"@_id": node.id,
|
|
109
153
|
...data.length > 0 && { data }
|
|
110
154
|
};
|
|
111
155
|
});
|
|
112
|
-
const edges = graph.edges.map((
|
|
156
|
+
const edges = graph.edges.map((edge) => {
|
|
113
157
|
const data = [];
|
|
114
|
-
if (
|
|
158
|
+
if (edge.label) data.push({
|
|
115
159
|
"@_key": "label",
|
|
116
|
-
"#text":
|
|
160
|
+
"#text": edge.label
|
|
117
161
|
});
|
|
118
|
-
if (
|
|
162
|
+
if (edge.data !== void 0) data.push({
|
|
119
163
|
"@_key": "data",
|
|
120
|
-
"#text": JSON.stringify(
|
|
164
|
+
"#text": JSON.stringify(edge.data)
|
|
121
165
|
});
|
|
122
|
-
if (
|
|
166
|
+
if (edge.style !== void 0) data.push({
|
|
167
|
+
"@_key": "style",
|
|
168
|
+
"#text": JSON.stringify(edge.style)
|
|
169
|
+
});
|
|
170
|
+
if (edge.x !== void 0) data.push({
|
|
123
171
|
"@_key": "x",
|
|
124
|
-
"#text":
|
|
172
|
+
"#text": edge.x
|
|
125
173
|
});
|
|
126
|
-
if (
|
|
174
|
+
if (edge.y !== void 0) data.push({
|
|
127
175
|
"@_key": "y",
|
|
128
|
-
"#text":
|
|
176
|
+
"#text": edge.y
|
|
129
177
|
});
|
|
130
|
-
if (
|
|
178
|
+
if (edge.width !== void 0) data.push({
|
|
131
179
|
"@_key": "width",
|
|
132
|
-
"#text":
|
|
180
|
+
"#text": edge.width
|
|
133
181
|
});
|
|
134
|
-
if (
|
|
182
|
+
if (edge.height !== void 0) data.push({
|
|
135
183
|
"@_key": "height",
|
|
136
|
-
"#text":
|
|
184
|
+
"#text": edge.height
|
|
137
185
|
});
|
|
138
|
-
if (
|
|
186
|
+
if (edge.color) data.push({
|
|
139
187
|
"@_key": "color",
|
|
140
|
-
"#text":
|
|
188
|
+
"#text": edge.color
|
|
189
|
+
});
|
|
190
|
+
if (edge.weight !== void 0) data.push({
|
|
191
|
+
"@_key": "weight",
|
|
192
|
+
"#text": edge.weight
|
|
141
193
|
});
|
|
142
194
|
return {
|
|
143
|
-
"@_id":
|
|
144
|
-
"@_source":
|
|
145
|
-
"@_target":
|
|
195
|
+
"@_id": edge.id,
|
|
196
|
+
"@_source": edge.sourceId,
|
|
197
|
+
"@_target": edge.targetId,
|
|
146
198
|
...data.length > 0 && { data }
|
|
147
199
|
};
|
|
148
200
|
});
|
|
@@ -151,6 +203,18 @@ function toGraphML(graph) {
|
|
|
151
203
|
"@_key": "graphData",
|
|
152
204
|
"#text": JSON.stringify(graph.data)
|
|
153
205
|
});
|
|
206
|
+
if (graph.initialNodeId) graphData.push({
|
|
207
|
+
"@_key": "graphInitialNodeId",
|
|
208
|
+
"#text": graph.initialNodeId
|
|
209
|
+
});
|
|
210
|
+
if (graph.direction !== void 0) graphData.push({
|
|
211
|
+
"@_key": "direction",
|
|
212
|
+
"#text": graph.direction
|
|
213
|
+
});
|
|
214
|
+
if (graph.style !== void 0) graphData.push({
|
|
215
|
+
"@_key": "graphStyle",
|
|
216
|
+
"#text": JSON.stringify(graph.style)
|
|
217
|
+
});
|
|
154
218
|
const obj = {
|
|
155
219
|
"?xml": {
|
|
156
220
|
"@_version": "1.0",
|
|
@@ -196,40 +260,57 @@ function fromGraphML(xml) {
|
|
|
196
260
|
const graphEl = graphml.graph;
|
|
197
261
|
if (!graphEl) throw new Error("GraphML: missing <graph> element");
|
|
198
262
|
const graphType = graphEl["@_edgedefault"] === "undirected" ? "undirected" : "directed";
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const dataMap = parseDataElements(n.data);
|
|
205
|
-
return {
|
|
263
|
+
const graphDataMap = parseDataElements(graphEl.data);
|
|
264
|
+
const graphData = graphDataMap.graphData !== void 0 ? tryParseJSON(graphDataMap.graphData) : void 0;
|
|
265
|
+
const nodes = asArray(graphEl.node).map((nodeEl) => {
|
|
266
|
+
const dataMap = parseDataElements(nodeEl.data);
|
|
267
|
+
const node = {
|
|
206
268
|
type: "node",
|
|
207
|
-
id: String(
|
|
269
|
+
id: String(nodeEl["@_id"]),
|
|
208
270
|
parentId: dataMap.parentId ?? null,
|
|
209
271
|
initialNodeId: dataMap.initialNodeId ?? null,
|
|
210
272
|
label: dataMap.label ?? "",
|
|
211
273
|
data: dataMap.data !== void 0 ? tryParseJSON(dataMap.data) : void 0
|
|
212
274
|
};
|
|
275
|
+
if (dataMap.x !== void 0) node.x = parseNumber(dataMap.x);
|
|
276
|
+
if (dataMap.y !== void 0) node.y = parseNumber(dataMap.y);
|
|
277
|
+
if (dataMap.width !== void 0) node.width = parseNumber(dataMap.width);
|
|
278
|
+
if (dataMap.height !== void 0) node.height = parseNumber(dataMap.height);
|
|
279
|
+
if (dataMap.shape !== void 0) node.shape = dataMap.shape;
|
|
280
|
+
if (dataMap.color !== void 0) node.color = dataMap.color;
|
|
281
|
+
if (dataMap.style !== void 0) node.style = tryParseJSON(dataMap.style);
|
|
282
|
+
return node;
|
|
213
283
|
});
|
|
214
|
-
const edges = asArray(graphEl.edge).map((
|
|
215
|
-
const dataMap = parseDataElements(
|
|
216
|
-
|
|
284
|
+
const edges = asArray(graphEl.edge).map((edgeEl) => {
|
|
285
|
+
const dataMap = parseDataElements(edgeEl.data);
|
|
286
|
+
const edge = {
|
|
217
287
|
type: "edge",
|
|
218
|
-
id: String(
|
|
219
|
-
sourceId: String(
|
|
220
|
-
targetId: String(
|
|
288
|
+
id: String(edgeEl["@_id"]),
|
|
289
|
+
sourceId: String(edgeEl["@_source"]),
|
|
290
|
+
targetId: String(edgeEl["@_target"]),
|
|
221
291
|
label: dataMap.label ?? "",
|
|
222
292
|
data: dataMap.data !== void 0 ? tryParseJSON(dataMap.data) : void 0
|
|
223
293
|
};
|
|
294
|
+
if (dataMap.weight !== void 0) edge.weight = parseNumber(dataMap.weight);
|
|
295
|
+
if (dataMap.x !== void 0) edge.x = parseNumber(dataMap.x);
|
|
296
|
+
if (dataMap.y !== void 0) edge.y = parseNumber(dataMap.y);
|
|
297
|
+
if (dataMap.width !== void 0) edge.width = parseNumber(dataMap.width);
|
|
298
|
+
if (dataMap.height !== void 0) edge.height = parseNumber(dataMap.height);
|
|
299
|
+
if (dataMap.color !== void 0) edge.color = dataMap.color;
|
|
300
|
+
if (dataMap.style !== void 0) edge.style = tryParseJSON(dataMap.style);
|
|
301
|
+
return edge;
|
|
224
302
|
});
|
|
225
|
-
|
|
303
|
+
const graph = {
|
|
226
304
|
id: String(graphEl["@_id"] ?? ""),
|
|
227
305
|
type: graphType,
|
|
228
|
-
initialNodeId: null,
|
|
306
|
+
initialNodeId: graphDataMap.graphInitialNodeId ?? null,
|
|
229
307
|
nodes,
|
|
230
308
|
edges,
|
|
231
309
|
data: graphData
|
|
232
310
|
};
|
|
311
|
+
if (graphDataMap.direction !== void 0) graph.direction = parseDirection(graphDataMap.direction);
|
|
312
|
+
if (graphDataMap.graphStyle !== void 0) graph.style = tryParseJSON(graphDataMap.graphStyle);
|
|
313
|
+
return graph;
|
|
233
314
|
}
|
|
234
315
|
function asArray(val) {
|
|
235
316
|
if (val === void 0) return [];
|
|
@@ -237,7 +318,7 @@ function asArray(val) {
|
|
|
237
318
|
}
|
|
238
319
|
function parseDataElements(dataEls) {
|
|
239
320
|
const map = {};
|
|
240
|
-
for (const
|
|
321
|
+
for (const dataEl of asArray(dataEls)) if (dataEl && dataEl["@_key"]) map[dataEl["@_key"]] = String(dataEl["#text"] ?? "");
|
|
241
322
|
return map;
|
|
242
323
|
}
|
|
243
324
|
function tryParseJSON(str) {
|
|
@@ -247,6 +328,17 @@ function tryParseJSON(str) {
|
|
|
247
328
|
return str;
|
|
248
329
|
}
|
|
249
330
|
}
|
|
331
|
+
function parseNumber(value) {
|
|
332
|
+
return Number(value);
|
|
333
|
+
}
|
|
334
|
+
function parseDirection(value) {
|
|
335
|
+
return [
|
|
336
|
+
"up",
|
|
337
|
+
"down",
|
|
338
|
+
"left",
|
|
339
|
+
"right"
|
|
340
|
+
].includes(value) ? value : void 0;
|
|
341
|
+
}
|
|
250
342
|
/** Bidirectional converter for GraphML XML format. */
|
|
251
343
|
const graphmlConverter = createFormatConverter(toGraphML, fromGraphML);
|
|
252
344
|
|