@ogabrielluiz/patchflow 0.1.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/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/chunk-B7DUSPQH.js +42 -0
- package/dist/chunk-B7DUSPQH.js.map +1 -0
- package/dist/index.cjs +4702 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +4652 -0
- package/dist/index.js.map +1 -0
- package/dist/types.cjs +38 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +177 -0
- package/dist/types.d.ts +177 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,4702 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all)
|
|
13
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from))
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
31
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
|
+
|
|
33
|
+
// node_modules/@dagrejs/graphlib/lib/graph.js
|
|
34
|
+
var require_graph = __commonJS({
|
|
35
|
+
"node_modules/@dagrejs/graphlib/lib/graph.js"(exports2, module2) {
|
|
36
|
+
"use strict";
|
|
37
|
+
var DEFAULT_EDGE_NAME = "\0";
|
|
38
|
+
var GRAPH_NODE = "\0";
|
|
39
|
+
var EDGE_KEY_DELIM = "";
|
|
40
|
+
var Graph = class {
|
|
41
|
+
_isDirected = true;
|
|
42
|
+
_isMultigraph = false;
|
|
43
|
+
_isCompound = false;
|
|
44
|
+
// Label for the graph itself
|
|
45
|
+
_label;
|
|
46
|
+
// Defaults to be set when creating a new node
|
|
47
|
+
_defaultNodeLabelFn = () => void 0;
|
|
48
|
+
// Defaults to be set when creating a new edge
|
|
49
|
+
_defaultEdgeLabelFn = () => void 0;
|
|
50
|
+
// v -> label
|
|
51
|
+
_nodes = {};
|
|
52
|
+
// v -> edgeObj
|
|
53
|
+
_in = {};
|
|
54
|
+
// u -> v -> Number
|
|
55
|
+
_preds = {};
|
|
56
|
+
// v -> edgeObj
|
|
57
|
+
_out = {};
|
|
58
|
+
// v -> w -> Number
|
|
59
|
+
_sucs = {};
|
|
60
|
+
// e -> edgeObj
|
|
61
|
+
_edgeObjs = {};
|
|
62
|
+
// e -> label
|
|
63
|
+
_edgeLabels = {};
|
|
64
|
+
/* Number of nodes in the graph. Should only be changed by the implementation. */
|
|
65
|
+
_nodeCount = 0;
|
|
66
|
+
/* Number of edges in the graph. Should only be changed by the implementation. */
|
|
67
|
+
_edgeCount = 0;
|
|
68
|
+
_parent;
|
|
69
|
+
_children;
|
|
70
|
+
constructor(opts) {
|
|
71
|
+
if (opts) {
|
|
72
|
+
this._isDirected = Object.hasOwn(opts, "directed") ? opts.directed : true;
|
|
73
|
+
this._isMultigraph = Object.hasOwn(opts, "multigraph") ? opts.multigraph : false;
|
|
74
|
+
this._isCompound = Object.hasOwn(opts, "compound") ? opts.compound : false;
|
|
75
|
+
}
|
|
76
|
+
if (this._isCompound) {
|
|
77
|
+
this._parent = {};
|
|
78
|
+
this._children = {};
|
|
79
|
+
this._children[GRAPH_NODE] = {};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/* === Graph functions ========= */
|
|
83
|
+
/**
|
|
84
|
+
* Whether graph was created with 'directed' flag set to true or not.
|
|
85
|
+
*/
|
|
86
|
+
isDirected() {
|
|
87
|
+
return this._isDirected;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Whether graph was created with 'multigraph' flag set to true or not.
|
|
91
|
+
*/
|
|
92
|
+
isMultigraph() {
|
|
93
|
+
return this._isMultigraph;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Whether graph was created with 'compound' flag set to true or not.
|
|
97
|
+
*/
|
|
98
|
+
isCompound() {
|
|
99
|
+
return this._isCompound;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Sets the label of the graph.
|
|
103
|
+
*/
|
|
104
|
+
setGraph(label) {
|
|
105
|
+
this._label = label;
|
|
106
|
+
return this;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Gets the graph label.
|
|
110
|
+
*/
|
|
111
|
+
graph() {
|
|
112
|
+
return this._label;
|
|
113
|
+
}
|
|
114
|
+
/* === Node functions ========== */
|
|
115
|
+
/**
|
|
116
|
+
* Sets the default node label. If newDefault is a function, it will be
|
|
117
|
+
* invoked ach time when setting a label for a node. Otherwise, this label
|
|
118
|
+
* will be assigned as default label in case if no label was specified while
|
|
119
|
+
* setting a node.
|
|
120
|
+
* Complexity: O(1).
|
|
121
|
+
*/
|
|
122
|
+
setDefaultNodeLabel(newDefault) {
|
|
123
|
+
this._defaultNodeLabelFn = newDefault;
|
|
124
|
+
if (typeof newDefault !== "function") {
|
|
125
|
+
this._defaultNodeLabelFn = () => newDefault;
|
|
126
|
+
}
|
|
127
|
+
return this;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Gets the number of nodes in the graph.
|
|
131
|
+
* Complexity: O(1).
|
|
132
|
+
*/
|
|
133
|
+
nodeCount() {
|
|
134
|
+
return this._nodeCount;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Gets all nodes of the graph. Note, the in case of compound graph subnodes are
|
|
138
|
+
* not included in list.
|
|
139
|
+
* Complexity: O(1).
|
|
140
|
+
*/
|
|
141
|
+
nodes() {
|
|
142
|
+
return Object.keys(this._nodes);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Gets list of nodes without in-edges.
|
|
146
|
+
* Complexity: O(|V|).
|
|
147
|
+
*/
|
|
148
|
+
sources() {
|
|
149
|
+
var self = this;
|
|
150
|
+
return this.nodes().filter((v) => Object.keys(self._in[v]).length === 0);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Gets list of nodes without out-edges.
|
|
154
|
+
* Complexity: O(|V|).
|
|
155
|
+
*/
|
|
156
|
+
sinks() {
|
|
157
|
+
var self = this;
|
|
158
|
+
return this.nodes().filter((v) => Object.keys(self._out[v]).length === 0);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Invokes setNode method for each node in names list.
|
|
162
|
+
* Complexity: O(|names|).
|
|
163
|
+
*/
|
|
164
|
+
setNodes(vs, value) {
|
|
165
|
+
var args = arguments;
|
|
166
|
+
var self = this;
|
|
167
|
+
vs.forEach(function(v) {
|
|
168
|
+
if (args.length > 1) {
|
|
169
|
+
self.setNode(v, value);
|
|
170
|
+
} else {
|
|
171
|
+
self.setNode(v);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
return this;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Creates or updates the value for the node v in the graph. If label is supplied
|
|
178
|
+
* it is set as the value for the node. If label is not supplied and the node was
|
|
179
|
+
* created by this call then the default node label will be assigned.
|
|
180
|
+
* Complexity: O(1).
|
|
181
|
+
*/
|
|
182
|
+
setNode(v, value) {
|
|
183
|
+
if (Object.hasOwn(this._nodes, v)) {
|
|
184
|
+
if (arguments.length > 1) {
|
|
185
|
+
this._nodes[v] = value;
|
|
186
|
+
}
|
|
187
|
+
return this;
|
|
188
|
+
}
|
|
189
|
+
this._nodes[v] = arguments.length > 1 ? value : this._defaultNodeLabelFn(v);
|
|
190
|
+
if (this._isCompound) {
|
|
191
|
+
this._parent[v] = GRAPH_NODE;
|
|
192
|
+
this._children[v] = {};
|
|
193
|
+
this._children[GRAPH_NODE][v] = true;
|
|
194
|
+
}
|
|
195
|
+
this._in[v] = {};
|
|
196
|
+
this._preds[v] = {};
|
|
197
|
+
this._out[v] = {};
|
|
198
|
+
this._sucs[v] = {};
|
|
199
|
+
++this._nodeCount;
|
|
200
|
+
return this;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Gets the label of node with specified name.
|
|
204
|
+
* Complexity: O(|V|).
|
|
205
|
+
*/
|
|
206
|
+
node(v) {
|
|
207
|
+
return this._nodes[v];
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Detects whether graph has a node with specified name or not.
|
|
211
|
+
*/
|
|
212
|
+
hasNode(v) {
|
|
213
|
+
return Object.hasOwn(this._nodes, v);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Remove the node with the name from the graph or do nothing if the node is not in
|
|
217
|
+
* the graph. If the node was removed this function also removes any incident
|
|
218
|
+
* edges.
|
|
219
|
+
* Complexity: O(1).
|
|
220
|
+
*/
|
|
221
|
+
removeNode(v) {
|
|
222
|
+
var self = this;
|
|
223
|
+
if (Object.hasOwn(this._nodes, v)) {
|
|
224
|
+
var removeEdge = (e) => self.removeEdge(self._edgeObjs[e]);
|
|
225
|
+
delete this._nodes[v];
|
|
226
|
+
if (this._isCompound) {
|
|
227
|
+
this._removeFromParentsChildList(v);
|
|
228
|
+
delete this._parent[v];
|
|
229
|
+
this.children(v).forEach(function(child) {
|
|
230
|
+
self.setParent(child);
|
|
231
|
+
});
|
|
232
|
+
delete this._children[v];
|
|
233
|
+
}
|
|
234
|
+
Object.keys(this._in[v]).forEach(removeEdge);
|
|
235
|
+
delete this._in[v];
|
|
236
|
+
delete this._preds[v];
|
|
237
|
+
Object.keys(this._out[v]).forEach(removeEdge);
|
|
238
|
+
delete this._out[v];
|
|
239
|
+
delete this._sucs[v];
|
|
240
|
+
--this._nodeCount;
|
|
241
|
+
}
|
|
242
|
+
return this;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Sets node p as a parent for node v if it is defined, or removes the
|
|
246
|
+
* parent for v if p is undefined. Method throws an exception in case of
|
|
247
|
+
* invoking it in context of noncompound graph.
|
|
248
|
+
* Average-case complexity: O(1).
|
|
249
|
+
*/
|
|
250
|
+
setParent(v, parent) {
|
|
251
|
+
if (!this._isCompound) {
|
|
252
|
+
throw new Error("Cannot set parent in a non-compound graph");
|
|
253
|
+
}
|
|
254
|
+
if (parent === void 0) {
|
|
255
|
+
parent = GRAPH_NODE;
|
|
256
|
+
} else {
|
|
257
|
+
parent += "";
|
|
258
|
+
for (var ancestor = parent; ancestor !== void 0; ancestor = this.parent(ancestor)) {
|
|
259
|
+
if (ancestor === v) {
|
|
260
|
+
throw new Error("Setting " + parent + " as parent of " + v + " would create a cycle");
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
this.setNode(parent);
|
|
264
|
+
}
|
|
265
|
+
this.setNode(v);
|
|
266
|
+
this._removeFromParentsChildList(v);
|
|
267
|
+
this._parent[v] = parent;
|
|
268
|
+
this._children[parent][v] = true;
|
|
269
|
+
return this;
|
|
270
|
+
}
|
|
271
|
+
_removeFromParentsChildList(v) {
|
|
272
|
+
delete this._children[this._parent[v]][v];
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Gets parent node for node v.
|
|
276
|
+
* Complexity: O(1).
|
|
277
|
+
*/
|
|
278
|
+
parent(v) {
|
|
279
|
+
if (this._isCompound) {
|
|
280
|
+
var parent = this._parent[v];
|
|
281
|
+
if (parent !== GRAPH_NODE) {
|
|
282
|
+
return parent;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Gets list of direct children of node v.
|
|
288
|
+
* Complexity: O(1).
|
|
289
|
+
*/
|
|
290
|
+
children(v = GRAPH_NODE) {
|
|
291
|
+
if (this._isCompound) {
|
|
292
|
+
var children = this._children[v];
|
|
293
|
+
if (children) {
|
|
294
|
+
return Object.keys(children);
|
|
295
|
+
}
|
|
296
|
+
} else if (v === GRAPH_NODE) {
|
|
297
|
+
return this.nodes();
|
|
298
|
+
} else if (this.hasNode(v)) {
|
|
299
|
+
return [];
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Return all nodes that are predecessors of the specified node or undefined if node v is not in
|
|
304
|
+
* the graph. Behavior is undefined for undirected graphs - use neighbors instead.
|
|
305
|
+
* Complexity: O(|V|).
|
|
306
|
+
*/
|
|
307
|
+
predecessors(v) {
|
|
308
|
+
var predsV = this._preds[v];
|
|
309
|
+
if (predsV) {
|
|
310
|
+
return Object.keys(predsV);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Return all nodes that are successors of the specified node or undefined if node v is not in
|
|
315
|
+
* the graph. Behavior is undefined for undirected graphs - use neighbors instead.
|
|
316
|
+
* Complexity: O(|V|).
|
|
317
|
+
*/
|
|
318
|
+
successors(v) {
|
|
319
|
+
var sucsV = this._sucs[v];
|
|
320
|
+
if (sucsV) {
|
|
321
|
+
return Object.keys(sucsV);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Return all nodes that are predecessors or successors of the specified node or undefined if
|
|
326
|
+
* node v is not in the graph.
|
|
327
|
+
* Complexity: O(|V|).
|
|
328
|
+
*/
|
|
329
|
+
neighbors(v) {
|
|
330
|
+
var preds = this.predecessors(v);
|
|
331
|
+
if (preds) {
|
|
332
|
+
const union = new Set(preds);
|
|
333
|
+
for (var succ of this.successors(v)) {
|
|
334
|
+
union.add(succ);
|
|
335
|
+
}
|
|
336
|
+
return Array.from(union.values());
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
isLeaf(v) {
|
|
340
|
+
var neighbors;
|
|
341
|
+
if (this.isDirected()) {
|
|
342
|
+
neighbors = this.successors(v);
|
|
343
|
+
} else {
|
|
344
|
+
neighbors = this.neighbors(v);
|
|
345
|
+
}
|
|
346
|
+
return neighbors.length === 0;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Creates new graph with nodes filtered via filter. Edges incident to rejected node
|
|
350
|
+
* are also removed. In case of compound graph, if parent is rejected by filter,
|
|
351
|
+
* than all its children are rejected too.
|
|
352
|
+
* Average-case complexity: O(|E|+|V|).
|
|
353
|
+
*/
|
|
354
|
+
filterNodes(filter) {
|
|
355
|
+
var copy = new this.constructor({
|
|
356
|
+
directed: this._isDirected,
|
|
357
|
+
multigraph: this._isMultigraph,
|
|
358
|
+
compound: this._isCompound
|
|
359
|
+
});
|
|
360
|
+
copy.setGraph(this.graph());
|
|
361
|
+
var self = this;
|
|
362
|
+
Object.entries(this._nodes).forEach(function([v, value]) {
|
|
363
|
+
if (filter(v)) {
|
|
364
|
+
copy.setNode(v, value);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
Object.values(this._edgeObjs).forEach(function(e) {
|
|
368
|
+
if (copy.hasNode(e.v) && copy.hasNode(e.w)) {
|
|
369
|
+
copy.setEdge(e, self.edge(e));
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
var parents = {};
|
|
373
|
+
function findParent(v) {
|
|
374
|
+
var parent = self.parent(v);
|
|
375
|
+
if (parent === void 0 || copy.hasNode(parent)) {
|
|
376
|
+
parents[v] = parent;
|
|
377
|
+
return parent;
|
|
378
|
+
} else if (parent in parents) {
|
|
379
|
+
return parents[parent];
|
|
380
|
+
} else {
|
|
381
|
+
return findParent(parent);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (this._isCompound) {
|
|
385
|
+
copy.nodes().forEach((v) => copy.setParent(v, findParent(v)));
|
|
386
|
+
}
|
|
387
|
+
return copy;
|
|
388
|
+
}
|
|
389
|
+
/* === Edge functions ========== */
|
|
390
|
+
/**
|
|
391
|
+
* Sets the default edge label or factory function. This label will be
|
|
392
|
+
* assigned as default label in case if no label was specified while setting
|
|
393
|
+
* an edge or this function will be invoked each time when setting an edge
|
|
394
|
+
* with no label specified and returned value * will be used as a label for edge.
|
|
395
|
+
* Complexity: O(1).
|
|
396
|
+
*/
|
|
397
|
+
setDefaultEdgeLabel(newDefault) {
|
|
398
|
+
this._defaultEdgeLabelFn = newDefault;
|
|
399
|
+
if (typeof newDefault !== "function") {
|
|
400
|
+
this._defaultEdgeLabelFn = () => newDefault;
|
|
401
|
+
}
|
|
402
|
+
return this;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Gets the number of edges in the graph.
|
|
406
|
+
* Complexity: O(1).
|
|
407
|
+
*/
|
|
408
|
+
edgeCount() {
|
|
409
|
+
return this._edgeCount;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Gets edges of the graph. In case of compound graph subgraphs are not considered.
|
|
413
|
+
* Complexity: O(|E|).
|
|
414
|
+
*/
|
|
415
|
+
edges() {
|
|
416
|
+
return Object.values(this._edgeObjs);
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Establish an edges path over the nodes in nodes list. If some edge is already
|
|
420
|
+
* exists, it will update its label, otherwise it will create an edge between pair
|
|
421
|
+
* of nodes with label provided or default label if no label provided.
|
|
422
|
+
* Complexity: O(|nodes|).
|
|
423
|
+
*/
|
|
424
|
+
setPath(vs, value) {
|
|
425
|
+
var self = this;
|
|
426
|
+
var args = arguments;
|
|
427
|
+
vs.reduce(function(v, w) {
|
|
428
|
+
if (args.length > 1) {
|
|
429
|
+
self.setEdge(v, w, value);
|
|
430
|
+
} else {
|
|
431
|
+
self.setEdge(v, w);
|
|
432
|
+
}
|
|
433
|
+
return w;
|
|
434
|
+
});
|
|
435
|
+
return this;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Creates or updates the label for the edge (v, w) with the optionally supplied
|
|
439
|
+
* name. If label is supplied it is set as the value for the edge. If label is not
|
|
440
|
+
* supplied and the edge was created by this call then the default edge label will
|
|
441
|
+
* be assigned. The name parameter is only useful with multigraphs.
|
|
442
|
+
*/
|
|
443
|
+
setEdge() {
|
|
444
|
+
var v, w, name, value;
|
|
445
|
+
var valueSpecified = false;
|
|
446
|
+
var arg0 = arguments[0];
|
|
447
|
+
if (typeof arg0 === "object" && arg0 !== null && "v" in arg0) {
|
|
448
|
+
v = arg0.v;
|
|
449
|
+
w = arg0.w;
|
|
450
|
+
name = arg0.name;
|
|
451
|
+
if (arguments.length === 2) {
|
|
452
|
+
value = arguments[1];
|
|
453
|
+
valueSpecified = true;
|
|
454
|
+
}
|
|
455
|
+
} else {
|
|
456
|
+
v = arg0;
|
|
457
|
+
w = arguments[1];
|
|
458
|
+
name = arguments[3];
|
|
459
|
+
if (arguments.length > 2) {
|
|
460
|
+
value = arguments[2];
|
|
461
|
+
valueSpecified = true;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
v = "" + v;
|
|
465
|
+
w = "" + w;
|
|
466
|
+
if (name !== void 0) {
|
|
467
|
+
name = "" + name;
|
|
468
|
+
}
|
|
469
|
+
var e = edgeArgsToId(this._isDirected, v, w, name);
|
|
470
|
+
if (Object.hasOwn(this._edgeLabels, e)) {
|
|
471
|
+
if (valueSpecified) {
|
|
472
|
+
this._edgeLabels[e] = value;
|
|
473
|
+
}
|
|
474
|
+
return this;
|
|
475
|
+
}
|
|
476
|
+
if (name !== void 0 && !this._isMultigraph) {
|
|
477
|
+
throw new Error("Cannot set a named edge when isMultigraph = false");
|
|
478
|
+
}
|
|
479
|
+
this.setNode(v);
|
|
480
|
+
this.setNode(w);
|
|
481
|
+
this._edgeLabels[e] = valueSpecified ? value : this._defaultEdgeLabelFn(v, w, name);
|
|
482
|
+
var edgeObj = edgeArgsToObj(this._isDirected, v, w, name);
|
|
483
|
+
v = edgeObj.v;
|
|
484
|
+
w = edgeObj.w;
|
|
485
|
+
Object.freeze(edgeObj);
|
|
486
|
+
this._edgeObjs[e] = edgeObj;
|
|
487
|
+
incrementOrInitEntry(this._preds[w], v);
|
|
488
|
+
incrementOrInitEntry(this._sucs[v], w);
|
|
489
|
+
this._in[w][e] = edgeObj;
|
|
490
|
+
this._out[v][e] = edgeObj;
|
|
491
|
+
this._edgeCount++;
|
|
492
|
+
return this;
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Gets the label for the specified edge.
|
|
496
|
+
* Complexity: O(1).
|
|
497
|
+
*/
|
|
498
|
+
edge(v, w, name) {
|
|
499
|
+
var e = arguments.length === 1 ? edgeObjToId(this._isDirected, arguments[0]) : edgeArgsToId(this._isDirected, v, w, name);
|
|
500
|
+
return this._edgeLabels[e];
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Gets the label for the specified edge and converts it to an object.
|
|
504
|
+
* Complexity: O(1)
|
|
505
|
+
*/
|
|
506
|
+
edgeAsObj() {
|
|
507
|
+
const edge = this.edge(...arguments);
|
|
508
|
+
if (typeof edge !== "object") {
|
|
509
|
+
return { label: edge };
|
|
510
|
+
}
|
|
511
|
+
return edge;
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Detects whether the graph contains specified edge or not. No subgraphs are considered.
|
|
515
|
+
* Complexity: O(1).
|
|
516
|
+
*/
|
|
517
|
+
hasEdge(v, w, name) {
|
|
518
|
+
var e = arguments.length === 1 ? edgeObjToId(this._isDirected, arguments[0]) : edgeArgsToId(this._isDirected, v, w, name);
|
|
519
|
+
return Object.hasOwn(this._edgeLabels, e);
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Removes the specified edge from the graph. No subgraphs are considered.
|
|
523
|
+
* Complexity: O(1).
|
|
524
|
+
*/
|
|
525
|
+
removeEdge(v, w, name) {
|
|
526
|
+
var e = arguments.length === 1 ? edgeObjToId(this._isDirected, arguments[0]) : edgeArgsToId(this._isDirected, v, w, name);
|
|
527
|
+
var edge = this._edgeObjs[e];
|
|
528
|
+
if (edge) {
|
|
529
|
+
v = edge.v;
|
|
530
|
+
w = edge.w;
|
|
531
|
+
delete this._edgeLabels[e];
|
|
532
|
+
delete this._edgeObjs[e];
|
|
533
|
+
decrementOrRemoveEntry(this._preds[w], v);
|
|
534
|
+
decrementOrRemoveEntry(this._sucs[v], w);
|
|
535
|
+
delete this._in[w][e];
|
|
536
|
+
delete this._out[v][e];
|
|
537
|
+
this._edgeCount--;
|
|
538
|
+
}
|
|
539
|
+
return this;
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Return all edges that point to the node v. Optionally filters those edges down to just those
|
|
543
|
+
* coming from node u. Behavior is undefined for undirected graphs - use nodeEdges instead.
|
|
544
|
+
* Complexity: O(|E|).
|
|
545
|
+
*/
|
|
546
|
+
inEdges(v, u) {
|
|
547
|
+
var inV = this._in[v];
|
|
548
|
+
if (inV) {
|
|
549
|
+
var edges = Object.values(inV);
|
|
550
|
+
if (!u) {
|
|
551
|
+
return edges;
|
|
552
|
+
}
|
|
553
|
+
return edges.filter((edge) => edge.v === u);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Return all edges that are pointed at by node v. Optionally filters those edges down to just
|
|
558
|
+
* those point to w. Behavior is undefined for undirected graphs - use nodeEdges instead.
|
|
559
|
+
* Complexity: O(|E|).
|
|
560
|
+
*/
|
|
561
|
+
outEdges(v, w) {
|
|
562
|
+
var outV = this._out[v];
|
|
563
|
+
if (outV) {
|
|
564
|
+
var edges = Object.values(outV);
|
|
565
|
+
if (!w) {
|
|
566
|
+
return edges;
|
|
567
|
+
}
|
|
568
|
+
return edges.filter((edge) => edge.w === w);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Returns all edges to or from node v regardless of direction. Optionally filters those edges
|
|
573
|
+
* down to just those between nodes v and w regardless of direction.
|
|
574
|
+
* Complexity: O(|E|).
|
|
575
|
+
*/
|
|
576
|
+
nodeEdges(v, w) {
|
|
577
|
+
var inEdges = this.inEdges(v, w);
|
|
578
|
+
if (inEdges) {
|
|
579
|
+
return inEdges.concat(this.outEdges(v, w));
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
function incrementOrInitEntry(map, k) {
|
|
584
|
+
if (map[k]) {
|
|
585
|
+
map[k]++;
|
|
586
|
+
} else {
|
|
587
|
+
map[k] = 1;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
function decrementOrRemoveEntry(map, k) {
|
|
591
|
+
if (!--map[k]) {
|
|
592
|
+
delete map[k];
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
function edgeArgsToId(isDirected, v_, w_, name) {
|
|
596
|
+
var v = "" + v_;
|
|
597
|
+
var w = "" + w_;
|
|
598
|
+
if (!isDirected && v > w) {
|
|
599
|
+
var tmp = v;
|
|
600
|
+
v = w;
|
|
601
|
+
w = tmp;
|
|
602
|
+
}
|
|
603
|
+
return v + EDGE_KEY_DELIM + w + EDGE_KEY_DELIM + (name === void 0 ? DEFAULT_EDGE_NAME : name);
|
|
604
|
+
}
|
|
605
|
+
function edgeArgsToObj(isDirected, v_, w_, name) {
|
|
606
|
+
var v = "" + v_;
|
|
607
|
+
var w = "" + w_;
|
|
608
|
+
if (!isDirected && v > w) {
|
|
609
|
+
var tmp = v;
|
|
610
|
+
v = w;
|
|
611
|
+
w = tmp;
|
|
612
|
+
}
|
|
613
|
+
var edgeObj = { v, w };
|
|
614
|
+
if (name) {
|
|
615
|
+
edgeObj.name = name;
|
|
616
|
+
}
|
|
617
|
+
return edgeObj;
|
|
618
|
+
}
|
|
619
|
+
function edgeObjToId(isDirected, edgeObj) {
|
|
620
|
+
return edgeArgsToId(isDirected, edgeObj.v, edgeObj.w, edgeObj.name);
|
|
621
|
+
}
|
|
622
|
+
module2.exports = Graph;
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
// node_modules/@dagrejs/graphlib/lib/version.js
|
|
627
|
+
var require_version = __commonJS({
|
|
628
|
+
"node_modules/@dagrejs/graphlib/lib/version.js"(exports2, module2) {
|
|
629
|
+
"use strict";
|
|
630
|
+
module2.exports = "2.2.4";
|
|
631
|
+
}
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
// node_modules/@dagrejs/graphlib/lib/index.js
|
|
635
|
+
var require_lib = __commonJS({
|
|
636
|
+
"node_modules/@dagrejs/graphlib/lib/index.js"(exports2, module2) {
|
|
637
|
+
"use strict";
|
|
638
|
+
module2.exports = {
|
|
639
|
+
Graph: require_graph(),
|
|
640
|
+
version: require_version()
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
// node_modules/@dagrejs/graphlib/lib/json.js
|
|
646
|
+
var require_json = __commonJS({
|
|
647
|
+
"node_modules/@dagrejs/graphlib/lib/json.js"(exports2, module2) {
|
|
648
|
+
"use strict";
|
|
649
|
+
var Graph = require_graph();
|
|
650
|
+
module2.exports = {
|
|
651
|
+
write,
|
|
652
|
+
read
|
|
653
|
+
};
|
|
654
|
+
function write(g) {
|
|
655
|
+
var json = {
|
|
656
|
+
options: {
|
|
657
|
+
directed: g.isDirected(),
|
|
658
|
+
multigraph: g.isMultigraph(),
|
|
659
|
+
compound: g.isCompound()
|
|
660
|
+
},
|
|
661
|
+
nodes: writeNodes(g),
|
|
662
|
+
edges: writeEdges(g)
|
|
663
|
+
};
|
|
664
|
+
if (g.graph() !== void 0) {
|
|
665
|
+
json.value = structuredClone(g.graph());
|
|
666
|
+
}
|
|
667
|
+
return json;
|
|
668
|
+
}
|
|
669
|
+
function writeNodes(g) {
|
|
670
|
+
return g.nodes().map(function(v) {
|
|
671
|
+
var nodeValue = g.node(v);
|
|
672
|
+
var parent = g.parent(v);
|
|
673
|
+
var node = { v };
|
|
674
|
+
if (nodeValue !== void 0) {
|
|
675
|
+
node.value = nodeValue;
|
|
676
|
+
}
|
|
677
|
+
if (parent !== void 0) {
|
|
678
|
+
node.parent = parent;
|
|
679
|
+
}
|
|
680
|
+
return node;
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
function writeEdges(g) {
|
|
684
|
+
return g.edges().map(function(e) {
|
|
685
|
+
var edgeValue = g.edge(e);
|
|
686
|
+
var edge = { v: e.v, w: e.w };
|
|
687
|
+
if (e.name !== void 0) {
|
|
688
|
+
edge.name = e.name;
|
|
689
|
+
}
|
|
690
|
+
if (edgeValue !== void 0) {
|
|
691
|
+
edge.value = edgeValue;
|
|
692
|
+
}
|
|
693
|
+
return edge;
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
function read(json) {
|
|
697
|
+
var g = new Graph(json.options).setGraph(json.value);
|
|
698
|
+
json.nodes.forEach(function(entry) {
|
|
699
|
+
g.setNode(entry.v, entry.value);
|
|
700
|
+
if (entry.parent) {
|
|
701
|
+
g.setParent(entry.v, entry.parent);
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
json.edges.forEach(function(entry) {
|
|
705
|
+
g.setEdge({ v: entry.v, w: entry.w, name: entry.name }, entry.value);
|
|
706
|
+
});
|
|
707
|
+
return g;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
// node_modules/@dagrejs/graphlib/lib/alg/components.js
|
|
713
|
+
var require_components = __commonJS({
|
|
714
|
+
"node_modules/@dagrejs/graphlib/lib/alg/components.js"(exports2, module2) {
|
|
715
|
+
"use strict";
|
|
716
|
+
module2.exports = components;
|
|
717
|
+
function components(g) {
|
|
718
|
+
var visited = {};
|
|
719
|
+
var cmpts = [];
|
|
720
|
+
var cmpt;
|
|
721
|
+
function dfs(v) {
|
|
722
|
+
if (Object.hasOwn(visited, v)) return;
|
|
723
|
+
visited[v] = true;
|
|
724
|
+
cmpt.push(v);
|
|
725
|
+
g.successors(v).forEach(dfs);
|
|
726
|
+
g.predecessors(v).forEach(dfs);
|
|
727
|
+
}
|
|
728
|
+
g.nodes().forEach(function(v) {
|
|
729
|
+
cmpt = [];
|
|
730
|
+
dfs(v);
|
|
731
|
+
if (cmpt.length) {
|
|
732
|
+
cmpts.push(cmpt);
|
|
733
|
+
}
|
|
734
|
+
});
|
|
735
|
+
return cmpts;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
// node_modules/@dagrejs/graphlib/lib/data/priority-queue.js
|
|
741
|
+
var require_priority_queue = __commonJS({
|
|
742
|
+
"node_modules/@dagrejs/graphlib/lib/data/priority-queue.js"(exports2, module2) {
|
|
743
|
+
"use strict";
|
|
744
|
+
var PriorityQueue = class {
|
|
745
|
+
_arr = [];
|
|
746
|
+
_keyIndices = {};
|
|
747
|
+
/**
|
|
748
|
+
* Returns the number of elements in the queue. Takes `O(1)` time.
|
|
749
|
+
*/
|
|
750
|
+
size() {
|
|
751
|
+
return this._arr.length;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Returns the keys that are in the queue. Takes `O(n)` time.
|
|
755
|
+
*/
|
|
756
|
+
keys() {
|
|
757
|
+
return this._arr.map(function(x) {
|
|
758
|
+
return x.key;
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Returns `true` if **key** is in the queue and `false` if not.
|
|
763
|
+
*/
|
|
764
|
+
has(key) {
|
|
765
|
+
return Object.hasOwn(this._keyIndices, key);
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Returns the priority for **key**. If **key** is not present in the queue
|
|
769
|
+
* then this function returns `undefined`. Takes `O(1)` time.
|
|
770
|
+
*
|
|
771
|
+
* @param {Object} key
|
|
772
|
+
*/
|
|
773
|
+
priority(key) {
|
|
774
|
+
var index = this._keyIndices[key];
|
|
775
|
+
if (index !== void 0) {
|
|
776
|
+
return this._arr[index].priority;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Returns the key for the minimum element in this queue. If the queue is
|
|
781
|
+
* empty this function throws an Error. Takes `O(1)` time.
|
|
782
|
+
*/
|
|
783
|
+
min() {
|
|
784
|
+
if (this.size() === 0) {
|
|
785
|
+
throw new Error("Queue underflow");
|
|
786
|
+
}
|
|
787
|
+
return this._arr[0].key;
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Inserts a new key into the priority queue. If the key already exists in
|
|
791
|
+
* the queue this function returns `false`; otherwise it will return `true`.
|
|
792
|
+
* Takes `O(n)` time.
|
|
793
|
+
*
|
|
794
|
+
* @param {Object} key the key to add
|
|
795
|
+
* @param {Number} priority the initial priority for the key
|
|
796
|
+
*/
|
|
797
|
+
add(key, priority) {
|
|
798
|
+
var keyIndices = this._keyIndices;
|
|
799
|
+
key = String(key);
|
|
800
|
+
if (!Object.hasOwn(keyIndices, key)) {
|
|
801
|
+
var arr = this._arr;
|
|
802
|
+
var index = arr.length;
|
|
803
|
+
keyIndices[key] = index;
|
|
804
|
+
arr.push({ key, priority });
|
|
805
|
+
this._decrease(index);
|
|
806
|
+
return true;
|
|
807
|
+
}
|
|
808
|
+
return false;
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Removes and returns the smallest key in the queue. Takes `O(log n)` time.
|
|
812
|
+
*/
|
|
813
|
+
removeMin() {
|
|
814
|
+
this._swap(0, this._arr.length - 1);
|
|
815
|
+
var min = this._arr.pop();
|
|
816
|
+
delete this._keyIndices[min.key];
|
|
817
|
+
this._heapify(0);
|
|
818
|
+
return min.key;
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Decreases the priority for **key** to **priority**. If the new priority is
|
|
822
|
+
* greater than the previous priority, this function will throw an Error.
|
|
823
|
+
*
|
|
824
|
+
* @param {Object} key the key for which to raise priority
|
|
825
|
+
* @param {Number} priority the new priority for the key
|
|
826
|
+
*/
|
|
827
|
+
decrease(key, priority) {
|
|
828
|
+
var index = this._keyIndices[key];
|
|
829
|
+
if (priority > this._arr[index].priority) {
|
|
830
|
+
throw new Error("New priority is greater than current priority. Key: " + key + " Old: " + this._arr[index].priority + " New: " + priority);
|
|
831
|
+
}
|
|
832
|
+
this._arr[index].priority = priority;
|
|
833
|
+
this._decrease(index);
|
|
834
|
+
}
|
|
835
|
+
_heapify(i) {
|
|
836
|
+
var arr = this._arr;
|
|
837
|
+
var l = 2 * i;
|
|
838
|
+
var r = l + 1;
|
|
839
|
+
var largest = i;
|
|
840
|
+
if (l < arr.length) {
|
|
841
|
+
largest = arr[l].priority < arr[largest].priority ? l : largest;
|
|
842
|
+
if (r < arr.length) {
|
|
843
|
+
largest = arr[r].priority < arr[largest].priority ? r : largest;
|
|
844
|
+
}
|
|
845
|
+
if (largest !== i) {
|
|
846
|
+
this._swap(i, largest);
|
|
847
|
+
this._heapify(largest);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
_decrease(index) {
|
|
852
|
+
var arr = this._arr;
|
|
853
|
+
var priority = arr[index].priority;
|
|
854
|
+
var parent;
|
|
855
|
+
while (index !== 0) {
|
|
856
|
+
parent = index >> 1;
|
|
857
|
+
if (arr[parent].priority < priority) {
|
|
858
|
+
break;
|
|
859
|
+
}
|
|
860
|
+
this._swap(index, parent);
|
|
861
|
+
index = parent;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
_swap(i, j) {
|
|
865
|
+
var arr = this._arr;
|
|
866
|
+
var keyIndices = this._keyIndices;
|
|
867
|
+
var origArrI = arr[i];
|
|
868
|
+
var origArrJ = arr[j];
|
|
869
|
+
arr[i] = origArrJ;
|
|
870
|
+
arr[j] = origArrI;
|
|
871
|
+
keyIndices[origArrJ.key] = i;
|
|
872
|
+
keyIndices[origArrI.key] = j;
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
module2.exports = PriorityQueue;
|
|
876
|
+
}
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
// node_modules/@dagrejs/graphlib/lib/alg/dijkstra.js
|
|
880
|
+
var require_dijkstra = __commonJS({
|
|
881
|
+
"node_modules/@dagrejs/graphlib/lib/alg/dijkstra.js"(exports2, module2) {
|
|
882
|
+
"use strict";
|
|
883
|
+
var PriorityQueue = require_priority_queue();
|
|
884
|
+
module2.exports = dijkstra;
|
|
885
|
+
var DEFAULT_WEIGHT_FUNC = () => 1;
|
|
886
|
+
function dijkstra(g, source, weightFn, edgeFn) {
|
|
887
|
+
return runDijkstra(
|
|
888
|
+
g,
|
|
889
|
+
String(source),
|
|
890
|
+
weightFn || DEFAULT_WEIGHT_FUNC,
|
|
891
|
+
edgeFn || function(v) {
|
|
892
|
+
return g.outEdges(v);
|
|
893
|
+
}
|
|
894
|
+
);
|
|
895
|
+
}
|
|
896
|
+
function runDijkstra(g, source, weightFn, edgeFn) {
|
|
897
|
+
var results = {};
|
|
898
|
+
var pq = new PriorityQueue();
|
|
899
|
+
var v, vEntry;
|
|
900
|
+
var updateNeighbors = function(edge) {
|
|
901
|
+
var w = edge.v !== v ? edge.v : edge.w;
|
|
902
|
+
var wEntry = results[w];
|
|
903
|
+
var weight = weightFn(edge);
|
|
904
|
+
var distance = vEntry.distance + weight;
|
|
905
|
+
if (weight < 0) {
|
|
906
|
+
throw new Error("dijkstra does not allow negative edge weights. Bad edge: " + edge + " Weight: " + weight);
|
|
907
|
+
}
|
|
908
|
+
if (distance < wEntry.distance) {
|
|
909
|
+
wEntry.distance = distance;
|
|
910
|
+
wEntry.predecessor = v;
|
|
911
|
+
pq.decrease(w, distance);
|
|
912
|
+
}
|
|
913
|
+
};
|
|
914
|
+
g.nodes().forEach(function(v2) {
|
|
915
|
+
var distance = v2 === source ? 0 : Number.POSITIVE_INFINITY;
|
|
916
|
+
results[v2] = { distance };
|
|
917
|
+
pq.add(v2, distance);
|
|
918
|
+
});
|
|
919
|
+
while (pq.size() > 0) {
|
|
920
|
+
v = pq.removeMin();
|
|
921
|
+
vEntry = results[v];
|
|
922
|
+
if (vEntry.distance === Number.POSITIVE_INFINITY) {
|
|
923
|
+
break;
|
|
924
|
+
}
|
|
925
|
+
edgeFn(v).forEach(updateNeighbors);
|
|
926
|
+
}
|
|
927
|
+
return results;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
});
|
|
931
|
+
|
|
932
|
+
// node_modules/@dagrejs/graphlib/lib/alg/dijkstra-all.js
|
|
933
|
+
var require_dijkstra_all = __commonJS({
|
|
934
|
+
"node_modules/@dagrejs/graphlib/lib/alg/dijkstra-all.js"(exports2, module2) {
|
|
935
|
+
"use strict";
|
|
936
|
+
var dijkstra = require_dijkstra();
|
|
937
|
+
module2.exports = dijkstraAll;
|
|
938
|
+
function dijkstraAll(g, weightFunc, edgeFunc) {
|
|
939
|
+
return g.nodes().reduce(function(acc, v) {
|
|
940
|
+
acc[v] = dijkstra(g, v, weightFunc, edgeFunc);
|
|
941
|
+
return acc;
|
|
942
|
+
}, {});
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
// node_modules/@dagrejs/graphlib/lib/alg/tarjan.js
|
|
948
|
+
var require_tarjan = __commonJS({
|
|
949
|
+
"node_modules/@dagrejs/graphlib/lib/alg/tarjan.js"(exports2, module2) {
|
|
950
|
+
"use strict";
|
|
951
|
+
module2.exports = tarjan;
|
|
952
|
+
function tarjan(g) {
|
|
953
|
+
var index = 0;
|
|
954
|
+
var stack = [];
|
|
955
|
+
var visited = {};
|
|
956
|
+
var results = [];
|
|
957
|
+
function dfs(v) {
|
|
958
|
+
var entry = visited[v] = {
|
|
959
|
+
onStack: true,
|
|
960
|
+
lowlink: index,
|
|
961
|
+
index: index++
|
|
962
|
+
};
|
|
963
|
+
stack.push(v);
|
|
964
|
+
g.successors(v).forEach(function(w2) {
|
|
965
|
+
if (!Object.hasOwn(visited, w2)) {
|
|
966
|
+
dfs(w2);
|
|
967
|
+
entry.lowlink = Math.min(entry.lowlink, visited[w2].lowlink);
|
|
968
|
+
} else if (visited[w2].onStack) {
|
|
969
|
+
entry.lowlink = Math.min(entry.lowlink, visited[w2].index);
|
|
970
|
+
}
|
|
971
|
+
});
|
|
972
|
+
if (entry.lowlink === entry.index) {
|
|
973
|
+
var cmpt = [];
|
|
974
|
+
var w;
|
|
975
|
+
do {
|
|
976
|
+
w = stack.pop();
|
|
977
|
+
visited[w].onStack = false;
|
|
978
|
+
cmpt.push(w);
|
|
979
|
+
} while (v !== w);
|
|
980
|
+
results.push(cmpt);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
g.nodes().forEach(function(v) {
|
|
984
|
+
if (!Object.hasOwn(visited, v)) {
|
|
985
|
+
dfs(v);
|
|
986
|
+
}
|
|
987
|
+
});
|
|
988
|
+
return results;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
});
|
|
992
|
+
|
|
993
|
+
// node_modules/@dagrejs/graphlib/lib/alg/find-cycles.js
|
|
994
|
+
var require_find_cycles = __commonJS({
|
|
995
|
+
"node_modules/@dagrejs/graphlib/lib/alg/find-cycles.js"(exports2, module2) {
|
|
996
|
+
"use strict";
|
|
997
|
+
var tarjan = require_tarjan();
|
|
998
|
+
module2.exports = findCycles;
|
|
999
|
+
function findCycles(g) {
|
|
1000
|
+
return tarjan(g).filter(function(cmpt) {
|
|
1001
|
+
return cmpt.length > 1 || cmpt.length === 1 && g.hasEdge(cmpt[0], cmpt[0]);
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
// node_modules/@dagrejs/graphlib/lib/alg/floyd-warshall.js
|
|
1008
|
+
var require_floyd_warshall = __commonJS({
|
|
1009
|
+
"node_modules/@dagrejs/graphlib/lib/alg/floyd-warshall.js"(exports2, module2) {
|
|
1010
|
+
"use strict";
|
|
1011
|
+
module2.exports = floydWarshall;
|
|
1012
|
+
var DEFAULT_WEIGHT_FUNC = () => 1;
|
|
1013
|
+
function floydWarshall(g, weightFn, edgeFn) {
|
|
1014
|
+
return runFloydWarshall(
|
|
1015
|
+
g,
|
|
1016
|
+
weightFn || DEFAULT_WEIGHT_FUNC,
|
|
1017
|
+
edgeFn || function(v) {
|
|
1018
|
+
return g.outEdges(v);
|
|
1019
|
+
}
|
|
1020
|
+
);
|
|
1021
|
+
}
|
|
1022
|
+
function runFloydWarshall(g, weightFn, edgeFn) {
|
|
1023
|
+
var results = {};
|
|
1024
|
+
var nodes = g.nodes();
|
|
1025
|
+
nodes.forEach(function(v) {
|
|
1026
|
+
results[v] = {};
|
|
1027
|
+
results[v][v] = { distance: 0 };
|
|
1028
|
+
nodes.forEach(function(w) {
|
|
1029
|
+
if (v !== w) {
|
|
1030
|
+
results[v][w] = { distance: Number.POSITIVE_INFINITY };
|
|
1031
|
+
}
|
|
1032
|
+
});
|
|
1033
|
+
edgeFn(v).forEach(function(edge) {
|
|
1034
|
+
var w = edge.v === v ? edge.w : edge.v;
|
|
1035
|
+
var d = weightFn(edge);
|
|
1036
|
+
results[v][w] = { distance: d, predecessor: v };
|
|
1037
|
+
});
|
|
1038
|
+
});
|
|
1039
|
+
nodes.forEach(function(k) {
|
|
1040
|
+
var rowK = results[k];
|
|
1041
|
+
nodes.forEach(function(i) {
|
|
1042
|
+
var rowI = results[i];
|
|
1043
|
+
nodes.forEach(function(j) {
|
|
1044
|
+
var ik = rowI[k];
|
|
1045
|
+
var kj = rowK[j];
|
|
1046
|
+
var ij = rowI[j];
|
|
1047
|
+
var altDistance = ik.distance + kj.distance;
|
|
1048
|
+
if (altDistance < ij.distance) {
|
|
1049
|
+
ij.distance = altDistance;
|
|
1050
|
+
ij.predecessor = kj.predecessor;
|
|
1051
|
+
}
|
|
1052
|
+
});
|
|
1053
|
+
});
|
|
1054
|
+
});
|
|
1055
|
+
return results;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
});
|
|
1059
|
+
|
|
1060
|
+
// node_modules/@dagrejs/graphlib/lib/alg/topsort.js
|
|
1061
|
+
var require_topsort = __commonJS({
|
|
1062
|
+
"node_modules/@dagrejs/graphlib/lib/alg/topsort.js"(exports2, module2) {
|
|
1063
|
+
"use strict";
|
|
1064
|
+
function topsort(g) {
|
|
1065
|
+
var visited = {};
|
|
1066
|
+
var stack = {};
|
|
1067
|
+
var results = [];
|
|
1068
|
+
function visit(node) {
|
|
1069
|
+
if (Object.hasOwn(stack, node)) {
|
|
1070
|
+
throw new CycleException();
|
|
1071
|
+
}
|
|
1072
|
+
if (!Object.hasOwn(visited, node)) {
|
|
1073
|
+
stack[node] = true;
|
|
1074
|
+
visited[node] = true;
|
|
1075
|
+
g.predecessors(node).forEach(visit);
|
|
1076
|
+
delete stack[node];
|
|
1077
|
+
results.push(node);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
g.sinks().forEach(visit);
|
|
1081
|
+
if (Object.keys(visited).length !== g.nodeCount()) {
|
|
1082
|
+
throw new CycleException();
|
|
1083
|
+
}
|
|
1084
|
+
return results;
|
|
1085
|
+
}
|
|
1086
|
+
var CycleException = class extends Error {
|
|
1087
|
+
constructor() {
|
|
1088
|
+
super(...arguments);
|
|
1089
|
+
}
|
|
1090
|
+
};
|
|
1091
|
+
module2.exports = topsort;
|
|
1092
|
+
topsort.CycleException = CycleException;
|
|
1093
|
+
}
|
|
1094
|
+
});
|
|
1095
|
+
|
|
1096
|
+
// node_modules/@dagrejs/graphlib/lib/alg/is-acyclic.js
|
|
1097
|
+
var require_is_acyclic = __commonJS({
|
|
1098
|
+
"node_modules/@dagrejs/graphlib/lib/alg/is-acyclic.js"(exports2, module2) {
|
|
1099
|
+
"use strict";
|
|
1100
|
+
var topsort = require_topsort();
|
|
1101
|
+
module2.exports = isAcyclic;
|
|
1102
|
+
function isAcyclic(g) {
|
|
1103
|
+
try {
|
|
1104
|
+
topsort(g);
|
|
1105
|
+
} catch (e) {
|
|
1106
|
+
if (e instanceof topsort.CycleException) {
|
|
1107
|
+
return false;
|
|
1108
|
+
}
|
|
1109
|
+
throw e;
|
|
1110
|
+
}
|
|
1111
|
+
return true;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
});
|
|
1115
|
+
|
|
1116
|
+
// node_modules/@dagrejs/graphlib/lib/alg/dfs.js
|
|
1117
|
+
var require_dfs = __commonJS({
|
|
1118
|
+
"node_modules/@dagrejs/graphlib/lib/alg/dfs.js"(exports2, module2) {
|
|
1119
|
+
"use strict";
|
|
1120
|
+
module2.exports = dfs;
|
|
1121
|
+
function dfs(g, vs, order) {
|
|
1122
|
+
if (!Array.isArray(vs)) {
|
|
1123
|
+
vs = [vs];
|
|
1124
|
+
}
|
|
1125
|
+
var navigation = g.isDirected() ? (v) => g.successors(v) : (v) => g.neighbors(v);
|
|
1126
|
+
var orderFunc = order === "post" ? postOrderDfs : preOrderDfs;
|
|
1127
|
+
var acc = [];
|
|
1128
|
+
var visited = {};
|
|
1129
|
+
vs.forEach((v) => {
|
|
1130
|
+
if (!g.hasNode(v)) {
|
|
1131
|
+
throw new Error("Graph does not have node: " + v);
|
|
1132
|
+
}
|
|
1133
|
+
orderFunc(v, navigation, visited, acc);
|
|
1134
|
+
});
|
|
1135
|
+
return acc;
|
|
1136
|
+
}
|
|
1137
|
+
function postOrderDfs(v, navigation, visited, acc) {
|
|
1138
|
+
var stack = [[v, false]];
|
|
1139
|
+
while (stack.length > 0) {
|
|
1140
|
+
var curr = stack.pop();
|
|
1141
|
+
if (curr[1]) {
|
|
1142
|
+
acc.push(curr[0]);
|
|
1143
|
+
} else {
|
|
1144
|
+
if (!Object.hasOwn(visited, curr[0])) {
|
|
1145
|
+
visited[curr[0]] = true;
|
|
1146
|
+
stack.push([curr[0], true]);
|
|
1147
|
+
forEachRight(navigation(curr[0]), (w) => stack.push([w, false]));
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
function preOrderDfs(v, navigation, visited, acc) {
|
|
1153
|
+
var stack = [v];
|
|
1154
|
+
while (stack.length > 0) {
|
|
1155
|
+
var curr = stack.pop();
|
|
1156
|
+
if (!Object.hasOwn(visited, curr)) {
|
|
1157
|
+
visited[curr] = true;
|
|
1158
|
+
acc.push(curr);
|
|
1159
|
+
forEachRight(navigation(curr), (w) => stack.push(w));
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
function forEachRight(array, iteratee) {
|
|
1164
|
+
var length = array.length;
|
|
1165
|
+
while (length--) {
|
|
1166
|
+
iteratee(array[length], length, array);
|
|
1167
|
+
}
|
|
1168
|
+
return array;
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
});
|
|
1172
|
+
|
|
1173
|
+
// node_modules/@dagrejs/graphlib/lib/alg/postorder.js
|
|
1174
|
+
var require_postorder = __commonJS({
|
|
1175
|
+
"node_modules/@dagrejs/graphlib/lib/alg/postorder.js"(exports2, module2) {
|
|
1176
|
+
"use strict";
|
|
1177
|
+
var dfs = require_dfs();
|
|
1178
|
+
module2.exports = postorder;
|
|
1179
|
+
function postorder(g, vs) {
|
|
1180
|
+
return dfs(g, vs, "post");
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
});
|
|
1184
|
+
|
|
1185
|
+
// node_modules/@dagrejs/graphlib/lib/alg/preorder.js
|
|
1186
|
+
var require_preorder = __commonJS({
|
|
1187
|
+
"node_modules/@dagrejs/graphlib/lib/alg/preorder.js"(exports2, module2) {
|
|
1188
|
+
"use strict";
|
|
1189
|
+
var dfs = require_dfs();
|
|
1190
|
+
module2.exports = preorder;
|
|
1191
|
+
function preorder(g, vs) {
|
|
1192
|
+
return dfs(g, vs, "pre");
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
});
|
|
1196
|
+
|
|
1197
|
+
// node_modules/@dagrejs/graphlib/lib/alg/prim.js
|
|
1198
|
+
var require_prim = __commonJS({
|
|
1199
|
+
"node_modules/@dagrejs/graphlib/lib/alg/prim.js"(exports2, module2) {
|
|
1200
|
+
"use strict";
|
|
1201
|
+
var Graph = require_graph();
|
|
1202
|
+
var PriorityQueue = require_priority_queue();
|
|
1203
|
+
module2.exports = prim;
|
|
1204
|
+
function prim(g, weightFunc) {
|
|
1205
|
+
var result = new Graph();
|
|
1206
|
+
var parents = {};
|
|
1207
|
+
var pq = new PriorityQueue();
|
|
1208
|
+
var v;
|
|
1209
|
+
function updateNeighbors(edge) {
|
|
1210
|
+
var w = edge.v === v ? edge.w : edge.v;
|
|
1211
|
+
var pri = pq.priority(w);
|
|
1212
|
+
if (pri !== void 0) {
|
|
1213
|
+
var edgeWeight = weightFunc(edge);
|
|
1214
|
+
if (edgeWeight < pri) {
|
|
1215
|
+
parents[w] = v;
|
|
1216
|
+
pq.decrease(w, edgeWeight);
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
if (g.nodeCount() === 0) {
|
|
1221
|
+
return result;
|
|
1222
|
+
}
|
|
1223
|
+
g.nodes().forEach(function(v2) {
|
|
1224
|
+
pq.add(v2, Number.POSITIVE_INFINITY);
|
|
1225
|
+
result.setNode(v2);
|
|
1226
|
+
});
|
|
1227
|
+
pq.decrease(g.nodes()[0], 0);
|
|
1228
|
+
var init = false;
|
|
1229
|
+
while (pq.size() > 0) {
|
|
1230
|
+
v = pq.removeMin();
|
|
1231
|
+
if (Object.hasOwn(parents, v)) {
|
|
1232
|
+
result.setEdge(v, parents[v]);
|
|
1233
|
+
} else if (init) {
|
|
1234
|
+
throw new Error("Input graph is not connected: " + g);
|
|
1235
|
+
} else {
|
|
1236
|
+
init = true;
|
|
1237
|
+
}
|
|
1238
|
+
g.nodeEdges(v).forEach(updateNeighbors);
|
|
1239
|
+
}
|
|
1240
|
+
return result;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
});
|
|
1244
|
+
|
|
1245
|
+
// node_modules/@dagrejs/graphlib/lib/alg/index.js
|
|
1246
|
+
var require_alg = __commonJS({
|
|
1247
|
+
"node_modules/@dagrejs/graphlib/lib/alg/index.js"(exports2, module2) {
|
|
1248
|
+
"use strict";
|
|
1249
|
+
module2.exports = {
|
|
1250
|
+
components: require_components(),
|
|
1251
|
+
dijkstra: require_dijkstra(),
|
|
1252
|
+
dijkstraAll: require_dijkstra_all(),
|
|
1253
|
+
findCycles: require_find_cycles(),
|
|
1254
|
+
floydWarshall: require_floyd_warshall(),
|
|
1255
|
+
isAcyclic: require_is_acyclic(),
|
|
1256
|
+
postorder: require_postorder(),
|
|
1257
|
+
preorder: require_preorder(),
|
|
1258
|
+
prim: require_prim(),
|
|
1259
|
+
tarjan: require_tarjan(),
|
|
1260
|
+
topsort: require_topsort()
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1263
|
+
});
|
|
1264
|
+
|
|
1265
|
+
// node_modules/@dagrejs/graphlib/index.js
|
|
1266
|
+
var require_graphlib = __commonJS({
|
|
1267
|
+
"node_modules/@dagrejs/graphlib/index.js"(exports2, module2) {
|
|
1268
|
+
"use strict";
|
|
1269
|
+
var lib = require_lib();
|
|
1270
|
+
module2.exports = {
|
|
1271
|
+
Graph: lib.Graph,
|
|
1272
|
+
json: require_json(),
|
|
1273
|
+
alg: require_alg(),
|
|
1274
|
+
version: lib.version
|
|
1275
|
+
};
|
|
1276
|
+
}
|
|
1277
|
+
});
|
|
1278
|
+
|
|
1279
|
+
// node_modules/@dagrejs/dagre/lib/data/list.js
|
|
1280
|
+
var require_list = __commonJS({
|
|
1281
|
+
"node_modules/@dagrejs/dagre/lib/data/list.js"(exports2, module2) {
|
|
1282
|
+
"use strict";
|
|
1283
|
+
var List = class {
|
|
1284
|
+
constructor() {
|
|
1285
|
+
let sentinel = {};
|
|
1286
|
+
sentinel._next = sentinel._prev = sentinel;
|
|
1287
|
+
this._sentinel = sentinel;
|
|
1288
|
+
}
|
|
1289
|
+
dequeue() {
|
|
1290
|
+
let sentinel = this._sentinel;
|
|
1291
|
+
let entry = sentinel._prev;
|
|
1292
|
+
if (entry !== sentinel) {
|
|
1293
|
+
unlink(entry);
|
|
1294
|
+
return entry;
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
enqueue(entry) {
|
|
1298
|
+
let sentinel = this._sentinel;
|
|
1299
|
+
if (entry._prev && entry._next) {
|
|
1300
|
+
unlink(entry);
|
|
1301
|
+
}
|
|
1302
|
+
entry._next = sentinel._next;
|
|
1303
|
+
sentinel._next._prev = entry;
|
|
1304
|
+
sentinel._next = entry;
|
|
1305
|
+
entry._prev = sentinel;
|
|
1306
|
+
}
|
|
1307
|
+
toString() {
|
|
1308
|
+
let strs = [];
|
|
1309
|
+
let sentinel = this._sentinel;
|
|
1310
|
+
let curr = sentinel._prev;
|
|
1311
|
+
while (curr !== sentinel) {
|
|
1312
|
+
strs.push(JSON.stringify(curr, filterOutLinks));
|
|
1313
|
+
curr = curr._prev;
|
|
1314
|
+
}
|
|
1315
|
+
return "[" + strs.join(", ") + "]";
|
|
1316
|
+
}
|
|
1317
|
+
};
|
|
1318
|
+
function unlink(entry) {
|
|
1319
|
+
entry._prev._next = entry._next;
|
|
1320
|
+
entry._next._prev = entry._prev;
|
|
1321
|
+
delete entry._next;
|
|
1322
|
+
delete entry._prev;
|
|
1323
|
+
}
|
|
1324
|
+
function filterOutLinks(k, v) {
|
|
1325
|
+
if (k !== "_next" && k !== "_prev") {
|
|
1326
|
+
return v;
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
module2.exports = List;
|
|
1330
|
+
}
|
|
1331
|
+
});
|
|
1332
|
+
|
|
1333
|
+
// node_modules/@dagrejs/dagre/lib/greedy-fas.js
|
|
1334
|
+
var require_greedy_fas = __commonJS({
|
|
1335
|
+
"node_modules/@dagrejs/dagre/lib/greedy-fas.js"(exports2, module2) {
|
|
1336
|
+
"use strict";
|
|
1337
|
+
var Graph = require_graphlib().Graph;
|
|
1338
|
+
var List = require_list();
|
|
1339
|
+
module2.exports = greedyFAS;
|
|
1340
|
+
var DEFAULT_WEIGHT_FN = () => 1;
|
|
1341
|
+
function greedyFAS(g, weightFn) {
|
|
1342
|
+
if (g.nodeCount() <= 1) {
|
|
1343
|
+
return [];
|
|
1344
|
+
}
|
|
1345
|
+
let state = buildState(g, weightFn || DEFAULT_WEIGHT_FN);
|
|
1346
|
+
let results = doGreedyFAS(state.graph, state.buckets, state.zeroIdx);
|
|
1347
|
+
return results.flatMap((e) => g.outEdges(e.v, e.w));
|
|
1348
|
+
}
|
|
1349
|
+
function doGreedyFAS(g, buckets, zeroIdx) {
|
|
1350
|
+
let results = [];
|
|
1351
|
+
let sources = buckets[buckets.length - 1];
|
|
1352
|
+
let sinks = buckets[0];
|
|
1353
|
+
let entry;
|
|
1354
|
+
while (g.nodeCount()) {
|
|
1355
|
+
while (entry = sinks.dequeue()) {
|
|
1356
|
+
removeNode(g, buckets, zeroIdx, entry);
|
|
1357
|
+
}
|
|
1358
|
+
while (entry = sources.dequeue()) {
|
|
1359
|
+
removeNode(g, buckets, zeroIdx, entry);
|
|
1360
|
+
}
|
|
1361
|
+
if (g.nodeCount()) {
|
|
1362
|
+
for (let i = buckets.length - 2; i > 0; --i) {
|
|
1363
|
+
entry = buckets[i].dequeue();
|
|
1364
|
+
if (entry) {
|
|
1365
|
+
results = results.concat(removeNode(g, buckets, zeroIdx, entry, true));
|
|
1366
|
+
break;
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
return results;
|
|
1372
|
+
}
|
|
1373
|
+
function removeNode(g, buckets, zeroIdx, entry, collectPredecessors) {
|
|
1374
|
+
let results = collectPredecessors ? [] : void 0;
|
|
1375
|
+
g.inEdges(entry.v).forEach((edge) => {
|
|
1376
|
+
let weight = g.edge(edge);
|
|
1377
|
+
let uEntry = g.node(edge.v);
|
|
1378
|
+
if (collectPredecessors) {
|
|
1379
|
+
results.push({ v: edge.v, w: edge.w });
|
|
1380
|
+
}
|
|
1381
|
+
uEntry.out -= weight;
|
|
1382
|
+
assignBucket(buckets, zeroIdx, uEntry);
|
|
1383
|
+
});
|
|
1384
|
+
g.outEdges(entry.v).forEach((edge) => {
|
|
1385
|
+
let weight = g.edge(edge);
|
|
1386
|
+
let w = edge.w;
|
|
1387
|
+
let wEntry = g.node(w);
|
|
1388
|
+
wEntry["in"] -= weight;
|
|
1389
|
+
assignBucket(buckets, zeroIdx, wEntry);
|
|
1390
|
+
});
|
|
1391
|
+
g.removeNode(entry.v);
|
|
1392
|
+
return results;
|
|
1393
|
+
}
|
|
1394
|
+
function buildState(g, weightFn) {
|
|
1395
|
+
let fasGraph = new Graph();
|
|
1396
|
+
let maxIn = 0;
|
|
1397
|
+
let maxOut = 0;
|
|
1398
|
+
g.nodes().forEach((v) => {
|
|
1399
|
+
fasGraph.setNode(v, { v, "in": 0, out: 0 });
|
|
1400
|
+
});
|
|
1401
|
+
g.edges().forEach((e) => {
|
|
1402
|
+
let prevWeight = fasGraph.edge(e.v, e.w) || 0;
|
|
1403
|
+
let weight = weightFn(e);
|
|
1404
|
+
let edgeWeight = prevWeight + weight;
|
|
1405
|
+
fasGraph.setEdge(e.v, e.w, edgeWeight);
|
|
1406
|
+
maxOut = Math.max(maxOut, fasGraph.node(e.v).out += weight);
|
|
1407
|
+
maxIn = Math.max(maxIn, fasGraph.node(e.w)["in"] += weight);
|
|
1408
|
+
});
|
|
1409
|
+
let buckets = range(maxOut + maxIn + 3).map(() => new List());
|
|
1410
|
+
let zeroIdx = maxIn + 1;
|
|
1411
|
+
fasGraph.nodes().forEach((v) => {
|
|
1412
|
+
assignBucket(buckets, zeroIdx, fasGraph.node(v));
|
|
1413
|
+
});
|
|
1414
|
+
return { graph: fasGraph, buckets, zeroIdx };
|
|
1415
|
+
}
|
|
1416
|
+
function assignBucket(buckets, zeroIdx, entry) {
|
|
1417
|
+
if (!entry.out) {
|
|
1418
|
+
buckets[0].enqueue(entry);
|
|
1419
|
+
} else if (!entry["in"]) {
|
|
1420
|
+
buckets[buckets.length - 1].enqueue(entry);
|
|
1421
|
+
} else {
|
|
1422
|
+
buckets[entry.out - entry["in"] + zeroIdx].enqueue(entry);
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
function range(limit) {
|
|
1426
|
+
const range2 = [];
|
|
1427
|
+
for (let i = 0; i < limit; i++) {
|
|
1428
|
+
range2.push(i);
|
|
1429
|
+
}
|
|
1430
|
+
return range2;
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
});
|
|
1434
|
+
|
|
1435
|
+
// node_modules/@dagrejs/dagre/lib/util.js
|
|
1436
|
+
var require_util = __commonJS({
|
|
1437
|
+
"node_modules/@dagrejs/dagre/lib/util.js"(exports2, module2) {
|
|
1438
|
+
"use strict";
|
|
1439
|
+
var Graph = require_graphlib().Graph;
|
|
1440
|
+
module2.exports = {
|
|
1441
|
+
addBorderNode,
|
|
1442
|
+
addDummyNode,
|
|
1443
|
+
applyWithChunking,
|
|
1444
|
+
asNonCompoundGraph,
|
|
1445
|
+
buildLayerMatrix,
|
|
1446
|
+
intersectRect,
|
|
1447
|
+
mapValues,
|
|
1448
|
+
maxRank,
|
|
1449
|
+
normalizeRanks,
|
|
1450
|
+
notime,
|
|
1451
|
+
partition,
|
|
1452
|
+
pick,
|
|
1453
|
+
predecessorWeights,
|
|
1454
|
+
range,
|
|
1455
|
+
removeEmptyRanks,
|
|
1456
|
+
simplify,
|
|
1457
|
+
successorWeights,
|
|
1458
|
+
time,
|
|
1459
|
+
uniqueId,
|
|
1460
|
+
zipObject
|
|
1461
|
+
};
|
|
1462
|
+
function addDummyNode(g, type, attrs, name) {
|
|
1463
|
+
var v = name;
|
|
1464
|
+
while (g.hasNode(v)) {
|
|
1465
|
+
v = uniqueId(name);
|
|
1466
|
+
}
|
|
1467
|
+
attrs.dummy = type;
|
|
1468
|
+
g.setNode(v, attrs);
|
|
1469
|
+
return v;
|
|
1470
|
+
}
|
|
1471
|
+
function simplify(g) {
|
|
1472
|
+
let simplified = new Graph().setGraph(g.graph());
|
|
1473
|
+
g.nodes().forEach((v) => simplified.setNode(v, g.node(v)));
|
|
1474
|
+
g.edges().forEach((e) => {
|
|
1475
|
+
let simpleLabel = simplified.edge(e.v, e.w) || { weight: 0, minlen: 1 };
|
|
1476
|
+
let label = g.edge(e);
|
|
1477
|
+
simplified.setEdge(e.v, e.w, {
|
|
1478
|
+
weight: simpleLabel.weight + label.weight,
|
|
1479
|
+
minlen: Math.max(simpleLabel.minlen, label.minlen)
|
|
1480
|
+
});
|
|
1481
|
+
});
|
|
1482
|
+
return simplified;
|
|
1483
|
+
}
|
|
1484
|
+
function asNonCompoundGraph(g) {
|
|
1485
|
+
let simplified = new Graph({ multigraph: g.isMultigraph() }).setGraph(g.graph());
|
|
1486
|
+
g.nodes().forEach((v) => {
|
|
1487
|
+
if (!g.children(v).length) {
|
|
1488
|
+
simplified.setNode(v, g.node(v));
|
|
1489
|
+
}
|
|
1490
|
+
});
|
|
1491
|
+
g.edges().forEach((e) => {
|
|
1492
|
+
simplified.setEdge(e, g.edge(e));
|
|
1493
|
+
});
|
|
1494
|
+
return simplified;
|
|
1495
|
+
}
|
|
1496
|
+
function successorWeights(g) {
|
|
1497
|
+
let weightMap = g.nodes().map((v) => {
|
|
1498
|
+
let sucs = {};
|
|
1499
|
+
g.outEdges(v).forEach((e) => {
|
|
1500
|
+
sucs[e.w] = (sucs[e.w] || 0) + g.edge(e).weight;
|
|
1501
|
+
});
|
|
1502
|
+
return sucs;
|
|
1503
|
+
});
|
|
1504
|
+
return zipObject(g.nodes(), weightMap);
|
|
1505
|
+
}
|
|
1506
|
+
function predecessorWeights(g) {
|
|
1507
|
+
let weightMap = g.nodes().map((v) => {
|
|
1508
|
+
let preds = {};
|
|
1509
|
+
g.inEdges(v).forEach((e) => {
|
|
1510
|
+
preds[e.v] = (preds[e.v] || 0) + g.edge(e).weight;
|
|
1511
|
+
});
|
|
1512
|
+
return preds;
|
|
1513
|
+
});
|
|
1514
|
+
return zipObject(g.nodes(), weightMap);
|
|
1515
|
+
}
|
|
1516
|
+
function intersectRect(rect, point) {
|
|
1517
|
+
let x = rect.x;
|
|
1518
|
+
let y = rect.y;
|
|
1519
|
+
let dx = point.x - x;
|
|
1520
|
+
let dy = point.y - y;
|
|
1521
|
+
let w = rect.width / 2;
|
|
1522
|
+
let h = rect.height / 2;
|
|
1523
|
+
if (!dx && !dy) {
|
|
1524
|
+
throw new Error("Not possible to find intersection inside of the rectangle");
|
|
1525
|
+
}
|
|
1526
|
+
let sx, sy;
|
|
1527
|
+
if (Math.abs(dy) * w > Math.abs(dx) * h) {
|
|
1528
|
+
if (dy < 0) {
|
|
1529
|
+
h = -h;
|
|
1530
|
+
}
|
|
1531
|
+
sx = h * dx / dy;
|
|
1532
|
+
sy = h;
|
|
1533
|
+
} else {
|
|
1534
|
+
if (dx < 0) {
|
|
1535
|
+
w = -w;
|
|
1536
|
+
}
|
|
1537
|
+
sx = w;
|
|
1538
|
+
sy = w * dy / dx;
|
|
1539
|
+
}
|
|
1540
|
+
return { x: x + sx, y: y + sy };
|
|
1541
|
+
}
|
|
1542
|
+
function buildLayerMatrix(g) {
|
|
1543
|
+
let layering = range(maxRank(g) + 1).map(() => []);
|
|
1544
|
+
g.nodes().forEach((v) => {
|
|
1545
|
+
let node = g.node(v);
|
|
1546
|
+
let rank = node.rank;
|
|
1547
|
+
if (rank !== void 0) {
|
|
1548
|
+
layering[rank][node.order] = v;
|
|
1549
|
+
}
|
|
1550
|
+
});
|
|
1551
|
+
return layering;
|
|
1552
|
+
}
|
|
1553
|
+
function normalizeRanks(g) {
|
|
1554
|
+
let nodeRanks = g.nodes().map((v) => {
|
|
1555
|
+
let rank = g.node(v).rank;
|
|
1556
|
+
if (rank === void 0) {
|
|
1557
|
+
return Number.MAX_VALUE;
|
|
1558
|
+
}
|
|
1559
|
+
return rank;
|
|
1560
|
+
});
|
|
1561
|
+
let min = applyWithChunking(Math.min, nodeRanks);
|
|
1562
|
+
g.nodes().forEach((v) => {
|
|
1563
|
+
let node = g.node(v);
|
|
1564
|
+
if (Object.hasOwn(node, "rank")) {
|
|
1565
|
+
node.rank -= min;
|
|
1566
|
+
}
|
|
1567
|
+
});
|
|
1568
|
+
}
|
|
1569
|
+
function removeEmptyRanks(g) {
|
|
1570
|
+
let nodeRanks = g.nodes().map((v) => g.node(v).rank);
|
|
1571
|
+
let offset = applyWithChunking(Math.min, nodeRanks);
|
|
1572
|
+
let layers = [];
|
|
1573
|
+
g.nodes().forEach((v) => {
|
|
1574
|
+
let rank = g.node(v).rank - offset;
|
|
1575
|
+
if (!layers[rank]) {
|
|
1576
|
+
layers[rank] = [];
|
|
1577
|
+
}
|
|
1578
|
+
layers[rank].push(v);
|
|
1579
|
+
});
|
|
1580
|
+
let delta = 0;
|
|
1581
|
+
let nodeRankFactor = g.graph().nodeRankFactor;
|
|
1582
|
+
Array.from(layers).forEach((vs, i) => {
|
|
1583
|
+
if (vs === void 0 && i % nodeRankFactor !== 0) {
|
|
1584
|
+
--delta;
|
|
1585
|
+
} else if (vs !== void 0 && delta) {
|
|
1586
|
+
vs.forEach((v) => g.node(v).rank += delta);
|
|
1587
|
+
}
|
|
1588
|
+
});
|
|
1589
|
+
}
|
|
1590
|
+
function addBorderNode(g, prefix, rank, order) {
|
|
1591
|
+
let node = {
|
|
1592
|
+
width: 0,
|
|
1593
|
+
height: 0
|
|
1594
|
+
};
|
|
1595
|
+
if (arguments.length >= 4) {
|
|
1596
|
+
node.rank = rank;
|
|
1597
|
+
node.order = order;
|
|
1598
|
+
}
|
|
1599
|
+
return addDummyNode(g, "border", node, prefix);
|
|
1600
|
+
}
|
|
1601
|
+
function splitToChunks(array, chunkSize = CHUNKING_THRESHOLD) {
|
|
1602
|
+
const chunks = [];
|
|
1603
|
+
for (let i = 0; i < array.length; i += chunkSize) {
|
|
1604
|
+
const chunk = array.slice(i, i + chunkSize);
|
|
1605
|
+
chunks.push(chunk);
|
|
1606
|
+
}
|
|
1607
|
+
return chunks;
|
|
1608
|
+
}
|
|
1609
|
+
var CHUNKING_THRESHOLD = 65535;
|
|
1610
|
+
function applyWithChunking(fn, argsArray) {
|
|
1611
|
+
if (argsArray.length > CHUNKING_THRESHOLD) {
|
|
1612
|
+
const chunks = splitToChunks(argsArray);
|
|
1613
|
+
return fn.apply(null, chunks.map((chunk) => fn.apply(null, chunk)));
|
|
1614
|
+
} else {
|
|
1615
|
+
return fn.apply(null, argsArray);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
function maxRank(g) {
|
|
1619
|
+
const nodes = g.nodes();
|
|
1620
|
+
const nodeRanks = nodes.map((v) => {
|
|
1621
|
+
let rank = g.node(v).rank;
|
|
1622
|
+
if (rank === void 0) {
|
|
1623
|
+
return Number.MIN_VALUE;
|
|
1624
|
+
}
|
|
1625
|
+
return rank;
|
|
1626
|
+
});
|
|
1627
|
+
return applyWithChunking(Math.max, nodeRanks);
|
|
1628
|
+
}
|
|
1629
|
+
function partition(collection, fn) {
|
|
1630
|
+
let result = { lhs: [], rhs: [] };
|
|
1631
|
+
collection.forEach((value) => {
|
|
1632
|
+
if (fn(value)) {
|
|
1633
|
+
result.lhs.push(value);
|
|
1634
|
+
} else {
|
|
1635
|
+
result.rhs.push(value);
|
|
1636
|
+
}
|
|
1637
|
+
});
|
|
1638
|
+
return result;
|
|
1639
|
+
}
|
|
1640
|
+
function time(name, fn) {
|
|
1641
|
+
let start = Date.now();
|
|
1642
|
+
try {
|
|
1643
|
+
return fn();
|
|
1644
|
+
} finally {
|
|
1645
|
+
console.log(name + " time: " + (Date.now() - start) + "ms");
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
function notime(name, fn) {
|
|
1649
|
+
return fn();
|
|
1650
|
+
}
|
|
1651
|
+
var idCounter = 0;
|
|
1652
|
+
function uniqueId(prefix) {
|
|
1653
|
+
var id = ++idCounter;
|
|
1654
|
+
return prefix + ("" + id);
|
|
1655
|
+
}
|
|
1656
|
+
function range(start, limit, step = 1) {
|
|
1657
|
+
if (limit == null) {
|
|
1658
|
+
limit = start;
|
|
1659
|
+
start = 0;
|
|
1660
|
+
}
|
|
1661
|
+
let endCon = (i) => i < limit;
|
|
1662
|
+
if (step < 0) {
|
|
1663
|
+
endCon = (i) => limit < i;
|
|
1664
|
+
}
|
|
1665
|
+
const range2 = [];
|
|
1666
|
+
for (let i = start; endCon(i); i += step) {
|
|
1667
|
+
range2.push(i);
|
|
1668
|
+
}
|
|
1669
|
+
return range2;
|
|
1670
|
+
}
|
|
1671
|
+
function pick(source, keys) {
|
|
1672
|
+
const dest = {};
|
|
1673
|
+
for (const key of keys) {
|
|
1674
|
+
if (source[key] !== void 0) {
|
|
1675
|
+
dest[key] = source[key];
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
return dest;
|
|
1679
|
+
}
|
|
1680
|
+
function mapValues(obj, funcOrProp) {
|
|
1681
|
+
let func = funcOrProp;
|
|
1682
|
+
if (typeof funcOrProp === "string") {
|
|
1683
|
+
func = (val) => val[funcOrProp];
|
|
1684
|
+
}
|
|
1685
|
+
return Object.entries(obj).reduce((acc, [k, v]) => {
|
|
1686
|
+
acc[k] = func(v, k);
|
|
1687
|
+
return acc;
|
|
1688
|
+
}, {});
|
|
1689
|
+
}
|
|
1690
|
+
function zipObject(props, values) {
|
|
1691
|
+
return props.reduce((acc, key, i) => {
|
|
1692
|
+
acc[key] = values[i];
|
|
1693
|
+
return acc;
|
|
1694
|
+
}, {});
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
});
|
|
1698
|
+
|
|
1699
|
+
// node_modules/@dagrejs/dagre/lib/acyclic.js
|
|
1700
|
+
var require_acyclic = __commonJS({
|
|
1701
|
+
"node_modules/@dagrejs/dagre/lib/acyclic.js"(exports2, module2) {
|
|
1702
|
+
"use strict";
|
|
1703
|
+
var greedyFAS = require_greedy_fas();
|
|
1704
|
+
var uniqueId = require_util().uniqueId;
|
|
1705
|
+
module2.exports = {
|
|
1706
|
+
run,
|
|
1707
|
+
undo
|
|
1708
|
+
};
|
|
1709
|
+
function run(g) {
|
|
1710
|
+
let fas = g.graph().acyclicer === "greedy" ? greedyFAS(g, weightFn(g)) : dfsFAS(g);
|
|
1711
|
+
fas.forEach((e) => {
|
|
1712
|
+
let label = g.edge(e);
|
|
1713
|
+
g.removeEdge(e);
|
|
1714
|
+
label.forwardName = e.name;
|
|
1715
|
+
label.reversed = true;
|
|
1716
|
+
g.setEdge(e.w, e.v, label, uniqueId("rev"));
|
|
1717
|
+
});
|
|
1718
|
+
function weightFn(g2) {
|
|
1719
|
+
return (e) => {
|
|
1720
|
+
return g2.edge(e).weight;
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
function dfsFAS(g) {
|
|
1725
|
+
let fas = [];
|
|
1726
|
+
let stack = {};
|
|
1727
|
+
let visited = {};
|
|
1728
|
+
function dfs(v) {
|
|
1729
|
+
if (Object.hasOwn(visited, v)) {
|
|
1730
|
+
return;
|
|
1731
|
+
}
|
|
1732
|
+
visited[v] = true;
|
|
1733
|
+
stack[v] = true;
|
|
1734
|
+
g.outEdges(v).forEach((e) => {
|
|
1735
|
+
if (Object.hasOwn(stack, e.w)) {
|
|
1736
|
+
fas.push(e);
|
|
1737
|
+
} else {
|
|
1738
|
+
dfs(e.w);
|
|
1739
|
+
}
|
|
1740
|
+
});
|
|
1741
|
+
delete stack[v];
|
|
1742
|
+
}
|
|
1743
|
+
g.nodes().forEach(dfs);
|
|
1744
|
+
return fas;
|
|
1745
|
+
}
|
|
1746
|
+
function undo(g) {
|
|
1747
|
+
g.edges().forEach((e) => {
|
|
1748
|
+
let label = g.edge(e);
|
|
1749
|
+
if (label.reversed) {
|
|
1750
|
+
g.removeEdge(e);
|
|
1751
|
+
let forwardName = label.forwardName;
|
|
1752
|
+
delete label.reversed;
|
|
1753
|
+
delete label.forwardName;
|
|
1754
|
+
g.setEdge(e.w, e.v, label, forwardName);
|
|
1755
|
+
}
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
});
|
|
1760
|
+
|
|
1761
|
+
// node_modules/@dagrejs/dagre/lib/normalize.js
|
|
1762
|
+
var require_normalize = __commonJS({
|
|
1763
|
+
"node_modules/@dagrejs/dagre/lib/normalize.js"(exports2, module2) {
|
|
1764
|
+
"use strict";
|
|
1765
|
+
var util = require_util();
|
|
1766
|
+
module2.exports = {
|
|
1767
|
+
run,
|
|
1768
|
+
undo
|
|
1769
|
+
};
|
|
1770
|
+
function run(g) {
|
|
1771
|
+
g.graph().dummyChains = [];
|
|
1772
|
+
g.edges().forEach((edge) => normalizeEdge(g, edge));
|
|
1773
|
+
}
|
|
1774
|
+
function normalizeEdge(g, e) {
|
|
1775
|
+
let v = e.v;
|
|
1776
|
+
let vRank = g.node(v).rank;
|
|
1777
|
+
let w = e.w;
|
|
1778
|
+
let wRank = g.node(w).rank;
|
|
1779
|
+
let name = e.name;
|
|
1780
|
+
let edgeLabel = g.edge(e);
|
|
1781
|
+
let labelRank = edgeLabel.labelRank;
|
|
1782
|
+
if (wRank === vRank + 1) return;
|
|
1783
|
+
g.removeEdge(e);
|
|
1784
|
+
let dummy, attrs, i;
|
|
1785
|
+
for (i = 0, ++vRank; vRank < wRank; ++i, ++vRank) {
|
|
1786
|
+
edgeLabel.points = [];
|
|
1787
|
+
attrs = {
|
|
1788
|
+
width: 0,
|
|
1789
|
+
height: 0,
|
|
1790
|
+
edgeLabel,
|
|
1791
|
+
edgeObj: e,
|
|
1792
|
+
rank: vRank
|
|
1793
|
+
};
|
|
1794
|
+
dummy = util.addDummyNode(g, "edge", attrs, "_d");
|
|
1795
|
+
if (vRank === labelRank) {
|
|
1796
|
+
attrs.width = edgeLabel.width;
|
|
1797
|
+
attrs.height = edgeLabel.height;
|
|
1798
|
+
attrs.dummy = "edge-label";
|
|
1799
|
+
attrs.labelpos = edgeLabel.labelpos;
|
|
1800
|
+
}
|
|
1801
|
+
g.setEdge(v, dummy, { weight: edgeLabel.weight }, name);
|
|
1802
|
+
if (i === 0) {
|
|
1803
|
+
g.graph().dummyChains.push(dummy);
|
|
1804
|
+
}
|
|
1805
|
+
v = dummy;
|
|
1806
|
+
}
|
|
1807
|
+
g.setEdge(v, w, { weight: edgeLabel.weight }, name);
|
|
1808
|
+
}
|
|
1809
|
+
function undo(g) {
|
|
1810
|
+
g.graph().dummyChains.forEach((v) => {
|
|
1811
|
+
let node = g.node(v);
|
|
1812
|
+
let origLabel = node.edgeLabel;
|
|
1813
|
+
let w;
|
|
1814
|
+
g.setEdge(node.edgeObj, origLabel);
|
|
1815
|
+
while (node.dummy) {
|
|
1816
|
+
w = g.successors(v)[0];
|
|
1817
|
+
g.removeNode(v);
|
|
1818
|
+
origLabel.points.push({ x: node.x, y: node.y });
|
|
1819
|
+
if (node.dummy === "edge-label") {
|
|
1820
|
+
origLabel.x = node.x;
|
|
1821
|
+
origLabel.y = node.y;
|
|
1822
|
+
origLabel.width = node.width;
|
|
1823
|
+
origLabel.height = node.height;
|
|
1824
|
+
}
|
|
1825
|
+
v = w;
|
|
1826
|
+
node = g.node(v);
|
|
1827
|
+
}
|
|
1828
|
+
});
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
});
|
|
1832
|
+
|
|
1833
|
+
// node_modules/@dagrejs/dagre/lib/rank/util.js
|
|
1834
|
+
var require_util2 = __commonJS({
|
|
1835
|
+
"node_modules/@dagrejs/dagre/lib/rank/util.js"(exports2, module2) {
|
|
1836
|
+
"use strict";
|
|
1837
|
+
var { applyWithChunking } = require_util();
|
|
1838
|
+
module2.exports = {
|
|
1839
|
+
longestPath,
|
|
1840
|
+
slack
|
|
1841
|
+
};
|
|
1842
|
+
function longestPath(g) {
|
|
1843
|
+
var visited = {};
|
|
1844
|
+
function dfs(v) {
|
|
1845
|
+
var label = g.node(v);
|
|
1846
|
+
if (Object.hasOwn(visited, v)) {
|
|
1847
|
+
return label.rank;
|
|
1848
|
+
}
|
|
1849
|
+
visited[v] = true;
|
|
1850
|
+
let outEdgesMinLens = g.outEdges(v).map((e) => {
|
|
1851
|
+
if (e == null) {
|
|
1852
|
+
return Number.POSITIVE_INFINITY;
|
|
1853
|
+
}
|
|
1854
|
+
return dfs(e.w) - g.edge(e).minlen;
|
|
1855
|
+
});
|
|
1856
|
+
var rank = applyWithChunking(Math.min, outEdgesMinLens);
|
|
1857
|
+
if (rank === Number.POSITIVE_INFINITY) {
|
|
1858
|
+
rank = 0;
|
|
1859
|
+
}
|
|
1860
|
+
return label.rank = rank;
|
|
1861
|
+
}
|
|
1862
|
+
g.sources().forEach(dfs);
|
|
1863
|
+
}
|
|
1864
|
+
function slack(g, e) {
|
|
1865
|
+
return g.node(e.w).rank - g.node(e.v).rank - g.edge(e).minlen;
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
});
|
|
1869
|
+
|
|
1870
|
+
// node_modules/@dagrejs/dagre/lib/rank/feasible-tree.js
|
|
1871
|
+
var require_feasible_tree = __commonJS({
|
|
1872
|
+
"node_modules/@dagrejs/dagre/lib/rank/feasible-tree.js"(exports2, module2) {
|
|
1873
|
+
"use strict";
|
|
1874
|
+
var Graph = require_graphlib().Graph;
|
|
1875
|
+
var slack = require_util2().slack;
|
|
1876
|
+
module2.exports = feasibleTree;
|
|
1877
|
+
function feasibleTree(g) {
|
|
1878
|
+
var t = new Graph({ directed: false });
|
|
1879
|
+
var start = g.nodes()[0];
|
|
1880
|
+
var size = g.nodeCount();
|
|
1881
|
+
t.setNode(start, {});
|
|
1882
|
+
var edge, delta;
|
|
1883
|
+
while (tightTree(t, g) < size) {
|
|
1884
|
+
edge = findMinSlackEdge(t, g);
|
|
1885
|
+
delta = t.hasNode(edge.v) ? slack(g, edge) : -slack(g, edge);
|
|
1886
|
+
shiftRanks(t, g, delta);
|
|
1887
|
+
}
|
|
1888
|
+
return t;
|
|
1889
|
+
}
|
|
1890
|
+
function tightTree(t, g) {
|
|
1891
|
+
function dfs(v) {
|
|
1892
|
+
g.nodeEdges(v).forEach((e) => {
|
|
1893
|
+
var edgeV = e.v, w = v === edgeV ? e.w : edgeV;
|
|
1894
|
+
if (!t.hasNode(w) && !slack(g, e)) {
|
|
1895
|
+
t.setNode(w, {});
|
|
1896
|
+
t.setEdge(v, w, {});
|
|
1897
|
+
dfs(w);
|
|
1898
|
+
}
|
|
1899
|
+
});
|
|
1900
|
+
}
|
|
1901
|
+
t.nodes().forEach(dfs);
|
|
1902
|
+
return t.nodeCount();
|
|
1903
|
+
}
|
|
1904
|
+
function findMinSlackEdge(t, g) {
|
|
1905
|
+
const edges = g.edges();
|
|
1906
|
+
return edges.reduce((acc, edge) => {
|
|
1907
|
+
let edgeSlack = Number.POSITIVE_INFINITY;
|
|
1908
|
+
if (t.hasNode(edge.v) !== t.hasNode(edge.w)) {
|
|
1909
|
+
edgeSlack = slack(g, edge);
|
|
1910
|
+
}
|
|
1911
|
+
if (edgeSlack < acc[0]) {
|
|
1912
|
+
return [edgeSlack, edge];
|
|
1913
|
+
}
|
|
1914
|
+
return acc;
|
|
1915
|
+
}, [Number.POSITIVE_INFINITY, null])[1];
|
|
1916
|
+
}
|
|
1917
|
+
function shiftRanks(t, g, delta) {
|
|
1918
|
+
t.nodes().forEach((v) => g.node(v).rank += delta);
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
});
|
|
1922
|
+
|
|
1923
|
+
// node_modules/@dagrejs/dagre/lib/rank/network-simplex.js
|
|
1924
|
+
var require_network_simplex = __commonJS({
|
|
1925
|
+
"node_modules/@dagrejs/dagre/lib/rank/network-simplex.js"(exports2, module2) {
|
|
1926
|
+
"use strict";
|
|
1927
|
+
var feasibleTree = require_feasible_tree();
|
|
1928
|
+
var slack = require_util2().slack;
|
|
1929
|
+
var initRank = require_util2().longestPath;
|
|
1930
|
+
var preorder = require_graphlib().alg.preorder;
|
|
1931
|
+
var postorder = require_graphlib().alg.postorder;
|
|
1932
|
+
var simplify = require_util().simplify;
|
|
1933
|
+
module2.exports = networkSimplex;
|
|
1934
|
+
networkSimplex.initLowLimValues = initLowLimValues;
|
|
1935
|
+
networkSimplex.initCutValues = initCutValues;
|
|
1936
|
+
networkSimplex.calcCutValue = calcCutValue;
|
|
1937
|
+
networkSimplex.leaveEdge = leaveEdge;
|
|
1938
|
+
networkSimplex.enterEdge = enterEdge;
|
|
1939
|
+
networkSimplex.exchangeEdges = exchangeEdges;
|
|
1940
|
+
function networkSimplex(g) {
|
|
1941
|
+
g = simplify(g);
|
|
1942
|
+
initRank(g);
|
|
1943
|
+
var t = feasibleTree(g);
|
|
1944
|
+
initLowLimValues(t);
|
|
1945
|
+
initCutValues(t, g);
|
|
1946
|
+
var e, f;
|
|
1947
|
+
while (e = leaveEdge(t)) {
|
|
1948
|
+
f = enterEdge(t, g, e);
|
|
1949
|
+
exchangeEdges(t, g, e, f);
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
function initCutValues(t, g) {
|
|
1953
|
+
var vs = postorder(t, t.nodes());
|
|
1954
|
+
vs = vs.slice(0, vs.length - 1);
|
|
1955
|
+
vs.forEach((v) => assignCutValue(t, g, v));
|
|
1956
|
+
}
|
|
1957
|
+
function assignCutValue(t, g, child) {
|
|
1958
|
+
var childLab = t.node(child);
|
|
1959
|
+
var parent = childLab.parent;
|
|
1960
|
+
t.edge(child, parent).cutvalue = calcCutValue(t, g, child);
|
|
1961
|
+
}
|
|
1962
|
+
function calcCutValue(t, g, child) {
|
|
1963
|
+
var childLab = t.node(child);
|
|
1964
|
+
var parent = childLab.parent;
|
|
1965
|
+
var childIsTail = true;
|
|
1966
|
+
var graphEdge = g.edge(child, parent);
|
|
1967
|
+
var cutValue = 0;
|
|
1968
|
+
if (!graphEdge) {
|
|
1969
|
+
childIsTail = false;
|
|
1970
|
+
graphEdge = g.edge(parent, child);
|
|
1971
|
+
}
|
|
1972
|
+
cutValue = graphEdge.weight;
|
|
1973
|
+
g.nodeEdges(child).forEach((e) => {
|
|
1974
|
+
var isOutEdge = e.v === child, other = isOutEdge ? e.w : e.v;
|
|
1975
|
+
if (other !== parent) {
|
|
1976
|
+
var pointsToHead = isOutEdge === childIsTail, otherWeight = g.edge(e).weight;
|
|
1977
|
+
cutValue += pointsToHead ? otherWeight : -otherWeight;
|
|
1978
|
+
if (isTreeEdge(t, child, other)) {
|
|
1979
|
+
var otherCutValue = t.edge(child, other).cutvalue;
|
|
1980
|
+
cutValue += pointsToHead ? -otherCutValue : otherCutValue;
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
});
|
|
1984
|
+
return cutValue;
|
|
1985
|
+
}
|
|
1986
|
+
function initLowLimValues(tree, root) {
|
|
1987
|
+
if (arguments.length < 2) {
|
|
1988
|
+
root = tree.nodes()[0];
|
|
1989
|
+
}
|
|
1990
|
+
dfsAssignLowLim(tree, {}, 1, root);
|
|
1991
|
+
}
|
|
1992
|
+
function dfsAssignLowLim(tree, visited, nextLim, v, parent) {
|
|
1993
|
+
var low = nextLim;
|
|
1994
|
+
var label = tree.node(v);
|
|
1995
|
+
visited[v] = true;
|
|
1996
|
+
tree.neighbors(v).forEach((w) => {
|
|
1997
|
+
if (!Object.hasOwn(visited, w)) {
|
|
1998
|
+
nextLim = dfsAssignLowLim(tree, visited, nextLim, w, v);
|
|
1999
|
+
}
|
|
2000
|
+
});
|
|
2001
|
+
label.low = low;
|
|
2002
|
+
label.lim = nextLim++;
|
|
2003
|
+
if (parent) {
|
|
2004
|
+
label.parent = parent;
|
|
2005
|
+
} else {
|
|
2006
|
+
delete label.parent;
|
|
2007
|
+
}
|
|
2008
|
+
return nextLim;
|
|
2009
|
+
}
|
|
2010
|
+
function leaveEdge(tree) {
|
|
2011
|
+
return tree.edges().find((e) => tree.edge(e).cutvalue < 0);
|
|
2012
|
+
}
|
|
2013
|
+
function enterEdge(t, g, edge) {
|
|
2014
|
+
var v = edge.v;
|
|
2015
|
+
var w = edge.w;
|
|
2016
|
+
if (!g.hasEdge(v, w)) {
|
|
2017
|
+
v = edge.w;
|
|
2018
|
+
w = edge.v;
|
|
2019
|
+
}
|
|
2020
|
+
var vLabel = t.node(v);
|
|
2021
|
+
var wLabel = t.node(w);
|
|
2022
|
+
var tailLabel = vLabel;
|
|
2023
|
+
var flip = false;
|
|
2024
|
+
if (vLabel.lim > wLabel.lim) {
|
|
2025
|
+
tailLabel = wLabel;
|
|
2026
|
+
flip = true;
|
|
2027
|
+
}
|
|
2028
|
+
var candidates = g.edges().filter((edge2) => {
|
|
2029
|
+
return flip === isDescendant(t, t.node(edge2.v), tailLabel) && flip !== isDescendant(t, t.node(edge2.w), tailLabel);
|
|
2030
|
+
});
|
|
2031
|
+
return candidates.reduce((acc, edge2) => {
|
|
2032
|
+
if (slack(g, edge2) < slack(g, acc)) {
|
|
2033
|
+
return edge2;
|
|
2034
|
+
}
|
|
2035
|
+
return acc;
|
|
2036
|
+
});
|
|
2037
|
+
}
|
|
2038
|
+
function exchangeEdges(t, g, e, f) {
|
|
2039
|
+
var v = e.v;
|
|
2040
|
+
var w = e.w;
|
|
2041
|
+
t.removeEdge(v, w);
|
|
2042
|
+
t.setEdge(f.v, f.w, {});
|
|
2043
|
+
initLowLimValues(t);
|
|
2044
|
+
initCutValues(t, g);
|
|
2045
|
+
updateRanks(t, g);
|
|
2046
|
+
}
|
|
2047
|
+
function updateRanks(t, g) {
|
|
2048
|
+
var root = t.nodes().find((v) => !g.node(v).parent);
|
|
2049
|
+
var vs = preorder(t, root);
|
|
2050
|
+
vs = vs.slice(1);
|
|
2051
|
+
vs.forEach((v) => {
|
|
2052
|
+
var parent = t.node(v).parent, edge = g.edge(v, parent), flipped = false;
|
|
2053
|
+
if (!edge) {
|
|
2054
|
+
edge = g.edge(parent, v);
|
|
2055
|
+
flipped = true;
|
|
2056
|
+
}
|
|
2057
|
+
g.node(v).rank = g.node(parent).rank + (flipped ? edge.minlen : -edge.minlen);
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
function isTreeEdge(tree, u, v) {
|
|
2061
|
+
return tree.hasEdge(u, v);
|
|
2062
|
+
}
|
|
2063
|
+
function isDescendant(tree, vLabel, rootLabel) {
|
|
2064
|
+
return rootLabel.low <= vLabel.lim && vLabel.lim <= rootLabel.lim;
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
});
|
|
2068
|
+
|
|
2069
|
+
// node_modules/@dagrejs/dagre/lib/rank/index.js
|
|
2070
|
+
var require_rank = __commonJS({
|
|
2071
|
+
"node_modules/@dagrejs/dagre/lib/rank/index.js"(exports2, module2) {
|
|
2072
|
+
"use strict";
|
|
2073
|
+
var rankUtil = require_util2();
|
|
2074
|
+
var longestPath = rankUtil.longestPath;
|
|
2075
|
+
var feasibleTree = require_feasible_tree();
|
|
2076
|
+
var networkSimplex = require_network_simplex();
|
|
2077
|
+
module2.exports = rank;
|
|
2078
|
+
function rank(g) {
|
|
2079
|
+
var ranker = g.graph().ranker;
|
|
2080
|
+
if (ranker instanceof Function) {
|
|
2081
|
+
return ranker(g);
|
|
2082
|
+
}
|
|
2083
|
+
switch (g.graph().ranker) {
|
|
2084
|
+
case "network-simplex":
|
|
2085
|
+
networkSimplexRanker(g);
|
|
2086
|
+
break;
|
|
2087
|
+
case "tight-tree":
|
|
2088
|
+
tightTreeRanker(g);
|
|
2089
|
+
break;
|
|
2090
|
+
case "longest-path":
|
|
2091
|
+
longestPathRanker(g);
|
|
2092
|
+
break;
|
|
2093
|
+
case "none":
|
|
2094
|
+
break;
|
|
2095
|
+
default:
|
|
2096
|
+
networkSimplexRanker(g);
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
var longestPathRanker = longestPath;
|
|
2100
|
+
function tightTreeRanker(g) {
|
|
2101
|
+
longestPath(g);
|
|
2102
|
+
feasibleTree(g);
|
|
2103
|
+
}
|
|
2104
|
+
function networkSimplexRanker(g) {
|
|
2105
|
+
networkSimplex(g);
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
});
|
|
2109
|
+
|
|
2110
|
+
// node_modules/@dagrejs/dagre/lib/parent-dummy-chains.js
|
|
2111
|
+
var require_parent_dummy_chains = __commonJS({
|
|
2112
|
+
"node_modules/@dagrejs/dagre/lib/parent-dummy-chains.js"(exports2, module2) {
|
|
2113
|
+
"use strict";
|
|
2114
|
+
module2.exports = parentDummyChains;
|
|
2115
|
+
function parentDummyChains(g) {
|
|
2116
|
+
let postorderNums = postorder(g);
|
|
2117
|
+
g.graph().dummyChains.forEach((v) => {
|
|
2118
|
+
let node = g.node(v);
|
|
2119
|
+
let edgeObj = node.edgeObj;
|
|
2120
|
+
let pathData = findPath(g, postorderNums, edgeObj.v, edgeObj.w);
|
|
2121
|
+
let path = pathData.path;
|
|
2122
|
+
let lca = pathData.lca;
|
|
2123
|
+
let pathIdx = 0;
|
|
2124
|
+
let pathV = path[pathIdx];
|
|
2125
|
+
let ascending = true;
|
|
2126
|
+
while (v !== edgeObj.w) {
|
|
2127
|
+
node = g.node(v);
|
|
2128
|
+
if (ascending) {
|
|
2129
|
+
while ((pathV = path[pathIdx]) !== lca && g.node(pathV).maxRank < node.rank) {
|
|
2130
|
+
pathIdx++;
|
|
2131
|
+
}
|
|
2132
|
+
if (pathV === lca) {
|
|
2133
|
+
ascending = false;
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
if (!ascending) {
|
|
2137
|
+
while (pathIdx < path.length - 1 && g.node(pathV = path[pathIdx + 1]).minRank <= node.rank) {
|
|
2138
|
+
pathIdx++;
|
|
2139
|
+
}
|
|
2140
|
+
pathV = path[pathIdx];
|
|
2141
|
+
}
|
|
2142
|
+
g.setParent(v, pathV);
|
|
2143
|
+
v = g.successors(v)[0];
|
|
2144
|
+
}
|
|
2145
|
+
});
|
|
2146
|
+
}
|
|
2147
|
+
function findPath(g, postorderNums, v, w) {
|
|
2148
|
+
let vPath = [];
|
|
2149
|
+
let wPath = [];
|
|
2150
|
+
let low = Math.min(postorderNums[v].low, postorderNums[w].low);
|
|
2151
|
+
let lim = Math.max(postorderNums[v].lim, postorderNums[w].lim);
|
|
2152
|
+
let parent;
|
|
2153
|
+
let lca;
|
|
2154
|
+
parent = v;
|
|
2155
|
+
do {
|
|
2156
|
+
parent = g.parent(parent);
|
|
2157
|
+
vPath.push(parent);
|
|
2158
|
+
} while (parent && (postorderNums[parent].low > low || lim > postorderNums[parent].lim));
|
|
2159
|
+
lca = parent;
|
|
2160
|
+
parent = w;
|
|
2161
|
+
while ((parent = g.parent(parent)) !== lca) {
|
|
2162
|
+
wPath.push(parent);
|
|
2163
|
+
}
|
|
2164
|
+
return { path: vPath.concat(wPath.reverse()), lca };
|
|
2165
|
+
}
|
|
2166
|
+
function postorder(g) {
|
|
2167
|
+
let result = {};
|
|
2168
|
+
let lim = 0;
|
|
2169
|
+
function dfs(v) {
|
|
2170
|
+
let low = lim;
|
|
2171
|
+
g.children(v).forEach(dfs);
|
|
2172
|
+
result[v] = { low, lim: lim++ };
|
|
2173
|
+
}
|
|
2174
|
+
g.children().forEach(dfs);
|
|
2175
|
+
return result;
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
});
|
|
2179
|
+
|
|
2180
|
+
// node_modules/@dagrejs/dagre/lib/nesting-graph.js
|
|
2181
|
+
var require_nesting_graph = __commonJS({
|
|
2182
|
+
"node_modules/@dagrejs/dagre/lib/nesting-graph.js"(exports2, module2) {
|
|
2183
|
+
"use strict";
|
|
2184
|
+
var util = require_util();
|
|
2185
|
+
module2.exports = {
|
|
2186
|
+
run,
|
|
2187
|
+
cleanup
|
|
2188
|
+
};
|
|
2189
|
+
function run(g) {
|
|
2190
|
+
let root = util.addDummyNode(g, "root", {}, "_root");
|
|
2191
|
+
let depths = treeDepths(g);
|
|
2192
|
+
let depthsArr = Object.values(depths);
|
|
2193
|
+
let height = util.applyWithChunking(Math.max, depthsArr) - 1;
|
|
2194
|
+
let nodeSep = 2 * height + 1;
|
|
2195
|
+
g.graph().nestingRoot = root;
|
|
2196
|
+
g.edges().forEach((e) => g.edge(e).minlen *= nodeSep);
|
|
2197
|
+
let weight = sumWeights(g) + 1;
|
|
2198
|
+
g.children().forEach((child) => dfs(g, root, nodeSep, weight, height, depths, child));
|
|
2199
|
+
g.graph().nodeRankFactor = nodeSep;
|
|
2200
|
+
}
|
|
2201
|
+
function dfs(g, root, nodeSep, weight, height, depths, v) {
|
|
2202
|
+
let children = g.children(v);
|
|
2203
|
+
if (!children.length) {
|
|
2204
|
+
if (v !== root) {
|
|
2205
|
+
g.setEdge(root, v, { weight: 0, minlen: nodeSep });
|
|
2206
|
+
}
|
|
2207
|
+
return;
|
|
2208
|
+
}
|
|
2209
|
+
let top = util.addBorderNode(g, "_bt");
|
|
2210
|
+
let bottom = util.addBorderNode(g, "_bb");
|
|
2211
|
+
let label = g.node(v);
|
|
2212
|
+
g.setParent(top, v);
|
|
2213
|
+
label.borderTop = top;
|
|
2214
|
+
g.setParent(bottom, v);
|
|
2215
|
+
label.borderBottom = bottom;
|
|
2216
|
+
children.forEach((child) => {
|
|
2217
|
+
dfs(g, root, nodeSep, weight, height, depths, child);
|
|
2218
|
+
let childNode = g.node(child);
|
|
2219
|
+
let childTop = childNode.borderTop ? childNode.borderTop : child;
|
|
2220
|
+
let childBottom = childNode.borderBottom ? childNode.borderBottom : child;
|
|
2221
|
+
let thisWeight = childNode.borderTop ? weight : 2 * weight;
|
|
2222
|
+
let minlen = childTop !== childBottom ? 1 : height - depths[v] + 1;
|
|
2223
|
+
g.setEdge(top, childTop, {
|
|
2224
|
+
weight: thisWeight,
|
|
2225
|
+
minlen,
|
|
2226
|
+
nestingEdge: true
|
|
2227
|
+
});
|
|
2228
|
+
g.setEdge(childBottom, bottom, {
|
|
2229
|
+
weight: thisWeight,
|
|
2230
|
+
minlen,
|
|
2231
|
+
nestingEdge: true
|
|
2232
|
+
});
|
|
2233
|
+
});
|
|
2234
|
+
if (!g.parent(v)) {
|
|
2235
|
+
g.setEdge(root, top, { weight: 0, minlen: height + depths[v] });
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
function treeDepths(g) {
|
|
2239
|
+
var depths = {};
|
|
2240
|
+
function dfs2(v, depth) {
|
|
2241
|
+
var children = g.children(v);
|
|
2242
|
+
if (children && children.length) {
|
|
2243
|
+
children.forEach((child) => dfs2(child, depth + 1));
|
|
2244
|
+
}
|
|
2245
|
+
depths[v] = depth;
|
|
2246
|
+
}
|
|
2247
|
+
g.children().forEach((v) => dfs2(v, 1));
|
|
2248
|
+
return depths;
|
|
2249
|
+
}
|
|
2250
|
+
function sumWeights(g) {
|
|
2251
|
+
return g.edges().reduce((acc, e) => acc + g.edge(e).weight, 0);
|
|
2252
|
+
}
|
|
2253
|
+
function cleanup(g) {
|
|
2254
|
+
var graphLabel = g.graph();
|
|
2255
|
+
g.removeNode(graphLabel.nestingRoot);
|
|
2256
|
+
delete graphLabel.nestingRoot;
|
|
2257
|
+
g.edges().forEach((e) => {
|
|
2258
|
+
var edge = g.edge(e);
|
|
2259
|
+
if (edge.nestingEdge) {
|
|
2260
|
+
g.removeEdge(e);
|
|
2261
|
+
}
|
|
2262
|
+
});
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
});
|
|
2266
|
+
|
|
2267
|
+
// node_modules/@dagrejs/dagre/lib/add-border-segments.js
|
|
2268
|
+
var require_add_border_segments = __commonJS({
|
|
2269
|
+
"node_modules/@dagrejs/dagre/lib/add-border-segments.js"(exports2, module2) {
|
|
2270
|
+
"use strict";
|
|
2271
|
+
var util = require_util();
|
|
2272
|
+
module2.exports = addBorderSegments;
|
|
2273
|
+
function addBorderSegments(g) {
|
|
2274
|
+
function dfs(v) {
|
|
2275
|
+
let children = g.children(v);
|
|
2276
|
+
let node = g.node(v);
|
|
2277
|
+
if (children.length) {
|
|
2278
|
+
children.forEach(dfs);
|
|
2279
|
+
}
|
|
2280
|
+
if (Object.hasOwn(node, "minRank")) {
|
|
2281
|
+
node.borderLeft = [];
|
|
2282
|
+
node.borderRight = [];
|
|
2283
|
+
for (let rank = node.minRank, maxRank = node.maxRank + 1; rank < maxRank; ++rank) {
|
|
2284
|
+
addBorderNode(g, "borderLeft", "_bl", v, node, rank);
|
|
2285
|
+
addBorderNode(g, "borderRight", "_br", v, node, rank);
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
g.children().forEach(dfs);
|
|
2290
|
+
}
|
|
2291
|
+
function addBorderNode(g, prop, prefix, sg, sgNode, rank) {
|
|
2292
|
+
let label = { width: 0, height: 0, rank, borderType: prop };
|
|
2293
|
+
let prev = sgNode[prop][rank - 1];
|
|
2294
|
+
let curr = util.addDummyNode(g, "border", label, prefix);
|
|
2295
|
+
sgNode[prop][rank] = curr;
|
|
2296
|
+
g.setParent(curr, sg);
|
|
2297
|
+
if (prev) {
|
|
2298
|
+
g.setEdge(prev, curr, { weight: 1 });
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
});
|
|
2303
|
+
|
|
2304
|
+
// node_modules/@dagrejs/dagre/lib/coordinate-system.js
|
|
2305
|
+
var require_coordinate_system = __commonJS({
|
|
2306
|
+
"node_modules/@dagrejs/dagre/lib/coordinate-system.js"(exports2, module2) {
|
|
2307
|
+
"use strict";
|
|
2308
|
+
module2.exports = {
|
|
2309
|
+
adjust,
|
|
2310
|
+
undo
|
|
2311
|
+
};
|
|
2312
|
+
function adjust(g) {
|
|
2313
|
+
let rankDir = g.graph().rankdir.toLowerCase();
|
|
2314
|
+
if (rankDir === "lr" || rankDir === "rl") {
|
|
2315
|
+
swapWidthHeight(g);
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
function undo(g) {
|
|
2319
|
+
let rankDir = g.graph().rankdir.toLowerCase();
|
|
2320
|
+
if (rankDir === "bt" || rankDir === "rl") {
|
|
2321
|
+
reverseY(g);
|
|
2322
|
+
}
|
|
2323
|
+
if (rankDir === "lr" || rankDir === "rl") {
|
|
2324
|
+
swapXY(g);
|
|
2325
|
+
swapWidthHeight(g);
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
function swapWidthHeight(g) {
|
|
2329
|
+
g.nodes().forEach((v) => swapWidthHeightOne(g.node(v)));
|
|
2330
|
+
g.edges().forEach((e) => swapWidthHeightOne(g.edge(e)));
|
|
2331
|
+
}
|
|
2332
|
+
function swapWidthHeightOne(attrs) {
|
|
2333
|
+
let w = attrs.width;
|
|
2334
|
+
attrs.width = attrs.height;
|
|
2335
|
+
attrs.height = w;
|
|
2336
|
+
}
|
|
2337
|
+
function reverseY(g) {
|
|
2338
|
+
g.nodes().forEach((v) => reverseYOne(g.node(v)));
|
|
2339
|
+
g.edges().forEach((e) => {
|
|
2340
|
+
let edge = g.edge(e);
|
|
2341
|
+
edge.points.forEach(reverseYOne);
|
|
2342
|
+
if (Object.hasOwn(edge, "y")) {
|
|
2343
|
+
reverseYOne(edge);
|
|
2344
|
+
}
|
|
2345
|
+
});
|
|
2346
|
+
}
|
|
2347
|
+
function reverseYOne(attrs) {
|
|
2348
|
+
attrs.y = -attrs.y;
|
|
2349
|
+
}
|
|
2350
|
+
function swapXY(g) {
|
|
2351
|
+
g.nodes().forEach((v) => swapXYOne(g.node(v)));
|
|
2352
|
+
g.edges().forEach((e) => {
|
|
2353
|
+
let edge = g.edge(e);
|
|
2354
|
+
edge.points.forEach(swapXYOne);
|
|
2355
|
+
if (Object.hasOwn(edge, "x")) {
|
|
2356
|
+
swapXYOne(edge);
|
|
2357
|
+
}
|
|
2358
|
+
});
|
|
2359
|
+
}
|
|
2360
|
+
function swapXYOne(attrs) {
|
|
2361
|
+
let x = attrs.x;
|
|
2362
|
+
attrs.x = attrs.y;
|
|
2363
|
+
attrs.y = x;
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
});
|
|
2367
|
+
|
|
2368
|
+
// node_modules/@dagrejs/dagre/lib/order/init-order.js
|
|
2369
|
+
var require_init_order = __commonJS({
|
|
2370
|
+
"node_modules/@dagrejs/dagre/lib/order/init-order.js"(exports2, module2) {
|
|
2371
|
+
"use strict";
|
|
2372
|
+
var util = require_util();
|
|
2373
|
+
module2.exports = initOrder;
|
|
2374
|
+
function initOrder(g) {
|
|
2375
|
+
let visited = {};
|
|
2376
|
+
let simpleNodes = g.nodes().filter((v) => !g.children(v).length);
|
|
2377
|
+
let simpleNodesRanks = simpleNodes.map((v) => g.node(v).rank);
|
|
2378
|
+
let maxRank = util.applyWithChunking(Math.max, simpleNodesRanks);
|
|
2379
|
+
let layers = util.range(maxRank + 1).map(() => []);
|
|
2380
|
+
function dfs(v) {
|
|
2381
|
+
if (visited[v]) return;
|
|
2382
|
+
visited[v] = true;
|
|
2383
|
+
let node = g.node(v);
|
|
2384
|
+
layers[node.rank].push(v);
|
|
2385
|
+
g.successors(v).forEach(dfs);
|
|
2386
|
+
}
|
|
2387
|
+
let orderedVs = simpleNodes.sort((a, b) => g.node(a).rank - g.node(b).rank);
|
|
2388
|
+
orderedVs.forEach(dfs);
|
|
2389
|
+
return layers;
|
|
2390
|
+
}
|
|
2391
|
+
}
|
|
2392
|
+
});
|
|
2393
|
+
|
|
2394
|
+
// node_modules/@dagrejs/dagre/lib/order/cross-count.js
|
|
2395
|
+
var require_cross_count = __commonJS({
|
|
2396
|
+
"node_modules/@dagrejs/dagre/lib/order/cross-count.js"(exports2, module2) {
|
|
2397
|
+
"use strict";
|
|
2398
|
+
var zipObject = require_util().zipObject;
|
|
2399
|
+
module2.exports = crossCount;
|
|
2400
|
+
function crossCount(g, layering) {
|
|
2401
|
+
let cc = 0;
|
|
2402
|
+
for (let i = 1; i < layering.length; ++i) {
|
|
2403
|
+
cc += twoLayerCrossCount(g, layering[i - 1], layering[i]);
|
|
2404
|
+
}
|
|
2405
|
+
return cc;
|
|
2406
|
+
}
|
|
2407
|
+
function twoLayerCrossCount(g, northLayer, southLayer) {
|
|
2408
|
+
let southPos = zipObject(southLayer, southLayer.map((v, i) => i));
|
|
2409
|
+
let southEntries = northLayer.flatMap((v) => {
|
|
2410
|
+
return g.outEdges(v).map((e) => {
|
|
2411
|
+
return { pos: southPos[e.w], weight: g.edge(e).weight };
|
|
2412
|
+
}).sort((a, b) => a.pos - b.pos);
|
|
2413
|
+
});
|
|
2414
|
+
let firstIndex = 1;
|
|
2415
|
+
while (firstIndex < southLayer.length) firstIndex <<= 1;
|
|
2416
|
+
let treeSize = 2 * firstIndex - 1;
|
|
2417
|
+
firstIndex -= 1;
|
|
2418
|
+
let tree = new Array(treeSize).fill(0);
|
|
2419
|
+
let cc = 0;
|
|
2420
|
+
southEntries.forEach((entry) => {
|
|
2421
|
+
let index = entry.pos + firstIndex;
|
|
2422
|
+
tree[index] += entry.weight;
|
|
2423
|
+
let weightSum = 0;
|
|
2424
|
+
while (index > 0) {
|
|
2425
|
+
if (index % 2) {
|
|
2426
|
+
weightSum += tree[index + 1];
|
|
2427
|
+
}
|
|
2428
|
+
index = index - 1 >> 1;
|
|
2429
|
+
tree[index] += entry.weight;
|
|
2430
|
+
}
|
|
2431
|
+
cc += entry.weight * weightSum;
|
|
2432
|
+
});
|
|
2433
|
+
return cc;
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
});
|
|
2437
|
+
|
|
2438
|
+
// node_modules/@dagrejs/dagre/lib/order/barycenter.js
|
|
2439
|
+
var require_barycenter = __commonJS({
|
|
2440
|
+
"node_modules/@dagrejs/dagre/lib/order/barycenter.js"(exports2, module2) {
|
|
2441
|
+
"use strict";
|
|
2442
|
+
module2.exports = barycenter;
|
|
2443
|
+
function barycenter(g, movable = []) {
|
|
2444
|
+
return movable.map((v) => {
|
|
2445
|
+
let inV = g.inEdges(v);
|
|
2446
|
+
if (!inV.length) {
|
|
2447
|
+
return { v };
|
|
2448
|
+
} else {
|
|
2449
|
+
let result = inV.reduce((acc, e) => {
|
|
2450
|
+
let edge = g.edge(e), nodeU = g.node(e.v);
|
|
2451
|
+
return {
|
|
2452
|
+
sum: acc.sum + edge.weight * nodeU.order,
|
|
2453
|
+
weight: acc.weight + edge.weight
|
|
2454
|
+
};
|
|
2455
|
+
}, { sum: 0, weight: 0 });
|
|
2456
|
+
return {
|
|
2457
|
+
v,
|
|
2458
|
+
barycenter: result.sum / result.weight,
|
|
2459
|
+
weight: result.weight
|
|
2460
|
+
};
|
|
2461
|
+
}
|
|
2462
|
+
});
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
});
|
|
2466
|
+
|
|
2467
|
+
// node_modules/@dagrejs/dagre/lib/order/resolve-conflicts.js
|
|
2468
|
+
var require_resolve_conflicts = __commonJS({
|
|
2469
|
+
"node_modules/@dagrejs/dagre/lib/order/resolve-conflicts.js"(exports2, module2) {
|
|
2470
|
+
"use strict";
|
|
2471
|
+
var util = require_util();
|
|
2472
|
+
module2.exports = resolveConflicts;
|
|
2473
|
+
function resolveConflicts(entries, cg) {
|
|
2474
|
+
let mappedEntries = {};
|
|
2475
|
+
entries.forEach((entry, i) => {
|
|
2476
|
+
let tmp = mappedEntries[entry.v] = {
|
|
2477
|
+
indegree: 0,
|
|
2478
|
+
"in": [],
|
|
2479
|
+
out: [],
|
|
2480
|
+
vs: [entry.v],
|
|
2481
|
+
i
|
|
2482
|
+
};
|
|
2483
|
+
if (entry.barycenter !== void 0) {
|
|
2484
|
+
tmp.barycenter = entry.barycenter;
|
|
2485
|
+
tmp.weight = entry.weight;
|
|
2486
|
+
}
|
|
2487
|
+
});
|
|
2488
|
+
cg.edges().forEach((e) => {
|
|
2489
|
+
let entryV = mappedEntries[e.v];
|
|
2490
|
+
let entryW = mappedEntries[e.w];
|
|
2491
|
+
if (entryV !== void 0 && entryW !== void 0) {
|
|
2492
|
+
entryW.indegree++;
|
|
2493
|
+
entryV.out.push(mappedEntries[e.w]);
|
|
2494
|
+
}
|
|
2495
|
+
});
|
|
2496
|
+
let sourceSet = Object.values(mappedEntries).filter((entry) => !entry.indegree);
|
|
2497
|
+
return doResolveConflicts(sourceSet);
|
|
2498
|
+
}
|
|
2499
|
+
function doResolveConflicts(sourceSet) {
|
|
2500
|
+
let entries = [];
|
|
2501
|
+
function handleIn(vEntry) {
|
|
2502
|
+
return (uEntry) => {
|
|
2503
|
+
if (uEntry.merged) {
|
|
2504
|
+
return;
|
|
2505
|
+
}
|
|
2506
|
+
if (uEntry.barycenter === void 0 || vEntry.barycenter === void 0 || uEntry.barycenter >= vEntry.barycenter) {
|
|
2507
|
+
mergeEntries(vEntry, uEntry);
|
|
2508
|
+
}
|
|
2509
|
+
};
|
|
2510
|
+
}
|
|
2511
|
+
function handleOut(vEntry) {
|
|
2512
|
+
return (wEntry) => {
|
|
2513
|
+
wEntry["in"].push(vEntry);
|
|
2514
|
+
if (--wEntry.indegree === 0) {
|
|
2515
|
+
sourceSet.push(wEntry);
|
|
2516
|
+
}
|
|
2517
|
+
};
|
|
2518
|
+
}
|
|
2519
|
+
while (sourceSet.length) {
|
|
2520
|
+
let entry = sourceSet.pop();
|
|
2521
|
+
entries.push(entry);
|
|
2522
|
+
entry["in"].reverse().forEach(handleIn(entry));
|
|
2523
|
+
entry.out.forEach(handleOut(entry));
|
|
2524
|
+
}
|
|
2525
|
+
return entries.filter((entry) => !entry.merged).map((entry) => {
|
|
2526
|
+
return util.pick(entry, ["vs", "i", "barycenter", "weight"]);
|
|
2527
|
+
});
|
|
2528
|
+
}
|
|
2529
|
+
function mergeEntries(target, source) {
|
|
2530
|
+
let sum = 0;
|
|
2531
|
+
let weight = 0;
|
|
2532
|
+
if (target.weight) {
|
|
2533
|
+
sum += target.barycenter * target.weight;
|
|
2534
|
+
weight += target.weight;
|
|
2535
|
+
}
|
|
2536
|
+
if (source.weight) {
|
|
2537
|
+
sum += source.barycenter * source.weight;
|
|
2538
|
+
weight += source.weight;
|
|
2539
|
+
}
|
|
2540
|
+
target.vs = source.vs.concat(target.vs);
|
|
2541
|
+
target.barycenter = sum / weight;
|
|
2542
|
+
target.weight = weight;
|
|
2543
|
+
target.i = Math.min(source.i, target.i);
|
|
2544
|
+
source.merged = true;
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
});
|
|
2548
|
+
|
|
2549
|
+
// node_modules/@dagrejs/dagre/lib/order/sort.js
|
|
2550
|
+
var require_sort = __commonJS({
|
|
2551
|
+
"node_modules/@dagrejs/dagre/lib/order/sort.js"(exports2, module2) {
|
|
2552
|
+
"use strict";
|
|
2553
|
+
var util = require_util();
|
|
2554
|
+
module2.exports = sort;
|
|
2555
|
+
function sort(entries, biasRight) {
|
|
2556
|
+
let parts = util.partition(entries, (entry) => {
|
|
2557
|
+
return Object.hasOwn(entry, "barycenter");
|
|
2558
|
+
});
|
|
2559
|
+
let sortable = parts.lhs, unsortable = parts.rhs.sort((a, b) => b.i - a.i), vs = [], sum = 0, weight = 0, vsIndex = 0;
|
|
2560
|
+
sortable.sort(compareWithBias(!!biasRight));
|
|
2561
|
+
vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
|
|
2562
|
+
sortable.forEach((entry) => {
|
|
2563
|
+
vsIndex += entry.vs.length;
|
|
2564
|
+
vs.push(entry.vs);
|
|
2565
|
+
sum += entry.barycenter * entry.weight;
|
|
2566
|
+
weight += entry.weight;
|
|
2567
|
+
vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
|
|
2568
|
+
});
|
|
2569
|
+
let result = { vs: vs.flat(true) };
|
|
2570
|
+
if (weight) {
|
|
2571
|
+
result.barycenter = sum / weight;
|
|
2572
|
+
result.weight = weight;
|
|
2573
|
+
}
|
|
2574
|
+
return result;
|
|
2575
|
+
}
|
|
2576
|
+
function consumeUnsortable(vs, unsortable, index) {
|
|
2577
|
+
let last;
|
|
2578
|
+
while (unsortable.length && (last = unsortable[unsortable.length - 1]).i <= index) {
|
|
2579
|
+
unsortable.pop();
|
|
2580
|
+
vs.push(last.vs);
|
|
2581
|
+
index++;
|
|
2582
|
+
}
|
|
2583
|
+
return index;
|
|
2584
|
+
}
|
|
2585
|
+
function compareWithBias(bias) {
|
|
2586
|
+
return (entryV, entryW) => {
|
|
2587
|
+
if (entryV.barycenter < entryW.barycenter) {
|
|
2588
|
+
return -1;
|
|
2589
|
+
} else if (entryV.barycenter > entryW.barycenter) {
|
|
2590
|
+
return 1;
|
|
2591
|
+
}
|
|
2592
|
+
return !bias ? entryV.i - entryW.i : entryW.i - entryV.i;
|
|
2593
|
+
};
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
});
|
|
2597
|
+
|
|
2598
|
+
// node_modules/@dagrejs/dagre/lib/order/sort-subgraph.js
|
|
2599
|
+
var require_sort_subgraph = __commonJS({
|
|
2600
|
+
"node_modules/@dagrejs/dagre/lib/order/sort-subgraph.js"(exports2, module2) {
|
|
2601
|
+
"use strict";
|
|
2602
|
+
var barycenter = require_barycenter();
|
|
2603
|
+
var resolveConflicts = require_resolve_conflicts();
|
|
2604
|
+
var sort = require_sort();
|
|
2605
|
+
module2.exports = sortSubgraph;
|
|
2606
|
+
function sortSubgraph(g, v, cg, biasRight) {
|
|
2607
|
+
let movable = g.children(v);
|
|
2608
|
+
let node = g.node(v);
|
|
2609
|
+
let bl = node ? node.borderLeft : void 0;
|
|
2610
|
+
let br = node ? node.borderRight : void 0;
|
|
2611
|
+
let subgraphs = {};
|
|
2612
|
+
if (bl) {
|
|
2613
|
+
movable = movable.filter((w) => w !== bl && w !== br);
|
|
2614
|
+
}
|
|
2615
|
+
let barycenters = barycenter(g, movable);
|
|
2616
|
+
barycenters.forEach((entry) => {
|
|
2617
|
+
if (g.children(entry.v).length) {
|
|
2618
|
+
let subgraphResult = sortSubgraph(g, entry.v, cg, biasRight);
|
|
2619
|
+
subgraphs[entry.v] = subgraphResult;
|
|
2620
|
+
if (Object.hasOwn(subgraphResult, "barycenter")) {
|
|
2621
|
+
mergeBarycenters(entry, subgraphResult);
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
});
|
|
2625
|
+
let entries = resolveConflicts(barycenters, cg);
|
|
2626
|
+
expandSubgraphs(entries, subgraphs);
|
|
2627
|
+
let result = sort(entries, biasRight);
|
|
2628
|
+
if (bl) {
|
|
2629
|
+
result.vs = [bl, result.vs, br].flat(true);
|
|
2630
|
+
if (g.predecessors(bl).length) {
|
|
2631
|
+
let blPred = g.node(g.predecessors(bl)[0]), brPred = g.node(g.predecessors(br)[0]);
|
|
2632
|
+
if (!Object.hasOwn(result, "barycenter")) {
|
|
2633
|
+
result.barycenter = 0;
|
|
2634
|
+
result.weight = 0;
|
|
2635
|
+
}
|
|
2636
|
+
result.barycenter = (result.barycenter * result.weight + blPred.order + brPred.order) / (result.weight + 2);
|
|
2637
|
+
result.weight += 2;
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
return result;
|
|
2641
|
+
}
|
|
2642
|
+
function expandSubgraphs(entries, subgraphs) {
|
|
2643
|
+
entries.forEach((entry) => {
|
|
2644
|
+
entry.vs = entry.vs.flatMap((v) => {
|
|
2645
|
+
if (subgraphs[v]) {
|
|
2646
|
+
return subgraphs[v].vs;
|
|
2647
|
+
}
|
|
2648
|
+
return v;
|
|
2649
|
+
});
|
|
2650
|
+
});
|
|
2651
|
+
}
|
|
2652
|
+
function mergeBarycenters(target, other) {
|
|
2653
|
+
if (target.barycenter !== void 0) {
|
|
2654
|
+
target.barycenter = (target.barycenter * target.weight + other.barycenter * other.weight) / (target.weight + other.weight);
|
|
2655
|
+
target.weight += other.weight;
|
|
2656
|
+
} else {
|
|
2657
|
+
target.barycenter = other.barycenter;
|
|
2658
|
+
target.weight = other.weight;
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
});
|
|
2663
|
+
|
|
2664
|
+
// node_modules/@dagrejs/dagre/lib/order/build-layer-graph.js
|
|
2665
|
+
var require_build_layer_graph = __commonJS({
|
|
2666
|
+
"node_modules/@dagrejs/dagre/lib/order/build-layer-graph.js"(exports2, module2) {
|
|
2667
|
+
"use strict";
|
|
2668
|
+
var Graph = require_graphlib().Graph;
|
|
2669
|
+
var util = require_util();
|
|
2670
|
+
module2.exports = buildLayerGraph;
|
|
2671
|
+
function buildLayerGraph(g, rank, relationship, nodesWithRank) {
|
|
2672
|
+
if (!nodesWithRank) {
|
|
2673
|
+
nodesWithRank = g.nodes();
|
|
2674
|
+
}
|
|
2675
|
+
let root = createRootNode(g), result = new Graph({ compound: true }).setGraph({ root }).setDefaultNodeLabel((v) => g.node(v));
|
|
2676
|
+
nodesWithRank.forEach((v) => {
|
|
2677
|
+
let node = g.node(v), parent = g.parent(v);
|
|
2678
|
+
if (node.rank === rank || node.minRank <= rank && rank <= node.maxRank) {
|
|
2679
|
+
result.setNode(v);
|
|
2680
|
+
result.setParent(v, parent || root);
|
|
2681
|
+
g[relationship](v).forEach((e) => {
|
|
2682
|
+
let u = e.v === v ? e.w : e.v, edge = result.edge(u, v), weight = edge !== void 0 ? edge.weight : 0;
|
|
2683
|
+
result.setEdge(u, v, { weight: g.edge(e).weight + weight });
|
|
2684
|
+
});
|
|
2685
|
+
if (Object.hasOwn(node, "minRank")) {
|
|
2686
|
+
result.setNode(v, {
|
|
2687
|
+
borderLeft: node.borderLeft[rank],
|
|
2688
|
+
borderRight: node.borderRight[rank]
|
|
2689
|
+
});
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
});
|
|
2693
|
+
return result;
|
|
2694
|
+
}
|
|
2695
|
+
function createRootNode(g) {
|
|
2696
|
+
var v;
|
|
2697
|
+
while (g.hasNode(v = util.uniqueId("_root"))) ;
|
|
2698
|
+
return v;
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
});
|
|
2702
|
+
|
|
2703
|
+
// node_modules/@dagrejs/dagre/lib/order/add-subgraph-constraints.js
|
|
2704
|
+
var require_add_subgraph_constraints = __commonJS({
|
|
2705
|
+
"node_modules/@dagrejs/dagre/lib/order/add-subgraph-constraints.js"(exports2, module2) {
|
|
2706
|
+
"use strict";
|
|
2707
|
+
module2.exports = addSubgraphConstraints;
|
|
2708
|
+
function addSubgraphConstraints(g, cg, vs) {
|
|
2709
|
+
let prev = {}, rootPrev;
|
|
2710
|
+
vs.forEach((v) => {
|
|
2711
|
+
let child = g.parent(v), parent, prevChild;
|
|
2712
|
+
while (child) {
|
|
2713
|
+
parent = g.parent(child);
|
|
2714
|
+
if (parent) {
|
|
2715
|
+
prevChild = prev[parent];
|
|
2716
|
+
prev[parent] = child;
|
|
2717
|
+
} else {
|
|
2718
|
+
prevChild = rootPrev;
|
|
2719
|
+
rootPrev = child;
|
|
2720
|
+
}
|
|
2721
|
+
if (prevChild && prevChild !== child) {
|
|
2722
|
+
cg.setEdge(prevChild, child);
|
|
2723
|
+
return;
|
|
2724
|
+
}
|
|
2725
|
+
child = parent;
|
|
2726
|
+
}
|
|
2727
|
+
});
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
});
|
|
2731
|
+
|
|
2732
|
+
// node_modules/@dagrejs/dagre/lib/order/index.js
|
|
2733
|
+
var require_order = __commonJS({
|
|
2734
|
+
"node_modules/@dagrejs/dagre/lib/order/index.js"(exports2, module2) {
|
|
2735
|
+
"use strict";
|
|
2736
|
+
var initOrder = require_init_order();
|
|
2737
|
+
var crossCount = require_cross_count();
|
|
2738
|
+
var sortSubgraph = require_sort_subgraph();
|
|
2739
|
+
var buildLayerGraph = require_build_layer_graph();
|
|
2740
|
+
var addSubgraphConstraints = require_add_subgraph_constraints();
|
|
2741
|
+
var Graph = require_graphlib().Graph;
|
|
2742
|
+
var util = require_util();
|
|
2743
|
+
module2.exports = order;
|
|
2744
|
+
function order(g, opts) {
|
|
2745
|
+
if (opts && typeof opts.customOrder === "function") {
|
|
2746
|
+
opts.customOrder(g, order);
|
|
2747
|
+
return;
|
|
2748
|
+
}
|
|
2749
|
+
let maxRank = util.maxRank(g), downLayerGraphs = buildLayerGraphs(g, util.range(1, maxRank + 1), "inEdges"), upLayerGraphs = buildLayerGraphs(g, util.range(maxRank - 1, -1, -1), "outEdges");
|
|
2750
|
+
let layering = initOrder(g);
|
|
2751
|
+
assignOrder(g, layering);
|
|
2752
|
+
if (opts && opts.disableOptimalOrderHeuristic) {
|
|
2753
|
+
return;
|
|
2754
|
+
}
|
|
2755
|
+
let bestCC = Number.POSITIVE_INFINITY, best;
|
|
2756
|
+
for (let i = 0, lastBest = 0; lastBest < 4; ++i, ++lastBest) {
|
|
2757
|
+
sweepLayerGraphs(i % 2 ? downLayerGraphs : upLayerGraphs, i % 4 >= 2);
|
|
2758
|
+
layering = util.buildLayerMatrix(g);
|
|
2759
|
+
let cc = crossCount(g, layering);
|
|
2760
|
+
if (cc < bestCC) {
|
|
2761
|
+
lastBest = 0;
|
|
2762
|
+
best = Object.assign({}, layering);
|
|
2763
|
+
bestCC = cc;
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
assignOrder(g, best);
|
|
2767
|
+
}
|
|
2768
|
+
function buildLayerGraphs(g, ranks, relationship) {
|
|
2769
|
+
const nodesByRank = /* @__PURE__ */ new Map();
|
|
2770
|
+
const addNodeToRank = (rank, node) => {
|
|
2771
|
+
if (!nodesByRank.has(rank)) {
|
|
2772
|
+
nodesByRank.set(rank, []);
|
|
2773
|
+
}
|
|
2774
|
+
nodesByRank.get(rank).push(node);
|
|
2775
|
+
};
|
|
2776
|
+
for (const v of g.nodes()) {
|
|
2777
|
+
const node = g.node(v);
|
|
2778
|
+
if (typeof node.rank === "number") {
|
|
2779
|
+
addNodeToRank(node.rank, v);
|
|
2780
|
+
}
|
|
2781
|
+
if (typeof node.minRank === "number" && typeof node.maxRank === "number") {
|
|
2782
|
+
for (let r = node.minRank; r <= node.maxRank; r++) {
|
|
2783
|
+
if (r !== node.rank) {
|
|
2784
|
+
addNodeToRank(r, v);
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
return ranks.map(function(rank) {
|
|
2790
|
+
return buildLayerGraph(g, rank, relationship, nodesByRank.get(rank) || []);
|
|
2791
|
+
});
|
|
2792
|
+
}
|
|
2793
|
+
function sweepLayerGraphs(layerGraphs, biasRight) {
|
|
2794
|
+
let cg = new Graph();
|
|
2795
|
+
layerGraphs.forEach(function(lg) {
|
|
2796
|
+
let root = lg.graph().root;
|
|
2797
|
+
let sorted = sortSubgraph(lg, root, cg, biasRight);
|
|
2798
|
+
sorted.vs.forEach((v, i) => lg.node(v).order = i);
|
|
2799
|
+
addSubgraphConstraints(lg, cg, sorted.vs);
|
|
2800
|
+
});
|
|
2801
|
+
}
|
|
2802
|
+
function assignOrder(g, layering) {
|
|
2803
|
+
Object.values(layering).forEach((layer) => layer.forEach((v, i) => g.node(v).order = i));
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
});
|
|
2807
|
+
|
|
2808
|
+
// node_modules/@dagrejs/dagre/lib/position/bk.js
|
|
2809
|
+
var require_bk = __commonJS({
|
|
2810
|
+
"node_modules/@dagrejs/dagre/lib/position/bk.js"(exports2, module2) {
|
|
2811
|
+
"use strict";
|
|
2812
|
+
var Graph = require_graphlib().Graph;
|
|
2813
|
+
var util = require_util();
|
|
2814
|
+
module2.exports = {
|
|
2815
|
+
positionX,
|
|
2816
|
+
findType1Conflicts,
|
|
2817
|
+
findType2Conflicts,
|
|
2818
|
+
addConflict,
|
|
2819
|
+
hasConflict,
|
|
2820
|
+
verticalAlignment,
|
|
2821
|
+
horizontalCompaction,
|
|
2822
|
+
alignCoordinates,
|
|
2823
|
+
findSmallestWidthAlignment,
|
|
2824
|
+
balance
|
|
2825
|
+
};
|
|
2826
|
+
function findType1Conflicts(g, layering) {
|
|
2827
|
+
let conflicts = {};
|
|
2828
|
+
function visitLayer(prevLayer, layer) {
|
|
2829
|
+
let k0 = 0, scanPos = 0, prevLayerLength = prevLayer.length, lastNode = layer[layer.length - 1];
|
|
2830
|
+
layer.forEach((v, i) => {
|
|
2831
|
+
let w = findOtherInnerSegmentNode(g, v), k1 = w ? g.node(w).order : prevLayerLength;
|
|
2832
|
+
if (w || v === lastNode) {
|
|
2833
|
+
layer.slice(scanPos, i + 1).forEach((scanNode) => {
|
|
2834
|
+
g.predecessors(scanNode).forEach((u) => {
|
|
2835
|
+
let uLabel = g.node(u), uPos = uLabel.order;
|
|
2836
|
+
if ((uPos < k0 || k1 < uPos) && !(uLabel.dummy && g.node(scanNode).dummy)) {
|
|
2837
|
+
addConflict(conflicts, u, scanNode);
|
|
2838
|
+
}
|
|
2839
|
+
});
|
|
2840
|
+
});
|
|
2841
|
+
scanPos = i + 1;
|
|
2842
|
+
k0 = k1;
|
|
2843
|
+
}
|
|
2844
|
+
});
|
|
2845
|
+
return layer;
|
|
2846
|
+
}
|
|
2847
|
+
layering.length && layering.reduce(visitLayer);
|
|
2848
|
+
return conflicts;
|
|
2849
|
+
}
|
|
2850
|
+
function findType2Conflicts(g, layering) {
|
|
2851
|
+
let conflicts = {};
|
|
2852
|
+
function scan(south, southPos, southEnd, prevNorthBorder, nextNorthBorder) {
|
|
2853
|
+
let v;
|
|
2854
|
+
util.range(southPos, southEnd).forEach((i) => {
|
|
2855
|
+
v = south[i];
|
|
2856
|
+
if (g.node(v).dummy) {
|
|
2857
|
+
g.predecessors(v).forEach((u) => {
|
|
2858
|
+
let uNode = g.node(u);
|
|
2859
|
+
if (uNode.dummy && (uNode.order < prevNorthBorder || uNode.order > nextNorthBorder)) {
|
|
2860
|
+
addConflict(conflicts, u, v);
|
|
2861
|
+
}
|
|
2862
|
+
});
|
|
2863
|
+
}
|
|
2864
|
+
});
|
|
2865
|
+
}
|
|
2866
|
+
function visitLayer(north, south) {
|
|
2867
|
+
let prevNorthPos = -1, nextNorthPos, southPos = 0;
|
|
2868
|
+
south.forEach((v, southLookahead) => {
|
|
2869
|
+
if (g.node(v).dummy === "border") {
|
|
2870
|
+
let predecessors = g.predecessors(v);
|
|
2871
|
+
if (predecessors.length) {
|
|
2872
|
+
nextNorthPos = g.node(predecessors[0]).order;
|
|
2873
|
+
scan(south, southPos, southLookahead, prevNorthPos, nextNorthPos);
|
|
2874
|
+
southPos = southLookahead;
|
|
2875
|
+
prevNorthPos = nextNorthPos;
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
scan(south, southPos, south.length, nextNorthPos, north.length);
|
|
2879
|
+
});
|
|
2880
|
+
return south;
|
|
2881
|
+
}
|
|
2882
|
+
layering.length && layering.reduce(visitLayer);
|
|
2883
|
+
return conflicts;
|
|
2884
|
+
}
|
|
2885
|
+
function findOtherInnerSegmentNode(g, v) {
|
|
2886
|
+
if (g.node(v).dummy) {
|
|
2887
|
+
return g.predecessors(v).find((u) => g.node(u).dummy);
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
function addConflict(conflicts, v, w) {
|
|
2891
|
+
if (v > w) {
|
|
2892
|
+
let tmp = v;
|
|
2893
|
+
v = w;
|
|
2894
|
+
w = tmp;
|
|
2895
|
+
}
|
|
2896
|
+
let conflictsV = conflicts[v];
|
|
2897
|
+
if (!conflictsV) {
|
|
2898
|
+
conflicts[v] = conflictsV = {};
|
|
2899
|
+
}
|
|
2900
|
+
conflictsV[w] = true;
|
|
2901
|
+
}
|
|
2902
|
+
function hasConflict(conflicts, v, w) {
|
|
2903
|
+
if (v > w) {
|
|
2904
|
+
let tmp = v;
|
|
2905
|
+
v = w;
|
|
2906
|
+
w = tmp;
|
|
2907
|
+
}
|
|
2908
|
+
return !!conflicts[v] && Object.hasOwn(conflicts[v], w);
|
|
2909
|
+
}
|
|
2910
|
+
function verticalAlignment(g, layering, conflicts, neighborFn) {
|
|
2911
|
+
let root = {}, align = {}, pos = {};
|
|
2912
|
+
layering.forEach((layer) => {
|
|
2913
|
+
layer.forEach((v, order) => {
|
|
2914
|
+
root[v] = v;
|
|
2915
|
+
align[v] = v;
|
|
2916
|
+
pos[v] = order;
|
|
2917
|
+
});
|
|
2918
|
+
});
|
|
2919
|
+
layering.forEach((layer) => {
|
|
2920
|
+
let prevIdx = -1;
|
|
2921
|
+
layer.forEach((v) => {
|
|
2922
|
+
let ws = neighborFn(v);
|
|
2923
|
+
if (ws.length) {
|
|
2924
|
+
ws = ws.sort((a, b) => pos[a] - pos[b]);
|
|
2925
|
+
let mp = (ws.length - 1) / 2;
|
|
2926
|
+
for (let i = Math.floor(mp), il = Math.ceil(mp); i <= il; ++i) {
|
|
2927
|
+
let w = ws[i];
|
|
2928
|
+
if (align[v] === v && prevIdx < pos[w] && !hasConflict(conflicts, v, w)) {
|
|
2929
|
+
align[w] = v;
|
|
2930
|
+
align[v] = root[v] = root[w];
|
|
2931
|
+
prevIdx = pos[w];
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
});
|
|
2936
|
+
});
|
|
2937
|
+
return { root, align };
|
|
2938
|
+
}
|
|
2939
|
+
function horizontalCompaction(g, layering, root, align, reverseSep) {
|
|
2940
|
+
let xs = {}, blockG = buildBlockGraph(g, layering, root, reverseSep), borderType = reverseSep ? "borderLeft" : "borderRight";
|
|
2941
|
+
function iterate(setXsFunc, nextNodesFunc) {
|
|
2942
|
+
let stack = blockG.nodes();
|
|
2943
|
+
let elem = stack.pop();
|
|
2944
|
+
let visited = {};
|
|
2945
|
+
while (elem) {
|
|
2946
|
+
if (visited[elem]) {
|
|
2947
|
+
setXsFunc(elem);
|
|
2948
|
+
} else {
|
|
2949
|
+
visited[elem] = true;
|
|
2950
|
+
stack.push(elem);
|
|
2951
|
+
stack = stack.concat(nextNodesFunc(elem));
|
|
2952
|
+
}
|
|
2953
|
+
elem = stack.pop();
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
function pass1(elem) {
|
|
2957
|
+
xs[elem] = blockG.inEdges(elem).reduce((acc, e) => {
|
|
2958
|
+
return Math.max(acc, xs[e.v] + blockG.edge(e));
|
|
2959
|
+
}, 0);
|
|
2960
|
+
}
|
|
2961
|
+
function pass2(elem) {
|
|
2962
|
+
let min = blockG.outEdges(elem).reduce((acc, e) => {
|
|
2963
|
+
return Math.min(acc, xs[e.w] - blockG.edge(e));
|
|
2964
|
+
}, Number.POSITIVE_INFINITY);
|
|
2965
|
+
let node = g.node(elem);
|
|
2966
|
+
if (min !== Number.POSITIVE_INFINITY && node.borderType !== borderType) {
|
|
2967
|
+
xs[elem] = Math.max(xs[elem], min);
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
iterate(pass1, blockG.predecessors.bind(blockG));
|
|
2971
|
+
iterate(pass2, blockG.successors.bind(blockG));
|
|
2972
|
+
Object.keys(align).forEach((v) => xs[v] = xs[root[v]]);
|
|
2973
|
+
return xs;
|
|
2974
|
+
}
|
|
2975
|
+
function buildBlockGraph(g, layering, root, reverseSep) {
|
|
2976
|
+
let blockGraph = new Graph(), graphLabel = g.graph(), sepFn = sep(graphLabel.nodesep, graphLabel.edgesep, reverseSep);
|
|
2977
|
+
layering.forEach((layer) => {
|
|
2978
|
+
let u;
|
|
2979
|
+
layer.forEach((v) => {
|
|
2980
|
+
let vRoot = root[v];
|
|
2981
|
+
blockGraph.setNode(vRoot);
|
|
2982
|
+
if (u) {
|
|
2983
|
+
var uRoot = root[u], prevMax = blockGraph.edge(uRoot, vRoot);
|
|
2984
|
+
blockGraph.setEdge(uRoot, vRoot, Math.max(sepFn(g, v, u), prevMax || 0));
|
|
2985
|
+
}
|
|
2986
|
+
u = v;
|
|
2987
|
+
});
|
|
2988
|
+
});
|
|
2989
|
+
return blockGraph;
|
|
2990
|
+
}
|
|
2991
|
+
function findSmallestWidthAlignment(g, xss) {
|
|
2992
|
+
return Object.values(xss).reduce((currentMinAndXs, xs) => {
|
|
2993
|
+
let max = Number.NEGATIVE_INFINITY;
|
|
2994
|
+
let min = Number.POSITIVE_INFINITY;
|
|
2995
|
+
Object.entries(xs).forEach(([v, x]) => {
|
|
2996
|
+
let halfWidth = width(g, v) / 2;
|
|
2997
|
+
max = Math.max(x + halfWidth, max);
|
|
2998
|
+
min = Math.min(x - halfWidth, min);
|
|
2999
|
+
});
|
|
3000
|
+
const newMin = max - min;
|
|
3001
|
+
if (newMin < currentMinAndXs[0]) {
|
|
3002
|
+
currentMinAndXs = [newMin, xs];
|
|
3003
|
+
}
|
|
3004
|
+
return currentMinAndXs;
|
|
3005
|
+
}, [Number.POSITIVE_INFINITY, null])[1];
|
|
3006
|
+
}
|
|
3007
|
+
function alignCoordinates(xss, alignTo) {
|
|
3008
|
+
let alignToVals = Object.values(alignTo), alignToMin = util.applyWithChunking(Math.min, alignToVals), alignToMax = util.applyWithChunking(Math.max, alignToVals);
|
|
3009
|
+
["u", "d"].forEach((vert) => {
|
|
3010
|
+
["l", "r"].forEach((horiz) => {
|
|
3011
|
+
let alignment = vert + horiz, xs = xss[alignment];
|
|
3012
|
+
if (xs === alignTo) return;
|
|
3013
|
+
let xsVals = Object.values(xs);
|
|
3014
|
+
let delta = alignToMin - util.applyWithChunking(Math.min, xsVals);
|
|
3015
|
+
if (horiz !== "l") {
|
|
3016
|
+
delta = alignToMax - util.applyWithChunking(Math.max, xsVals);
|
|
3017
|
+
}
|
|
3018
|
+
if (delta) {
|
|
3019
|
+
xss[alignment] = util.mapValues(xs, (x) => x + delta);
|
|
3020
|
+
}
|
|
3021
|
+
});
|
|
3022
|
+
});
|
|
3023
|
+
}
|
|
3024
|
+
function balance(xss, align) {
|
|
3025
|
+
return util.mapValues(xss.ul, (num, v) => {
|
|
3026
|
+
if (align) {
|
|
3027
|
+
return xss[align.toLowerCase()][v];
|
|
3028
|
+
} else {
|
|
3029
|
+
let xs = Object.values(xss).map((xs2) => xs2[v]).sort((a, b) => a - b);
|
|
3030
|
+
return (xs[1] + xs[2]) / 2;
|
|
3031
|
+
}
|
|
3032
|
+
});
|
|
3033
|
+
}
|
|
3034
|
+
function positionX(g) {
|
|
3035
|
+
let layering = util.buildLayerMatrix(g);
|
|
3036
|
+
let conflicts = Object.assign(
|
|
3037
|
+
findType1Conflicts(g, layering),
|
|
3038
|
+
findType2Conflicts(g, layering)
|
|
3039
|
+
);
|
|
3040
|
+
let xss = {};
|
|
3041
|
+
let adjustedLayering;
|
|
3042
|
+
["u", "d"].forEach((vert) => {
|
|
3043
|
+
adjustedLayering = vert === "u" ? layering : Object.values(layering).reverse();
|
|
3044
|
+
["l", "r"].forEach((horiz) => {
|
|
3045
|
+
if (horiz === "r") {
|
|
3046
|
+
adjustedLayering = adjustedLayering.map((inner) => {
|
|
3047
|
+
return Object.values(inner).reverse();
|
|
3048
|
+
});
|
|
3049
|
+
}
|
|
3050
|
+
let neighborFn = (vert === "u" ? g.predecessors : g.successors).bind(g);
|
|
3051
|
+
let align = verticalAlignment(g, adjustedLayering, conflicts, neighborFn);
|
|
3052
|
+
let xs = horizontalCompaction(
|
|
3053
|
+
g,
|
|
3054
|
+
adjustedLayering,
|
|
3055
|
+
align.root,
|
|
3056
|
+
align.align,
|
|
3057
|
+
horiz === "r"
|
|
3058
|
+
);
|
|
3059
|
+
if (horiz === "r") {
|
|
3060
|
+
xs = util.mapValues(xs, (x) => -x);
|
|
3061
|
+
}
|
|
3062
|
+
xss[vert + horiz] = xs;
|
|
3063
|
+
});
|
|
3064
|
+
});
|
|
3065
|
+
let smallestWidth = findSmallestWidthAlignment(g, xss);
|
|
3066
|
+
alignCoordinates(xss, smallestWidth);
|
|
3067
|
+
return balance(xss, g.graph().align);
|
|
3068
|
+
}
|
|
3069
|
+
function sep(nodeSep, edgeSep, reverseSep) {
|
|
3070
|
+
return (g, v, w) => {
|
|
3071
|
+
let vLabel = g.node(v);
|
|
3072
|
+
let wLabel = g.node(w);
|
|
3073
|
+
let sum = 0;
|
|
3074
|
+
let delta;
|
|
3075
|
+
sum += vLabel.width / 2;
|
|
3076
|
+
if (Object.hasOwn(vLabel, "labelpos")) {
|
|
3077
|
+
switch (vLabel.labelpos.toLowerCase()) {
|
|
3078
|
+
case "l":
|
|
3079
|
+
delta = -vLabel.width / 2;
|
|
3080
|
+
break;
|
|
3081
|
+
case "r":
|
|
3082
|
+
delta = vLabel.width / 2;
|
|
3083
|
+
break;
|
|
3084
|
+
}
|
|
3085
|
+
}
|
|
3086
|
+
if (delta) {
|
|
3087
|
+
sum += reverseSep ? delta : -delta;
|
|
3088
|
+
}
|
|
3089
|
+
delta = 0;
|
|
3090
|
+
sum += (vLabel.dummy ? edgeSep : nodeSep) / 2;
|
|
3091
|
+
sum += (wLabel.dummy ? edgeSep : nodeSep) / 2;
|
|
3092
|
+
sum += wLabel.width / 2;
|
|
3093
|
+
if (Object.hasOwn(wLabel, "labelpos")) {
|
|
3094
|
+
switch (wLabel.labelpos.toLowerCase()) {
|
|
3095
|
+
case "l":
|
|
3096
|
+
delta = wLabel.width / 2;
|
|
3097
|
+
break;
|
|
3098
|
+
case "r":
|
|
3099
|
+
delta = -wLabel.width / 2;
|
|
3100
|
+
break;
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
if (delta) {
|
|
3104
|
+
sum += reverseSep ? delta : -delta;
|
|
3105
|
+
}
|
|
3106
|
+
delta = 0;
|
|
3107
|
+
return sum;
|
|
3108
|
+
};
|
|
3109
|
+
}
|
|
3110
|
+
function width(g, v) {
|
|
3111
|
+
return g.node(v).width;
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3114
|
+
});
|
|
3115
|
+
|
|
3116
|
+
// node_modules/@dagrejs/dagre/lib/position/index.js
|
|
3117
|
+
var require_position = __commonJS({
|
|
3118
|
+
"node_modules/@dagrejs/dagre/lib/position/index.js"(exports2, module2) {
|
|
3119
|
+
"use strict";
|
|
3120
|
+
var util = require_util();
|
|
3121
|
+
var positionX = require_bk().positionX;
|
|
3122
|
+
module2.exports = position;
|
|
3123
|
+
function position(g) {
|
|
3124
|
+
g = util.asNonCompoundGraph(g);
|
|
3125
|
+
positionY(g);
|
|
3126
|
+
Object.entries(positionX(g)).forEach(([v, x]) => g.node(v).x = x);
|
|
3127
|
+
}
|
|
3128
|
+
function positionY(g) {
|
|
3129
|
+
let layering = util.buildLayerMatrix(g);
|
|
3130
|
+
let rankSep = g.graph().ranksep;
|
|
3131
|
+
let prevY = 0;
|
|
3132
|
+
layering.forEach((layer) => {
|
|
3133
|
+
const maxHeight = layer.reduce((acc, v) => {
|
|
3134
|
+
const height = g.node(v).height;
|
|
3135
|
+
if (acc > height) {
|
|
3136
|
+
return acc;
|
|
3137
|
+
} else {
|
|
3138
|
+
return height;
|
|
3139
|
+
}
|
|
3140
|
+
}, 0);
|
|
3141
|
+
layer.forEach((v) => g.node(v).y = prevY + maxHeight / 2);
|
|
3142
|
+
prevY += maxHeight + rankSep;
|
|
3143
|
+
});
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
});
|
|
3147
|
+
|
|
3148
|
+
// node_modules/@dagrejs/dagre/lib/layout.js
|
|
3149
|
+
var require_layout = __commonJS({
|
|
3150
|
+
"node_modules/@dagrejs/dagre/lib/layout.js"(exports2, module2) {
|
|
3151
|
+
"use strict";
|
|
3152
|
+
var acyclic = require_acyclic();
|
|
3153
|
+
var normalize2 = require_normalize();
|
|
3154
|
+
var rank = require_rank();
|
|
3155
|
+
var normalizeRanks = require_util().normalizeRanks;
|
|
3156
|
+
var parentDummyChains = require_parent_dummy_chains();
|
|
3157
|
+
var removeEmptyRanks = require_util().removeEmptyRanks;
|
|
3158
|
+
var nestingGraph = require_nesting_graph();
|
|
3159
|
+
var addBorderSegments = require_add_border_segments();
|
|
3160
|
+
var coordinateSystem = require_coordinate_system();
|
|
3161
|
+
var order = require_order();
|
|
3162
|
+
var position = require_position();
|
|
3163
|
+
var util = require_util();
|
|
3164
|
+
var Graph = require_graphlib().Graph;
|
|
3165
|
+
module2.exports = layout2;
|
|
3166
|
+
function layout2(g, opts) {
|
|
3167
|
+
let time = opts && opts.debugTiming ? util.time : util.notime;
|
|
3168
|
+
time("layout", () => {
|
|
3169
|
+
let layoutGraph = time(" buildLayoutGraph", () => buildLayoutGraph(g));
|
|
3170
|
+
time(" runLayout", () => runLayout(layoutGraph, time, opts));
|
|
3171
|
+
time(" updateInputGraph", () => updateInputGraph(g, layoutGraph));
|
|
3172
|
+
});
|
|
3173
|
+
}
|
|
3174
|
+
function runLayout(g, time, opts) {
|
|
3175
|
+
time(" makeSpaceForEdgeLabels", () => makeSpaceForEdgeLabels(g));
|
|
3176
|
+
time(" removeSelfEdges", () => removeSelfEdges(g));
|
|
3177
|
+
time(" acyclic", () => acyclic.run(g));
|
|
3178
|
+
time(" nestingGraph.run", () => nestingGraph.run(g));
|
|
3179
|
+
time(" rank", () => rank(util.asNonCompoundGraph(g)));
|
|
3180
|
+
time(" injectEdgeLabelProxies", () => injectEdgeLabelProxies(g));
|
|
3181
|
+
time(" removeEmptyRanks", () => removeEmptyRanks(g));
|
|
3182
|
+
time(" nestingGraph.cleanup", () => nestingGraph.cleanup(g));
|
|
3183
|
+
time(" normalizeRanks", () => normalizeRanks(g));
|
|
3184
|
+
time(" assignRankMinMax", () => assignRankMinMax(g));
|
|
3185
|
+
time(" removeEdgeLabelProxies", () => removeEdgeLabelProxies(g));
|
|
3186
|
+
time(" normalize.run", () => normalize2.run(g));
|
|
3187
|
+
time(" parentDummyChains", () => parentDummyChains(g));
|
|
3188
|
+
time(" addBorderSegments", () => addBorderSegments(g));
|
|
3189
|
+
time(" order", () => order(g, opts));
|
|
3190
|
+
time(" insertSelfEdges", () => insertSelfEdges(g));
|
|
3191
|
+
time(" adjustCoordinateSystem", () => coordinateSystem.adjust(g));
|
|
3192
|
+
time(" position", () => position(g));
|
|
3193
|
+
time(" positionSelfEdges", () => positionSelfEdges(g));
|
|
3194
|
+
time(" removeBorderNodes", () => removeBorderNodes(g));
|
|
3195
|
+
time(" normalize.undo", () => normalize2.undo(g));
|
|
3196
|
+
time(" fixupEdgeLabelCoords", () => fixupEdgeLabelCoords(g));
|
|
3197
|
+
time(" undoCoordinateSystem", () => coordinateSystem.undo(g));
|
|
3198
|
+
time(" translateGraph", () => translateGraph(g));
|
|
3199
|
+
time(" assignNodeIntersects", () => assignNodeIntersects(g));
|
|
3200
|
+
time(" reversePoints", () => reversePointsForReversedEdges(g));
|
|
3201
|
+
time(" acyclic.undo", () => acyclic.undo(g));
|
|
3202
|
+
}
|
|
3203
|
+
function updateInputGraph(inputGraph, layoutGraph) {
|
|
3204
|
+
inputGraph.nodes().forEach((v) => {
|
|
3205
|
+
let inputLabel = inputGraph.node(v);
|
|
3206
|
+
let layoutLabel = layoutGraph.node(v);
|
|
3207
|
+
if (inputLabel) {
|
|
3208
|
+
inputLabel.x = layoutLabel.x;
|
|
3209
|
+
inputLabel.y = layoutLabel.y;
|
|
3210
|
+
inputLabel.rank = layoutLabel.rank;
|
|
3211
|
+
if (layoutGraph.children(v).length) {
|
|
3212
|
+
inputLabel.width = layoutLabel.width;
|
|
3213
|
+
inputLabel.height = layoutLabel.height;
|
|
3214
|
+
}
|
|
3215
|
+
}
|
|
3216
|
+
});
|
|
3217
|
+
inputGraph.edges().forEach((e) => {
|
|
3218
|
+
let inputLabel = inputGraph.edge(e);
|
|
3219
|
+
let layoutLabel = layoutGraph.edge(e);
|
|
3220
|
+
inputLabel.points = layoutLabel.points;
|
|
3221
|
+
if (Object.hasOwn(layoutLabel, "x")) {
|
|
3222
|
+
inputLabel.x = layoutLabel.x;
|
|
3223
|
+
inputLabel.y = layoutLabel.y;
|
|
3224
|
+
}
|
|
3225
|
+
});
|
|
3226
|
+
inputGraph.graph().width = layoutGraph.graph().width;
|
|
3227
|
+
inputGraph.graph().height = layoutGraph.graph().height;
|
|
3228
|
+
}
|
|
3229
|
+
var graphNumAttrs = ["nodesep", "edgesep", "ranksep", "marginx", "marginy"];
|
|
3230
|
+
var graphDefaults = { ranksep: 50, edgesep: 20, nodesep: 50, rankdir: "tb" };
|
|
3231
|
+
var graphAttrs = ["acyclicer", "ranker", "rankdir", "align"];
|
|
3232
|
+
var nodeNumAttrs = ["width", "height", "rank"];
|
|
3233
|
+
var nodeDefaults = { width: 0, height: 0 };
|
|
3234
|
+
var edgeNumAttrs = ["minlen", "weight", "width", "height", "labeloffset"];
|
|
3235
|
+
var edgeDefaults = {
|
|
3236
|
+
minlen: 1,
|
|
3237
|
+
weight: 1,
|
|
3238
|
+
width: 0,
|
|
3239
|
+
height: 0,
|
|
3240
|
+
labeloffset: 10,
|
|
3241
|
+
labelpos: "r"
|
|
3242
|
+
};
|
|
3243
|
+
var edgeAttrs = ["labelpos"];
|
|
3244
|
+
function buildLayoutGraph(inputGraph) {
|
|
3245
|
+
let g = new Graph({ multigraph: true, compound: true });
|
|
3246
|
+
let graph = canonicalize(inputGraph.graph());
|
|
3247
|
+
g.setGraph(Object.assign(
|
|
3248
|
+
{},
|
|
3249
|
+
graphDefaults,
|
|
3250
|
+
selectNumberAttrs(graph, graphNumAttrs),
|
|
3251
|
+
util.pick(graph, graphAttrs)
|
|
3252
|
+
));
|
|
3253
|
+
inputGraph.nodes().forEach((v) => {
|
|
3254
|
+
let node = canonicalize(inputGraph.node(v));
|
|
3255
|
+
const newNode = selectNumberAttrs(node, nodeNumAttrs);
|
|
3256
|
+
Object.keys(nodeDefaults).forEach((k) => {
|
|
3257
|
+
if (newNode[k] === void 0) {
|
|
3258
|
+
newNode[k] = nodeDefaults[k];
|
|
3259
|
+
}
|
|
3260
|
+
});
|
|
3261
|
+
g.setNode(v, newNode);
|
|
3262
|
+
g.setParent(v, inputGraph.parent(v));
|
|
3263
|
+
});
|
|
3264
|
+
inputGraph.edges().forEach((e) => {
|
|
3265
|
+
let edge = canonicalize(inputGraph.edge(e));
|
|
3266
|
+
g.setEdge(e, Object.assign(
|
|
3267
|
+
{},
|
|
3268
|
+
edgeDefaults,
|
|
3269
|
+
selectNumberAttrs(edge, edgeNumAttrs),
|
|
3270
|
+
util.pick(edge, edgeAttrs)
|
|
3271
|
+
));
|
|
3272
|
+
});
|
|
3273
|
+
return g;
|
|
3274
|
+
}
|
|
3275
|
+
function makeSpaceForEdgeLabels(g) {
|
|
3276
|
+
let graph = g.graph();
|
|
3277
|
+
graph.ranksep /= 2;
|
|
3278
|
+
g.edges().forEach((e) => {
|
|
3279
|
+
let edge = g.edge(e);
|
|
3280
|
+
edge.minlen *= 2;
|
|
3281
|
+
if (edge.labelpos.toLowerCase() !== "c") {
|
|
3282
|
+
if (graph.rankdir === "TB" || graph.rankdir === "BT") {
|
|
3283
|
+
edge.width += edge.labeloffset;
|
|
3284
|
+
} else {
|
|
3285
|
+
edge.height += edge.labeloffset;
|
|
3286
|
+
}
|
|
3287
|
+
}
|
|
3288
|
+
});
|
|
3289
|
+
}
|
|
3290
|
+
function injectEdgeLabelProxies(g) {
|
|
3291
|
+
g.edges().forEach((e) => {
|
|
3292
|
+
let edge = g.edge(e);
|
|
3293
|
+
if (edge.width && edge.height) {
|
|
3294
|
+
let v = g.node(e.v);
|
|
3295
|
+
let w = g.node(e.w);
|
|
3296
|
+
let label = { rank: (w.rank - v.rank) / 2 + v.rank, e };
|
|
3297
|
+
util.addDummyNode(g, "edge-proxy", label, "_ep");
|
|
3298
|
+
}
|
|
3299
|
+
});
|
|
3300
|
+
}
|
|
3301
|
+
function assignRankMinMax(g) {
|
|
3302
|
+
let maxRank = 0;
|
|
3303
|
+
g.nodes().forEach((v) => {
|
|
3304
|
+
let node = g.node(v);
|
|
3305
|
+
if (node.borderTop) {
|
|
3306
|
+
node.minRank = g.node(node.borderTop).rank;
|
|
3307
|
+
node.maxRank = g.node(node.borderBottom).rank;
|
|
3308
|
+
maxRank = Math.max(maxRank, node.maxRank);
|
|
3309
|
+
}
|
|
3310
|
+
});
|
|
3311
|
+
g.graph().maxRank = maxRank;
|
|
3312
|
+
}
|
|
3313
|
+
function removeEdgeLabelProxies(g) {
|
|
3314
|
+
g.nodes().forEach((v) => {
|
|
3315
|
+
let node = g.node(v);
|
|
3316
|
+
if (node.dummy === "edge-proxy") {
|
|
3317
|
+
g.edge(node.e).labelRank = node.rank;
|
|
3318
|
+
g.removeNode(v);
|
|
3319
|
+
}
|
|
3320
|
+
});
|
|
3321
|
+
}
|
|
3322
|
+
function translateGraph(g) {
|
|
3323
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
3324
|
+
let maxX = 0;
|
|
3325
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
3326
|
+
let maxY = 0;
|
|
3327
|
+
let graphLabel = g.graph();
|
|
3328
|
+
let marginX = graphLabel.marginx || 0;
|
|
3329
|
+
let marginY = graphLabel.marginy || 0;
|
|
3330
|
+
function getExtremes(attrs) {
|
|
3331
|
+
let x = attrs.x;
|
|
3332
|
+
let y = attrs.y;
|
|
3333
|
+
let w = attrs.width;
|
|
3334
|
+
let h = attrs.height;
|
|
3335
|
+
minX = Math.min(minX, x - w / 2);
|
|
3336
|
+
maxX = Math.max(maxX, x + w / 2);
|
|
3337
|
+
minY = Math.min(minY, y - h / 2);
|
|
3338
|
+
maxY = Math.max(maxY, y + h / 2);
|
|
3339
|
+
}
|
|
3340
|
+
g.nodes().forEach((v) => getExtremes(g.node(v)));
|
|
3341
|
+
g.edges().forEach((e) => {
|
|
3342
|
+
let edge = g.edge(e);
|
|
3343
|
+
if (Object.hasOwn(edge, "x")) {
|
|
3344
|
+
getExtremes(edge);
|
|
3345
|
+
}
|
|
3346
|
+
});
|
|
3347
|
+
minX -= marginX;
|
|
3348
|
+
minY -= marginY;
|
|
3349
|
+
g.nodes().forEach((v) => {
|
|
3350
|
+
let node = g.node(v);
|
|
3351
|
+
node.x -= minX;
|
|
3352
|
+
node.y -= minY;
|
|
3353
|
+
});
|
|
3354
|
+
g.edges().forEach((e) => {
|
|
3355
|
+
let edge = g.edge(e);
|
|
3356
|
+
edge.points.forEach((p) => {
|
|
3357
|
+
p.x -= minX;
|
|
3358
|
+
p.y -= minY;
|
|
3359
|
+
});
|
|
3360
|
+
if (Object.hasOwn(edge, "x")) {
|
|
3361
|
+
edge.x -= minX;
|
|
3362
|
+
}
|
|
3363
|
+
if (Object.hasOwn(edge, "y")) {
|
|
3364
|
+
edge.y -= minY;
|
|
3365
|
+
}
|
|
3366
|
+
});
|
|
3367
|
+
graphLabel.width = maxX - minX + marginX;
|
|
3368
|
+
graphLabel.height = maxY - minY + marginY;
|
|
3369
|
+
}
|
|
3370
|
+
function assignNodeIntersects(g) {
|
|
3371
|
+
g.edges().forEach((e) => {
|
|
3372
|
+
let edge = g.edge(e);
|
|
3373
|
+
let nodeV = g.node(e.v);
|
|
3374
|
+
let nodeW = g.node(e.w);
|
|
3375
|
+
let p1, p2;
|
|
3376
|
+
if (!edge.points) {
|
|
3377
|
+
edge.points = [];
|
|
3378
|
+
p1 = nodeW;
|
|
3379
|
+
p2 = nodeV;
|
|
3380
|
+
} else {
|
|
3381
|
+
p1 = edge.points[0];
|
|
3382
|
+
p2 = edge.points[edge.points.length - 1];
|
|
3383
|
+
}
|
|
3384
|
+
edge.points.unshift(util.intersectRect(nodeV, p1));
|
|
3385
|
+
edge.points.push(util.intersectRect(nodeW, p2));
|
|
3386
|
+
});
|
|
3387
|
+
}
|
|
3388
|
+
function fixupEdgeLabelCoords(g) {
|
|
3389
|
+
g.edges().forEach((e) => {
|
|
3390
|
+
let edge = g.edge(e);
|
|
3391
|
+
if (Object.hasOwn(edge, "x")) {
|
|
3392
|
+
if (edge.labelpos === "l" || edge.labelpos === "r") {
|
|
3393
|
+
edge.width -= edge.labeloffset;
|
|
3394
|
+
}
|
|
3395
|
+
switch (edge.labelpos) {
|
|
3396
|
+
case "l":
|
|
3397
|
+
edge.x -= edge.width / 2 + edge.labeloffset;
|
|
3398
|
+
break;
|
|
3399
|
+
case "r":
|
|
3400
|
+
edge.x += edge.width / 2 + edge.labeloffset;
|
|
3401
|
+
break;
|
|
3402
|
+
}
|
|
3403
|
+
}
|
|
3404
|
+
});
|
|
3405
|
+
}
|
|
3406
|
+
function reversePointsForReversedEdges(g) {
|
|
3407
|
+
g.edges().forEach((e) => {
|
|
3408
|
+
let edge = g.edge(e);
|
|
3409
|
+
if (edge.reversed) {
|
|
3410
|
+
edge.points.reverse();
|
|
3411
|
+
}
|
|
3412
|
+
});
|
|
3413
|
+
}
|
|
3414
|
+
function removeBorderNodes(g) {
|
|
3415
|
+
g.nodes().forEach((v) => {
|
|
3416
|
+
if (g.children(v).length) {
|
|
3417
|
+
let node = g.node(v);
|
|
3418
|
+
let t = g.node(node.borderTop);
|
|
3419
|
+
let b = g.node(node.borderBottom);
|
|
3420
|
+
let l = g.node(node.borderLeft[node.borderLeft.length - 1]);
|
|
3421
|
+
let r = g.node(node.borderRight[node.borderRight.length - 1]);
|
|
3422
|
+
node.width = Math.abs(r.x - l.x);
|
|
3423
|
+
node.height = Math.abs(b.y - t.y);
|
|
3424
|
+
node.x = l.x + node.width / 2;
|
|
3425
|
+
node.y = t.y + node.height / 2;
|
|
3426
|
+
}
|
|
3427
|
+
});
|
|
3428
|
+
g.nodes().forEach((v) => {
|
|
3429
|
+
if (g.node(v).dummy === "border") {
|
|
3430
|
+
g.removeNode(v);
|
|
3431
|
+
}
|
|
3432
|
+
});
|
|
3433
|
+
}
|
|
3434
|
+
function removeSelfEdges(g) {
|
|
3435
|
+
g.edges().forEach((e) => {
|
|
3436
|
+
if (e.v === e.w) {
|
|
3437
|
+
var node = g.node(e.v);
|
|
3438
|
+
if (!node.selfEdges) {
|
|
3439
|
+
node.selfEdges = [];
|
|
3440
|
+
}
|
|
3441
|
+
node.selfEdges.push({ e, label: g.edge(e) });
|
|
3442
|
+
g.removeEdge(e);
|
|
3443
|
+
}
|
|
3444
|
+
});
|
|
3445
|
+
}
|
|
3446
|
+
function insertSelfEdges(g) {
|
|
3447
|
+
var layers = util.buildLayerMatrix(g);
|
|
3448
|
+
layers.forEach((layer) => {
|
|
3449
|
+
var orderShift = 0;
|
|
3450
|
+
layer.forEach((v, i) => {
|
|
3451
|
+
var node = g.node(v);
|
|
3452
|
+
node.order = i + orderShift;
|
|
3453
|
+
(node.selfEdges || []).forEach((selfEdge) => {
|
|
3454
|
+
util.addDummyNode(g, "selfedge", {
|
|
3455
|
+
width: selfEdge.label.width,
|
|
3456
|
+
height: selfEdge.label.height,
|
|
3457
|
+
rank: node.rank,
|
|
3458
|
+
order: i + ++orderShift,
|
|
3459
|
+
e: selfEdge.e,
|
|
3460
|
+
label: selfEdge.label
|
|
3461
|
+
}, "_se");
|
|
3462
|
+
});
|
|
3463
|
+
delete node.selfEdges;
|
|
3464
|
+
});
|
|
3465
|
+
});
|
|
3466
|
+
}
|
|
3467
|
+
function positionSelfEdges(g) {
|
|
3468
|
+
g.nodes().forEach((v) => {
|
|
3469
|
+
var node = g.node(v);
|
|
3470
|
+
if (node.dummy === "selfedge") {
|
|
3471
|
+
var selfNode = g.node(node.e.v);
|
|
3472
|
+
var x = selfNode.x + selfNode.width / 2;
|
|
3473
|
+
var y = selfNode.y;
|
|
3474
|
+
var dx = node.x - x;
|
|
3475
|
+
var dy = selfNode.height / 2;
|
|
3476
|
+
g.setEdge(node.e, node.label);
|
|
3477
|
+
g.removeNode(v);
|
|
3478
|
+
node.label.points = [
|
|
3479
|
+
{ x: x + 2 * dx / 3, y: y - dy },
|
|
3480
|
+
{ x: x + 5 * dx / 6, y: y - dy },
|
|
3481
|
+
{ x: x + dx, y },
|
|
3482
|
+
{ x: x + 5 * dx / 6, y: y + dy },
|
|
3483
|
+
{ x: x + 2 * dx / 3, y: y + dy }
|
|
3484
|
+
];
|
|
3485
|
+
node.label.x = node.x;
|
|
3486
|
+
node.label.y = node.y;
|
|
3487
|
+
}
|
|
3488
|
+
});
|
|
3489
|
+
}
|
|
3490
|
+
function selectNumberAttrs(obj, attrs) {
|
|
3491
|
+
return util.mapValues(util.pick(obj, attrs), Number);
|
|
3492
|
+
}
|
|
3493
|
+
function canonicalize(attrs) {
|
|
3494
|
+
var newAttrs = {};
|
|
3495
|
+
if (attrs) {
|
|
3496
|
+
Object.entries(attrs).forEach(([k, v]) => {
|
|
3497
|
+
if (typeof k === "string") {
|
|
3498
|
+
k = k.toLowerCase();
|
|
3499
|
+
}
|
|
3500
|
+
newAttrs[k] = v;
|
|
3501
|
+
});
|
|
3502
|
+
}
|
|
3503
|
+
return newAttrs;
|
|
3504
|
+
}
|
|
3505
|
+
}
|
|
3506
|
+
});
|
|
3507
|
+
|
|
3508
|
+
// node_modules/@dagrejs/dagre/lib/debug.js
|
|
3509
|
+
var require_debug = __commonJS({
|
|
3510
|
+
"node_modules/@dagrejs/dagre/lib/debug.js"(exports2, module2) {
|
|
3511
|
+
"use strict";
|
|
3512
|
+
var util = require_util();
|
|
3513
|
+
var Graph = require_graphlib().Graph;
|
|
3514
|
+
module2.exports = {
|
|
3515
|
+
debugOrdering
|
|
3516
|
+
};
|
|
3517
|
+
function debugOrdering(g) {
|
|
3518
|
+
let layerMatrix = util.buildLayerMatrix(g);
|
|
3519
|
+
let h = new Graph({ compound: true, multigraph: true }).setGraph({});
|
|
3520
|
+
g.nodes().forEach((v) => {
|
|
3521
|
+
h.setNode(v, { label: v });
|
|
3522
|
+
h.setParent(v, "layer" + g.node(v).rank);
|
|
3523
|
+
});
|
|
3524
|
+
g.edges().forEach((e) => h.setEdge(e.v, e.w, {}, e.name));
|
|
3525
|
+
layerMatrix.forEach((layer, i) => {
|
|
3526
|
+
let layerV = "layer" + i;
|
|
3527
|
+
h.setNode(layerV, { rank: "same" });
|
|
3528
|
+
layer.reduce((u, v) => {
|
|
3529
|
+
h.setEdge(u, v, { style: "invis" });
|
|
3530
|
+
return v;
|
|
3531
|
+
});
|
|
3532
|
+
});
|
|
3533
|
+
return h;
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3536
|
+
});
|
|
3537
|
+
|
|
3538
|
+
// node_modules/@dagrejs/dagre/lib/version.js
|
|
3539
|
+
var require_version2 = __commonJS({
|
|
3540
|
+
"node_modules/@dagrejs/dagre/lib/version.js"(exports2, module2) {
|
|
3541
|
+
"use strict";
|
|
3542
|
+
module2.exports = "1.1.8";
|
|
3543
|
+
}
|
|
3544
|
+
});
|
|
3545
|
+
|
|
3546
|
+
// node_modules/@dagrejs/dagre/index.js
|
|
3547
|
+
var require_dagre = __commonJS({
|
|
3548
|
+
"node_modules/@dagrejs/dagre/index.js"(exports2, module2) {
|
|
3549
|
+
"use strict";
|
|
3550
|
+
module2.exports = {
|
|
3551
|
+
graphlib: require_graphlib(),
|
|
3552
|
+
layout: require_layout(),
|
|
3553
|
+
debug: require_debug(),
|
|
3554
|
+
util: {
|
|
3555
|
+
time: require_util().time,
|
|
3556
|
+
notime: require_util().notime
|
|
3557
|
+
},
|
|
3558
|
+
version: require_version2()
|
|
3559
|
+
};
|
|
3560
|
+
}
|
|
3561
|
+
});
|
|
3562
|
+
|
|
3563
|
+
// src/index.ts
|
|
3564
|
+
var src_exports = {};
|
|
3565
|
+
__export(src_exports, {
|
|
3566
|
+
createTheme: () => createTheme,
|
|
3567
|
+
darkTheme: () => darkTheme,
|
|
3568
|
+
defaultTheme: () => defaultTheme,
|
|
3569
|
+
layout: () => layout,
|
|
3570
|
+
parse: () => parse,
|
|
3571
|
+
render: () => render,
|
|
3572
|
+
renderSvg: () => renderSvg
|
|
3573
|
+
});
|
|
3574
|
+
module.exports = __toCommonJS(src_exports);
|
|
3575
|
+
|
|
3576
|
+
// src/types.ts
|
|
3577
|
+
var SIGNAL_OPERATORS = {
|
|
3578
|
+
"->": "audio",
|
|
3579
|
+
">>": "cv",
|
|
3580
|
+
"p>": "pitch",
|
|
3581
|
+
"g>": "gate",
|
|
3582
|
+
"t>": "trigger",
|
|
3583
|
+
"c>": "clock"
|
|
3584
|
+
};
|
|
3585
|
+
|
|
3586
|
+
// src/errors.ts
|
|
3587
|
+
var errorMessages = {
|
|
3588
|
+
unknownOperator: (op) => `Unknown operator "${op}". Expected ->, >>, p>, g>, t>, or c>.`,
|
|
3589
|
+
unclosedParen: () => `Unclosed parenthesis in port name.`,
|
|
3590
|
+
missingPort: (side) => `Missing port name on ${side} side of connection.`,
|
|
3591
|
+
duplicateModule: (name) => `Module "${name}" declared more than once.`,
|
|
3592
|
+
didYouMean: (got, suggestion) => `Module "${got}" is not declared. Did you mean "${suggestion}"?`,
|
|
3593
|
+
syntaxError: (detail) => `Syntax error: ${detail}`,
|
|
3594
|
+
emptyDiagram: () => `Diagram is empty \u2014 no connections found.`
|
|
3595
|
+
};
|
|
3596
|
+
function editDistance(a, b) {
|
|
3597
|
+
const la = a.length;
|
|
3598
|
+
const lb = b.length;
|
|
3599
|
+
const dp = Array.from({ length: la + 1 }, () => Array(lb + 1).fill(0));
|
|
3600
|
+
for (let i = 0; i <= la; i++) dp[i][0] = i;
|
|
3601
|
+
for (let j = 0; j <= lb; j++) dp[0][j] = j;
|
|
3602
|
+
for (let i = 1; i <= la; i++) {
|
|
3603
|
+
for (let j = 1; j <= lb; j++) {
|
|
3604
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
3605
|
+
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
3606
|
+
}
|
|
3607
|
+
}
|
|
3608
|
+
return dp[la][lb];
|
|
3609
|
+
}
|
|
3610
|
+
function sanitizeForSvg(str) {
|
|
3611
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
3612
|
+
}
|
|
3613
|
+
|
|
3614
|
+
// src/parser.ts
|
|
3615
|
+
function normalize(str) {
|
|
3616
|
+
return str.trim().toLowerCase().replace(/\s+/g, "-");
|
|
3617
|
+
}
|
|
3618
|
+
function makeBlockId(module2, section) {
|
|
3619
|
+
return `${normalize(module2)}--${normalize(section)}`;
|
|
3620
|
+
}
|
|
3621
|
+
function parseGraphvizExtras(str) {
|
|
3622
|
+
const result = {};
|
|
3623
|
+
const parts = str.split(",");
|
|
3624
|
+
for (const part of parts) {
|
|
3625
|
+
const eqIdx = part.indexOf("=");
|
|
3626
|
+
if (eqIdx !== -1) {
|
|
3627
|
+
const key = part.slice(0, eqIdx).trim();
|
|
3628
|
+
const value = part.slice(eqIdx + 1).trim();
|
|
3629
|
+
result[key] = value;
|
|
3630
|
+
}
|
|
3631
|
+
}
|
|
3632
|
+
return result;
|
|
3633
|
+
}
|
|
3634
|
+
function parseEndpoint(raw) {
|
|
3635
|
+
const trimmed = raw.trim();
|
|
3636
|
+
const openParen = trimmed.lastIndexOf("(");
|
|
3637
|
+
const closeParen = trimmed.lastIndexOf(")");
|
|
3638
|
+
if (openParen === -1 || closeParen === -1 || closeParen < openParen) {
|
|
3639
|
+
return null;
|
|
3640
|
+
}
|
|
3641
|
+
const port = trimmed.slice(openParen + 1, closeParen);
|
|
3642
|
+
const before = trimmed.slice(0, openParen).trim();
|
|
3643
|
+
const dotIdx = before.indexOf(".");
|
|
3644
|
+
if (dotIdx !== -1) {
|
|
3645
|
+
const module2 = before.slice(0, dotIdx).trim();
|
|
3646
|
+
const section = before.slice(dotIdx + 1).trim();
|
|
3647
|
+
return { module: module2, section, port };
|
|
3648
|
+
}
|
|
3649
|
+
return { module: before, section: null, port };
|
|
3650
|
+
}
|
|
3651
|
+
var SORTED_OPERATORS = Object.keys(SIGNAL_OPERATORS).sort((a, b) => b.length - a.length);
|
|
3652
|
+
function findOperator(line) {
|
|
3653
|
+
for (const op of SORTED_OPERATORS) {
|
|
3654
|
+
const idx = line.indexOf(op);
|
|
3655
|
+
if (idx !== -1) {
|
|
3656
|
+
return { operator: op, index: idx };
|
|
3657
|
+
}
|
|
3658
|
+
}
|
|
3659
|
+
return null;
|
|
3660
|
+
}
|
|
3661
|
+
function parse(input) {
|
|
3662
|
+
const errors = [];
|
|
3663
|
+
const warnings = [];
|
|
3664
|
+
const normalized = input.replace(/\r\n/g, "\n");
|
|
3665
|
+
const lines = normalized.split("\n");
|
|
3666
|
+
const declaredModules = /* @__PURE__ */ new Map();
|
|
3667
|
+
const allBlocks = /* @__PURE__ */ new Map();
|
|
3668
|
+
const connections = [];
|
|
3669
|
+
let currentModuleName = null;
|
|
3670
|
+
let currentVoice = null;
|
|
3671
|
+
const voices = [];
|
|
3672
|
+
let lastParam = null;
|
|
3673
|
+
let connectionCounter = 0;
|
|
3674
|
+
for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
|
3675
|
+
const line = lines[lineIdx];
|
|
3676
|
+
const lineNum = lineIdx + 1;
|
|
3677
|
+
if (line.trim() === "") continue;
|
|
3678
|
+
if (line.startsWith("# patchflow")) continue;
|
|
3679
|
+
if (line.trim().startsWith("//")) continue;
|
|
3680
|
+
if (line.trimStart().startsWith("- ")) {
|
|
3681
|
+
lastParam = null;
|
|
3682
|
+
const connLine = line.trimStart().slice(2);
|
|
3683
|
+
let annotation = null;
|
|
3684
|
+
let workLine = connLine;
|
|
3685
|
+
const annotationIdx = workLine.indexOf(" // ");
|
|
3686
|
+
if (annotationIdx !== -1) {
|
|
3687
|
+
annotation = workLine.slice(annotationIdx + 4).trim();
|
|
3688
|
+
workLine = workLine.slice(0, annotationIdx);
|
|
3689
|
+
}
|
|
3690
|
+
let graphvizExtras = null;
|
|
3691
|
+
const bracketOpen = workLine.lastIndexOf("[");
|
|
3692
|
+
const bracketClose = workLine.lastIndexOf("]");
|
|
3693
|
+
if (bracketOpen !== -1 && bracketClose !== -1 && bracketClose > bracketOpen) {
|
|
3694
|
+
const extrasStr = workLine.slice(bracketOpen + 1, bracketClose);
|
|
3695
|
+
graphvizExtras = parseGraphvizExtras(extrasStr);
|
|
3696
|
+
workLine = workLine.slice(0, bracketOpen).trim();
|
|
3697
|
+
}
|
|
3698
|
+
const opResult = findOperator(workLine);
|
|
3699
|
+
if (!opResult) {
|
|
3700
|
+
errors.push({
|
|
3701
|
+
code: "SYNTAX_ERROR",
|
|
3702
|
+
message: errorMessages.syntaxError("no valid operator found"),
|
|
3703
|
+
line: lineNum,
|
|
3704
|
+
column: 1,
|
|
3705
|
+
length: line.length,
|
|
3706
|
+
severity: "error"
|
|
3707
|
+
});
|
|
3708
|
+
continue;
|
|
3709
|
+
}
|
|
3710
|
+
const { operator, index: opIdx } = opResult;
|
|
3711
|
+
const signalType = SIGNAL_OPERATORS[operator];
|
|
3712
|
+
const sourcePart = workLine.slice(0, opIdx).trim();
|
|
3713
|
+
const targetPart = workLine.slice(opIdx + operator.length).trim();
|
|
3714
|
+
const sourceEndpoint = parseEndpoint(sourcePart);
|
|
3715
|
+
const targetEndpoint = parseEndpoint(targetPart);
|
|
3716
|
+
if (!sourceEndpoint) {
|
|
3717
|
+
errors.push({
|
|
3718
|
+
code: "MISSING_PORT",
|
|
3719
|
+
message: errorMessages.missingPort("source"),
|
|
3720
|
+
line: lineNum,
|
|
3721
|
+
column: 1,
|
|
3722
|
+
length: line.length,
|
|
3723
|
+
severity: "error"
|
|
3724
|
+
});
|
|
3725
|
+
continue;
|
|
3726
|
+
}
|
|
3727
|
+
if (!targetEndpoint) {
|
|
3728
|
+
errors.push({
|
|
3729
|
+
code: "MISSING_PORT",
|
|
3730
|
+
message: errorMessages.missingPort("target"),
|
|
3731
|
+
line: lineNum,
|
|
3732
|
+
column: 1,
|
|
3733
|
+
length: line.length,
|
|
3734
|
+
severity: "error"
|
|
3735
|
+
});
|
|
3736
|
+
continue;
|
|
3737
|
+
}
|
|
3738
|
+
const sourceBlock = resolveBlock(sourceEndpoint, currentVoice);
|
|
3739
|
+
const targetBlock = resolveBlock(targetEndpoint, currentVoice);
|
|
3740
|
+
ensurePort(sourceBlock, sourceEndpoint.port, "out");
|
|
3741
|
+
ensurePort(targetBlock, targetEndpoint.port, "in");
|
|
3742
|
+
const conn = {
|
|
3743
|
+
id: `conn-${connectionCounter++}`,
|
|
3744
|
+
source: {
|
|
3745
|
+
blockId: sourceBlock.id,
|
|
3746
|
+
portId: sourceEndpoint.port.trim().toLowerCase(),
|
|
3747
|
+
portDisplay: sourceEndpoint.port.trim()
|
|
3748
|
+
},
|
|
3749
|
+
target: {
|
|
3750
|
+
blockId: targetBlock.id,
|
|
3751
|
+
portId: targetEndpoint.port.trim().toLowerCase(),
|
|
3752
|
+
portDisplay: targetEndpoint.port.trim()
|
|
3753
|
+
},
|
|
3754
|
+
signalType,
|
|
3755
|
+
annotation,
|
|
3756
|
+
graphvizExtras
|
|
3757
|
+
};
|
|
3758
|
+
connections.push(conn);
|
|
3759
|
+
continue;
|
|
3760
|
+
}
|
|
3761
|
+
if (line.trimStart().startsWith("|")) {
|
|
3762
|
+
if (lastParam) {
|
|
3763
|
+
const value = line.trimStart().slice(1).trim();
|
|
3764
|
+
lastParam.value += "; " + value;
|
|
3765
|
+
}
|
|
3766
|
+
continue;
|
|
3767
|
+
}
|
|
3768
|
+
if (line.trimStart().startsWith("*")) {
|
|
3769
|
+
const paramContent = line.trimStart().slice(1).trim();
|
|
3770
|
+
const colonIdx = paramContent.indexOf(":");
|
|
3771
|
+
let key;
|
|
3772
|
+
let value;
|
|
3773
|
+
if (colonIdx !== -1) {
|
|
3774
|
+
key = paramContent.slice(0, colonIdx).trim();
|
|
3775
|
+
value = paramContent.slice(colonIdx + 1).trim();
|
|
3776
|
+
} else {
|
|
3777
|
+
key = paramContent;
|
|
3778
|
+
value = "";
|
|
3779
|
+
}
|
|
3780
|
+
const param = { key, value };
|
|
3781
|
+
lastParam = param;
|
|
3782
|
+
if (currentModuleName) {
|
|
3783
|
+
const lowerName = currentModuleName.toLowerCase();
|
|
3784
|
+
const block = declaredModules.get(lowerName);
|
|
3785
|
+
if (block) {
|
|
3786
|
+
block.params.push(param);
|
|
3787
|
+
}
|
|
3788
|
+
}
|
|
3789
|
+
continue;
|
|
3790
|
+
}
|
|
3791
|
+
if (line.trim().endsWith(":") && !line.trim().startsWith("-") && !line.trim().startsWith("*") && !line.trim().startsWith("|")) {
|
|
3792
|
+
lastParam = null;
|
|
3793
|
+
const rawDecl = line.trim().slice(0, -1).trim();
|
|
3794
|
+
let moduleName = rawDecl;
|
|
3795
|
+
let variant = null;
|
|
3796
|
+
const variantMatch = rawDecl.match(/^(.+?)\s*\[(.+?)\]\s*$/);
|
|
3797
|
+
if (variantMatch) {
|
|
3798
|
+
moduleName = variantMatch[1].trim();
|
|
3799
|
+
variant = variantMatch[2].trim();
|
|
3800
|
+
}
|
|
3801
|
+
if (/^voice\s+/i.test(moduleName)) {
|
|
3802
|
+
currentVoice = moduleName;
|
|
3803
|
+
currentModuleName = null;
|
|
3804
|
+
if (!voices.includes(moduleName)) {
|
|
3805
|
+
voices.push(moduleName);
|
|
3806
|
+
}
|
|
3807
|
+
continue;
|
|
3808
|
+
}
|
|
3809
|
+
currentModuleName = moduleName;
|
|
3810
|
+
const lowerName = moduleName.toLowerCase();
|
|
3811
|
+
if (!declaredModules.has(lowerName)) {
|
|
3812
|
+
const block = {
|
|
3813
|
+
id: normalize(moduleName),
|
|
3814
|
+
label: moduleName,
|
|
3815
|
+
subLabel: variant,
|
|
3816
|
+
params: [],
|
|
3817
|
+
ports: [],
|
|
3818
|
+
parentModule: null,
|
|
3819
|
+
voice: currentVoice
|
|
3820
|
+
};
|
|
3821
|
+
declaredModules.set(lowerName, block);
|
|
3822
|
+
allBlocks.set(block.id, block);
|
|
3823
|
+
} else if (variant) {
|
|
3824
|
+
const existing = declaredModules.get(lowerName);
|
|
3825
|
+
if (!existing.subLabel) existing.subLabel = variant;
|
|
3826
|
+
}
|
|
3827
|
+
continue;
|
|
3828
|
+
}
|
|
3829
|
+
errors.push({
|
|
3830
|
+
code: "SYNTAX_ERROR",
|
|
3831
|
+
message: errorMessages.syntaxError("unrecognized line format"),
|
|
3832
|
+
line: lineNum,
|
|
3833
|
+
column: 1,
|
|
3834
|
+
length: line.length,
|
|
3835
|
+
severity: "error"
|
|
3836
|
+
});
|
|
3837
|
+
}
|
|
3838
|
+
let declaredBlocksList = [...declaredModules.values()];
|
|
3839
|
+
const stubBlocks = [];
|
|
3840
|
+
for (const [id, block] of allBlocks) {
|
|
3841
|
+
if (![...declaredModules.values()].find((b) => b.id === id)) {
|
|
3842
|
+
stubBlocks.push(block);
|
|
3843
|
+
}
|
|
3844
|
+
}
|
|
3845
|
+
const blocksToRemove = /* @__PURE__ */ new Set();
|
|
3846
|
+
for (const parent of declaredBlocksList) {
|
|
3847
|
+
const parentLabelLower = parent.label.trim().toLowerCase();
|
|
3848
|
+
const childSections = [];
|
|
3849
|
+
for (const block of [...declaredBlocksList, ...stubBlocks]) {
|
|
3850
|
+
if (block.parentModule && block.parentModule.trim().toLowerCase() === parentLabelLower) {
|
|
3851
|
+
childSections.push(block);
|
|
3852
|
+
}
|
|
3853
|
+
}
|
|
3854
|
+
if (childSections.length === 0) continue;
|
|
3855
|
+
const remainingParams = [];
|
|
3856
|
+
for (const param of parent.params) {
|
|
3857
|
+
const keyLower = param.key.trim().toLowerCase();
|
|
3858
|
+
const matchingSection = childSections.find(
|
|
3859
|
+
(s) => s.label.trim().toLowerCase() === keyLower
|
|
3860
|
+
);
|
|
3861
|
+
if (matchingSection) {
|
|
3862
|
+
matchingSection.params.push(param);
|
|
3863
|
+
} else {
|
|
3864
|
+
remainingParams.push(param);
|
|
3865
|
+
}
|
|
3866
|
+
}
|
|
3867
|
+
parent.params = remainingParams;
|
|
3868
|
+
if (remainingParams.length === 0) {
|
|
3869
|
+
const directlyReferenced = connections.some(
|
|
3870
|
+
(c) => c.source.blockId === parent.id || c.target.blockId === parent.id
|
|
3871
|
+
);
|
|
3872
|
+
if (!directlyReferenced) {
|
|
3873
|
+
blocksToRemove.add(parent.id);
|
|
3874
|
+
}
|
|
3875
|
+
}
|
|
3876
|
+
}
|
|
3877
|
+
if (blocksToRemove.size > 0) {
|
|
3878
|
+
declaredBlocksList = declaredBlocksList.filter((b) => !blocksToRemove.has(b.id));
|
|
3879
|
+
}
|
|
3880
|
+
const { forward, feedback } = detectFeedbackEdges(connections);
|
|
3881
|
+
const signalTypeStats = {};
|
|
3882
|
+
for (const conn of [...forward, ...feedback]) {
|
|
3883
|
+
signalTypeStats[conn.signalType] = (signalTypeStats[conn.signalType] || 0) + 1;
|
|
3884
|
+
}
|
|
3885
|
+
const declaredNames = [...declaredModules.keys()];
|
|
3886
|
+
for (const stub of stubBlocks) {
|
|
3887
|
+
const stubLower = stub.label.toLowerCase();
|
|
3888
|
+
for (const declName of declaredNames) {
|
|
3889
|
+
const dist = editDistance(stubLower, declName);
|
|
3890
|
+
if (dist > 0 && dist <= 2) {
|
|
3891
|
+
const declBlock = declaredModules.get(declName);
|
|
3892
|
+
warnings.push({
|
|
3893
|
+
code: "UNKNOWN_MODULE",
|
|
3894
|
+
message: errorMessages.didYouMean(stub.label, declBlock.label),
|
|
3895
|
+
line: 0,
|
|
3896
|
+
column: 1,
|
|
3897
|
+
length: stub.label.length,
|
|
3898
|
+
severity: "warning"
|
|
3899
|
+
});
|
|
3900
|
+
break;
|
|
3901
|
+
}
|
|
3902
|
+
}
|
|
3903
|
+
}
|
|
3904
|
+
const graph = {
|
|
3905
|
+
declaredBlocks: declaredBlocksList,
|
|
3906
|
+
stubBlocks,
|
|
3907
|
+
connections: forward,
|
|
3908
|
+
feedbackEdges: feedback,
|
|
3909
|
+
signalTypeStats,
|
|
3910
|
+
voices
|
|
3911
|
+
};
|
|
3912
|
+
return { graph, errors, warnings };
|
|
3913
|
+
function resolveBlock(endpoint, voice) {
|
|
3914
|
+
const { module: module2, section } = endpoint;
|
|
3915
|
+
if (section) {
|
|
3916
|
+
const blockId2 = makeBlockId(module2, section);
|
|
3917
|
+
if (allBlocks.has(blockId2)) {
|
|
3918
|
+
return allBlocks.get(blockId2);
|
|
3919
|
+
}
|
|
3920
|
+
const block2 = {
|
|
3921
|
+
id: blockId2,
|
|
3922
|
+
label: section,
|
|
3923
|
+
subLabel: null,
|
|
3924
|
+
params: [],
|
|
3925
|
+
ports: [],
|
|
3926
|
+
parentModule: module2,
|
|
3927
|
+
voice
|
|
3928
|
+
};
|
|
3929
|
+
allBlocks.set(blockId2, block2);
|
|
3930
|
+
return block2;
|
|
3931
|
+
}
|
|
3932
|
+
const lowerModule = module2.toLowerCase();
|
|
3933
|
+
if (declaredModules.has(lowerModule)) {
|
|
3934
|
+
return declaredModules.get(lowerModule);
|
|
3935
|
+
}
|
|
3936
|
+
const blockId = normalize(module2);
|
|
3937
|
+
if (allBlocks.has(blockId)) {
|
|
3938
|
+
return allBlocks.get(blockId);
|
|
3939
|
+
}
|
|
3940
|
+
const block = {
|
|
3941
|
+
id: blockId,
|
|
3942
|
+
label: module2,
|
|
3943
|
+
subLabel: null,
|
|
3944
|
+
params: [],
|
|
3945
|
+
ports: [],
|
|
3946
|
+
parentModule: null,
|
|
3947
|
+
voice
|
|
3948
|
+
};
|
|
3949
|
+
allBlocks.set(blockId, block);
|
|
3950
|
+
return block;
|
|
3951
|
+
}
|
|
3952
|
+
function ensurePort(block, portName, direction) {
|
|
3953
|
+
const portId = portName.trim().toLowerCase();
|
|
3954
|
+
const existing = block.ports.find((p) => p.id === portId && p.direction === direction);
|
|
3955
|
+
if (!existing) {
|
|
3956
|
+
block.ports.push({
|
|
3957
|
+
id: portId,
|
|
3958
|
+
display: portName.trim(),
|
|
3959
|
+
direction
|
|
3960
|
+
});
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
function detectFeedbackEdges(connections) {
|
|
3965
|
+
if (connections.length === 0) {
|
|
3966
|
+
return { forward: [], feedback: [] };
|
|
3967
|
+
}
|
|
3968
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
3969
|
+
const edgeMap = /* @__PURE__ */ new Map();
|
|
3970
|
+
for (const conn of connections) {
|
|
3971
|
+
const src = conn.source.blockId;
|
|
3972
|
+
const tgt = conn.target.blockId;
|
|
3973
|
+
if (!adjacency.has(src)) adjacency.set(src, /* @__PURE__ */ new Set());
|
|
3974
|
+
adjacency.get(src).add(tgt);
|
|
3975
|
+
const edgeKey = `${src}->${tgt}`;
|
|
3976
|
+
if (!edgeMap.has(edgeKey)) edgeMap.set(edgeKey, []);
|
|
3977
|
+
edgeMap.get(edgeKey).push(conn);
|
|
3978
|
+
}
|
|
3979
|
+
const WHITE = 0, GRAY = 1, BLACK = 2;
|
|
3980
|
+
const color = /* @__PURE__ */ new Map();
|
|
3981
|
+
const backEdges = /* @__PURE__ */ new Set();
|
|
3982
|
+
const nodes = /* @__PURE__ */ new Set();
|
|
3983
|
+
for (const conn of connections) {
|
|
3984
|
+
nodes.add(conn.source.blockId);
|
|
3985
|
+
nodes.add(conn.target.blockId);
|
|
3986
|
+
}
|
|
3987
|
+
for (const node of nodes) {
|
|
3988
|
+
color.set(node, WHITE);
|
|
3989
|
+
}
|
|
3990
|
+
function dfs(u) {
|
|
3991
|
+
color.set(u, GRAY);
|
|
3992
|
+
const neighbors = adjacency.get(u) || /* @__PURE__ */ new Set();
|
|
3993
|
+
for (const v of neighbors) {
|
|
3994
|
+
const c = color.get(v) ?? WHITE;
|
|
3995
|
+
if (c === GRAY) {
|
|
3996
|
+
backEdges.add(`${u}->${v}`);
|
|
3997
|
+
} else if (c === WHITE) {
|
|
3998
|
+
dfs(v);
|
|
3999
|
+
}
|
|
4000
|
+
}
|
|
4001
|
+
color.set(u, BLACK);
|
|
4002
|
+
}
|
|
4003
|
+
for (const node of nodes) {
|
|
4004
|
+
if (color.get(node) === WHITE) {
|
|
4005
|
+
dfs(node);
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
const forward = [];
|
|
4009
|
+
const feedback = [];
|
|
4010
|
+
for (const conn of connections) {
|
|
4011
|
+
const edgeKey = `${conn.source.blockId}->${conn.target.blockId}`;
|
|
4012
|
+
if (backEdges.has(edgeKey)) {
|
|
4013
|
+
feedback.push(conn);
|
|
4014
|
+
} else {
|
|
4015
|
+
forward.push(conn);
|
|
4016
|
+
}
|
|
4017
|
+
}
|
|
4018
|
+
return { forward, feedback };
|
|
4019
|
+
}
|
|
4020
|
+
|
|
4021
|
+
// src/layout.ts
|
|
4022
|
+
var import_dagre = __toESM(require_dagre(), 1);
|
|
4023
|
+
|
|
4024
|
+
// src/edge-routing.ts
|
|
4025
|
+
function smoothstepPath(source, target) {
|
|
4026
|
+
const dx = target.x - source.x;
|
|
4027
|
+
const controlOffset = Math.max(Math.abs(dx) * 0.4, 30);
|
|
4028
|
+
const cx1 = source.x + controlOffset;
|
|
4029
|
+
const cy1 = source.y;
|
|
4030
|
+
const cx2 = target.x - controlOffset;
|
|
4031
|
+
const cy2 = target.y;
|
|
4032
|
+
return `M ${source.x} ${source.y} C ${cx1} ${cy1}, ${cx2} ${cy2}, ${target.x} ${target.y}`;
|
|
4033
|
+
}
|
|
4034
|
+
function feedbackArcPath(source, target, diagramBottom, arcOffset) {
|
|
4035
|
+
const arcY = diagramBottom + arcOffset;
|
|
4036
|
+
return [
|
|
4037
|
+
`M ${source.x} ${source.y}`,
|
|
4038
|
+
`L ${source.x + 20} ${source.y}`,
|
|
4039
|
+
`L ${source.x + 20} ${arcY}`,
|
|
4040
|
+
`L ${target.x - 20} ${arcY}`,
|
|
4041
|
+
`L ${target.x - 20} ${target.y}`,
|
|
4042
|
+
`L ${target.x} ${target.y}`
|
|
4043
|
+
].join(" ");
|
|
4044
|
+
}
|
|
4045
|
+
function selfLoopArcPath(source, target, blockBottom, arcOffset) {
|
|
4046
|
+
const arcY = blockBottom + arcOffset;
|
|
4047
|
+
return [
|
|
4048
|
+
`M ${source.x} ${source.y}`,
|
|
4049
|
+
`L ${source.x + 15} ${source.y}`,
|
|
4050
|
+
`Q ${source.x + 15} ${arcY}, ${(source.x + target.x) / 2} ${arcY}`,
|
|
4051
|
+
`Q ${target.x - 15} ${arcY}, ${target.x - 15} ${target.y}`,
|
|
4052
|
+
`L ${target.x} ${target.y}`
|
|
4053
|
+
].join(" ");
|
|
4054
|
+
}
|
|
4055
|
+
|
|
4056
|
+
// src/layout.ts
|
|
4057
|
+
var MIN_WIDTH = 140;
|
|
4058
|
+
var MIN_HEIGHT = 90;
|
|
4059
|
+
function getBlockDimensions(block, portCount) {
|
|
4060
|
+
const labelWidth = block.label.length * 8;
|
|
4061
|
+
const subLabelWidth = block.subLabel ? block.subLabel.length * 7 : 0;
|
|
4062
|
+
const paramWidths = block.params.map((p) => `${p.key}: ${p.value}`.length * 7);
|
|
4063
|
+
const longestParam = paramWidths.length > 0 ? Math.max(...paramWidths) : 0;
|
|
4064
|
+
const width = Math.max(
|
|
4065
|
+
labelWidth + 40,
|
|
4066
|
+
subLabelWidth + 40,
|
|
4067
|
+
longestParam + 30,
|
|
4068
|
+
MIN_WIDTH
|
|
4069
|
+
);
|
|
4070
|
+
const labelArea = 50;
|
|
4071
|
+
const subLabelArea = block.subLabel ? 18 : 0;
|
|
4072
|
+
const paramsArea = 20 * block.params.length;
|
|
4073
|
+
const portsArea = Math.max(portCount / 2 * 24, 30);
|
|
4074
|
+
const padding = 20;
|
|
4075
|
+
const height = Math.max(labelArea + subLabelArea + paramsArea + portsArea + padding, MIN_HEIGHT);
|
|
4076
|
+
return { width, height };
|
|
4077
|
+
}
|
|
4078
|
+
function collectPorts(blocks, connections) {
|
|
4079
|
+
const byBlock = /* @__PURE__ */ new Map();
|
|
4080
|
+
for (const block of blocks) {
|
|
4081
|
+
const map = /* @__PURE__ */ new Map();
|
|
4082
|
+
for (const p of block.ports) {
|
|
4083
|
+
const existing = map.get(p.id);
|
|
4084
|
+
if (!existing || existing.direction === "in" && p.direction === "out") {
|
|
4085
|
+
map.set(p.id, { ...p });
|
|
4086
|
+
}
|
|
4087
|
+
}
|
|
4088
|
+
byBlock.set(block.id, map);
|
|
4089
|
+
}
|
|
4090
|
+
for (const conn of connections) {
|
|
4091
|
+
const srcBlock = byBlock.get(conn.source.blockId);
|
|
4092
|
+
if (srcBlock) {
|
|
4093
|
+
const existing = srcBlock.get(conn.source.portId);
|
|
4094
|
+
if (!existing || existing.direction === "in") {
|
|
4095
|
+
srcBlock.set(conn.source.portId, {
|
|
4096
|
+
id: conn.source.portId,
|
|
4097
|
+
display: conn.source.portDisplay,
|
|
4098
|
+
direction: "out"
|
|
4099
|
+
});
|
|
4100
|
+
}
|
|
4101
|
+
}
|
|
4102
|
+
const tgtBlock = byBlock.get(conn.target.blockId);
|
|
4103
|
+
if (tgtBlock) {
|
|
4104
|
+
const existing = tgtBlock.get(conn.target.portId);
|
|
4105
|
+
if (!existing) {
|
|
4106
|
+
tgtBlock.set(conn.target.portId, {
|
|
4107
|
+
id: conn.target.portId,
|
|
4108
|
+
display: conn.target.portDisplay,
|
|
4109
|
+
direction: "in"
|
|
4110
|
+
});
|
|
4111
|
+
}
|
|
4112
|
+
}
|
|
4113
|
+
}
|
|
4114
|
+
const result = /* @__PURE__ */ new Map();
|
|
4115
|
+
for (const [blockId, map] of byBlock) {
|
|
4116
|
+
result.set(blockId, Array.from(map.values()));
|
|
4117
|
+
}
|
|
4118
|
+
return result;
|
|
4119
|
+
}
|
|
4120
|
+
function placePorts(block, ports) {
|
|
4121
|
+
const inPorts = ports.filter((p) => p.direction === "in");
|
|
4122
|
+
const outPorts = ports.filter((p) => p.direction === "out");
|
|
4123
|
+
const layoutPorts = [];
|
|
4124
|
+
const startY = block.y + 40 + (block.subLabel ? 18 : 0);
|
|
4125
|
+
const spacing = 24;
|
|
4126
|
+
inPorts.forEach((p, i) => {
|
|
4127
|
+
layoutPorts.push({
|
|
4128
|
+
...p,
|
|
4129
|
+
position: { x: block.x, y: startY + i * spacing },
|
|
4130
|
+
signalType: null
|
|
4131
|
+
});
|
|
4132
|
+
});
|
|
4133
|
+
outPorts.forEach((p, i) => {
|
|
4134
|
+
layoutPorts.push({
|
|
4135
|
+
...p,
|
|
4136
|
+
position: { x: block.x + block.width, y: startY + i * spacing },
|
|
4137
|
+
signalType: null
|
|
4138
|
+
});
|
|
4139
|
+
});
|
|
4140
|
+
return layoutPorts;
|
|
4141
|
+
}
|
|
4142
|
+
function assignPortSignalTypes(blocks, forward, feedback) {
|
|
4143
|
+
const pick = (blockId, portId, direction, connections) => {
|
|
4144
|
+
for (const conn of connections) {
|
|
4145
|
+
if (direction === "out") {
|
|
4146
|
+
if (conn.source.blockId === blockId && conn.source.portId === portId) {
|
|
4147
|
+
return conn.signalType;
|
|
4148
|
+
}
|
|
4149
|
+
} else {
|
|
4150
|
+
if (conn.target.blockId === blockId && conn.target.portId === portId) {
|
|
4151
|
+
return conn.signalType;
|
|
4152
|
+
}
|
|
4153
|
+
}
|
|
4154
|
+
}
|
|
4155
|
+
return null;
|
|
4156
|
+
};
|
|
4157
|
+
for (const block of blocks) {
|
|
4158
|
+
for (const port of block.ports) {
|
|
4159
|
+
const fromForward = pick(block.id, port.id, port.direction, forward);
|
|
4160
|
+
if (fromForward) {
|
|
4161
|
+
port.signalType = fromForward;
|
|
4162
|
+
continue;
|
|
4163
|
+
}
|
|
4164
|
+
const fromFeedback = pick(block.id, port.id, port.direction, feedback);
|
|
4165
|
+
if (fromFeedback) {
|
|
4166
|
+
port.signalType = fromFeedback;
|
|
4167
|
+
}
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
}
|
|
4171
|
+
function findPortPosition(block, portId, direction) {
|
|
4172
|
+
const exact = block.ports.find((p) => p.id === portId && p.direction === direction);
|
|
4173
|
+
if (exact) return exact.position;
|
|
4174
|
+
const any = block.ports.find((p) => p.id === portId);
|
|
4175
|
+
return any.position;
|
|
4176
|
+
}
|
|
4177
|
+
function layout(graph, options = {}) {
|
|
4178
|
+
const direction = options.direction ?? "LR";
|
|
4179
|
+
const rankSep = options.rankSep ?? 160;
|
|
4180
|
+
const nodeSep = options.nodeSep ?? 40;
|
|
4181
|
+
const allBlocks = [...graph.declaredBlocks, ...graph.stubBlocks];
|
|
4182
|
+
const allConnections = [...graph.connections, ...graph.feedbackEdges];
|
|
4183
|
+
const portsByBlock = collectPorts(allBlocks, allConnections);
|
|
4184
|
+
const dimsByBlock = /* @__PURE__ */ new Map();
|
|
4185
|
+
for (const block of allBlocks) {
|
|
4186
|
+
const ports = portsByBlock.get(block.id) ?? [];
|
|
4187
|
+
dimsByBlock.set(block.id, getBlockDimensions(block, ports.length));
|
|
4188
|
+
}
|
|
4189
|
+
const g = new import_dagre.default.graphlib.Graph();
|
|
4190
|
+
g.setGraph({
|
|
4191
|
+
rankdir: direction,
|
|
4192
|
+
ranksep: rankSep,
|
|
4193
|
+
nodesep: nodeSep,
|
|
4194
|
+
marginx: 20,
|
|
4195
|
+
marginy: 20
|
|
4196
|
+
});
|
|
4197
|
+
g.setDefaultEdgeLabel(() => ({}));
|
|
4198
|
+
for (const block of allBlocks) {
|
|
4199
|
+
const d = dimsByBlock.get(block.id);
|
|
4200
|
+
g.setNode(block.id, { width: d.width, height: d.height });
|
|
4201
|
+
}
|
|
4202
|
+
for (const conn of graph.connections) {
|
|
4203
|
+
if (conn.source.blockId === conn.target.blockId) continue;
|
|
4204
|
+
g.setEdge(conn.source.blockId, conn.target.blockId);
|
|
4205
|
+
}
|
|
4206
|
+
import_dagre.default.layout(g);
|
|
4207
|
+
const layoutBlocks = [];
|
|
4208
|
+
const blocksById = /* @__PURE__ */ new Map();
|
|
4209
|
+
for (const block of allBlocks) {
|
|
4210
|
+
const node = g.node(block.id);
|
|
4211
|
+
const d = dimsByBlock.get(block.id);
|
|
4212
|
+
const nodeX = node?.x ?? 0;
|
|
4213
|
+
const nodeY = node?.y ?? 0;
|
|
4214
|
+
const x = nodeX - d.width / 2;
|
|
4215
|
+
const y = nodeY - d.height / 2;
|
|
4216
|
+
const partial = {
|
|
4217
|
+
id: block.id,
|
|
4218
|
+
label: block.label,
|
|
4219
|
+
subLabel: block.subLabel,
|
|
4220
|
+
params: block.params,
|
|
4221
|
+
ports: [],
|
|
4222
|
+
parentModule: block.parentModule,
|
|
4223
|
+
x,
|
|
4224
|
+
y,
|
|
4225
|
+
width: d.width,
|
|
4226
|
+
height: d.height
|
|
4227
|
+
};
|
|
4228
|
+
const ports = portsByBlock.get(block.id) ?? [];
|
|
4229
|
+
partial.ports = placePorts(partial, ports);
|
|
4230
|
+
layoutBlocks.push(partial);
|
|
4231
|
+
blocksById.set(block.id, partial);
|
|
4232
|
+
}
|
|
4233
|
+
assignPortSignalTypes(layoutBlocks, graph.connections, graph.feedbackEdges);
|
|
4234
|
+
let maxX = 0;
|
|
4235
|
+
let maxY = 0;
|
|
4236
|
+
for (const b of layoutBlocks) {
|
|
4237
|
+
if (b.x + b.width > maxX) maxX = b.x + b.width;
|
|
4238
|
+
if (b.y + b.height > maxY) maxY = b.y + b.height;
|
|
4239
|
+
}
|
|
4240
|
+
const hasFeedback = graph.feedbackEdges.length > 0;
|
|
4241
|
+
const feedbackArcOffset = 20;
|
|
4242
|
+
const diagramBottom = maxY + 10;
|
|
4243
|
+
const layoutConnections = [];
|
|
4244
|
+
for (const conn of graph.connections) {
|
|
4245
|
+
const srcBlock = blocksById.get(conn.source.blockId);
|
|
4246
|
+
const tgtBlock = blocksById.get(conn.target.blockId);
|
|
4247
|
+
if (!srcBlock || !tgtBlock) continue;
|
|
4248
|
+
const srcPos = findPortPosition(srcBlock, conn.source.portId, "out");
|
|
4249
|
+
const tgtPos = findPortPosition(tgtBlock, conn.target.portId, "in");
|
|
4250
|
+
let path;
|
|
4251
|
+
if (conn.source.blockId === conn.target.blockId) {
|
|
4252
|
+
const blockBottom = srcBlock.y + srcBlock.height;
|
|
4253
|
+
path = selfLoopArcPath(srcPos, tgtPos, blockBottom, 20);
|
|
4254
|
+
} else {
|
|
4255
|
+
path = smoothstepPath(srcPos, tgtPos);
|
|
4256
|
+
}
|
|
4257
|
+
layoutConnections.push({
|
|
4258
|
+
id: conn.id,
|
|
4259
|
+
source: conn.source,
|
|
4260
|
+
target: conn.target,
|
|
4261
|
+
signalType: conn.signalType,
|
|
4262
|
+
annotation: conn.annotation,
|
|
4263
|
+
path,
|
|
4264
|
+
isFeedback: false,
|
|
4265
|
+
sourcePoint: srcPos,
|
|
4266
|
+
targetPoint: tgtPos
|
|
4267
|
+
});
|
|
4268
|
+
}
|
|
4269
|
+
for (const conn of graph.feedbackEdges) {
|
|
4270
|
+
const srcBlock = blocksById.get(conn.source.blockId);
|
|
4271
|
+
const tgtBlock = blocksById.get(conn.target.blockId);
|
|
4272
|
+
if (!srcBlock || !tgtBlock) continue;
|
|
4273
|
+
const srcPos = findPortPosition(srcBlock, conn.source.portId, "out");
|
|
4274
|
+
const tgtPos = findPortPosition(tgtBlock, conn.target.portId, "in");
|
|
4275
|
+
const path = feedbackArcPath(srcPos, tgtPos, diagramBottom, feedbackArcOffset);
|
|
4276
|
+
layoutConnections.push({
|
|
4277
|
+
id: conn.id,
|
|
4278
|
+
source: conn.source,
|
|
4279
|
+
target: conn.target,
|
|
4280
|
+
signalType: conn.signalType,
|
|
4281
|
+
annotation: conn.annotation,
|
|
4282
|
+
path,
|
|
4283
|
+
isFeedback: true,
|
|
4284
|
+
sourcePoint: srcPos,
|
|
4285
|
+
targetPoint: tgtPos
|
|
4286
|
+
});
|
|
4287
|
+
}
|
|
4288
|
+
const margin = 20;
|
|
4289
|
+
const feedbackSpace = hasFeedback ? diagramBottom - maxY + feedbackArcOffset + 30 + 16 : 0;
|
|
4290
|
+
const width = maxX + margin;
|
|
4291
|
+
const height = maxY + margin + feedbackSpace;
|
|
4292
|
+
return {
|
|
4293
|
+
blocks: layoutBlocks,
|
|
4294
|
+
connections: layoutConnections,
|
|
4295
|
+
width,
|
|
4296
|
+
height,
|
|
4297
|
+
signalTypeStats: graph.signalTypeStats
|
|
4298
|
+
};
|
|
4299
|
+
}
|
|
4300
|
+
|
|
4301
|
+
// src/renderer.ts
|
|
4302
|
+
function genId() {
|
|
4303
|
+
return "pf-" + Math.random().toString(16).slice(2, 8);
|
|
4304
|
+
}
|
|
4305
|
+
function buildDesc(layoutResult) {
|
|
4306
|
+
const blockCount = layoutResult.blocks.length;
|
|
4307
|
+
const connCount = layoutResult.connections.length;
|
|
4308
|
+
const stats = layoutResult.signalTypeStats;
|
|
4309
|
+
const statsParts = [];
|
|
4310
|
+
const order = ["audio", "cv", "pitch", "gate", "trigger", "clock"];
|
|
4311
|
+
for (const t of order) {
|
|
4312
|
+
const n = stats[t] ?? 0;
|
|
4313
|
+
if (n > 0) statsParts.push(`${n} ${t}`);
|
|
4314
|
+
}
|
|
4315
|
+
let summary = `Patch diagram with ${blockCount} module${blockCount === 1 ? "" : "s"} and ${connCount} connection${connCount === 1 ? "" : "s"}.`;
|
|
4316
|
+
if (blockCount > 0 && blockCount <= 6) {
|
|
4317
|
+
const names = layoutResult.blocks.map((b) => sanitizeForSvg(b.label)).join(", ");
|
|
4318
|
+
summary += ` Modules: ${names}.`;
|
|
4319
|
+
}
|
|
4320
|
+
if (statsParts.length > 0) {
|
|
4321
|
+
summary += ` Signals: ${statsParts.join(", ")}.`;
|
|
4322
|
+
}
|
|
4323
|
+
return summary;
|
|
4324
|
+
}
|
|
4325
|
+
function buildBackground(theme, idPrefix, width, height) {
|
|
4326
|
+
if (!theme.grid) return "";
|
|
4327
|
+
return `<rect width="${width}" height="${height}" fill="url(#${idPrefix}-dots)"/>`;
|
|
4328
|
+
}
|
|
4329
|
+
function buildCables(theme, connections) {
|
|
4330
|
+
const parts = [];
|
|
4331
|
+
const tips = [];
|
|
4332
|
+
for (const conn of connections) {
|
|
4333
|
+
const cableColor = theme.cable.colors[conn.signalType];
|
|
4334
|
+
parts.push(
|
|
4335
|
+
`<path d="${conn.path}" stroke="${cableColor.stroke}" stroke-width="${theme.cable.width}" fill="none" stroke-linecap="round" stroke-linejoin="round" data-connection="${sanitizeForSvg(conn.id)}" data-signal="${conn.signalType}"/>`
|
|
4336
|
+
);
|
|
4337
|
+
tips.push(
|
|
4338
|
+
`<circle cx="${conn.sourcePoint.x}" cy="${conn.sourcePoint.y}" r="${theme.cable.plugTipRadius}" fill="${cableColor.plugTip}"/>`
|
|
4339
|
+
);
|
|
4340
|
+
tips.push(
|
|
4341
|
+
`<circle cx="${conn.targetPoint.x}" cy="${conn.targetPoint.y}" r="${theme.cable.plugTipRadius}" fill="${cableColor.plugTip}"/>`
|
|
4342
|
+
);
|
|
4343
|
+
}
|
|
4344
|
+
return parts.join("") + tips.join("");
|
|
4345
|
+
}
|
|
4346
|
+
function buildPanels(theme, idPrefix, blocks) {
|
|
4347
|
+
const parts = [];
|
|
4348
|
+
for (const block of blocks) {
|
|
4349
|
+
const moduleName = sanitizeForSvg(block.parentModule || block.label);
|
|
4350
|
+
const label = sanitizeForSvg(block.label);
|
|
4351
|
+
const fontFamily = sanitizeForSvg(theme.label.fontFamily);
|
|
4352
|
+
const insetX = block.x + 12;
|
|
4353
|
+
const insetY = block.y + 8;
|
|
4354
|
+
const insetW = block.width - 24;
|
|
4355
|
+
let group = `<g data-module="${moduleName}" filter="url(#${idPrefix}-panel-shadow)">`;
|
|
4356
|
+
group += `<rect x="${block.x}" y="${block.y}" width="${block.width}" height="${block.height}" fill="${theme.panel.fill}" stroke="${theme.panel.stroke}" stroke-width="0.75" rx="${theme.panel.cornerRadius}"/>`;
|
|
4357
|
+
group += `<line x1="${block.x}" y1="${block.y + 0.5}" x2="${block.x + block.width}" y2="${block.y + 0.5}" stroke="${theme.panel.highlight}" stroke-width="${theme.panel.bevelWidth}"/>`;
|
|
4358
|
+
group += `<line x1="${block.x}" y1="${block.y + block.height - 0.5}" x2="${block.x + block.width}" y2="${block.y + block.height - 0.5}" stroke="${theme.panel.shadow}" stroke-width="0.5"/>`;
|
|
4359
|
+
group += `<rect x="${insetX}" y="${insetY}" width="${insetW}" height="28" fill="${theme.label.plateFill}" stroke="${theme.label.plateStroke}" stroke-width="0.5"/>`;
|
|
4360
|
+
group += `<text x="${block.x + block.width / 2}" y="${block.y + 22}" text-anchor="middle" font-family="${fontFamily}" font-size="14" font-weight="700" fill="${theme.label.color}" letter-spacing="3">${label}</text>`;
|
|
4361
|
+
if (block.subLabel) {
|
|
4362
|
+
const subLabel = sanitizeForSvg(block.subLabel);
|
|
4363
|
+
const barX = insetX;
|
|
4364
|
+
const barY = insetY + 28;
|
|
4365
|
+
const barW = insetW;
|
|
4366
|
+
const barH = 16;
|
|
4367
|
+
group += `<rect class="pf-sublabel-bar" x="${barX}" y="${barY}" width="${barW}" height="${barH}" fill="${theme.panel.shadow}"/>`;
|
|
4368
|
+
group += `<text x="${block.x + block.width / 2}" y="${barY + barH / 2 + 3}" text-anchor="middle" font-family="${fontFamily}" font-size="10" fill="${theme.panel.fill}" letter-spacing="1">${subLabel}</text>`;
|
|
4369
|
+
}
|
|
4370
|
+
group += `</g>`;
|
|
4371
|
+
parts.push(group);
|
|
4372
|
+
}
|
|
4373
|
+
return parts.join("");
|
|
4374
|
+
}
|
|
4375
|
+
function buildParams(blocks, theme) {
|
|
4376
|
+
const parts = [];
|
|
4377
|
+
const monoFont = "'SF Mono', 'Fira Code', Consolas, 'Courier New', monospace";
|
|
4378
|
+
for (const block of blocks) {
|
|
4379
|
+
const pw = block.width - 24;
|
|
4380
|
+
const px = block.x + 12;
|
|
4381
|
+
let py = block.y + 40 + (block.subLabel ? 18 : 0);
|
|
4382
|
+
const blockLabelNorm = block.label.trim().toLowerCase();
|
|
4383
|
+
for (const param of block.params) {
|
|
4384
|
+
parts.push(
|
|
4385
|
+
`<rect x="${px}" y="${py}" width="${pw}" height="20" fill="${theme.param.plateFill}" stroke="${theme.param.plateStroke}" stroke-width="0.5"/>`
|
|
4386
|
+
);
|
|
4387
|
+
const keyNorm = param.key.trim().toLowerCase();
|
|
4388
|
+
const text = keyNorm === blockLabelNorm ? sanitizeForSvg(param.value) : `${sanitizeForSvg(param.key)}: ${sanitizeForSvg(param.value)}`;
|
|
4389
|
+
parts.push(
|
|
4390
|
+
`<text x="${px + pw / 2}" y="${py + 14}" text-anchor="middle" font-family="${monoFont}" font-size="10" fill="${theme.param.textColor}">${text}</text>`
|
|
4391
|
+
);
|
|
4392
|
+
py += 20;
|
|
4393
|
+
}
|
|
4394
|
+
}
|
|
4395
|
+
return parts.join("");
|
|
4396
|
+
}
|
|
4397
|
+
function buildJacks(theme, idPrefix, blocks) {
|
|
4398
|
+
if (theme.port.hideSocket) return "";
|
|
4399
|
+
const parts = [];
|
|
4400
|
+
const c = theme.port.colors;
|
|
4401
|
+
for (const block of blocks) {
|
|
4402
|
+
for (const port of block.ports) {
|
|
4403
|
+
const { x, y } = port.position;
|
|
4404
|
+
const id = sanitizeForSvg(`${block.id}.${port.id}`);
|
|
4405
|
+
let group = `<g data-port="${id}" filter="url(#${idPrefix}-jack-shadow)">`;
|
|
4406
|
+
group += `<circle cx="${x}" cy="${y}" r="8" fill="${c.bezel}" stroke="${c.bezelStroke}" stroke-width="0.75"/>`;
|
|
4407
|
+
group += `<circle cx="${x}" cy="${y}" r="5" fill="${c.ring}"/>`;
|
|
4408
|
+
group += `<circle cx="${x}" cy="${y}" r="3" fill="${c.hole}"/>`;
|
|
4409
|
+
group += `<circle cx="${x}" cy="${y}" r="1" fill="${c.pin}"/>`;
|
|
4410
|
+
group += `</g>`;
|
|
4411
|
+
parts.push(group);
|
|
4412
|
+
}
|
|
4413
|
+
}
|
|
4414
|
+
return parts.join("");
|
|
4415
|
+
}
|
|
4416
|
+
var SIGNAL_PILL_LABEL = {
|
|
4417
|
+
audio: "audio",
|
|
4418
|
+
cv: "cv",
|
|
4419
|
+
pitch: "1v/oct",
|
|
4420
|
+
gate: "gate",
|
|
4421
|
+
trigger: "trig",
|
|
4422
|
+
clock: "clk"
|
|
4423
|
+
};
|
|
4424
|
+
function buildLabels(theme, blocks) {
|
|
4425
|
+
const parts = [];
|
|
4426
|
+
const fontFamily = sanitizeForSvg(theme.port.fontFamily);
|
|
4427
|
+
const pillShow = theme.port.pill.show;
|
|
4428
|
+
const pillFontSize = theme.port.pill.fontSize;
|
|
4429
|
+
const pillTextColor = theme.port.pill.textColor;
|
|
4430
|
+
const pillRadius = theme.port.pill.cornerRadius;
|
|
4431
|
+
const pillPadX = 3;
|
|
4432
|
+
const pillHeight = 11;
|
|
4433
|
+
const pillGap = 6;
|
|
4434
|
+
const charWidth = 6.5;
|
|
4435
|
+
for (const block of blocks) {
|
|
4436
|
+
for (const port of block.ports) {
|
|
4437
|
+
const { x, y } = port.position;
|
|
4438
|
+
const isOut = port.direction === "out";
|
|
4439
|
+
const labelX = isOut ? x + 14 : x - 14;
|
|
4440
|
+
const labelY = y + 3;
|
|
4441
|
+
const anchor = isOut ? "start" : "end";
|
|
4442
|
+
const display = sanitizeForSvg(port.display);
|
|
4443
|
+
const labelWidth = port.display.length * charWidth;
|
|
4444
|
+
parts.push(
|
|
4445
|
+
`<text x="${labelX}" y="${labelY}" font-family="${fontFamily}" font-size="${theme.port.fontSize}" fill="${theme.port.labelColor}" font-weight="600" text-anchor="${anchor}">${display}</text>`
|
|
4446
|
+
);
|
|
4447
|
+
if (pillShow && port.signalType) {
|
|
4448
|
+
const pillText = SIGNAL_PILL_LABEL[port.signalType];
|
|
4449
|
+
const pillWidth = pillText.length * charWidth + pillPadX * 2;
|
|
4450
|
+
const pillColor = theme.cable.colors[port.signalType].stroke;
|
|
4451
|
+
let pillX;
|
|
4452
|
+
if (isOut) {
|
|
4453
|
+
pillX = labelX + labelWidth + pillGap;
|
|
4454
|
+
} else {
|
|
4455
|
+
pillX = labelX - labelWidth - pillGap - pillWidth;
|
|
4456
|
+
}
|
|
4457
|
+
const pillY = y - pillHeight / 2;
|
|
4458
|
+
const textX = pillX + pillWidth / 2;
|
|
4459
|
+
const textY = pillY + pillHeight / 2 + pillFontSize / 2 - 1;
|
|
4460
|
+
parts.push(
|
|
4461
|
+
`<rect class="pf-port-pill" x="${pillX}" y="${pillY}" width="${pillWidth}" height="${pillHeight}" rx="${pillRadius}" fill="${pillColor}" data-signal="${port.signalType}"/>`
|
|
4462
|
+
);
|
|
4463
|
+
parts.push(
|
|
4464
|
+
`<text class="pf-port-pill-text" x="${textX}" y="${textY}" text-anchor="middle" font-family="${fontFamily}" font-size="${pillFontSize}" fill="${pillTextColor}" font-weight="600">${sanitizeForSvg(pillText)}</text>`
|
|
4465
|
+
);
|
|
4466
|
+
}
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
return parts.join("");
|
|
4470
|
+
}
|
|
4471
|
+
function buildAnnotations(theme, connections) {
|
|
4472
|
+
const parts = [];
|
|
4473
|
+
const fontFamily = sanitizeForSvg(theme.annotation.fontFamily);
|
|
4474
|
+
const fontSize = theme.annotation.fontSize;
|
|
4475
|
+
const charWidth = fontSize * 0.55;
|
|
4476
|
+
for (const conn of connections) {
|
|
4477
|
+
if (!conn.annotation) continue;
|
|
4478
|
+
const sx = conn.sourcePoint.x;
|
|
4479
|
+
const sy = conn.sourcePoint.y;
|
|
4480
|
+
const tx = conn.targetPoint.x;
|
|
4481
|
+
const ty = conn.targetPoint.y;
|
|
4482
|
+
let x;
|
|
4483
|
+
let y;
|
|
4484
|
+
if (conn.isFeedback) {
|
|
4485
|
+
x = (sx + tx) / 2;
|
|
4486
|
+
y = Math.max(sy, ty) + 30;
|
|
4487
|
+
} else {
|
|
4488
|
+
x = (sx + tx) / 2;
|
|
4489
|
+
y = (sy + ty) / 2 - 14;
|
|
4490
|
+
}
|
|
4491
|
+
const prefix = conn.isFeedback ? "\u21BB " : "";
|
|
4492
|
+
let raw = conn.annotation;
|
|
4493
|
+
if (!conn.isFeedback) {
|
|
4494
|
+
const available = Math.abs(tx - sx);
|
|
4495
|
+
const prefixWidth = prefix.length * charWidth;
|
|
4496
|
+
const maxChars = Math.max(0, Math.floor((available - prefixWidth) / charWidth));
|
|
4497
|
+
if (maxChars > 0 && raw.length > maxChars) {
|
|
4498
|
+
raw = maxChars > 1 ? raw.slice(0, maxChars - 1) + "\u2026" : raw.slice(0, maxChars);
|
|
4499
|
+
}
|
|
4500
|
+
}
|
|
4501
|
+
const text = prefix + sanitizeForSvg(raw);
|
|
4502
|
+
parts.push(
|
|
4503
|
+
`<text x="${x}" y="${y}" text-anchor="middle" font-family="${fontFamily}" font-size="${fontSize}" fill="${theme.annotation.color}" paint-order="stroke fill" stroke="${theme.annotation.haloColor}" stroke-width="3" stroke-linejoin="round">${text}</text>`
|
|
4504
|
+
);
|
|
4505
|
+
}
|
|
4506
|
+
return parts.join("");
|
|
4507
|
+
}
|
|
4508
|
+
function buildLegend(theme, layoutResult) {
|
|
4509
|
+
const order = ["audio", "cv", "pitch", "gate", "trigger", "clock"];
|
|
4510
|
+
const used = order.filter((t) => (layoutResult.signalTypeStats[t] ?? 0) > 0);
|
|
4511
|
+
if (used.length === 0) return "";
|
|
4512
|
+
const parts = [];
|
|
4513
|
+
const fontFamily = sanitizeForSvg(theme.annotation.fontFamily);
|
|
4514
|
+
const itemWidth = 70;
|
|
4515
|
+
const y = layoutResult.height - 20;
|
|
4516
|
+
let x = 20;
|
|
4517
|
+
for (const sig of used) {
|
|
4518
|
+
const color = theme.cable.colors[sig].stroke;
|
|
4519
|
+
let g = `<g transform="translate(${x}, ${y})">`;
|
|
4520
|
+
g += `<line x1="0" y1="0" x2="20" y2="0" stroke="${color}" stroke-width="3" stroke-linecap="round"/>`;
|
|
4521
|
+
g += `<text x="26" y="3" font-family="${fontFamily}" font-size="9" fill="${theme.annotation.color}">${sig}</text>`;
|
|
4522
|
+
g += `</g>`;
|
|
4523
|
+
parts.push(g);
|
|
4524
|
+
x += itemWidth;
|
|
4525
|
+
}
|
|
4526
|
+
return parts.join("");
|
|
4527
|
+
}
|
|
4528
|
+
function renderSvg(layoutResult, theme) {
|
|
4529
|
+
const idPrefix = genId();
|
|
4530
|
+
const width = layoutResult.width;
|
|
4531
|
+
const height = layoutResult.height;
|
|
4532
|
+
const minWidth = Math.round(width);
|
|
4533
|
+
const desc = buildDesc(layoutResult);
|
|
4534
|
+
const defsParts = [];
|
|
4535
|
+
defsParts.push(
|
|
4536
|
+
`<filter id="${idPrefix}-panel-shadow" x="-20%" y="-20%" width="140%" height="140%"><feDropShadow dx="0" dy="2" stdDeviation="${theme.panel.shadowBlur}" flood-opacity="${theme.panel.shadowOpacity}"/></filter>`
|
|
4537
|
+
);
|
|
4538
|
+
defsParts.push(
|
|
4539
|
+
`<filter id="${idPrefix}-jack-shadow" x="-20%" y="-20%" width="140%" height="140%"><feDropShadow dx="0" dy="0.5" stdDeviation="0.8" flood-opacity="0.15"/></filter>`
|
|
4540
|
+
);
|
|
4541
|
+
if (theme.grid) {
|
|
4542
|
+
const spacing = theme.grid.spacing;
|
|
4543
|
+
defsParts.push(
|
|
4544
|
+
`<pattern id="${idPrefix}-dots" width="${spacing}" height="${spacing}" patternUnits="userSpaceOnUse"><circle cx="${spacing / 2}" cy="${spacing / 2}" r="${theme.grid.dotRadius}" fill="${theme.grid.dotColor}" opacity="${theme.grid.opacity}"/></pattern>`
|
|
4545
|
+
);
|
|
4546
|
+
}
|
|
4547
|
+
const layers = [
|
|
4548
|
+
`<g class="pf-layer-bg">${buildBackground(theme, idPrefix, width, height)}</g>`,
|
|
4549
|
+
`<g class="pf-layer-cables">${buildCables(theme, layoutResult.connections)}</g>`,
|
|
4550
|
+
`<g class="pf-layer-panels" >${buildPanels(theme, idPrefix, layoutResult.blocks)}</g>`,
|
|
4551
|
+
`<g class="pf-layer-params">${buildParams(layoutResult.blocks, theme)}</g>`,
|
|
4552
|
+
`<g class="pf-layer-jacks">${buildJacks(theme, idPrefix, layoutResult.blocks)}</g>`,
|
|
4553
|
+
`<g class="pf-layer-labels">${buildLabels(theme, layoutResult.blocks)}</g>`,
|
|
4554
|
+
`<g class="pf-layer-annotations">${buildAnnotations(theme, layoutResult.connections)}</g>`,
|
|
4555
|
+
`<g class="pf-layer-legend">${buildLegend(theme, layoutResult)}</g>`
|
|
4556
|
+
].join("");
|
|
4557
|
+
const style = `<style>@media print { .pf-panel, .pf-jack { filter: none; } }</style>`;
|
|
4558
|
+
const labelPadX = 130;
|
|
4559
|
+
const vbWidth = width + labelPadX * 2;
|
|
4560
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${-labelPadX} 0 ${vbWidth} ${height}" width="100%" data-pf-min-width="${minWidth + labelPadX * 2}" role="img" aria-labelledby="${idPrefix}-title ${idPrefix}-desc"><title id="${idPrefix}-title">Patch diagram</title><desc id="${idPrefix}-desc">${desc}</desc>` + style + `<defs>${defsParts.join("")}</defs>` + layers + `</svg>`;
|
|
4561
|
+
return svg;
|
|
4562
|
+
}
|
|
4563
|
+
|
|
4564
|
+
// src/themes/default.ts
|
|
4565
|
+
var defaultTheme = {
|
|
4566
|
+
background: "transparent",
|
|
4567
|
+
panel: {
|
|
4568
|
+
fill: "#e8e4dc",
|
|
4569
|
+
stroke: "#cec8be",
|
|
4570
|
+
highlight: "#f2efe8",
|
|
4571
|
+
shadow: "#bdb8ae",
|
|
4572
|
+
cornerRadius: 0,
|
|
4573
|
+
shadowBlur: 3,
|
|
4574
|
+
shadowOpacity: 0.1,
|
|
4575
|
+
bevelWidth: 1
|
|
4576
|
+
},
|
|
4577
|
+
label: {
|
|
4578
|
+
fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
4579
|
+
color: "#1a1a1a",
|
|
4580
|
+
subColor: "#888888",
|
|
4581
|
+
plateFill: "#f4f1ea",
|
|
4582
|
+
plateStroke: "#c5c0b6"
|
|
4583
|
+
},
|
|
4584
|
+
param: {
|
|
4585
|
+
plateFill: "#f0ede6",
|
|
4586
|
+
plateStroke: "#d5d0c6",
|
|
4587
|
+
textColor: "#555555"
|
|
4588
|
+
},
|
|
4589
|
+
port: {
|
|
4590
|
+
fontFamily: "'SF Mono', 'Fira Code', Consolas, 'Courier New', monospace",
|
|
4591
|
+
fontSize: 9,
|
|
4592
|
+
colors: {
|
|
4593
|
+
bezel: "#c0bbb2",
|
|
4594
|
+
bezelStroke: "#a8a39a",
|
|
4595
|
+
ring: "#8a8580",
|
|
4596
|
+
hole: "#555555",
|
|
4597
|
+
pin: "#333333"
|
|
4598
|
+
},
|
|
4599
|
+
hideSocket: false,
|
|
4600
|
+
labelColor: "#1a1a1a",
|
|
4601
|
+
pill: {
|
|
4602
|
+
show: true,
|
|
4603
|
+
fontSize: 8,
|
|
4604
|
+
textColor: "#ffffff",
|
|
4605
|
+
cornerRadius: 0
|
|
4606
|
+
}
|
|
4607
|
+
},
|
|
4608
|
+
cable: {
|
|
4609
|
+
width: 3,
|
|
4610
|
+
colors: {
|
|
4611
|
+
audio: { stroke: "#e88ca5", plugTip: "#d47a93" },
|
|
4612
|
+
cv: { stroke: "#7bafd4", plugTip: "#6a9ec3" },
|
|
4613
|
+
pitch: { stroke: "#8cb87c", plugTip: "#7ba76b" },
|
|
4614
|
+
gate: { stroke: "#d4a054", plugTip: "#c49244" },
|
|
4615
|
+
trigger: { stroke: "#d4a054", plugTip: "#c49244" },
|
|
4616
|
+
clock: { stroke: "#d4a054", plugTip: "#c49244" }
|
|
4617
|
+
},
|
|
4618
|
+
plugTipRadius: 3.5
|
|
4619
|
+
},
|
|
4620
|
+
annotation: {
|
|
4621
|
+
fontFamily: "'SF Mono', 'Fira Code', Consolas, 'Courier New', monospace",
|
|
4622
|
+
fontSize: 9,
|
|
4623
|
+
color: "#888888",
|
|
4624
|
+
haloColor: "#f7f5f0"
|
|
4625
|
+
},
|
|
4626
|
+
grid: {
|
|
4627
|
+
dotColor: "#aaaaaa",
|
|
4628
|
+
dotRadius: 0.5,
|
|
4629
|
+
spacing: 12,
|
|
4630
|
+
opacity: 0.3
|
|
4631
|
+
}
|
|
4632
|
+
};
|
|
4633
|
+
function deepMerge(target, source) {
|
|
4634
|
+
const result = { ...target };
|
|
4635
|
+
const src = source;
|
|
4636
|
+
const tgt = target;
|
|
4637
|
+
for (const key in src) {
|
|
4638
|
+
const sourceVal = src[key];
|
|
4639
|
+
const targetVal = tgt[key];
|
|
4640
|
+
if (sourceVal !== null && typeof sourceVal === "object" && !Array.isArray(sourceVal) && targetVal !== null && typeof targetVal === "object" && !Array.isArray(targetVal)) {
|
|
4641
|
+
result[key] = deepMerge(
|
|
4642
|
+
targetVal,
|
|
4643
|
+
sourceVal
|
|
4644
|
+
);
|
|
4645
|
+
} else if (sourceVal !== void 0) {
|
|
4646
|
+
result[key] = sourceVal;
|
|
4647
|
+
}
|
|
4648
|
+
}
|
|
4649
|
+
return result;
|
|
4650
|
+
}
|
|
4651
|
+
function createTheme(overrides) {
|
|
4652
|
+
return deepMerge(defaultTheme, overrides);
|
|
4653
|
+
}
|
|
4654
|
+
|
|
4655
|
+
// src/themes/dark.ts
|
|
4656
|
+
var darkTheme = createTheme({
|
|
4657
|
+
port: {
|
|
4658
|
+
// Port labels sit outside the panel, on the page. Use a light cream so
|
|
4659
|
+
// they read on dark page backgrounds.
|
|
4660
|
+
labelColor: "#e8e4dc"
|
|
4661
|
+
},
|
|
4662
|
+
annotation: {
|
|
4663
|
+
// Annotations on cables sit on the page bg. Lighten the text and match
|
|
4664
|
+
// the halo to the GitHub dark page bg so the "chip" doesn't flash cream.
|
|
4665
|
+
color: "#d0d0d0",
|
|
4666
|
+
haloColor: "#0d1117"
|
|
4667
|
+
},
|
|
4668
|
+
grid: {
|
|
4669
|
+
// Faint dot grid needs to be visible on dark backgrounds too.
|
|
4670
|
+
dotColor: "#555555",
|
|
4671
|
+
dotRadius: 0.5,
|
|
4672
|
+
spacing: 12,
|
|
4673
|
+
opacity: 0.5
|
|
4674
|
+
}
|
|
4675
|
+
});
|
|
4676
|
+
|
|
4677
|
+
// src/index.ts
|
|
4678
|
+
function render(notation, options) {
|
|
4679
|
+
const parseResult = parse(notation);
|
|
4680
|
+
const { graph } = parseResult;
|
|
4681
|
+
const totalBlocks = graph.declaredBlocks.length + graph.stubBlocks.length;
|
|
4682
|
+
const totalConnections = graph.connections.length + graph.feedbackEdges.length;
|
|
4683
|
+
if (totalBlocks === 0 && totalConnections === 0) {
|
|
4684
|
+
throw new Error("patchflow parse error: empty patch \u2014 no modules or connections found");
|
|
4685
|
+
}
|
|
4686
|
+
const layoutResult = layout(graph, {
|
|
4687
|
+
direction: "LR"
|
|
4688
|
+
});
|
|
4689
|
+
const theme = options?.theme ? createTheme(options.theme) : defaultTheme;
|
|
4690
|
+
return renderSvg(layoutResult, theme);
|
|
4691
|
+
}
|
|
4692
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
4693
|
+
0 && (module.exports = {
|
|
4694
|
+
createTheme,
|
|
4695
|
+
darkTheme,
|
|
4696
|
+
defaultTheme,
|
|
4697
|
+
layout,
|
|
4698
|
+
parse,
|
|
4699
|
+
render,
|
|
4700
|
+
renderSvg
|
|
4701
|
+
});
|
|
4702
|
+
//# sourceMappingURL=index.cjs.map
|