Skip to content

Commit fd76e0e

Browse files
committed
chore: replace dagre/dagre-d3 with dagre-d3-es
Replace the dagre and dagre-d3 libraries with dagre-d3-es. Both dagre and dagre-d3 are deprecated and unmaintained, and haven't been updated for more than 3 years. Since dagre-d3 still requires an old version of d3, this causes a bunch of security warnings, e.g. GHSA-36jr-mh4h-2g58 The [dagre-d3-es](https://github.com/tbo47/dagre-es) package is a fork that contains support for `"d3": "^7.6.1"`. Also, it's ESM, so we will hopefully get smaller bundle sizes too. The only issue is that this fork isn't very well used (only has 3000 weekly downloads), compared to `dagre-d3`'s 250,000 weekly downloads. (although to be fair, a large proportion of dagre-d3's downloads probably come from mermaid) Since it's is a less popular package, **I've pinned `dagre-d3-es` to `"7.0.2"` instead of `"^7.0.2"`**. This does mean if there is a bug in `dagre-d3-es`, we will have to manually bump it ourselves, but it also means we won't accidentally be sending a buggy version of `dagre-d3-es` out to users in cases something changes (it might be worth disabling renovate for this if we're feeling paranoid!)
1 parent 537a627 commit fd76e0e

13 files changed

+42
-60
lines changed

package.json

-3
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,6 @@
105105
"vitepress-plugin-search": "^1.0.4-alpha.15",
106106
"vitest": "^0.25.1"
107107
},
108-
"resolutions": {
109-
"d3": "^7.6.1"
110-
},
111108
"sideEffects": [
112109
"**/*.css",
113110
"**/*.scss"

packages/mermaid/package.json

+1-5
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@
5454
"dependencies": {
5555
"@braintree/sanitize-url": "^6.0.0",
5656
"d3": "^7.0.0",
57-
"dagre": "^0.8.5",
58-
"dagre-d3": "^0.6.4",
57+
"dagre-d3-es": "7.0.2",
5958
"dompurify": "2.4.1",
6059
"fast-clone": "^1.5.13",
6160
"graphlib": "^2.1.8",
@@ -98,9 +97,6 @@
9897
"typescript": "^4.8.4",
9998
"unist-util-flatmap": "^1.0.0"
10099
},
101-
"resolutions": {
102-
"d3": "^7.0.0"
103-
},
104100
"files": [
105101
"dist",
106102
"README.md"

packages/mermaid/src/dagre-wrapper/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import dagre from 'dagre';
1+
import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js';
22
import graphlib from 'graphlib';
33
import insertMarkers from './markers';
44
import { updateNodeBounds } from './shapes/util';
@@ -95,7 +95,7 @@ const recursiveRender = (_elem, graph, diagramtype, parentCluster) => {
9595
log.info('### Layout ###');
9696
log.info('#############################################');
9797
log.info(graph);
98-
dagre.layout(graph);
98+
dagreLayout(graph);
9999
log.info('Graph after layout:', graphlib.json.write(graph));
100100
// Move the nodes to the correct place
101101
let diff = 0;

packages/mermaid/src/dagre-wrapper/mermaid-graphlib.spec.js

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import graphlib from 'graphlib';
2-
import dagre from 'dagre';
32
import {
43
validate,
54
adjustClustersAndEdges,

packages/mermaid/src/diagrams/class/classRenderer.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { select } from 'd3';
2-
import dagre from 'dagre';
2+
import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js';
33
import graphlib from 'graphlib';
44
import { log } from '../../logger';
55
import svgDraw from './svgDraw';
@@ -238,7 +238,7 @@ export const draw = function (text, id, _version, diagObj) {
238238
}
239239
});
240240

241-
dagre.layout(g);
241+
dagreLayout(g);
242242
g.nodes().forEach(function (v) {
243243
if (typeof v !== 'undefined' && typeof g.node(v) !== 'undefined') {
244244
log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v)));

packages/mermaid/src/diagrams/er/erRenderer.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import graphlib from 'graphlib';
22
import { line, curveBasis, select } from 'd3';
3-
import dagre from 'dagre';
3+
import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js';
44
import { getConfig } from '../../config';
55
import { log } from '../../logger';
66
import erMarkers from './erMarkers';
@@ -637,7 +637,7 @@ export const draw = function (text, id, _version, diagObj) {
637637
// Add all the relationships to the graph
638638
const relationships = addRelationships(diagObj.db.getRelationships(), g);
639639

640-
dagre.layout(g); // Node and edge positions will be updated
640+
dagreLayout(g); // Node and edge positions will be updated
641641

642642
// Adjust the positions of the entities so that they adhere to the layout
643643
adjustEntities(svg, g);

packages/mermaid/src/diagrams/flowchart/flowChartShapes.js

+13-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import dagreD3 from 'dagre-d3';
1+
import { intersectPolygon } from 'dagre-d3-es/src/dagre-js/intersect/intersect-polygon.js';
2+
import { intersectRect } from 'dagre-d3-es/src/dagre-js/intersect/intersect-rect.js';
23

34
/**
45
* @param parent
@@ -17,7 +18,7 @@ function question(parent, bbox, node) {
1718
];
1819
const shapeSvg = insertPolygonShape(parent, s, s, points);
1920
node.intersect = function (point) {
20-
return dagreD3.intersect.polygon(node, points, point);
21+
return intersectPolygon(node, points, point);
2122
};
2223
return shapeSvg;
2324
}
@@ -42,7 +43,7 @@ function hexagon(parent, bbox, node) {
4243
];
4344
const shapeSvg = insertPolygonShape(parent, w, h, points);
4445
node.intersect = function (point) {
45-
return dagreD3.intersect.polygon(node, points, point);
46+
return intersectPolygon(node, points, point);
4647
};
4748
return shapeSvg;
4849
}
@@ -64,7 +65,7 @@ function rect_left_inv_arrow(parent, bbox, node) {
6465
];
6566
const shapeSvg = insertPolygonShape(parent, w, h, points);
6667
node.intersect = function (point) {
67-
return dagreD3.intersect.polygon(node, points, point);
68+
return intersectPolygon(node, points, point);
6869
};
6970
return shapeSvg;
7071
}
@@ -85,7 +86,7 @@ function lean_right(parent, bbox, node) {
8586
];
8687
const shapeSvg = insertPolygonShape(parent, w, h, points);
8788
node.intersect = function (point) {
88-
return dagreD3.intersect.polygon(node, points, point);
89+
return intersectPolygon(node, points, point);
8990
};
9091
return shapeSvg;
9192
}
@@ -106,7 +107,7 @@ function lean_left(parent, bbox, node) {
106107
];
107108
const shapeSvg = insertPolygonShape(parent, w, h, points);
108109
node.intersect = function (point) {
109-
return dagreD3.intersect.polygon(node, points, point);
110+
return intersectPolygon(node, points, point);
110111
};
111112
return shapeSvg;
112113
}
@@ -127,7 +128,7 @@ function trapezoid(parent, bbox, node) {
127128
];
128129
const shapeSvg = insertPolygonShape(parent, w, h, points);
129130
node.intersect = function (point) {
130-
return dagreD3.intersect.polygon(node, points, point);
131+
return intersectPolygon(node, points, point);
131132
};
132133
return shapeSvg;
133134
}
@@ -148,7 +149,7 @@ function inv_trapezoid(parent, bbox, node) {
148149
];
149150
const shapeSvg = insertPolygonShape(parent, w, h, points);
150151
node.intersect = function (point) {
151-
return dagreD3.intersect.polygon(node, points, point);
152+
return intersectPolygon(node, points, point);
152153
};
153154
return shapeSvg;
154155
}
@@ -170,7 +171,7 @@ function rect_right_inv_arrow(parent, bbox, node) {
170171
];
171172
const shapeSvg = insertPolygonShape(parent, w, h, points);
172173
node.intersect = function (point) {
173-
return dagreD3.intersect.polygon(node, points, point);
174+
return intersectPolygon(node, points, point);
174175
};
175176
return shapeSvg;
176177
}
@@ -194,7 +195,7 @@ function stadium(parent, bbox, node) {
194195
.attr('height', h);
195196

196197
node.intersect = function (point) {
197-
return dagreD3.intersect.rect(node, point);
198+
return intersectRect(node, point);
198199
};
199200
return shapeSvg;
200201
}
@@ -221,7 +222,7 @@ function subroutine(parent, bbox, node) {
221222
];
222223
const shapeSvg = insertPolygonShape(parent, w, h, points);
223224
node.intersect = function (point) {
224-
return dagreD3.intersect.polygon(node, points, point);
225+
return intersectPolygon(node, points, point);
225226
};
226227
return shapeSvg;
227228
}
@@ -270,7 +271,7 @@ function cylinder(parent, bbox, node) {
270271
.attr('transform', 'translate(' + -w / 2 + ',' + -(h / 2 + ry) + ')');
271272

272273
node.intersect = function (point) {
273-
const pos = dagreD3.intersect.rect(node, point);
274+
const pos = intersectRect(node, point);
274275
const x = pos.x - node.x;
275276

276277
if (

packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import flowDb from './flowDb';
55
import { getConfig } from '../../config';
66

77
import { render } from '../../dagre-wrapper/index.js';
8-
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
8+
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';
99
import { log } from '../../logger';
1010
import common, { evaluate } from '../common/common';
1111
import { interpolateToCurve, getStylesFromArray } from '../../utils';

packages/mermaid/src/diagrams/flowchart/flowRenderer.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import graphlib from 'graphlib';
22
import { select, curveLinear, selectAll } from 'd3';
33
import { getConfig } from '../../config';
4-
import dagreD3 from 'dagre-d3';
5-
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
4+
import { render as Render } from 'dagre-d3-es';
5+
import { applyStyle } from 'dagre-d3-es/src/dagre-js/util.js';
6+
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';
67
import { log } from '../../logger';
78
import common, { evaluate } from '../common/common';
89
import { interpolateToCurve, getStylesFromArray } from '../../utils';
@@ -370,7 +371,6 @@ export const draw = function (text, id, _version, diagObj) {
370371
addEdges(edges, g, diagObj);
371372

372373
// Create the renderer
373-
const Render = dagreD3.render;
374374
const render = new Render();
375375

376376
// Add custom shapes
@@ -390,7 +390,7 @@ export const draw = function (text, id, _version, diagObj) {
390390
.attr('orient', 'auto');
391391

392392
const path = marker.append('path').attr('d', 'M 0 0 L 0 0 L 0 0 z');
393-
dagreD3.util.applyStyle(path, edge[type + 'Style']);
393+
applyStyle(path, edge[type + 'Style']);
394394
};
395395

396396
// Override normal arrowhead defined in d3. Remove style & add class to allow css styling.

packages/mermaid/src/diagrams/requirement/requirementRenderer.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { line, select } from 'd3';
2-
import dagre from 'dagre';
2+
import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js';
33
import graphlib from 'graphlib';
44
import { log } from '../../logger';
55
import { configureSvgSize } from '../../setupGraphViewbox';
@@ -348,7 +348,7 @@ export const draw = (text, id, _version, diagObj) => {
348348
drawReqs(requirements, g, svg);
349349
drawElements(elements, g, svg);
350350
addRelationships(relationships, g);
351-
dagre.layout(g);
351+
dagreLayout(g);
352352
adjustEntities(svg, g);
353353

354354
relationships.forEach(function (rel) {

packages/mermaid/src/diagrams/state/stateRenderer.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { select } from 'd3';
2-
import dagre from 'dagre';
2+
import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js';
33
import graphlib from 'graphlib';
44
import { log } from '../../logger';
55
import common from '../common/common';
@@ -239,7 +239,7 @@ const renderDoc = (doc, diagram, parentId, altBkg, root, domDocument, diagObj) =
239239
);
240240
});
241241

242-
dagre.layout(graph);
242+
dagreLayout(graph);
243243

244244
log.debug('Graph after layout', graph.nodes());
245245
const svgElem = diagram.node();

packages/mermaid/src/tests/setup.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
import { vi } from 'vitest';
22
vi.mock('d3');
3-
vi.mock('dagre-d3');
3+
vi.mock('dagre-d3-es');

pnpm-lock.yaml

+12-23
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)