diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index bb035bd39..2837952f7 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -77,19 +77,58 @@
flowchart LR - subgraph Apa["Apa"] - A["Start"] - B["This is B"] +subgraph Apa["Apa"] + A["Start"] + B["This is B"] +end + A --> B & C["C"] + Apa --> C ++
+flowchart LR +subgraph Apa["Apa"] + B["This is B"] + A["Start"] +end + A --> B & C["C"] + Apa --> C ++
+flowchart LR +subgraph Apa["Apa"] + subgraph Gorilla + A["Start"] + B["This is B"] end +end + A --> B & C["C"] + Gorilla --> C ++
+flowchart LR +subgraph Apa["Apa"] + subgraph Gorilla + A["Start"] + B["This is B"] + end +end A --> B & C["C"] Apa --> C
flowchart LR - subgraph Apa["Apa"] - B --> B & C +subgraph Apa["Apa"] + subgraph Gorilla + B["This is B"] + A["Start"] end +end +Apa --> C +A --> B & C["C"]
diff --git a/packages/mermaid-layout-elk/src/find-common-ancestor.ts b/packages/mermaid-layout-elk/src/find-common-ancestor.ts index 83990b2f3..793ab1918 100644 --- a/packages/mermaid-layout-elk/src/find-common-ancestor.ts +++ b/packages/mermaid-layout-elk/src/find-common-ancestor.ts @@ -8,6 +8,7 @@ export const findCommonAncestor = (id1: string, id2: string, treeData: TreeData) const visited = new Set(); let currentId = id1; + // Edge case with self edges if (id1 === id2) { return parentById[id1] || 'root'; } diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js index 73b6797df..3699827a1 100644 --- a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js +++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js @@ -152,27 +152,58 @@ export const validate = (graph) => { return true; }; +const findCommonEdges = (graph, id1, id2) => { + const edges1 = graph.edges().filter((edge) => edge.v === id1 || edge.w === id1); + const edges2 = graph.edges().filter((edge) => edge.v === id2 || edge.w === id2); + const edges1Prim = edges1.map((edge) => { + return { v: edge.v === id1 ? id2 : edge.v, w: edge.w === id1 ? id1 : edge.w }; + }); + const edges2Prim = edges2.map((edge) => { + return { v: edge.v, w: edge.w }; + }); + const result = edges1Prim.filter((edgeIn1) => { + return edges2Prim.filter((edge) => edgeIn1.v === edge.v && edgeIn1.w === edge.w).length > 0; + }); + + return result; +}; + /** * Finds a child that is not a cluster. When faking an edge between a node and a cluster. * * @param id * @param {any} graph */ -export const findNonClusterChild = (id, graph) => { - log.trace('Searching', id); - const children = graph.children(id).reverse(); +export const findNonClusterChild = (id, graph, clusterId) => { + const children = graph.children(id); log.trace('Searching children of id ', id, children); if (children.length < 1) { - log.trace('This is a valid node', id); return id; } + let reserve; for (const child of children) { - const _id = findNonClusterChild(child, graph); + const _id = findNonClusterChild(child, graph, clusterId); + + // Edge chase where the cluster has an edge to a node and the selected + // child has a link to the same node + const commonEdges = findCommonEdges(graph, clusterId, _id); + if (_id) { - log.trace('Found replacement for', id, ' => ', _id); - return _id; + if (commonEdges.length > 0) { + // console.log( + // '\x1B[44;93;4m abc24 The replacement also has an edge', + // clusterId, + // ' => ', + // _id, + // graph.edges() + // ); + reserve = _id; + } else { + return _id; + } } } + return reserve; }; const getAnchorId = (id) => { @@ -207,10 +238,10 @@ export const adjustClustersAndEdges = (graph, depth) => { 'Cluster identified', id, ' Replacement id in edges: ', - findNonClusterChild(id, graph) + findNonClusterChild(id, graph, id) ); descendants[id] = extractDescendants(id, graph); - clusterDb[id] = { id: findNonClusterChild(id, graph), clusterData: graph.node(id) }; + clusterDb[id] = { id: findNonClusterChild(id, graph, id), clusterData: graph.node(id) }; } });