@hpcc-js/wasm-graphviz 1.24.1 → 1.25.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hpcc-js/wasm-graphviz",
3
- "version": "1.24.1",
3
+ "version": "1.25.0",
4
4
  "description": "hpcc-js - WASM Graphviz",
5
5
  "type": "module",
6
6
  "exports": {
@@ -18,7 +18,7 @@
18
18
  ],
19
19
  "scripts": {
20
20
  "clean": "rimraf coverage dist dist-test types .nyc_output",
21
- "gen-types": "tsgo --project tsconfig.json --emitDeclarationOnly",
21
+ "gen-types": "tsc --project tsconfig.json --emitDeclarationOnly",
22
22
  "gen-types-watch": "npm run gen-types -- --watch",
23
23
  "bundle": "node esbuild.js",
24
24
  "bundle-dev": "npm run bundle -- --development",
@@ -56,5 +56,5 @@
56
56
  },
57
57
  "homepage": "https://hpcc-systems.github.io/hpcc-js-wasm/",
58
58
  "license": "Apache-2.0",
59
- "gitHead": "66515f510e2045ad74b336a52f3ab55974ebed9e"
59
+ "gitHead": "e9302b649306927c2844eda31d3ee58b17b8eb8a"
60
60
  }
package/src/graphviz.ts CHANGED
@@ -8,6 +8,22 @@ import type {
8
8
  GraphDotAttr, GraphAttrs as GraphAttrs
9
9
  } from "./types.ts";
10
10
 
11
+ type AttrValues<T> = Partial<{ [K in keyof T]: NonNullable<T[K]> }>;
12
+
13
+ function applyAttrs<T extends object>(
14
+ attrs: AttrValues<T> | undefined,
15
+ apply: (attr: string, value: string | number | boolean) => void
16
+ ): void {
17
+ if (!attrs) {
18
+ return;
19
+ }
20
+ for (const [attr, value] of Object.entries(attrs)) {
21
+ if (value !== undefined) {
22
+ apply(attr, value as string | number | boolean);
23
+ }
24
+ }
25
+ }
26
+
11
27
  /**
12
28
  * Various graphic and data formats for end user, web, documents and other applications. See [Output Formats](https://graphviz.org/docs/outputs/) for more information.
13
29
  */
@@ -117,6 +133,35 @@ let g_graphviz: Promise<Graphviz> | undefined;
117
133
  */
118
134
  export type GraphType = "directed" | "undirected" | "strict directed" | "strict undirected";
119
135
 
136
+ export interface GraphInit {
137
+ name?: string;
138
+ type?: GraphType;
139
+ attrs?: AttrValues<GraphAttrs>;
140
+ htmlAttrs?: AttrValues<GraphAttrs>;
141
+ }
142
+
143
+ export interface NodeInit {
144
+ name: string;
145
+ attrs?: AttrValues<NodeAttrs>;
146
+ htmlAttrs?: AttrValues<NodeAttrs>;
147
+ }
148
+
149
+ export interface EdgeInit {
150
+ tail: string;
151
+ head: string;
152
+ key?: string;
153
+ attrs?: AttrValues<EdgeAttrs>;
154
+ htmlAttrs?: AttrValues<EdgeAttrs>;
155
+ }
156
+
157
+ export interface SubgraphInit {
158
+ name: string;
159
+ attrs?: AttrValues<ClusterAttrs>;
160
+ htmlAttrs?: AttrValues<ClusterAttrs>;
161
+ }
162
+
163
+ export type ClusterInit = SubgraphInit;
164
+
120
165
  /**
121
166
  * A subgraph (or cluster) inside a {@link Graph}.
122
167
  *
@@ -148,8 +193,15 @@ export class Subgraph {
148
193
  /**
149
194
  * Create (or find) a node and add it to this subgraph.
150
195
  */
151
- addNode(name: string): this {
196
+ addNode(name: string): this;
197
+ addNode(init: NodeInit): this;
198
+ addNode(nameOrInit: string | NodeInit): this {
199
+ const init = typeof nameOrInit === "string" ? { name: nameOrInit } : nameOrInit;
200
+ const { name, attrs, htmlAttrs } = init;
201
+
152
202
  this._sg.addNode(name);
203
+ applyAttrs<NodeAttrs>(attrs, (attr, value) => this.setNodeAttr(name, attr, value));
204
+ applyAttrs<NodeAttrs>(htmlAttrs, (attr, value) => this.setNodeHtmlAttr(name, attr, value));
153
205
  return this;
154
206
  }
155
207
 
@@ -157,8 +209,23 @@ export class Subgraph {
157
209
  * Create an edge inside this subgraph. Both endpoints are created
158
210
  * automatically if they do not already exist.
159
211
  */
160
- addEdge(tail: string, head: string, key: string = ""): this {
161
- this._sg.addEdge(tail, head, key);
212
+ addEdge(tail: string, head: string, key?: string): this;
213
+ addEdge(init: EdgeInit): this;
214
+ addEdge(tailOrInit: string | EdgeInit, head?: string, key: string = ""): this {
215
+ const init = typeof tailOrInit === "string"
216
+ ? { tail: tailOrInit, head: head!, key }
217
+ : tailOrInit;
218
+ const { tail, head: resolvedHead, key: resolvedKey = "", attrs, htmlAttrs } = init;
219
+
220
+ this._sg.addEdge(tail, resolvedHead, resolvedKey);
221
+ applyAttrs<EdgeAttrs>(attrs, (attr, value) => this.setEdgeAttr(tail, resolvedHead, resolvedKey, attr, value));
222
+ applyAttrs<EdgeAttrs>(htmlAttrs, (attr, value) => this.setEdgeHtmlAttr(tail, resolvedHead, resolvedKey, attr, value));
223
+ return this;
224
+ }
225
+
226
+ applyInit(init: SubgraphInit): this {
227
+ applyAttrs<ClusterAttrs>(init.attrs, (attr, value) => this.setAttr(attr, value));
228
+ applyAttrs<ClusterAttrs>(init.htmlAttrs, (attr, value) => this.setHtmlAttr(attr, value));
162
229
  return this;
163
230
  }
164
231
 
@@ -497,8 +564,15 @@ export class Graph {
497
564
  * Create a node. If a node with this name already exists it is returned
498
565
  * unchanged.
499
566
  */
500
- addNode(name: string): this {
567
+ addNode(name: string): this;
568
+ addNode(init: NodeInit): this;
569
+ addNode(nameOrInit: string | NodeInit): this {
570
+ const init = typeof nameOrInit === "string" ? { name: nameOrInit } : nameOrInit;
571
+ const { name, attrs, htmlAttrs } = init;
572
+
501
573
  this._graph.addNode(name);
574
+ applyAttrs<NodeAttrs>(attrs, (attr, value) => this.setNodeAttr(name, attr, value));
575
+ applyAttrs<NodeAttrs>(htmlAttrs, (attr, value) => this.setNodeHtmlAttr(name, attr, value));
502
576
  return this;
503
577
  }
504
578
 
@@ -508,8 +582,23 @@ export class Graph {
508
582
  * parallel edges between the same pair of nodes; omit (or pass `""`) for
509
583
  * an anonymous edge.
510
584
  */
511
- addEdge(tail: string, head: string, key: string = ""): this {
512
- this._graph.addEdge(tail, head, key);
585
+ addEdge(tail: string, head: string, key?: string): this;
586
+ addEdge(init: EdgeInit): this;
587
+ addEdge(tailOrInit: string | EdgeInit, head?: string, key: string = ""): this {
588
+ const init = typeof tailOrInit === "string"
589
+ ? { tail: tailOrInit, head: head!, key }
590
+ : tailOrInit;
591
+ const { tail, head: resolvedHead, key: resolvedKey = "", attrs, htmlAttrs } = init;
592
+
593
+ this._graph.addEdge(tail, resolvedHead, resolvedKey);
594
+ applyAttrs<EdgeAttrs>(attrs, (attr, value) => this.setEdgeAttr(tail, resolvedHead, resolvedKey, attr, value));
595
+ applyAttrs<EdgeAttrs>(htmlAttrs, (attr, value) => this.setEdgeHtmlAttr(tail, resolvedHead, resolvedKey, attr, value));
596
+ return this;
597
+ }
598
+
599
+ applyInit(init: GraphInit): this {
600
+ applyAttrs<GraphAttrs>(init.attrs, (attr, value) => this.setGraphAttr(attr, value));
601
+ applyAttrs<GraphAttrs>(init.htmlAttrs, (attr, value) => this.setGraphHtmlAttr(attr, value));
513
602
  return this;
514
603
  }
515
604
 
@@ -849,10 +938,13 @@ export class Graph {
849
938
  * cluster.setAttr("label", "My Cluster").addEdge("a", "b");
850
939
  * ```
851
940
  */
852
- addSubgraph(name: string): Subgraph {
941
+ addSubgraph(name: string): Subgraph;
942
+ addSubgraph(init: SubgraphInit): Subgraph;
943
+ addSubgraph(nameOrInit: string | SubgraphInit): Subgraph {
944
+ const init = typeof nameOrInit === "string" ? { name: nameOrInit } : nameOrInit;
853
945
  // addSubgraph only returns null when the internal graph pointer is null,
854
946
  // which cannot happen while this Graph instance is alive.
855
- return new Subgraph(this._graph.addSubgraph(name)!);
947
+ return new Subgraph(this._graph.addSubgraph(init.name)!).applyInit(init);
856
948
  }
857
949
 
858
950
  /**
@@ -1287,10 +1379,17 @@ export class Graphviz {
1287
1379
  * const svg = graphviz.dot(graph.toDot());
1288
1380
  * ```
1289
1381
  */
1290
- createGraph(name: string = "G", type: GraphType = "directed"): Graph {
1291
- const directed = !type.includes("undirected") ? 1 : 0;
1292
- const strict = type.startsWith("strict") ? 1 : 0;
1293
- return new Graph(new this._module.CGraph(name, directed, strict), this._module);
1382
+ createGraph(name?: string, type?: GraphType): Graph;
1383
+ createGraph(init: GraphInit): Graph;
1384
+ createGraph(nameOrInit: string | GraphInit = "G", type: GraphType = "directed"): Graph {
1385
+ const init = typeof nameOrInit === "string"
1386
+ ? { name: nameOrInit, type }
1387
+ : nameOrInit;
1388
+ const resolvedName = init.name ?? "G";
1389
+ const resolvedType = init.type ?? "directed";
1390
+ const directed = !resolvedType.includes("undirected") ? 1 : 0;
1391
+ const strict = resolvedType.startsWith("strict") ? 1 : 0;
1392
+ return new Graph(new this._module.CGraph(resolvedName, directed, strict), this._module).applyInit(init);
1294
1393
  }
1295
1394
 
1296
1395
  /**
@@ -1,5 +1,8 @@
1
1
  import type { MainModule, CGraph as CGraphWasm, CSubgraph as CSubgraphWasm } from "../types/graphvizlib.js";
2
2
  import type { NodeDotAttr, NodeAttrs, EdgeDotAttr, EdgeAttrs, ClusterDotAttr, ClusterAttrs, GraphDotAttr, GraphAttrs as GraphAttrs } from "./types.ts";
3
+ type AttrValues<T> = Partial<{
4
+ [K in keyof T]: NonNullable<T[K]>;
5
+ }>;
3
6
  /**
4
7
  * Various graphic and data formats for end user, web, documents and other applications. See [Output Formats](https://graphviz.org/docs/outputs/) for more information.
5
8
  */
@@ -64,6 +67,30 @@ export interface Options {
64
67
  * - `"strict undirected"` – undirected graph that disallows parallel edges and self-loops
65
68
  */
66
69
  export type GraphType = "directed" | "undirected" | "strict directed" | "strict undirected";
70
+ export interface GraphInit {
71
+ name?: string;
72
+ type?: GraphType;
73
+ attrs?: AttrValues<GraphAttrs>;
74
+ htmlAttrs?: AttrValues<GraphAttrs>;
75
+ }
76
+ export interface NodeInit {
77
+ name: string;
78
+ attrs?: AttrValues<NodeAttrs>;
79
+ htmlAttrs?: AttrValues<NodeAttrs>;
80
+ }
81
+ export interface EdgeInit {
82
+ tail: string;
83
+ head: string;
84
+ key?: string;
85
+ attrs?: AttrValues<EdgeAttrs>;
86
+ htmlAttrs?: AttrValues<EdgeAttrs>;
87
+ }
88
+ export interface SubgraphInit {
89
+ name: string;
90
+ attrs?: AttrValues<ClusterAttrs>;
91
+ htmlAttrs?: AttrValues<ClusterAttrs>;
92
+ }
93
+ export type ClusterInit = SubgraphInit;
67
94
  /**
68
95
  * A subgraph (or cluster) inside a {@link Graph}.
69
96
  *
@@ -92,11 +119,14 @@ export declare class Subgraph {
92
119
  * Create (or find) a node and add it to this subgraph.
93
120
  */
94
121
  addNode(name: string): this;
122
+ addNode(init: NodeInit): this;
95
123
  /**
96
124
  * Create an edge inside this subgraph. Both endpoints are created
97
125
  * automatically if they do not already exist.
98
126
  */
99
127
  addEdge(tail: string, head: string, key?: string): this;
128
+ addEdge(init: EdgeInit): this;
129
+ applyInit(init: SubgraphInit): this;
100
130
  /**
101
131
  * Remove a node from this subgraph only. The node (and any edges
102
132
  * connecting it) remains in the root graph and all other subgraphs.
@@ -278,6 +308,7 @@ export declare class Graph {
278
308
  * unchanged.
279
309
  */
280
310
  addNode(name: string): this;
311
+ addNode(init: NodeInit): this;
281
312
  /**
282
313
  * Create an edge from `tail` to `head`. Both nodes are created
283
314
  * automatically if they do not already exist. `key` distinguishes
@@ -285,6 +316,8 @@ export declare class Graph {
285
316
  * an anonymous edge.
286
317
  */
287
318
  addEdge(tail: string, head: string, key?: string): this;
319
+ addEdge(init: EdgeInit): this;
320
+ applyInit(init: GraphInit): this;
288
321
  /**
289
322
  * Replace this graph with one parsed from DOT source using Graphviz cgraph
290
323
  * reading support.
@@ -461,6 +494,7 @@ export declare class Graph {
461
494
  * ```
462
495
  */
463
496
  addSubgraph(name: string): Subgraph;
497
+ addSubgraph(init: SubgraphInit): Subgraph;
464
498
  /**
465
499
  * Look up an existing subgraph by name without creating a new one.
466
500
  * Returns a {@link Subgraph} wrapper if a subgraph with that name exists,
@@ -722,6 +756,7 @@ export declare class Graphviz {
722
756
  * ```
723
757
  */
724
758
  createGraph(name?: string, type?: GraphType): Graph;
759
+ createGraph(init: GraphInit): Graph;
725
760
  /**
726
761
  * Parse DOT source into a mutable {@link Graph}. The returned graph can
727
762
  * be queried, modified, rendered directly, or serialised back to DOT with
@@ -729,3 +764,4 @@ export declare class Graphviz {
729
764
  */
730
765
  read(dotSource: string): Graph;
731
766
  }
767
+ export {};