@hpcc-js/wasm-graphviz 1.24.0 → 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/README.md CHANGED
@@ -6,11 +6,12 @@ outline: deep
6
6
 
7
7
  # @hpcc-js/wasm-graphviz
8
8
 
9
- This package provides a WebAssembly wrapper around the [Graphviz](https://www.graphviz.org/) library. This allows for the rendering of DOT language graphs directly within a browser or NodeJS type environment.
9
+ This package provides a WebAssembly wrapper around the [Graphviz](https://www.graphviz.org/) library. This allows for the rendering of DOT language graphs directly within a browser or NodeJS type environment.
10
10
 
11
11
  ## Installation
12
12
 
13
13
  ::: code-group
14
+
14
15
  ```sh [npm]
15
16
  npm install @hpcc-js/wasm-graphviz
16
17
  ```
@@ -22,6 +23,7 @@ yarn add @hpcc-js/wasm-graphviz
22
23
  ```sh [pnpm]
23
24
  pnpm add @hpcc-js/wasm-graphviz
24
25
  ```
26
+
25
27
  :::
26
28
 
27
29
  ## Quick Start
@@ -37,8 +39,15 @@ document.body.innerHTML = svg;
37
39
  ## Programmatic Graph Construction
38
40
 
39
41
  Instead of writing DOT source by hand you can build graphs programmatically using
40
- `createGraph`. The resulting `Graph` object can be rendered directly via
41
- `graph.layout()` or serialised to DOT first with `graph.toDot()`.
42
+ `createGraph`. The resulting `Graph` object can be rendered directly via
43
+ `graph.layout()` or serialised to DOT first with `graph.write()` / `graph.toDot()`.
44
+
45
+ Attribute names and values follow Graphviz itself; see the official Graphviz
46
+ [attribute reference](https://graphviz.org/docs/attrs/) for the supported graph,
47
+ node, edge, and cluster attributes.
48
+
49
+ Existing DOT can also be parsed into a mutable graph with `read`, and any
50
+ programmatic graph can be written back to DOT with `write` (`toDot` is an alias).
42
51
 
43
52
  ### Basic usage
44
53
 
@@ -51,18 +60,56 @@ const graphviz = await Graphviz.load();
51
60
  using graph = graphviz.createGraph("G");
52
61
 
53
62
  graph
54
- .addNode("a")
55
- .addNode("b")
56
- .addEdge("a", "b")
57
- .setNodeAttr("a", "shape", "box")
58
- .setNodeAttr("a", "color", "red")
59
- .setGraphAttr("rankdir", "LR");
63
+ .addNode("a")
64
+ .addNode("b")
65
+ .addEdge("a", "b")
66
+ .setNodeAttr("a", "shape", "box")
67
+ .setNodeAttr("a", "color", "red")
68
+ .setGraphAttr("rankdir", "LR");
60
69
 
61
70
  // Render directly — no DOT round-trip needed
62
71
  const svg = graph.layout("svg", "dot");
63
72
  document.body.innerHTML = svg;
64
73
  ```
65
74
 
75
+ ### One-shot JSON init objects
76
+
77
+ You can also create graphs, clusters, nodes, and edges from a single object
78
+ that includes their attributes.
79
+
80
+ ```typescript
81
+ using graph = graphviz.createGraph({
82
+ name: "G",
83
+ type: "directed",
84
+ attrs: { rankdir: "LR" }
85
+ });
86
+
87
+ {
88
+ using cluster = graph.addSubgraph({
89
+ name: "cluster_0",
90
+ attrs: { label: "Group A", style: "filled", color: "lightgrey" }
91
+ });
92
+
93
+ cluster.addNode({
94
+ name: "a",
95
+ attrs: { shape: "box", color: "red" },
96
+ htmlAttrs: { label: "<B>A</B>" }
97
+ });
98
+
99
+ cluster.addEdge({
100
+ tail: "a",
101
+ head: "b",
102
+ attrs: { label: "hello" }
103
+ });
104
+ }
105
+ ```
106
+
107
+ ```typescript
108
+ using graph = graphviz.read(`digraph G { a -> b [label="hello"] }`);
109
+ graph.setGraphAttr("rankdir", "LR");
110
+ const dot = graph.write();
111
+ ```
112
+
66
113
  ### Graph types
67
114
 
68
115
  ```typescript
@@ -89,14 +136,14 @@ const svg2 = graph.layout(); // updated render
89
136
 
90
137
  The full set of mutation methods on `Graph`:
91
138
 
92
- | Method | Effect |
93
- |---|---|
94
- | `removeNode(name)` | Removes the node and all its edges from the root graph |
95
- | `removeEdge(tail, head, key?)` | Removes a single edge |
96
- | `removeSubgraph(name)` | Dissolves a cluster boundary (nodes/edges remain in the root graph) |
97
- | `removeGraphAttr(attr)` | Resets a graph-level attribute to its default |
98
- | `removeNodeAttr(node, attr)` | Resets a node attribute to its default |
99
- | `removeEdgeAttr(tail, head, key, attr)` | Resets an edge attribute to its default |
139
+ | Method | Effect |
140
+ | --------------------------------------- | ------------------------------------------------------------------- |
141
+ | `removeNode(name)` | Removes the node and all its edges from the root graph |
142
+ | `removeEdge(tail, head, key?)` | Removes a single edge |
143
+ | `removeSubgraph(name)` | Dissolves a cluster boundary (nodes/edges remain in the root graph) |
144
+ | `removeGraphAttr(attr)` | Resets a graph-level attribute to its default |
145
+ | `removeNodeAttr(node, attr)` | Resets a node attribute to its default |
146
+ | `removeEdgeAttr(tail, head, key, attr)` | Resets an edge attribute to its default |
100
147
 
101
148
  `Subgraph` has the same `removeNode` / `removeEdge` pair (scoped to the
102
149
  subgraph only — root graph is unaffected) plus `removeAttr` /
@@ -115,19 +162,19 @@ graph.addNode("alice");
115
162
  graph.addEdge("alice", "bob");
116
163
  graph.addSubgraph("cluster_a");
117
164
 
118
- graph.hasNode("alice"); // true
119
- graph.hasNode("charlie"); // false
120
- graph.hasEdge("alice", "bob"); // true (key defaults to "")
121
- graph.hasEdge("bob", "alice"); // false (directed)
122
- graph.hasSubgraph("cluster_a"); // true
165
+ graph.hasNode("alice"); // true
166
+ graph.hasNode("charlie"); // false
167
+ graph.hasEdge("alice", "bob"); // true (key defaults to "")
168
+ graph.hasEdge("bob", "alice"); // false (directed)
169
+ graph.hasSubgraph("cluster_a"); // true
123
170
  ```
124
171
 
125
172
  #### Count queries
126
173
 
127
174
  ```typescript
128
- graph.nodeCount(); // number of nodes
129
- graph.edgeCount(); // number of edges
130
- graph.subgraphCount(); // number of direct subgraphs
175
+ graph.nodeCount(); // number of nodes
176
+ graph.edgeCount(); // number of edges
177
+ graph.subgraphCount(); // number of direct subgraphs
131
178
  ```
132
179
 
133
180
  #### Reading attributes
@@ -137,10 +184,26 @@ graph.setNodeAttr("alice", "color", "red");
137
184
  graph.setEdgeAttr("alice", "bob", "", "label", "hello");
138
185
  graph.setGraphAttr("rankdir", "LR");
139
186
 
140
- graph.getNodeAttr("alice", "color"); // "red"
187
+ graph.getNodeAttr("alice", "color"); // "red"
141
188
  graph.getEdgeAttr("alice", "bob", "", "label"); // "hello"
142
- graph.getGraphAttr("rankdir"); // "LR"
143
- graph.getNodeAttr("alice", "missing"); // "" (unknown attr)
189
+ graph.getGraphAttr("rankdir"); // "LR"
190
+ graph.getNodeAttr("alice", "missing"); // "" (unknown attr)
191
+
192
+ // Omit the value to reset an attribute to Graphviz's default empty value.
193
+ graph.setNodeAttr("alice", "color");
194
+ graph.getNodeAttr("alice", "color"); // ""
195
+
196
+ // Pass a final defaultValue argument to declare Graphviz's default for unset objects.
197
+ graph.addNode("charlie");
198
+ graph.setNodeAttr("alice", "color", "red", "blue");
199
+ graph.getNodeAttr("charlie", "color"); // "blue"
200
+
201
+ // Or declare defaults directly for graph, node, and edge attributes.
202
+ graph.setDefaultNodeAttr("shape", "box");
203
+ graph.setDefaultEdgeAttr("color", "red");
204
+
205
+ // Use HTML-like attributes for Graphviz HTML labels.
206
+ graph.setNodeHtmlAttr("alice", "label", "<B>Alice</B>");
144
207
  ```
145
208
 
146
209
  #### Node / edge / subgraph lists
@@ -151,9 +214,9 @@ const nodes = graph.nodeNames();
151
214
  const subgraphs = graph.subgraphNames();
152
215
 
153
216
  // Returns EdgeInfo[] — { tail: string, head: string, key: string }
154
- const allEdges = graph.edges(); // every edge exactly once
217
+ const allEdges = graph.edges(); // every edge exactly once
155
218
  const outgoing = graph.outEdges("alice"); // edges leaving alice
156
- const incoming = graph.inEdges("bob"); // edges entering bob
219
+ const incoming = graph.inEdges("bob"); // edges entering bob
157
220
  const incident = graph.nodeEdges("alice"); // all edges on alice (in + out)
158
221
  ```
159
222
 
@@ -171,12 +234,12 @@ using graph = graphviz.createGraph("G");
171
234
 
172
235
  // Each Subgraph wrapper also needs to be deleted (or use `using`)
173
236
  {
174
- using cluster = graph.addSubgraph("cluster_0");
175
- cluster
176
- .setAttr("label", "My Cluster")
177
- .setAttr("style", "filled")
178
- .setAttr("color", "lightblue")
179
- .addEdge("a", "b");
237
+ using cluster = graph.addSubgraph("cluster_0");
238
+ cluster
239
+ .setAttr("label", "My Cluster")
240
+ .setAttr("style", "filled")
241
+ .setAttr("color", "lightblue")
242
+ .addEdge("a", "b");
180
243
  }
181
244
 
182
245
  const svg = graph.layout();
@@ -184,14 +247,15 @@ const svg = graph.layout();
184
247
 
185
248
  ### Memory management
186
249
 
187
- Every `Graph` and `Subgraph` wraps a native WASM object. You must release it
250
+ Every `Graph` and `Subgraph` wraps a native WASM object. You must release it
188
251
  when finished to avoid memory leaks:
189
252
 
190
253
  - **Preferred — `using` keyword** (TypeScript ≥ 5.2 with `"target": "ES2022"` or later):
254
+
191
255
  ```typescript
192
256
  {
193
- using graph = graphviz.createGraph("G");
194
- // ... graph is automatically deleted when the block exits
257
+ using graph = graphviz.createGraph("G");
258
+ // ... graph is automatically deleted when the block exits
195
259
  }
196
260
  ```
197
261
 
@@ -199,13 +263,13 @@ when finished to avoid memory leaks:
199
263
  ```typescript
200
264
  const graph = graphviz.createGraph("G");
201
265
  try {
202
- // ...
266
+ // ...
203
267
  } finally {
204
- graph.delete();
268
+ graph.delete();
205
269
  }
206
270
  ```
207
271
 
208
- Subgraph wrappers follow the same rule. The underlying subgraph _data_ is
272
+ Subgraph wrappers follow the same rule. The underlying subgraph _data_ is
209
273
  owned by the parent `Graph` and freed automatically when the parent is deleted;
210
274
  only the thin JS wrapper needs an explicit `delete()` / `using` block.
211
275
 
@@ -213,4 +277,4 @@ only the thin JS wrapper needs an explicit `delete()` / `using` block.
213
277
 
214
278
  ## Reference
215
279
 
216
- * [API Documentation](https://hpcc-systems.github.io/hpcc-js-wasm/docs/graphviz/src/graphviz/classes/Graphviz.html)
280
+ - [API Documentation](https://hpcc-systems.github.io/hpcc-js-wasm/docs/graphviz/src/graphviz/classes/Graphviz.html)