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) };
     }
   });