@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 +107 -43
- package/dist/index.js +2 -2
- package/dist/index.js.map +3 -3
- package/package.json +4 -4
- package/src/graphviz.ts +387 -52
- package/src/types.ts +6 -0
- package/types/graphviz.d.ts +136 -27
- package/types/graphvizlib.d.ts +52 -0
- package/types/types.d.ts +3 -0
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.
|
|
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`.
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
|
93
|
-
|
|
94
|
-
| `removeNode(name)`
|
|
95
|
-
| `removeEdge(tail, head, key?)`
|
|
96
|
-
| `removeSubgraph(name)`
|
|
97
|
-
| `removeGraphAttr(attr)`
|
|
98
|
-
| `removeNodeAttr(node, attr)`
|
|
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");
|
|
119
|
-
graph.hasNode("charlie");
|
|
120
|
-
graph.hasEdge("alice", "bob");
|
|
121
|
-
graph.hasEdge("bob", "alice");
|
|
122
|
-
graph.hasSubgraph("cluster_a");
|
|
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();
|
|
129
|
-
graph.edgeCount();
|
|
130
|
-
graph.subgraphCount();
|
|
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");
|
|
187
|
+
graph.getNodeAttr("alice", "color"); // "red"
|
|
141
188
|
graph.getEdgeAttr("alice", "bob", "", "label"); // "hello"
|
|
142
|
-
graph.getGraphAttr("rankdir");
|
|
143
|
-
graph.getNodeAttr("alice", "missing");
|
|
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();
|
|
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");
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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.
|
|
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
|
-
|
|
194
|
-
|
|
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
|
-
|
|
268
|
+
graph.delete();
|
|
205
269
|
}
|
|
206
270
|
```
|
|
207
271
|
|
|
208
|
-
Subgraph wrappers follow the same rule.
|
|
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
|
-
|
|
280
|
+
- [API Documentation](https://hpcc-systems.github.io/hpcc-js-wasm/docs/graphviz/src/graphviz/classes/Graphviz.html)
|