From d0eca268ad854ceb0fe736c1144cf73f876c4fe4 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Thu, 4 Jan 2024 16:05:19 +0100 Subject: [PATCH] #3358 Multiple arrows --- cypress/platform/knsv2.html | 37 ++++++++++++++++++- packages/mermaid/src/dagre-wrapper/edges.js | 6 ++- .../mermaid/src/diagrams/block/blockDB.ts | 27 ++++++++++++-- .../src/diagrams/block/blockRenderer.ts | 3 +- .../src/diagrams/block/parser/block.jison | 22 +++++++---- .../src/diagrams/block/renderHelpers.ts | 8 +++- 6 files changed, 86 insertions(+), 17 deletions(-) diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index 80512993a..cefce1fb8 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -73,8 +73,41 @@ block-beta
 block-beta
       columns 3
-      A space space:3 B("GORILLA")
-      A("APA") --o B
+      A
+      space
+      block
+        E
+        F
+      end
+      E --> A
+    
+
+block-beta
+      columns 3
+      C space A space B
+      B --> A
+      B --> C
+      block
+        D
+        E
+      end
+      E --> A
+    
+
+block-beta
+      columns 2
+      C A B
+      block
+        D
+        E
+      end
+    
+
+block-beta
+      columns 2
+      A B C D
+      A --o B
+      A --> C
 
     
diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js
index 656390329..8a71cc594 100644
--- a/packages/mermaid/src/dagre-wrapper/edges.js
+++ b/packages/mermaid/src/dagre-wrapper/edges.js
@@ -375,9 +375,9 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
   let pointsHasChanged = false;
   const tail = graph.node(e.v);
   var head = graph.node(e.w);
-  log.info('abc88 InsertEdge (head & tail): ', head, tail);
+  log.info('abc88 InsertEdge (head & tail): ', e.v, head, ' --- ', e.w, tail);
 
-  if (head.intersect && tail.intersect) {
+  if (head?.intersect && tail?.intersect) {
     points = points.slice(1, edge.points.length - 1);
     points.unshift(tail.intersect(points[0]));
     log.info(
@@ -387,6 +387,8 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
       head.intersect(points[points.length - 1])
     );
     points.push(head.intersect(points[points.length - 1]));
+  } else {
+    log.info('abc88 No intersect');
   }
   if (edge.toCluster) {
     log.info('to cluster abc88', clusterDb[edge.toCluster]);
diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
index f5876849e..c3861feab 100644
--- a/packages/mermaid/src/diagrams/block/blockDB.ts
+++ b/packages/mermaid/src/diagrams/block/blockDB.ts
@@ -19,7 +19,9 @@ import clone from 'lodash-es/clone.js';
 let blockDatabase: Record = {};
 let edgeList: Block[] = [];
 let edgeCount: Record = {};
-const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
+
+const populateBlockDatabase = (_blockList: Block[], parent: Block): void => {
+  const blockList = _blockList.flat();
   const children = [];
   for (const block of blockList) {
     if (block.type === 'column-setting') {
@@ -161,10 +163,10 @@ export const generateId = () => {
 
 type ISetHierarchy = (block: Block[]) => void;
 const setHierarchy = (block: Block[]): void => {
-  log.debug('The hierarchy', JSON.stringify(block, null, 2));
+  log.debug('The document from parsing', JSON.stringify(block, null, 2));
   rootBlock.children = block;
   populateBlockDatabase(block, rootBlock);
-  log.debug('The hierarchy', JSON.stringify(rootBlock, null, 2));
+  log.debug('The document after popuplation', JSON.stringify(rootBlock, null, 2));
   blocks = rootBlock.children;
 };
 
@@ -190,6 +192,23 @@ const getColumns = (blockid: string): number => {
 };
 
 type IGetBlocks = () => Block[];
+/**
+ * Returns all the blocks as a flat array
+ * @returns
+ */
+const getBlocksFlat: IGetBlocks = () => {
+  const result: Block[] = [];
+  console.log('abc88 getBlocksFlat', blockDatabase);
+  const keys = Object.keys(blockDatabase);
+  for (const key of keys) {
+    result.push(blockDatabase[key]);
+  }
+  return result;
+};
+/**
+ * Returns the the hirarchy of blocks
+ * @returns
+ */
 const getBlocks: IGetBlocks = () => {
   return blocks || [];
 };
@@ -218,6 +237,7 @@ export interface BlockDB extends DiagramDB {
   addLink: IAddLink;
   getLogger: IGetLogger;
   getEdges: IGetEdges;
+  getBlocksFlat: IGetBlocks;
   getBlocks: IGetBlocks;
   getBlock: IGetBlock;
   setBlock: ISetBlock;
@@ -237,6 +257,7 @@ const db: BlockDB = {
   edgeTypeStr2Type: edgeTypeStr2Type,
   edgeStrToEdgeData,
   getLogger, // TODO: remove
+  getBlocksFlat,
   getBlocks,
   getEdges,
   getLinks,
diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts
index 991adda3f..77e9cd939 100644
--- a/packages/mermaid/src/diagrams/block/blockRenderer.ts
+++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts
@@ -45,6 +45,7 @@ export const draw = async function (
   insertMarkers(svg, markers, diagObj.type, true);
 
   const bl = db.getBlocks();
+  const blArr = db.getBlocksFlat();
   const edges = db.getEdges();
 
   const nodes = svg.insert('g').attr('class', 'block');
@@ -52,7 +53,7 @@ export const draw = async function (
   const bounds = layout(db);
   // log.debug('Here be blocks', bl);
   await insertBlocks(nodes, bl, db);
-  await insertEdges(nodes, edges, bl, db);
+  await insertEdges(nodes, edges, blArr, db);
 
   // log.debug('Here', bl);
 
diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
index d5e0ff828..579639d06 100644
--- a/packages/mermaid/src/diagrams/block/parser/block.jison
+++ b/packages/mermaid/src/diagrams/block/parser/block.jison
@@ -18,6 +18,7 @@
 %x NODE
 %x BLOCK_ARROW
 %x ARROW_DIR
+%x LLABEL
 
 
 // as per section 6.1 of RFC 2234 [2]
@@ -45,7 +46,7 @@ CRLF \u000D\u000A
 [`]["]          { this.popState();}
 ["]                     this.pushState("string");
 ["]             { yy.getLogger().debug('LEX: POPPING STR:', yytext);this.popState();}
-[^"]*           { yy.getLogger().debug('LEX: STR ebd:', yytext); return "STR";}
+[^"]*           { yy.getLogger().debug('LEX: STR end:', yytext); return "STR";}
 space[:]\d+            {  yytext = yytext.replace(/space\:/,'');yy.getLogger().info('SPACE NUM (LEX)', yytext); return 'SPACE_BLOCK'; }
 space                  { yytext = '1'; yy.getLogger().info('COLUMNS (LEX)', yytext); return 'SPACE_BLOCK'; }
 "style"               return 'STYLE';
@@ -130,9 +131,14 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
 \s*[xo<]?\=\=+[=xo>]\s*                 { yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; }
 \s*[xo<]?\-?\.+\-[xo>]?\s*              { yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; }
 \s*\~\~[\~]+\s*                         { yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; }
-\s*[xo<]?\-\-\s*                        { yy.getLogger().info('Lex: START_LINK', yytext); return 'START_LINK'; }
-\s*[xo<]?\=\=\s*                        { yy.getLogger().info('Lex: START_LINK', yytext); return 'START_LINK'; }
-\s*[xo<]?\-\.\s*                        { yy.getLogger().info('Lex: START_LINK', yytext); return 'START_LINK'; }
+\s*[xo<]?\-\-\s*                        { yy.getLogger().info('Lex: START_LINK', yytext);this.pushState("LLABEL");return 'START_LINK'; }
+\s*[xo<]?\=\=\s*                        { yy.getLogger().info('Lex: START_LINK', yytext);this.pushState("LLABEL");return 'START_LINK'; }
+\s*[xo<]?\-\.\s*                        { yy.getLogger().info('Lex: START_LINK', yytext);this.pushState("LLABEL");return 'START_LINK'; }
+["][`]           { this.pushState("md_string");}
+["]              { yy.getLogger().info('Lex: Starting string');this.pushState("string"); return "LINK_LABEL";}
+\s*[xo<]?\-\-+[-xo>]\s*                 { this.popState(); yy.getLogger().info('Lex: LINK', '#'+yytext+'#'); return 'LINK'; }
+\s*[xo<]?\=\=+[=xo>]\s*                 { this.popState(); yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; }
+\s*[xo<]?\-?\.+\-[xo>]?\s*              { this.popState(); yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; }
 
 /lex
 
@@ -177,9 +183,9 @@ document
 
 link
   : LINK
-  { yy.getLogger().info("Rule: link: ", $1); }
-  | START_LINK
-  { yy.getLogger().info("Rule: link: ", $1); }
+  { yy.getLogger().info("Rule: link: ", $1, yytext); }
+  | START_LINK LINK_LABEL STR LINK
+  { yy.getLogger().info("Rule: LABEL link: ", $1, $3, $4); $$=$4; }
   ;
 
 statement
@@ -192,7 +198,7 @@ statement
 
 nodeStatement
   : nodeStatement link node {
-    yy.getLogger().info('Rule: (nodeStatement link node) ', $1, $2, $3, 'abc88 typestr =>',$2);
+    yy.getLogger().info('Rule: (nodeStatement link node) ', $1, $2, $3, 'abc88 typestr: ',$2);
     const edgeData = yy.edgeStrToEdgeData($2)
     $$ = [
       {id: $1.id, label: $1.label, type:$1.type, directions: $1.directions},
diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
index 73933426d..a6daa7651 100644
--- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
+++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
@@ -134,6 +134,7 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
     // props: vertex.props,
     padding: padding ?? (getConfig()?.flowchart?.padding || 0),
   };
+  console.log('abc88 return node', vertex.id, node);
   return node;
 }
 type IOperation = (elem: any, block: any, db: any) => Promise;
@@ -208,6 +209,7 @@ export async function insertEdges(
 
   for (const block of blocks) {
     if (block.size) {
+      console.log('abc88 block', block, block.id);
       g.setNode(block.id, {
         width: block.size.width,
         height: block.size.height,
@@ -216,12 +218,16 @@ export async function insertEdges(
     }
   }
 
-  // log.debug('abc88 edges', edges);
+  console.log('abc88 edges', edges);
   for (const edge of edges) {
     // elem, e, edge, clusterDb, diagramType, graph;
     if (edge.start && edge.end) {
       const startBlock = db.getBlock(edge.start);
+      const startBlock2 = g.node(edge.start);
       const endBlock = db.getBlock(edge.end);
+      const endBlock2 = g.node(edge.end);
+      console.log('abc88 startBlock', startBlock2);
+      console.log('abc88 endBlock', endBlock2);
 
       if (startBlock?.size && endBlock?.size) {
         const start = startBlock.size;