1 | import { i as isUndefined, G as Graph } from "./graph-fe24fab6.js";
|
2 | import { m as map, l as layout } from "./layout-163b9689.js";
|
3 | import { c as clone } from "./clone-9ea6bfeb.js";
|
4 | import { c as createLabel, g as getSubGraphTitleMargins, i as intersectRect, a as insertMarkers, b as clear$2, d as clear$3, u as updateNodeBounds, s as setNodeElem, e as insertNode, f as insertEdgeLabel, p as positionNode, h as insertEdge, j as positionEdgeLabel } from "./edges-ce5cfb7c.js";
|
5 | import { l as log, c as getConfig, p as evaluate, j as d3select } from "./mermaid-dcacb631.js";
|
6 | import { a as createText } from "./createText-b70fe78a.js";
|
7 | function write(g) {
|
8 | var json = {
|
9 | options: {
|
10 | directed: g.isDirected(),
|
11 | multigraph: g.isMultigraph(),
|
12 | compound: g.isCompound()
|
13 | },
|
14 | nodes: writeNodes(g),
|
15 | edges: writeEdges(g)
|
16 | };
|
17 | if (!isUndefined(g.graph())) {
|
18 | json.value = clone(g.graph());
|
19 | }
|
20 | return json;
|
21 | }
|
22 | function writeNodes(g) {
|
23 | return map(g.nodes(), function(v) {
|
24 | var nodeValue = g.node(v);
|
25 | var parent = g.parent(v);
|
26 | var node = { v };
|
27 | if (!isUndefined(nodeValue)) {
|
28 | node.value = nodeValue;
|
29 | }
|
30 | if (!isUndefined(parent)) {
|
31 | node.parent = parent;
|
32 | }
|
33 | return node;
|
34 | });
|
35 | }
|
36 | function writeEdges(g) {
|
37 | return map(g.edges(), function(e) {
|
38 | var edgeValue = g.edge(e);
|
39 | var edge = { v: e.v, w: e.w };
|
40 | if (!isUndefined(e.name)) {
|
41 | edge.name = e.name;
|
42 | }
|
43 | if (!isUndefined(edgeValue)) {
|
44 | edge.value = edgeValue;
|
45 | }
|
46 | return edge;
|
47 | });
|
48 | }
|
49 | let clusterDb = {};
|
50 | let descendants = {};
|
51 | let parents = {};
|
52 | const clear$1 = () => {
|
53 | descendants = {};
|
54 | parents = {};
|
55 | clusterDb = {};
|
56 | };
|
57 | const isDescendant = (id, ancestorId) => {
|
58 | log.trace("In isDescendant", ancestorId, " ", id, " = ", descendants[ancestorId].includes(id));
|
59 | if (descendants[ancestorId].includes(id)) {
|
60 | return true;
|
61 | }
|
62 | return false;
|
63 | };
|
64 | const edgeInCluster = (edge, clusterId) => {
|
65 | log.info("Descendants of ", clusterId, " is ", descendants[clusterId]);
|
66 | log.info("Edge is ", edge);
|
67 | if (edge.v === clusterId) {
|
68 | return false;
|
69 | }
|
70 | if (edge.w === clusterId) {
|
71 | return false;
|
72 | }
|
73 | if (!descendants[clusterId]) {
|
74 | log.debug("Tilt, ", clusterId, ",not in descendants");
|
75 | return false;
|
76 | }
|
77 | return descendants[clusterId].includes(edge.v) || isDescendant(edge.v, clusterId) || isDescendant(edge.w, clusterId) || descendants[clusterId].includes(edge.w);
|
78 | };
|
79 | const copy = (clusterId, graph, newGraph, rootId) => {
|
80 | log.warn(
|
81 | "Copying children of ",
|
82 | clusterId,
|
83 | "root",
|
84 | rootId,
|
85 | "data",
|
86 | graph.node(clusterId),
|
87 | rootId
|
88 | );
|
89 | const nodes = graph.children(clusterId) || [];
|
90 | if (clusterId !== rootId) {
|
91 | nodes.push(clusterId);
|
92 | }
|
93 | log.warn("Copying (nodes) clusterId", clusterId, "nodes", nodes);
|
94 | nodes.forEach((node) => {
|
95 | if (graph.children(node).length > 0) {
|
96 | copy(node, graph, newGraph, rootId);
|
97 | } else {
|
98 | const data = graph.node(node);
|
99 | log.info("cp ", node, " to ", rootId, " with parent ", clusterId);
|
100 | newGraph.setNode(node, data);
|
101 | if (rootId !== graph.parent(node)) {
|
102 | log.warn("Setting parent", node, graph.parent(node));
|
103 | newGraph.setParent(node, graph.parent(node));
|
104 | }
|
105 | if (clusterId !== rootId && node !== clusterId) {
|
106 | log.debug("Setting parent", node, clusterId);
|
107 | newGraph.setParent(node, clusterId);
|
108 | } else {
|
109 | log.info("In copy ", clusterId, "root", rootId, "data", graph.node(clusterId), rootId);
|
110 | log.debug(
|
111 | "Not Setting parent for node=",
|
112 | node,
|
113 | "cluster!==rootId",
|
114 | clusterId !== rootId,
|
115 | "node!==clusterId",
|
116 | node !== clusterId
|
117 | );
|
118 | }
|
119 | const edges = graph.edges(node);
|
120 | log.debug("Copying Edges", edges);
|
121 | edges.forEach((edge) => {
|
122 | log.info("Edge", edge);
|
123 | const data2 = graph.edge(edge.v, edge.w, edge.name);
|
124 | log.info("Edge data", data2, rootId);
|
125 | try {
|
126 | if (edgeInCluster(edge, rootId)) {
|
127 | log.info("Copying as ", edge.v, edge.w, data2, edge.name);
|
128 | newGraph.setEdge(edge.v, edge.w, data2, edge.name);
|
129 | log.info("newGraph edges ", newGraph.edges(), newGraph.edge(newGraph.edges()[0]));
|
130 | } else {
|
131 | log.info(
|
132 | "Skipping copy of edge ",
|
133 | edge.v,
|
134 | "-->",
|
135 | edge.w,
|
136 | " rootId: ",
|
137 | rootId,
|
138 | " clusterId:",
|
139 | clusterId
|
140 | );
|
141 | }
|
142 | } catch (e) {
|
143 | log.error(e);
|
144 | }
|
145 | });
|
146 | }
|
147 | log.debug("Removing node", node);
|
148 | graph.removeNode(node);
|
149 | });
|
150 | };
|
151 | const extractDescendants = (id, graph) => {
|
152 | const children = graph.children(id);
|
153 | let res = [...children];
|
154 | for (const child of children) {
|
155 | parents[child] = id;
|
156 | res = [...res, ...extractDescendants(child, graph)];
|
157 | }
|
158 | return res;
|
159 | };
|
160 | const findNonClusterChild = (id, graph) => {
|
161 | log.trace("Searching", id);
|
162 | const children = graph.children(id);
|
163 | log.trace("Searching children of id ", id, children);
|
164 | if (children.length < 1) {
|
165 | log.trace("This is a valid node", id);
|
166 | return id;
|
167 | }
|
168 | for (const child of children) {
|
169 | const _id = findNonClusterChild(child, graph);
|
170 | if (_id) {
|
171 | log.trace("Found replacement for", id, " => ", _id);
|
172 | return _id;
|
173 | }
|
174 | }
|
175 | };
|
176 | const getAnchorId = (id) => {
|
177 | if (!clusterDb[id]) {
|
178 | return id;
|
179 | }
|
180 | if (!clusterDb[id].externalConnections) {
|
181 | return id;
|
182 | }
|
183 | if (clusterDb[id]) {
|
184 | return clusterDb[id].id;
|
185 | }
|
186 | return id;
|
187 | };
|
188 | const adjustClustersAndEdges = (graph, depth) => {
|
189 | if (!graph || depth > 10) {
|
190 | log.debug("Opting out, no graph ");
|
191 | return;
|
192 | } else {
|
193 | log.debug("Opting in, graph ");
|
194 | }
|
195 | graph.nodes().forEach(function(id) {
|
196 | const children = graph.children(id);
|
197 | if (children.length > 0) {
|
198 | log.warn(
|
199 | "Cluster identified",
|
200 | id,
|
201 | " Replacement id in edges: ",
|
202 | findNonClusterChild(id, graph)
|
203 | );
|
204 | descendants[id] = extractDescendants(id, graph);
|
205 | clusterDb[id] = { id: findNonClusterChild(id, graph), clusterData: graph.node(id) };
|
206 | }
|
207 | });
|
208 | graph.nodes().forEach(function(id) {
|
209 | const children = graph.children(id);
|
210 | const edges = graph.edges();
|
211 | if (children.length > 0) {
|
212 | log.debug("Cluster identified", id, descendants);
|
213 | edges.forEach((edge) => {
|
214 | if (edge.v !== id && edge.w !== id) {
|
215 | const d1 = isDescendant(edge.v, id);
|
216 | const d2 = isDescendant(edge.w, id);
|
217 | if (d1 ^ d2) {
|
218 | log.warn("Edge: ", edge, " leaves cluster ", id);
|
219 | log.warn("Descendants of XXX ", id, ": ", descendants[id]);
|
220 | clusterDb[id].externalConnections = true;
|
221 | }
|
222 | }
|
223 | });
|
224 | } else {
|
225 | log.debug("Not a cluster ", id, descendants);
|
226 | }
|
227 | });
|
228 | for (let id of Object.keys(clusterDb)) {
|
229 | const nonClusterChild = clusterDb[id].id;
|
230 | const parent = graph.parent(nonClusterChild);
|
231 | if (parent !== id && clusterDb[parent] && !clusterDb[parent].externalConnections) {
|
232 | clusterDb[id].id = parent;
|
233 | }
|
234 | }
|
235 | graph.edges().forEach(function(e) {
|
236 | const edge = graph.edge(e);
|
237 | log.warn("Edge " + e.v + " -> " + e.w + ": " + JSON.stringify(e));
|
238 | log.warn("Edge " + e.v + " -> " + e.w + ": " + JSON.stringify(graph.edge(e)));
|
239 | let v = e.v;
|
240 | let w = e.w;
|
241 | log.warn(
|
242 | "Fix XXX",
|
243 | clusterDb,
|
244 | "ids:",
|
245 | e.v,
|
246 | e.w,
|
247 | "Translating: ",
|
248 | clusterDb[e.v],
|
249 | " --- ",
|
250 | clusterDb[e.w]
|
251 | );
|
252 | if (clusterDb[e.v] && clusterDb[e.w] && clusterDb[e.v] === clusterDb[e.w]) {
|
253 | log.warn("Fixing and trixing link to self - removing XXX", e.v, e.w, e.name);
|
254 | log.warn("Fixing and trixing - removing XXX", e.v, e.w, e.name);
|
255 | v = getAnchorId(e.v);
|
256 | w = getAnchorId(e.w);
|
257 | graph.removeEdge(e.v, e.w, e.name);
|
258 | const specialId = e.w + "---" + e.v;
|
259 | graph.setNode(specialId, {
|
260 | domId: specialId,
|
261 | id: specialId,
|
262 | labelStyle: "",
|
263 | labelText: edge.label,
|
264 | padding: 0,
|
265 | shape: "labelRect",
|
266 | style: ""
|
267 | });
|
268 | const edge1 = structuredClone(edge);
|
269 | const edge2 = structuredClone(edge);
|
270 | edge1.label = "";
|
271 | edge1.arrowTypeEnd = "none";
|
272 | edge2.label = "";
|
273 | edge1.fromCluster = e.v;
|
274 | edge2.toCluster = e.v;
|
275 | graph.setEdge(v, specialId, edge1, e.name + "-cyclic-special");
|
276 | graph.setEdge(specialId, w, edge2, e.name + "-cyclic-special");
|
277 | } else if (clusterDb[e.v] || clusterDb[e.w]) {
|
278 | log.warn("Fixing and trixing - removing XXX", e.v, e.w, e.name);
|
279 | v = getAnchorId(e.v);
|
280 | w = getAnchorId(e.w);
|
281 | graph.removeEdge(e.v, e.w, e.name);
|
282 | if (v !== e.v) {
|
283 | const parent = graph.parent(v);
|
284 | clusterDb[parent].externalConnections = true;
|
285 | edge.fromCluster = e.v;
|
286 | }
|
287 | if (w !== e.w) {
|
288 | const parent = graph.parent(w);
|
289 | clusterDb[parent].externalConnections = true;
|
290 | edge.toCluster = e.w;
|
291 | }
|
292 | log.warn("Fix Replacing with XXX", v, w, e.name);
|
293 | graph.setEdge(v, w, edge, e.name);
|
294 | }
|
295 | });
|
296 | log.warn("Adjusted Graph", write(graph));
|
297 | extractor(graph, 0);
|
298 | log.trace(clusterDb);
|
299 | };
|
300 | const extractor = (graph, depth) => {
|
301 | log.warn("extractor - ", depth, write(graph), graph.children("D"));
|
302 | if (depth > 10) {
|
303 | log.error("Bailing out");
|
304 | return;
|
305 | }
|
306 | let nodes = graph.nodes();
|
307 | let hasChildren = false;
|
308 | for (const node of nodes) {
|
309 | const children = graph.children(node);
|
310 | hasChildren = hasChildren || children.length > 0;
|
311 | }
|
312 | if (!hasChildren) {
|
313 | log.debug("Done, no node has children", graph.nodes());
|
314 | return;
|
315 | }
|
316 | log.debug("Nodes = ", nodes, depth);
|
317 | for (const node of nodes) {
|
318 | log.debug(
|
319 | "Extracting node",
|
320 | node,
|
321 | clusterDb,
|
322 | clusterDb[node] && !clusterDb[node].externalConnections,
|
323 | !graph.parent(node),
|
324 | graph.node(node),
|
325 | graph.children("D"),
|
326 | " Depth ",
|
327 | depth
|
328 | );
|
329 | if (!clusterDb[node]) {
|
330 | log.debug("Not a cluster", node, depth);
|
331 | } else if (!clusterDb[node].externalConnections &&
|
332 | graph.children(node) && graph.children(node).length > 0) {
|
333 | log.warn(
|
334 | "Cluster without external connections, without a parent and with children",
|
335 | node,
|
336 | depth
|
337 | );
|
338 | const graphSettings = graph.graph();
|
339 | let dir = graphSettings.rankdir === "TB" ? "LR" : "TB";
|
340 | if (clusterDb[node] && clusterDb[node].clusterData && clusterDb[node].clusterData.dir) {
|
341 | dir = clusterDb[node].clusterData.dir;
|
342 | log.warn("Fixing dir", clusterDb[node].clusterData.dir, dir);
|
343 | }
|
344 | const clusterGraph = new Graph({
|
345 | multigraph: true,
|
346 | compound: true
|
347 | }).setGraph({
|
348 | rankdir: dir,
|
349 |
|
350 | nodesep: 50,
|
351 | ranksep: 50,
|
352 | marginx: 8,
|
353 | marginy: 8
|
354 | }).setDefaultEdgeLabel(function() {
|
355 | return {};
|
356 | });
|
357 | log.warn("Old graph before copy", write(graph));
|
358 | copy(node, graph, clusterGraph, node);
|
359 | graph.setNode(node, {
|
360 | clusterNode: true,
|
361 | id: node,
|
362 | clusterData: clusterDb[node].clusterData,
|
363 | labelText: clusterDb[node].labelText,
|
364 | graph: clusterGraph
|
365 | });
|
366 | log.warn("New graph after copy node: (", node, ")", write(clusterGraph));
|
367 | log.debug("Old graph after copy", write(graph));
|
368 | } else {
|
369 | log.warn(
|
370 | "Cluster ** ",
|
371 | node,
|
372 | " **not meeting the criteria !externalConnections:",
|
373 | !clusterDb[node].externalConnections,
|
374 | " no parent: ",
|
375 | !graph.parent(node),
|
376 | " children ",
|
377 | graph.children(node) && graph.children(node).length > 0,
|
378 | graph.children("D"),
|
379 | depth
|
380 | );
|
381 | log.debug(clusterDb);
|
382 | }
|
383 | }
|
384 | nodes = graph.nodes();
|
385 | log.warn("New list of nodes", nodes);
|
386 | for (const node of nodes) {
|
387 | const data = graph.node(node);
|
388 | log.warn(" Now next level", node, data);
|
389 | if (data.clusterNode) {
|
390 | extractor(data.graph, depth + 1);
|
391 | }
|
392 | }
|
393 | };
|
394 | const sorter = (graph, nodes) => {
|
395 | if (nodes.length === 0) {
|
396 | return [];
|
397 | }
|
398 | let result = Object.assign(nodes);
|
399 | nodes.forEach((node) => {
|
400 | const children = graph.children(node);
|
401 | const sorted = sorter(graph, children);
|
402 | result = [...result, ...sorted];
|
403 | });
|
404 | return result;
|
405 | };
|
406 | const sortNodesByHierarchy = (graph) => sorter(graph, graph.children());
|
407 | const rect = (parent, node) => {
|
408 | log.info("Creating subgraph rect for ", node.id, node);
|
409 | const siteConfig = getConfig();
|
410 | const shapeSvg = parent.insert("g").attr("class", "cluster" + (node.class ? " " + node.class : "")).attr("id", node.id);
|
411 | const rect2 = shapeSvg.insert("rect", ":first-child");
|
412 | const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels);
|
413 | const label = shapeSvg.insert("g").attr("class", "cluster-label");
|
414 | const text = node.labelType === "markdown" ? createText(label, node.labelText, { style: node.labelStyle, useHtmlLabels }) : label.node().appendChild(createLabel(node.labelText, node.labelStyle, void 0, true));
|
415 | let bbox = text.getBBox();
|
416 | if (evaluate(siteConfig.flowchart.htmlLabels)) {
|
417 | const div = text.children[0];
|
418 | const dv = d3select(text);
|
419 | bbox = div.getBoundingClientRect();
|
420 | dv.attr("width", bbox.width);
|
421 | dv.attr("height", bbox.height);
|
422 | }
|
423 | const padding = 0 * node.padding;
|
424 | const halfPadding = padding / 2;
|
425 | const width = node.width <= bbox.width + padding ? bbox.width + padding : node.width;
|
426 | if (node.width <= bbox.width + padding) {
|
427 | node.diff = (bbox.width - node.width) / 2 - node.padding / 2;
|
428 | } else {
|
429 | node.diff = -node.padding / 2;
|
430 | }
|
431 | log.trace("Data ", node, JSON.stringify(node));
|
432 | rect2.attr("style", node.style).attr("rx", node.rx).attr("ry", node.ry).attr("x", node.x - width / 2).attr("y", node.y - node.height / 2 - halfPadding).attr("width", width).attr("height", node.height + padding);
|
433 | const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig);
|
434 | if (useHtmlLabels) {
|
435 | label.attr(
|
436 | "transform",
|
437 |
|
438 | `translate(${node.x - bbox.width / 2}, ${node.y - node.height / 2 + subGraphTitleTopMargin})`
|
439 | );
|
440 | } else {
|
441 | label.attr(
|
442 | "transform",
|
443 |
|
444 | `translate(${node.x}, ${node.y - node.height / 2 + subGraphTitleTopMargin})`
|
445 | );
|
446 | }
|
447 | const rectBox = rect2.node().getBBox();
|
448 | node.width = rectBox.width;
|
449 | node.height = rectBox.height;
|
450 | node.intersect = function(point) {
|
451 | return intersectRect(node, point);
|
452 | };
|
453 | return shapeSvg;
|
454 | };
|
455 | const noteGroup = (parent, node) => {
|
456 | const shapeSvg = parent.insert("g").attr("class", "note-cluster").attr("id", node.id);
|
457 | const rect2 = shapeSvg.insert("rect", ":first-child");
|
458 | const padding = 0 * node.padding;
|
459 | const halfPadding = padding / 2;
|
460 | rect2.attr("rx", node.rx).attr("ry", node.ry).attr("x", node.x - node.width / 2 - halfPadding).attr("y", node.y - node.height / 2 - halfPadding).attr("width", node.width + padding).attr("height", node.height + padding).attr("fill", "none");
|
461 | const rectBox = rect2.node().getBBox();
|
462 | node.width = rectBox.width;
|
463 | node.height = rectBox.height;
|
464 | node.intersect = function(point) {
|
465 | return intersectRect(node, point);
|
466 | };
|
467 | return shapeSvg;
|
468 | };
|
469 | const roundedWithTitle = (parent, node) => {
|
470 | const siteConfig = getConfig();
|
471 | const shapeSvg = parent.insert("g").attr("class", node.classes).attr("id", node.id);
|
472 | const rect2 = shapeSvg.insert("rect", ":first-child");
|
473 | const label = shapeSvg.insert("g").attr("class", "cluster-label");
|
474 | const innerRect = shapeSvg.append("rect");
|
475 | const text = label.node().appendChild(createLabel(node.labelText, node.labelStyle, void 0, true));
|
476 | let bbox = text.getBBox();
|
477 | if (evaluate(siteConfig.flowchart.htmlLabels)) {
|
478 | const div = text.children[0];
|
479 | const dv = d3select(text);
|
480 | bbox = div.getBoundingClientRect();
|
481 | dv.attr("width", bbox.width);
|
482 | dv.attr("height", bbox.height);
|
483 | }
|
484 | bbox = text.getBBox();
|
485 | const padding = 0 * node.padding;
|
486 | const halfPadding = padding / 2;
|
487 | const width = node.width <= bbox.width + node.padding ? bbox.width + node.padding : node.width;
|
488 | if (node.width <= bbox.width + node.padding) {
|
489 | node.diff = (bbox.width + node.padding * 0 - node.width) / 2;
|
490 | } else {
|
491 | node.diff = -node.padding / 2;
|
492 | }
|
493 | rect2.attr("class", "outer").attr("x", node.x - width / 2 - halfPadding).attr("y", node.y - node.height / 2 - halfPadding).attr("width", width + padding).attr("height", node.height + padding);
|
494 | innerRect.attr("class", "inner").attr("x", node.x - width / 2 - halfPadding).attr("y", node.y - node.height / 2 - halfPadding + bbox.height - 1).attr("width", width + padding).attr("height", node.height + padding - bbox.height - 3);
|
495 | const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig);
|
496 | label.attr(
|
497 | "transform",
|
498 | `translate(${node.x - bbox.width / 2}, ${node.y - node.height / 2 - node.padding / 3 + (evaluate(siteConfig.flowchart.htmlLabels) ? 5 : 3) + subGraphTitleTopMargin})`
|
499 | );
|
500 | const rectBox = rect2.node().getBBox();
|
501 | node.height = rectBox.height;
|
502 | node.intersect = function(point) {
|
503 | return intersectRect(node, point);
|
504 | };
|
505 | return shapeSvg;
|
506 | };
|
507 | const divider = (parent, node) => {
|
508 | const shapeSvg = parent.insert("g").attr("class", node.classes).attr("id", node.id);
|
509 | const rect2 = shapeSvg.insert("rect", ":first-child");
|
510 | const padding = 0 * node.padding;
|
511 | const halfPadding = padding / 2;
|
512 | rect2.attr("class", "divider").attr("x", node.x - node.width / 2 - halfPadding).attr("y", node.y - node.height / 2).attr("width", node.width + padding).attr("height", node.height + padding);
|
513 | const rectBox = rect2.node().getBBox();
|
514 | node.width = rectBox.width;
|
515 | node.height = rectBox.height;
|
516 | node.diff = -node.padding / 2;
|
517 | node.intersect = function(point) {
|
518 | return intersectRect(node, point);
|
519 | };
|
520 | return shapeSvg;
|
521 | };
|
522 | const shapes = { rect, roundedWithTitle, noteGroup, divider };
|
523 | let clusterElems = {};
|
524 | const insertCluster = (elem, node) => {
|
525 | log.trace("Inserting cluster");
|
526 | const shape = node.shape || "rect";
|
527 | clusterElems[node.id] = shapes[shape](elem, node);
|
528 | };
|
529 | const clear = () => {
|
530 | clusterElems = {};
|
531 | };
|
532 | const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, siteConfig) => {
|
533 | log.info("Graph in recursive render: XXX", write(graph), parentCluster);
|
534 | const dir = graph.graph().rankdir;
|
535 | log.trace("Dir in recursive render - dir:", dir);
|
536 | const elem = _elem.insert("g").attr("class", "root");
|
537 | if (!graph.nodes()) {
|
538 | log.info("No nodes found for", graph);
|
539 | } else {
|
540 | log.info("Recursive render XXX", graph.nodes());
|
541 | }
|
542 | if (graph.edges().length > 0) {
|
543 | log.trace("Recursive edges", graph.edge(graph.edges()[0]));
|
544 | }
|
545 | const clusters = elem.insert("g").attr("class", "clusters");
|
546 | const edgePaths = elem.insert("g").attr("class", "edgePaths");
|
547 | const edgeLabels = elem.insert("g").attr("class", "edgeLabels");
|
548 | const nodes = elem.insert("g").attr("class", "nodes");
|
549 | await Promise.all(
|
550 | graph.nodes().map(async function(v) {
|
551 | const node = graph.node(v);
|
552 | if (parentCluster !== void 0) {
|
553 | const data = JSON.parse(JSON.stringify(parentCluster.clusterData));
|
554 | log.info("Setting data for cluster XXX (", v, ") ", data, parentCluster);
|
555 | graph.setNode(parentCluster.id, data);
|
556 | if (!graph.parent(v)) {
|
557 | log.trace("Setting parent", v, parentCluster.id);
|
558 | graph.setParent(v, parentCluster.id, data);
|
559 | }
|
560 | }
|
561 | log.info("(Insert) Node XXX" + v + ": " + JSON.stringify(graph.node(v)));
|
562 | if (node && node.clusterNode) {
|
563 | log.info("Cluster identified", v, node.width, graph.node(v));
|
564 | const o = await recursiveRender(
|
565 | nodes,
|
566 | node.graph,
|
567 | diagramType,
|
568 | id,
|
569 | graph.node(v),
|
570 | siteConfig
|
571 | );
|
572 | const newEl = o.elem;
|
573 | updateNodeBounds(node, newEl);
|
574 | node.diff = o.diff || 0;
|
575 | log.info("Node bounds (abc123)", v, node, node.width, node.x, node.y);
|
576 | setNodeElem(newEl, node);
|
577 | log.warn("Recursive render complete ", newEl, node);
|
578 | } else {
|
579 | if (graph.children(v).length > 0) {
|
580 | log.info("Cluster - the non recursive path XXX", v, node.id, node, graph);
|
581 | log.info(findNonClusterChild(node.id, graph));
|
582 | clusterDb[node.id] = { id: findNonClusterChild(node.id, graph), node };
|
583 | } else {
|
584 | log.info("Node - the non recursive path", v, node.id, node);
|
585 | await insertNode(nodes, graph.node(v), dir);
|
586 | }
|
587 | }
|
588 | })
|
589 | );
|
590 | graph.edges().forEach(function(e) {
|
591 | const edge = graph.edge(e.v, e.w, e.name);
|
592 | log.info("Edge " + e.v + " -> " + e.w + ": " + JSON.stringify(e));
|
593 | log.info("Edge " + e.v + " -> " + e.w + ": ", e, " ", JSON.stringify(graph.edge(e)));
|
594 | log.info("Fix", clusterDb, "ids:", e.v, e.w, "Translating: ", clusterDb[e.v], clusterDb[e.w]);
|
595 | insertEdgeLabel(edgeLabels, edge);
|
596 | });
|
597 | graph.edges().forEach(function(e) {
|
598 | log.info("Edge " + e.v + " -> " + e.w + ": " + JSON.stringify(e));
|
599 | });
|
600 | log.info("#############################################");
|
601 | log.info("### Layout ###");
|
602 | log.info("#############################################");
|
603 | log.info(graph);
|
604 | layout(graph);
|
605 | log.info("Graph after layout:", write(graph));
|
606 | let diff = 0;
|
607 | const { subGraphTitleTotalMargin } = getSubGraphTitleMargins(siteConfig);
|
608 | sortNodesByHierarchy(graph).forEach(function(v) {
|
609 | const node = graph.node(v);
|
610 | log.info("Position " + v + ": " + JSON.stringify(graph.node(v)));
|
611 | log.info(
|
612 | "Position " + v + ": (" + node.x,
|
613 | "," + node.y,
|
614 | ") width: ",
|
615 | node.width,
|
616 | " height: ",
|
617 | node.height
|
618 | );
|
619 | if (node && node.clusterNode) {
|
620 | node.y += subGraphTitleTotalMargin;
|
621 | positionNode(node);
|
622 | } else {
|
623 | if (graph.children(v).length > 0) {
|
624 | node.height += subGraphTitleTotalMargin;
|
625 | insertCluster(clusters, node);
|
626 | clusterDb[node.id].node = node;
|
627 | } else {
|
628 | node.y += subGraphTitleTotalMargin / 2;
|
629 | positionNode(node);
|
630 | }
|
631 | }
|
632 | });
|
633 | graph.edges().forEach(function(e) {
|
634 | const edge = graph.edge(e);
|
635 | log.info("Edge " + e.v + " -> " + e.w + ": " + JSON.stringify(edge), edge);
|
636 | edge.points.forEach((point) => point.y += subGraphTitleTotalMargin / 2);
|
637 | const paths = insertEdge(edgePaths, e, edge, clusterDb, diagramType, graph, id);
|
638 | positionEdgeLabel(edge, paths);
|
639 | });
|
640 | graph.nodes().forEach(function(v) {
|
641 | const n = graph.node(v);
|
642 | log.info(v, n.type, n.diff);
|
643 | if (n.type === "group") {
|
644 | diff = n.diff;
|
645 | }
|
646 | });
|
647 | return { elem, diff };
|
648 | };
|
649 | const render = async (elem, graph, markers, diagramType, id) => {
|
650 | insertMarkers(elem, markers, diagramType, id);
|
651 | clear$2();
|
652 | clear$3();
|
653 | clear();
|
654 | clear$1();
|
655 | log.warn("Graph at first:", JSON.stringify(write(graph)));
|
656 | adjustClustersAndEdges(graph);
|
657 | log.warn("Graph after:", JSON.stringify(write(graph)));
|
658 | const siteConfig = getConfig();
|
659 | await recursiveRender(elem, graph, diagramType, id, void 0, siteConfig);
|
660 | };
|
661 | export {
|
662 | render as r
|
663 | };
|