@dagrejs/dagre 0.8.0 → 1.0.1

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.
@@ -1,12 +1,11 @@
1
1
  "use strict";
2
2
 
3
- var _ = require("../lodash"),
4
- feasibleTree = require("./feasible-tree"),
5
- slack = require("./util").slack,
6
- initRank = require("./util").longestPath,
7
- preorder = require("../graphlib").alg.preorder,
8
- postorder = require("../graphlib").alg.postorder,
9
- simplify = require("../util").simplify;
3
+ var feasibleTree = require("./feasible-tree");
4
+ var slack = require("./util").slack;
5
+ var initRank = require("./util").longestPath;
6
+ var preorder = require("@dagrejs/graphlib").alg.preorder;
7
+ var postorder = require("@dagrejs/graphlib").alg.postorder;
8
+ var simplify = require("../util").simplify;
10
9
 
11
10
  module.exports = networkSimplex;
12
11
 
@@ -71,14 +70,12 @@ function networkSimplex(g) {
71
70
  function initCutValues(t, g) {
72
71
  var vs = postorder(t, t.nodes());
73
72
  vs = vs.slice(0, vs.length - 1);
74
- _.forEach(vs, function(v) {
75
- assignCutValue(t, g, v);
76
- });
73
+ vs.forEach(v => assignCutValue(t, g, v));
77
74
  }
78
75
 
79
76
  function assignCutValue(t, g, child) {
80
- var childLab = t.node(child),
81
- parent = childLab.parent;
77
+ var childLab = t.node(child);
78
+ var parent = childLab.parent;
82
79
  t.edge(child, parent).cutvalue = calcCutValue(t, g, child);
83
80
  }
84
81
 
@@ -87,14 +84,14 @@ function assignCutValue(t, g, child) {
87
84
  * return the cut value for the edge between the child and its parent.
88
85
  */
89
86
  function calcCutValue(t, g, child) {
90
- var childLab = t.node(child),
91
- parent = childLab.parent,
92
- // True if the child is on the tail end of the edge in the directed graph
93
- childIsTail = true,
94
- // The graph's view of the tree edge we're inspecting
95
- graphEdge = g.edge(child, parent),
96
- // The accumulated cut value for the edge between this node and its parent
97
- cutValue = 0;
87
+ var childLab = t.node(child);
88
+ var parent = childLab.parent;
89
+ // True if the child is on the tail end of the edge in the directed graph
90
+ var childIsTail = true;
91
+ // The graph's view of the tree edge we're inspecting
92
+ var graphEdge = g.edge(child, parent);
93
+ // The accumulated cut value for the edge between this node and its parent
94
+ var cutValue = 0;
98
95
 
99
96
  if (!graphEdge) {
100
97
  childIsTail = false;
@@ -103,13 +100,13 @@ function calcCutValue(t, g, child) {
103
100
 
104
101
  cutValue = graphEdge.weight;
105
102
 
106
- _.forEach(g.nodeEdges(child), function(e) {
103
+ g.nodeEdges(child).forEach(function(e) {
107
104
  var isOutEdge = e.v === child,
108
- other = isOutEdge ? e.w : e.v;
105
+ other = isOutEdge ? e.w : e.v;
109
106
 
110
107
  if (other !== parent) {
111
108
  var pointsToHead = isOutEdge === childIsTail,
112
- otherWeight = g.edge(e).weight;
109
+ otherWeight = g.edge(e).weight;
113
110
 
114
111
  cutValue += pointsToHead ? otherWeight : -otherWeight;
115
112
  if (isTreeEdge(t, child, other)) {
@@ -130,12 +127,12 @@ function initLowLimValues(tree, root) {
130
127
  }
131
128
 
132
129
  function dfsAssignLowLim(tree, visited, nextLim, v, parent) {
133
- var low = nextLim,
134
- label = tree.node(v);
130
+ var low = nextLim;
131
+ var label = tree.node(v);
135
132
 
136
133
  visited[v] = true;
137
- _.forEach(tree.neighbors(v), function(w) {
138
- if (!_.has(visited, w)) {
134
+ tree.neighbors(v).forEach(function(w) {
135
+ if (!visited.hasOwnProperty(w)) {
139
136
  nextLim = dfsAssignLowLim(tree, visited, nextLim, w, v);
140
137
  }
141
138
  });
@@ -153,14 +150,12 @@ function dfsAssignLowLim(tree, visited, nextLim, v, parent) {
153
150
  }
154
151
 
155
152
  function leaveEdge(tree) {
156
- return _.find(tree.edges(), function(e) {
157
- return tree.edge(e).cutvalue < 0;
158
- });
153
+ return tree.edges().find(e => tree.edge(e).cutvalue < 0);
159
154
  }
160
155
 
161
156
  function enterEdge(t, g, edge) {
162
- var v = edge.v,
163
- w = edge.w;
157
+ var v = edge.v;
158
+ var w = edge.w;
164
159
 
165
160
  // For the rest of this function we assume that v is the tail and w is the
166
161
  // head, so if we don't have this edge in the graph we should flip it to
@@ -170,10 +165,10 @@ function enterEdge(t, g, edge) {
170
165
  w = edge.v;
171
166
  }
172
167
 
173
- var vLabel = t.node(v),
174
- wLabel = t.node(w),
175
- tailLabel = vLabel,
176
- flip = false;
168
+ var vLabel = t.node(v);
169
+ var wLabel = t.node(w);
170
+ var tailLabel = vLabel;
171
+ var flip = false;
177
172
 
178
173
  // If the root is in the tail of the edge then we need to flip the logic that
179
174
  // checks for the head and tail nodes in the candidates function below.
@@ -182,17 +177,23 @@ function enterEdge(t, g, edge) {
182
177
  flip = true;
183
178
  }
184
179
 
185
- var candidates = _.filter(g.edges(), function(edge) {
180
+ var candidates = g.edges().filter(function(edge) {
186
181
  return flip === isDescendant(t, t.node(edge.v), tailLabel) &&
187
182
  flip !== isDescendant(t, t.node(edge.w), tailLabel);
188
183
  });
189
184
 
190
- return _.minBy(candidates, function(edge) { return slack(g, edge); });
185
+ return candidates.reduce((acc, edge) => {
186
+ if (slack(g, edge) < slack(g, acc)) {
187
+ return edge;
188
+ }
189
+
190
+ return acc;
191
+ });
191
192
  }
192
193
 
193
194
  function exchangeEdges(t, g, e, f) {
194
- var v = e.v,
195
- w = e.w;
195
+ var v = e.v;
196
+ var w = e.w;
196
197
  t.removeEdge(v, w);
197
198
  t.setEdge(f.v, f.w, {});
198
199
  initLowLimValues(t);
@@ -201,13 +202,13 @@ function exchangeEdges(t, g, e, f) {
201
202
  }
202
203
 
203
204
  function updateRanks(t, g) {
204
- var root = _.find(t.nodes(), function(v) { return !g.node(v).parent; }),
205
- vs = preorder(t, root);
205
+ var root = t.nodes().find(v => !g.node(v).parent);
206
+ var vs = preorder(t, root);
206
207
  vs = vs.slice(1);
207
- _.forEach(vs, function(v) {
208
+ vs.forEach(function(v) {
208
209
  var parent = t.node(v).parent,
209
- edge = g.edge(v, parent),
210
- flipped = false;
210
+ edge = g.edge(v, parent),
211
+ flipped = false;
211
212
 
212
213
  if (!edge) {
213
214
  edge = g.edge(parent, v);
package/lib/rank/util.js CHANGED
@@ -1,7 +1,5 @@
1
1
  "use strict";
2
2
 
3
- var _ = require("../lodash");
4
-
5
3
  module.exports = {
6
4
  longestPath: longestPath,
7
5
  slack: slack
@@ -33,25 +31,27 @@ function longestPath(g) {
33
31
 
34
32
  function dfs(v) {
35
33
  var label = g.node(v);
36
- if (_.has(visited, v)) {
34
+ if (visited.hasOwnProperty(v)) {
37
35
  return label.rank;
38
36
  }
39
37
  visited[v] = true;
40
38
 
41
- var rank = _.minBy(_.map(g.outEdges(v), function(e) {
39
+ var rank = Math.min(...g.outEdges(v).map(e => {
40
+ if (e == null) {
41
+ return Number.POSITIVE_INFINITY;
42
+ }
43
+
42
44
  return dfs(e.w) - g.edge(e).minlen;
43
45
  }));
44
46
 
45
- if (rank === Number.POSITIVE_INFINITY || // return value of _.map([]) for Lodash 3
46
- rank === undefined || // return value of _.map([]) for Lodash 4
47
- rank === null) { // return value of _.map([null])
47
+ if (rank === Number.POSITIVE_INFINITY) {
48
48
  rank = 0;
49
49
  }
50
50
 
51
51
  return (label.rank = rank);
52
52
  }
53
53
 
54
- _.forEach(g.sources(), dfs);
54
+ g.sources().forEach(dfs);
55
55
  }
56
56
 
57
57
  /*
package/lib/util.js CHANGED
@@ -1,23 +1,29 @@
1
+ /* eslint "no-console": off */
2
+
1
3
  "use strict";
2
4
 
3
- var _ = require("./lodash"),
4
- Graph = require("./graphlib").Graph;
5
+ var Graph = require("@dagrejs/graphlib").Graph;
5
6
 
6
7
  module.exports = {
7
- addDummyNode: addDummyNode,
8
- simplify: simplify,
9
- asNonCompoundGraph: asNonCompoundGraph,
10
- successorWeights: successorWeights,
11
- predecessorWeights: predecessorWeights,
12
- intersectRect: intersectRect,
13
- buildLayerMatrix: buildLayerMatrix,
14
- normalizeRanks: normalizeRanks,
15
- removeEmptyRanks: removeEmptyRanks,
16
- addBorderNode: addBorderNode,
17
- maxRank: maxRank,
18
- partition: partition,
19
- time: time,
20
- notime: notime
8
+ addBorderNode,
9
+ addDummyNode,
10
+ asNonCompoundGraph,
11
+ buildLayerMatrix,
12
+ intersectRect,
13
+ mapValues,
14
+ maxRank,
15
+ normalizeRanks,
16
+ notime,
17
+ partition,
18
+ pick,
19
+ predecessorWeights,
20
+ range,
21
+ removeEmptyRanks,
22
+ simplify,
23
+ successorWeights,
24
+ time,
25
+ uniqueId,
26
+ zipObject,
21
27
  };
22
28
 
23
29
  /*
@@ -26,7 +32,7 @@ module.exports = {
26
32
  function addDummyNode(g, type, attrs, name) {
27
33
  var v;
28
34
  do {
29
- v = _.uniqueId(name);
35
+ v = uniqueId(name);
30
36
  } while (g.hasNode(v));
31
37
 
32
38
  attrs.dummy = type;
@@ -40,10 +46,10 @@ function addDummyNode(g, type, attrs, name) {
40
46
  */
41
47
  function simplify(g) {
42
48
  var simplified = new Graph().setGraph(g.graph());
43
- _.forEach(g.nodes(), function(v) { simplified.setNode(v, g.node(v)); });
44
- _.forEach(g.edges(), function(e) {
45
- var simpleLabel = simplified.edge(e.v, e.w) || { weight: 0, minlen: 1 },
46
- label = g.edge(e);
49
+ g.nodes().forEach(v => simplified.setNode(v, g.node(v)));
50
+ g.edges().forEach(e => {
51
+ var simpleLabel = simplified.edge(e.v, e.w) || { weight: 0, minlen: 1 };
52
+ var label = g.edge(e);
47
53
  simplified.setEdge(e.v, e.w, {
48
54
  weight: simpleLabel.weight + label.weight,
49
55
  minlen: Math.max(simpleLabel.minlen, label.minlen)
@@ -54,37 +60,37 @@ function simplify(g) {
54
60
 
55
61
  function asNonCompoundGraph(g) {
56
62
  var simplified = new Graph({ multigraph: g.isMultigraph() }).setGraph(g.graph());
57
- _.forEach(g.nodes(), function(v) {
63
+ g.nodes().forEach(v => {
58
64
  if (!g.children(v).length) {
59
65
  simplified.setNode(v, g.node(v));
60
66
  }
61
67
  });
62
- _.forEach(g.edges(), function(e) {
68
+ g.edges().forEach(e => {
63
69
  simplified.setEdge(e, g.edge(e));
64
70
  });
65
71
  return simplified;
66
72
  }
67
73
 
68
74
  function successorWeights(g) {
69
- var weightMap = _.map(g.nodes(), function(v) {
75
+ var weightMap = g.nodes().map(v => {
70
76
  var sucs = {};
71
- _.forEach(g.outEdges(v), function(e) {
77
+ g.outEdges(v).forEach(e => {
72
78
  sucs[e.w] = (sucs[e.w] || 0) + g.edge(e).weight;
73
79
  });
74
80
  return sucs;
75
81
  });
76
- return _.zipObject(g.nodes(), weightMap);
82
+ return zipObject(g.nodes(), weightMap);
77
83
  }
78
84
 
79
85
  function predecessorWeights(g) {
80
- var weightMap = _.map(g.nodes(), function(v) {
86
+ var weightMap = g.nodes().map(v => {
81
87
  var preds = {};
82
- _.forEach(g.inEdges(v), function(e) {
88
+ g.inEdges(v).forEach(e => {
83
89
  preds[e.v] = (preds[e.v] || 0) + g.edge(e).weight;
84
90
  });
85
91
  return preds;
86
92
  });
87
- return _.zipObject(g.nodes(), weightMap);
93
+ return zipObject(g.nodes(), weightMap);
88
94
  }
89
95
 
90
96
  /*
@@ -131,11 +137,11 @@ function intersectRect(rect, point) {
131
137
  * function will produce a matrix with the ids of each node.
132
138
  */
133
139
  function buildLayerMatrix(g) {
134
- var layering = _.map(_.range(maxRank(g) + 1), function() { return []; });
135
- _.forEach(g.nodes(), function(v) {
136
- var node = g.node(v),
137
- rank = node.rank;
138
- if (!_.isUndefined(rank)) {
140
+ var layering = range(maxRank(g) + 1).map(() => []);
141
+ g.nodes().forEach(v => {
142
+ var node = g.node(v);
143
+ var rank = node.rank;
144
+ if (rank !== undefined) {
139
145
  layering[rank][node.order] = v;
140
146
  }
141
147
  });
@@ -147,10 +153,17 @@ function buildLayerMatrix(g) {
147
153
  * rank(v) >= 0 and at least one node w has rank(w) = 0.
148
154
  */
149
155
  function normalizeRanks(g) {
150
- var min = _.minBy(_.map(g.nodes(), function(v) { return g.node(v).rank; }));
151
- _.forEach(g.nodes(), function(v) {
156
+ var min = Math.min(...g.nodes().map(v => {
157
+ var rank = g.node(v).rank;
158
+ if (rank === undefined) {
159
+ return Number.MAX_VALUE;
160
+ }
161
+
162
+ return rank;
163
+ }));
164
+ g.nodes().forEach(v => {
152
165
  var node = g.node(v);
153
- if (_.has(node, "rank")) {
166
+ if (node.hasOwnProperty("rank")) {
154
167
  node.rank -= min;
155
168
  }
156
169
  });
@@ -158,10 +171,10 @@ function normalizeRanks(g) {
158
171
 
159
172
  function removeEmptyRanks(g) {
160
173
  // Ranks may not start at 0, so we need to offset them
161
- var offset = _.minBy(_.map(g.nodes(), function(v) { return g.node(v).rank; }));
174
+ var offset = Math.min(...g.nodes().map(v => g.node(v).rank));
162
175
 
163
176
  var layers = [];
164
- _.forEach(g.nodes(), function(v) {
177
+ g.nodes().forEach(v => {
165
178
  var rank = g.node(v).rank - offset;
166
179
  if (!layers[rank]) {
167
180
  layers[rank] = [];
@@ -169,13 +182,13 @@ function removeEmptyRanks(g) {
169
182
  layers[rank].push(v);
170
183
  });
171
184
 
172
- var delta = 0,
173
- nodeRankFactor = g.graph().nodeRankFactor;
174
- _.forEach(layers, function(vs, i) {
175
- if (_.isUndefined(vs) && i % nodeRankFactor !== 0) {
185
+ var delta = 0;
186
+ var nodeRankFactor = g.graph().nodeRankFactor;
187
+ Array.from(layers).forEach((vs, i) => {
188
+ if (vs === undefined && i % nodeRankFactor !== 0) {
176
189
  --delta;
177
- } else if (delta) {
178
- _.forEach(vs, function(v) { g.node(v).rank += delta; });
190
+ } else if (vs !== undefined && delta) {
191
+ vs.forEach(v => g.node(v).rank += delta);
179
192
  }
180
193
  });
181
194
  }
@@ -193,11 +206,13 @@ function addBorderNode(g, prefix, rank, order) {
193
206
  }
194
207
 
195
208
  function maxRank(g) {
196
- return _.max(_.map(g.nodes(), function(v) {
209
+ return Math.max(...g.nodes().map(v => {
197
210
  var rank = g.node(v).rank;
198
- if (!_.isUndefined(rank)) {
199
- return rank;
211
+ if (rank === undefined) {
212
+ return Number.MIN_VALUE;
200
213
  }
214
+
215
+ return rank;
201
216
  }));
202
217
  }
203
218
 
@@ -208,7 +223,7 @@ function maxRank(g) {
208
223
  */
209
224
  function partition(collection, fn) {
210
225
  var result = { lhs: [], rhs: [] };
211
- _.forEach(collection, function(value) {
226
+ collection.forEach(value => {
212
227
  if (fn(value)) {
213
228
  result.lhs.push(value);
214
229
  } else {
@@ -223,14 +238,69 @@ function partition(collection, fn) {
223
238
  * time it takes to execute the function.
224
239
  */
225
240
  function time(name, fn) {
226
- var start = _.now();
241
+ var start = Date.now();
227
242
  try {
228
243
  return fn();
229
244
  } finally {
230
- console.log(name + " time: " + (_.now() - start) + "ms");
245
+ console.log(name + " time: " + (Date.now() - start) + "ms");
231
246
  }
232
247
  }
233
248
 
234
249
  function notime(name, fn) {
235
250
  return fn();
236
251
  }
252
+
253
+ let idCounter = 0;
254
+ function uniqueId(prefix) {
255
+ var id = ++idCounter;
256
+ return toString(prefix) + id;
257
+ }
258
+
259
+ function range(start, limit, step = 1) {
260
+ if (limit == null) {
261
+ limit = start;
262
+ start = 0;
263
+ }
264
+
265
+ let endCon = (i) => i < limit;
266
+ if (step < 0) {
267
+ endCon = (i) => limit < i;
268
+ }
269
+
270
+ const range = [];
271
+ for (let i = start; endCon(i); i += step) {
272
+ range.push(i);
273
+ }
274
+
275
+ return range;
276
+ }
277
+
278
+ function pick(source, keys) {
279
+ const dest = {};
280
+ for (const key of keys) {
281
+ if (source[key] !== undefined) {
282
+ dest[key] = source[key];
283
+ }
284
+ }
285
+
286
+ return dest;
287
+ }
288
+
289
+ function mapValues(obj, funcOrProp) {
290
+ let func = funcOrProp;
291
+ if (typeof funcOrProp === 'string') {
292
+ func = (val) => val[funcOrProp];
293
+ }
294
+
295
+ return Object.entries(obj).reduce((acc, [k, v]) => {
296
+ acc[k] = func(v, k);
297
+ return acc;
298
+ }, {});
299
+ }
300
+
301
+ function zipObject(props, values) {
302
+ return props.reduce((acc, key, i) => {
303
+ acc[key] = values[i];
304
+ return acc;
305
+ }, {});
306
+ }
package/lib/version.js CHANGED
@@ -1 +1 @@
1
- module.exports = "0.8.0";
1
+ module.exports = "1.0.1";
package/package.json CHANGED
@@ -1,45 +1,51 @@
1
1
  {
2
2
  "name": "@dagrejs/dagre",
3
- "version": "0.8.0",
3
+ "version": "1.0.1",
4
4
  "description": "Graph layout for JavaScript",
5
5
  "author": "Chris Pettitt <cpettitt@gmail.com>",
6
6
  "contributors": [
7
7
  "Matthew Dahl (https://github.com/sandersky)"
8
8
  ],
9
+ "license": "MIT",
9
10
  "main": "index.js",
11
+ "scripts": {
12
+ "lint": "make lint",
13
+ "test": "make test"
14
+ },
15
+ "files": [
16
+ "index.js",
17
+ "dist/",
18
+ "lib/"
19
+ ],
10
20
  "keywords": [
11
21
  "graph",
12
22
  "layout"
13
23
  ],
14
24
  "dependencies": {
15
- "@dagrejs/graphlib": "^2.1.4",
16
- "lodash": "^4.11.1"
25
+ "@dagrejs/graphlib": "2.1.13"
17
26
  },
18
27
  "devDependencies": {
19
- "benchmark": "^1.0.0",
20
- "browserify": "^6.1.0",
21
- "chai": "^1.9.2",
22
- "istanbul": "^0.3.2",
23
- "jscs": "^1.7.3",
24
- "jshint": "^2.5.6",
25
- "jshint-stylish": "^1.0.0",
26
- "karma": "^0.13.22",
27
- "karma-chrome-launcher": "^0.2.0",
28
- "karma-firefox-launcher": "^0.1.6",
29
- "karma-mocha": "^0.2.0",
30
- "karma-phantomjs-launcher": "^1.0.0",
31
- "karma-requirejs": "^0.2.5",
32
- "karma-safari-launcher": "^0.1.1",
33
- "mocha": "^1.21.5",
34
- "phantomjs-prebuilt": "^2.1.7",
35
- "requirejs": "^2.1.22",
36
- "semver": "^4.1.0",
37
- "sprintf": "^0.1.4",
38
- "uglify-js": "^2.4.15"
28
+ "benchmark": "2.1.4",
29
+ "browserify": "17.0.0",
30
+ "chai": "4.3.6",
31
+ "eslint": "8.35.0",
32
+ "jshint": "2.13.5",
33
+ "jshint-stylish": "2.2.1",
34
+ "karma": "6.4.1",
35
+ "karma-chrome-launcher": "3.1.1",
36
+ "karma-firefox-launcher": "2.1.2",
37
+ "karma-mocha": "2.0.1",
38
+ "karma-requirejs": "1.1.0",
39
+ "karma-safari-launcher": "1.0.0",
40
+ "mocha": "10.1.0",
41
+ "nyc": "^15.1.0",
42
+ "requirejs": "2.3.6",
43
+ "semver": "7.3.7",
44
+ "sprintf": "0.1.5",
45
+ "uglify-js": "3.17.4"
39
46
  },
40
47
  "repository": {
41
48
  "type": "git",
42
49
  "url": "https://github.com/dagrejs/dagre.git"
43
- },
44
- "license": "MIT"
50
+ }
45
51
  }
package/.jscsrc DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "disallowSpaceAfterPrefixUnaryOperators": true,
3
- "disallowTrailingWhitespace": true,
4
- "maximumLineLength": 100,
5
- "validateQuoteMarks": true
6
- }
package/.jshintrc DELETED
@@ -1,24 +0,0 @@
1
- {
2
- "camelcase": true,
3
- "eqeqeq": true,
4
- "expr": true,
5
- "freeze": true,
6
- "immed": true,
7
- "newcap": true,
8
- "noarg": true,
9
- "quotmark": "double",
10
- "trailing": true,
11
- "undef": true,
12
- "unused": true,
13
-
14
- "laxbreak": true,
15
-
16
- "node": true,
17
-
18
- "globals": {
19
- "afterEach": false,
20
- "beforeEach": false,
21
- "describe": false,
22
- "it": false
23
- }
24
- }
package/.travis.yml DELETED
@@ -1,7 +0,0 @@
1
- language: node_js
2
- node_js:
3
- - "lts/*"
4
- script: KARMA_OPTS="--browsers Firefox,PhantomJS" make -e test
5
- before_script:
6
- - export DISPLAY=:99.0
7
- - sh -e /etc/init.d/xvfb start
package/bower.json DELETED
@@ -1,26 +0,0 @@
1
- {
2
- "name": "dagre",
3
- "version": "0.8.0",
4
- "main": [
5
- "dist/dagre.core.js"
6
- ],
7
- "ignore": [
8
- ".*",
9
- "README.md",
10
- "CHANGELOG.md",
11
- "Makefile",
12
- "browser.js",
13
- "dist/dagre.js",
14
- "dist/dagre.min.js",
15
- "index.js",
16
- "karma*",
17
- "lib/**",
18
- "package.json",
19
- "src/**",
20
- "test/**"
21
- ],
22
- "dependencies": {
23
- "@dagrejs/graphlib": "^2.1.4",
24
- "lodash": "^4.11.1"
25
- }
26
- }