@dagrejs/dagre 1.1.5 → 1.1.8

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/dist/dagre.js CHANGED
@@ -1161,6 +1161,8 @@ module.exports = buildLayerGraph;
1161
1161
  * 2. Base nodes in the input graph have a rank attribute
1162
1162
  * 3. Subgraph nodes in the input graph has minRank and maxRank attributes
1163
1163
  * 4. Edges have an assigned weight
1164
+ * 5. If `nodesWithRank` is not undefined, it must contains only the nodes
1165
+ * which belong to `g` and belong to `rank`.
1164
1166
  *
1165
1167
  * Post-conditions:
1166
1168
  *
@@ -1175,12 +1177,16 @@ module.exports = buildLayerGraph;
1175
1177
  * 5. The weights for copied edges are aggregated as need, since the output
1176
1178
  * graph is not a multi-graph.
1177
1179
  */
1178
- function buildLayerGraph(g, rank, relationship) {
1180
+ function buildLayerGraph(g, rank, relationship, nodesWithRank) {
1181
+ if (!nodesWithRank) {
1182
+ nodesWithRank = g.nodes();
1183
+ }
1179
1184
  let root = createRootNode(g),
1180
- result = new Graph({ compound: true }).setGraph({ root: root })
1181
- .setDefaultNodeLabel(v => g.node(v));
1185
+ result = new Graph({ compound: true })
1186
+ .setGraph({ root: root })
1187
+ .setDefaultNodeLabel((v) => g.node(v));
1182
1188
 
1183
- g.nodes().forEach(v => {
1189
+ nodesWithRank.forEach((v) => {
1184
1190
  let node = g.node(v),
1185
1191
  parent = g.parent(v);
1186
1192
 
@@ -1346,8 +1352,38 @@ function order(g, opts) {
1346
1352
  }
1347
1353
 
1348
1354
  function buildLayerGraphs(g, ranks, relationship) {
1349
- return ranks.map(function(rank) {
1350
- return buildLayerGraph(g, rank, relationship);
1355
+ // Build an index mapping from rank to the nodes with that rank.
1356
+ // This helps to avoid a quadratic search for all nodes with the same rank as
1357
+ // the current node.
1358
+ const nodesByRank = new Map();
1359
+ const addNodeToRank = (rank, node) => {
1360
+ if (!nodesByRank.has(rank)) {
1361
+ nodesByRank.set(rank, []);
1362
+ }
1363
+ nodesByRank.get(rank).push(node);
1364
+ };
1365
+
1366
+ // Visit the nodes in their original order in the graph, and add each
1367
+ // node to the ranks(s) that it belongs to.
1368
+ for (const v of g.nodes()) {
1369
+ const node = g.node(v);
1370
+ if (typeof node.rank === "number") {
1371
+ addNodeToRank(node.rank, v);
1372
+ }
1373
+ // If there is a range of ranks, add it to each, but skip the `node.rank` which
1374
+ // has already had the node added.
1375
+ if (typeof node.minRank === "number" && typeof node.maxRank === "number") {
1376
+ for (let r = node.minRank; r <= node.maxRank; r++) {
1377
+ if (r !== node.rank) {
1378
+ // Don't add this node to its `node.rank` twice.
1379
+ addNodeToRank(r, v);
1380
+ }
1381
+ }
1382
+ }
1383
+ }
1384
+
1385
+ return ranks.map(function (rank) {
1386
+ return buildLayerGraph(g, rank, relationship, nodesByRank.get(rank) || []);
1351
1387
  });
1352
1388
  }
1353
1389
 
@@ -2996,7 +3032,7 @@ function zipObject(props, values) {
2996
3032
  }
2997
3033
 
2998
3034
  },{"@dagrejs/graphlib":29}],28:[function(require,module,exports){
2999
- module.exports = "1.1.5";
3035
+ module.exports = "1.1.8";
3000
3036
 
3001
3037
  },{}],29:[function(require,module,exports){
3002
3038
  /**
package/dist/dagre.min.js CHANGED
@@ -153,6 +153,8 @@ g.graph().nodeRankFactor=nodeSep}function dfs(g,root,nodeSep,weight,height,depth
153
153
  * 2. Base nodes in the input graph have a rank attribute
154
154
  * 3. Subgraph nodes in the input graph has minRank and maxRank attributes
155
155
  * 4. Edges have an assigned weight
156
+ * 5. If `nodesWithRank` is not undefined, it must contains only the nodes
157
+ * which belong to `g` and belong to `rank`.
156
158
  *
157
159
  * Post-conditions:
158
160
  *
@@ -166,7 +168,7 @@ g.graph().nodeRankFactor=nodeSep}function dfs(g,root,nodeSep,weight,height,depth
166
168
  * parameter, are added to the output graph.
167
169
  * 5. The weights for copied edges are aggregated as need, since the output
168
170
  * graph is not a multi-graph.
169
- */function buildLayerGraph(g,rank,relationship){let root=createRootNode(g),result=new Graph({compound:true}).setGraph({root:root}).setDefaultNodeLabel(v=>g.node(v));g.nodes().forEach(v=>{let node=g.node(v),parent=g.parent(v);if(node.rank===rank||node.minRank<=rank&&rank<=node.maxRank){result.setNode(v);result.setParent(v,parent||root);
171
+ */function buildLayerGraph(g,rank,relationship,nodesWithRank){if(!nodesWithRank){nodesWithRank=g.nodes()}let root=createRootNode(g),result=new Graph({compound:true}).setGraph({root:root}).setDefaultNodeLabel(v=>g.node(v));nodesWithRank.forEach(v=>{let node=g.node(v),parent=g.parent(v);if(node.rank===rank||node.minRank<=rank&&rank<=node.maxRank){result.setNode(v);result.setParent(v,parent||root);
170
172
  // This assumes we have only short edges!
171
173
  g[relationship](v).forEach(e=>{let u=e.v===v?e.w:e.v,edge=result.edge(u,v),weight=edge!==undefined?edge.weight:0;result.setEdge(u,v,{weight:g.edge(e).weight+weight})});if(Object.hasOwn(node,"minRank")){result.setNode(v,{borderLeft:node.borderLeft[rank],borderRight:node.borderRight[rank]})}}});return result}function createRootNode(g){var v;while(g.hasNode(v=util.uniqueId("_root")));return v}},{"../util":27,"@dagrejs/graphlib":29}],14:[function(require,module,exports){"use strict";let zipObject=require("../util").zipObject;module.exports=crossCount;
172
174
  /*
@@ -207,7 +209,19 @@ let cc=0;southEntries.forEach(entry=>{let index=entry.pos+firstIndex;tree[index]
207
209
  *
208
210
  * 1. Graph nodes will have an "order" attribute based on the results of the
209
211
  * algorithm.
210
- */function order(g,opts){if(opts&&typeof opts.customOrder==="function"){opts.customOrder(g,order);return}let maxRank=util.maxRank(g),downLayerGraphs=buildLayerGraphs(g,util.range(1,maxRank+1),"inEdges"),upLayerGraphs=buildLayerGraphs(g,util.range(maxRank-1,-1,-1),"outEdges");let layering=initOrder(g);assignOrder(g,layering);if(opts&&opts.disableOptimalOrderHeuristic){return}let bestCC=Number.POSITIVE_INFINITY,best;for(let i=0,lastBest=0;lastBest<4;++i,++lastBest){sweepLayerGraphs(i%2?downLayerGraphs:upLayerGraphs,i%4>=2);layering=util.buildLayerMatrix(g);let cc=crossCount(g,layering);if(cc<bestCC){lastBest=0;best=Object.assign({},layering);bestCC=cc}}assignOrder(g,best)}function buildLayerGraphs(g,ranks,relationship){return ranks.map(function(rank){return buildLayerGraph(g,rank,relationship)})}function sweepLayerGraphs(layerGraphs,biasRight){let cg=new Graph;layerGraphs.forEach(function(lg){let root=lg.graph().root;let sorted=sortSubgraph(lg,root,cg,biasRight);sorted.vs.forEach((v,i)=>lg.node(v).order=i);addSubgraphConstraints(lg,cg,sorted.vs)})}function assignOrder(g,layering){Object.values(layering).forEach(layer=>layer.forEach((v,i)=>g.node(v).order=i))}},{"../util":27,"./add-subgraph-constraints":11,"./build-layer-graph":13,"./cross-count":14,"./init-order":16,"./sort-subgraph":18,"@dagrejs/graphlib":29}],16:[function(require,module,exports){"use strict";let util=require("../util");module.exports=initOrder;
212
+ */function order(g,opts){if(opts&&typeof opts.customOrder==="function"){opts.customOrder(g,order);return}let maxRank=util.maxRank(g),downLayerGraphs=buildLayerGraphs(g,util.range(1,maxRank+1),"inEdges"),upLayerGraphs=buildLayerGraphs(g,util.range(maxRank-1,-1,-1),"outEdges");let layering=initOrder(g);assignOrder(g,layering);if(opts&&opts.disableOptimalOrderHeuristic){return}let bestCC=Number.POSITIVE_INFINITY,best;for(let i=0,lastBest=0;lastBest<4;++i,++lastBest){sweepLayerGraphs(i%2?downLayerGraphs:upLayerGraphs,i%4>=2);layering=util.buildLayerMatrix(g);let cc=crossCount(g,layering);if(cc<bestCC){lastBest=0;best=Object.assign({},layering);bestCC=cc}}assignOrder(g,best)}function buildLayerGraphs(g,ranks,relationship){
213
+ // Build an index mapping from rank to the nodes with that rank.
214
+ // This helps to avoid a quadratic search for all nodes with the same rank as
215
+ // the current node.
216
+ const nodesByRank=new Map;const addNodeToRank=(rank,node)=>{if(!nodesByRank.has(rank)){nodesByRank.set(rank,[])}nodesByRank.get(rank).push(node)};
217
+ // Visit the nodes in their original order in the graph, and add each
218
+ // node to the ranks(s) that it belongs to.
219
+ for(const v of g.nodes()){const node=g.node(v);if(typeof node.rank==="number"){addNodeToRank(node.rank,v)}
220
+ // If there is a range of ranks, add it to each, but skip the `node.rank` which
221
+ // has already had the node added.
222
+ if(typeof node.minRank==="number"&&typeof node.maxRank==="number"){for(let r=node.minRank;r<=node.maxRank;r++){if(r!==node.rank){
223
+ // Don't add this node to its `node.rank` twice.
224
+ addNodeToRank(r,v)}}}}return ranks.map(function(rank){return buildLayerGraph(g,rank,relationship,nodesByRank.get(rank)||[])})}function sweepLayerGraphs(layerGraphs,biasRight){let cg=new Graph;layerGraphs.forEach(function(lg){let root=lg.graph().root;let sorted=sortSubgraph(lg,root,cg,biasRight);sorted.vs.forEach((v,i)=>lg.node(v).order=i);addSubgraphConstraints(lg,cg,sorted.vs)})}function assignOrder(g,layering){Object.values(layering).forEach(layer=>layer.forEach((v,i)=>g.node(v).order=i))}},{"../util":27,"./add-subgraph-constraints":11,"./build-layer-graph":13,"./cross-count":14,"./init-order":16,"./sort-subgraph":18,"@dagrejs/graphlib":29}],16:[function(require,module,exports){"use strict";let util=require("../util");module.exports=initOrder;
211
225
  /*
212
226
  * Assigns an initial order value for each node by performing a DFS search
213
227
  * starting from nodes in the first rank. Nodes are assigned an order in their
@@ -495,7 +509,7 @@ let nodeRanks=g.nodes().map(v=>g.node(v).rank);let offset=applyWithChunking(Math
495
509
  /*
496
510
  * Returns a new function that wraps `fn` with a timer. The wrapper logs the
497
511
  * time it takes to execute the function.
498
- */function time(name,fn){let start=Date.now();try{return fn()}finally{console.log(name+" time: "+(Date.now()-start)+"ms")}}function notime(name,fn){return fn()}let idCounter=0;function uniqueId(prefix){var id=++idCounter;return prefix+(""+id)}function range(start,limit,step=1){if(limit==null){limit=start;start=0}let endCon=i=>i<limit;if(step<0){endCon=i=>limit<i}const range=[];for(let i=start;endCon(i);i+=step){range.push(i)}return range}function pick(source,keys){const dest={};for(const key of keys){if(source[key]!==undefined){dest[key]=source[key]}}return dest}function mapValues(obj,funcOrProp){let func=funcOrProp;if(typeof funcOrProp==="string"){func=val=>val[funcOrProp]}return Object.entries(obj).reduce((acc,[k,v])=>{acc[k]=func(v,k);return acc},{})}function zipObject(props,values){return props.reduce((acc,key,i)=>{acc[key]=values[i];return acc},{})}},{"@dagrejs/graphlib":29}],28:[function(require,module,exports){module.exports="1.1.5"},{}],29:[function(require,module,exports){
512
+ */function time(name,fn){let start=Date.now();try{return fn()}finally{console.log(name+" time: "+(Date.now()-start)+"ms")}}function notime(name,fn){return fn()}let idCounter=0;function uniqueId(prefix){var id=++idCounter;return prefix+(""+id)}function range(start,limit,step=1){if(limit==null){limit=start;start=0}let endCon=i=>i<limit;if(step<0){endCon=i=>limit<i}const range=[];for(let i=start;endCon(i);i+=step){range.push(i)}return range}function pick(source,keys){const dest={};for(const key of keys){if(source[key]!==undefined){dest[key]=source[key]}}return dest}function mapValues(obj,funcOrProp){let func=funcOrProp;if(typeof funcOrProp==="string"){func=val=>val[funcOrProp]}return Object.entries(obj).reduce((acc,[k,v])=>{acc[k]=func(v,k);return acc},{})}function zipObject(props,values){return props.reduce((acc,key,i)=>{acc[key]=values[i];return acc},{})}},{"@dagrejs/graphlib":29}],28:[function(require,module,exports){module.exports="1.1.8"},{}],29:[function(require,module,exports){
499
513
  /**
500
514
  * Copyright (c) 2014, Chris Pettitt
501
515
  * All rights reserved.
package/index.d.ts CHANGED
@@ -57,7 +57,7 @@ declare module '@dagrejs/dagre' {
57
57
  function dijkstra(graph: Graph, source: string, weightFn?: WeightFn, edgeFn?: EdgeFn): any;
58
58
  function dijkstraAll(graph: Graph, weightFn?: WeightFn, edgeFn?: EdgeFn): any;
59
59
  function findCycles(graph: Graph): string[][];
60
- function floydWarchall(graph: Graph, weightFn?: WeightFn, edgeFn?: EdgeFn): any;
60
+ function floydWarshall(graph: Graph, weightFn?: WeightFn, edgeFn?: EdgeFn): any;
61
61
  function isAcyclic(graph: Graph): boolean;
62
62
  function postorder(graph: Graph, nodeNames: string | string[]): string[];
63
63
  function preorder(graph: Graph, nodeNames: string | string[]): string[];
@@ -19,6 +19,8 @@ module.exports = buildLayerGraph;
19
19
  * 2. Base nodes in the input graph have a rank attribute
20
20
  * 3. Subgraph nodes in the input graph has minRank and maxRank attributes
21
21
  * 4. Edges have an assigned weight
22
+ * 5. If `nodesWithRank` is not undefined, it must contains only the nodes
23
+ * which belong to `g` and belong to `rank`.
22
24
  *
23
25
  * Post-conditions:
24
26
  *
@@ -33,12 +35,16 @@ module.exports = buildLayerGraph;
33
35
  * 5. The weights for copied edges are aggregated as need, since the output
34
36
  * graph is not a multi-graph.
35
37
  */
36
- function buildLayerGraph(g, rank, relationship) {
38
+ function buildLayerGraph(g, rank, relationship, nodesWithRank) {
39
+ if (!nodesWithRank) {
40
+ nodesWithRank = g.nodes();
41
+ }
37
42
  let root = createRootNode(g),
38
- result = new Graph({ compound: true }).setGraph({ root: root })
39
- .setDefaultNodeLabel(v => g.node(v));
43
+ result = new Graph({ compound: true })
44
+ .setGraph({ root: root })
45
+ .setDefaultNodeLabel((v) => g.node(v));
40
46
 
41
- g.nodes().forEach(v => {
47
+ nodesWithRank.forEach((v) => {
42
48
  let node = g.node(v),
43
49
  parent = g.parent(v);
44
50
 
@@ -61,8 +61,38 @@ function order(g, opts) {
61
61
  }
62
62
 
63
63
  function buildLayerGraphs(g, ranks, relationship) {
64
- return ranks.map(function(rank) {
65
- return buildLayerGraph(g, rank, relationship);
64
+ // Build an index mapping from rank to the nodes with that rank.
65
+ // This helps to avoid a quadratic search for all nodes with the same rank as
66
+ // the current node.
67
+ const nodesByRank = new Map();
68
+ const addNodeToRank = (rank, node) => {
69
+ if (!nodesByRank.has(rank)) {
70
+ nodesByRank.set(rank, []);
71
+ }
72
+ nodesByRank.get(rank).push(node);
73
+ };
74
+
75
+ // Visit the nodes in their original order in the graph, and add each
76
+ // node to the ranks(s) that it belongs to.
77
+ for (const v of g.nodes()) {
78
+ const node = g.node(v);
79
+ if (typeof node.rank === "number") {
80
+ addNodeToRank(node.rank, v);
81
+ }
82
+ // If there is a range of ranks, add it to each, but skip the `node.rank` which
83
+ // has already had the node added.
84
+ if (typeof node.minRank === "number" && typeof node.maxRank === "number") {
85
+ for (let r = node.minRank; r <= node.maxRank; r++) {
86
+ if (r !== node.rank) {
87
+ // Don't add this node to its `node.rank` twice.
88
+ addNodeToRank(r, v);
89
+ }
90
+ }
91
+ }
92
+ }
93
+
94
+ return ranks.map(function (rank) {
95
+ return buildLayerGraph(g, rank, relationship, nodesByRank.get(rank) || []);
66
96
  });
67
97
  }
68
98
 
package/lib/version.js CHANGED
@@ -1 +1 @@
1
- module.exports = "1.1.5";
1
+ module.exports = "1.1.8";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dagrejs/dagre",
3
- "version": "1.1.5",
3
+ "version": "1.1.8",
4
4
  "description": "Graph layout for JavaScript",
5
5
  "author": "Chris Pettitt <cpettitt@gmail.com>",
6
6
  "contributors": [