From 5fc99f1982ab5b90f7664979fc9666b30d93d21e Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Mon, 28 Aug 2023 12:51:49 +0200 Subject: [PATCH] #3358 Adding db calls from node statements --- cypress/platform/knsv2.html | 9 +- .../mermaid/src/diagrams/block/blockDB.ts | 100 ++++++++++++------ .../mermaid/src/diagrams/block/blockTypes.ts | 33 ++++++ .../src/diagrams/block/parser/block.jison | 12 +-- .../src/diagrams/block/parser/block.spec.ts | 19 +++- .../diagrams/flowchart/parser/flow.spec.js | 2 +- 6 files changed, 128 insertions(+), 47 deletions(-) diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index 1b1ccd685..e19d53ae4 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -58,13 +58,8 @@
-stateDiagram-v2
-    [*] --> Still
-    Still --> [*]
-    Still --> Moving
-    Moving --> Still
-    Moving --> Crash
-    Crash --> [*]    
 flowchart RL
diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
index a0c97fc0f..bec5c33c3 100644
--- a/packages/mermaid/src/diagrams/block/blockDB.ts
+++ b/packages/mermaid/src/diagrams/block/blockDB.ts
@@ -1,6 +1,6 @@
 // import type { BlockDB } from './blockTypes.js';
 import type { DiagramDB } from '../../diagram-api/types.js';
-import { BlockConfig } from './blockTypes.js';
+import { BlockConfig, BlockType, Block, Link } from './blockTypes.js';
 
 import * as configApi from '../../config.js';
 // import common from '../common/common.js';
@@ -13,47 +13,78 @@ import {
   // getDiagramTitle,
   clear as commonClear,
 } from '../../commonDb.js';
+import { log } from '../../logger.js';
 
 // export type TBlockColumnsDefaultValue = 'H'; // Do we support something else, like 'auto' | 0?
 
+// Initialize the node database for simple lookups
+let nodeDatabase: Record = {};
+const blockDatabase: Record = {};
+
+// Function to get a node by its ID
+export const getNodeById = (id: string): Node | undefined => {
+  return nodeDatabase[id];
+};
+
 // TODO: Convert to generic TreeNode type? Convert to class?
-export interface Block {
-  ID: string;
-  label?: string;
-  parent?: Block;
-  children?: Block[];
-  columns?: number; // | TBlockColumnsDefaultValue;
-}
 
-export interface Link {
-  source: Block;
-  target: Block;
-}
-
-let rootBlocks: Block[] = [];
+let rootBlock = { ID: 'root', children: [] as Block[], columns: -1 };
 let blocks: Block[] = [];
 const links: Link[] = [];
-let rootBlock = { ID: 'root', children: [], columns: -1 } as Block;
-let currentBlock: Block | undefined;
+// let rootBlock = { ID: 'root', children: [], columns: -1 } as Block;
+let currentBlock = rootBlock;
 
 const clear = (): void => {
-  rootBlocks = [];
-  blocks = [];
+  log.info('Clear called');
+  // rootBlocks = [];
+  blocks = [] as Block[];
   commonClear();
   rootBlock = { ID: 'root', children: [], columns: -1 };
   currentBlock = rootBlock;
+  nodeDatabase = {};
+  blockDatabase[rootBlock.ID] = rootBlock;
 };
 
-type IAddBlock = (block: Block) => Block;
-const addBlock: IAddBlock = (block: Block, parent?: Block): Block => {
-  if (parent) {
-    parent.children ??= [];
-    parent.children.push(block);
-  } else {
-    rootBlocks.push(block);
+// type IAddBlock = (block: Block) => Block;
+// const addBlock: IAddBlock = (block: Block, parent?: Block): Block => {
+//   log.info('addBlock', block, parent);
+//   if (parent) {
+//     parent.children ??= [];
+//     parent.children.push(block);
+//   } else {
+//     rootBlock.children.push(block);
+//   }
+//   blocks.push(block);
+//   return block;
+// };
+
+type ITypeStr2Type = (typeStr: string) => BlockType;
+export function typeStr2Type(typeStr: string) {
+  // TODO: add all types
+  switch (typeStr) {
+    case '[]':
+      return 'square';
+    case '()':
+      return 'round';
+    default:
+      return 'square';
   }
-  blocks.push(block);
-  return block;
+}
+
+type IAddBlock = (id: string, label: string, type: BlockType) => Block;
+// Function to add a node to the database
+export const addBlock = (id: string, _label?: string, type?: BlockType) => {
+  log.info('addNode called:', id, _label, type);
+  const label = _label || id;
+  const node: Block = {
+    ID: id,
+    label,
+    type: type || 'square',
+  };
+  blockDatabase[node.ID] = node;
+  currentBlock.children ??= [];
+  currentBlock.children.push(node);
+  return node;
 };
 
 type IAddLink = (link: Link) => Link;
@@ -84,16 +115,21 @@ const getBlock = (id: string, blocks: Block[]): Block | undefined => {
 
 type IGetColumns = (blockID: string) => number;
 const getColumns = (blockID: string): number => {
-  const blocks = [rootBlock];
-  const block = getBlock(blockID, blocks);
+  const block = blockDatabase[blockID];
   if (!block) {
     return -1;
   }
-  return block.columns || -1;
+  if (block.columns) {
+    return block.columns;
+  }
+  if (!block.children) {
+    return -1;
+  }
+  return block.children.length;
 };
 
 type IGetBlocks = () => Block[];
-const getBlocks: IGetBlocks = () => blocks;
+const getBlocks: IGetBlocks = () => rootBlock.children || [];
 
 type IGetLinks = () => Link[];
 const getLinks: IGetLinks = () => links;
@@ -111,12 +147,14 @@ export interface BlockDB extends DiagramDB {
   getLinks: IGetLinks;
   setColumns: ISetColumns;
   getColumns: IGetColumns;
+  typeStr2Type: ITypeStr2Type;
 }
 
 const db: BlockDB = {
   getConfig: () => configApi.getConfig().block,
   addBlock: addBlock,
   addLink: addLink,
+  typeStr2Type: typeStr2Type,
   getLogger, // TODO: remove
   getBlocks,
   getLinks,
diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
index c190c5779..b373d6b9c 100644
--- a/packages/mermaid/src/diagrams/block/blockTypes.ts
+++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
@@ -3,3 +3,36 @@ import type { BaseDiagramConfig } from '../../config.type.js';
 export interface BlockConfig extends BaseDiagramConfig {
   padding?: number;
 }
+
+export type BlockType =
+  | 'round'
+  | 'square'
+  | 'diamond'
+  | 'hexagon'
+  | 'odd'
+  | 'lean_right'
+  | 'lean_left'
+  | 'trapezoid'
+  | 'inv_trapezoid'
+  | 'odd_right'
+  | 'circle'
+  | 'ellipse'
+  | 'stadium'
+  | 'subroutine'
+  | 'cylinder'
+  | 'group'
+  | 'doublecircle';
+
+export interface Block {
+  ID: string;
+  label?: string;
+  parent?: Block;
+  type?: BlockType;
+  children?: Block[];
+  columns?: number; // | TBlockColumnsDefaultValue;
+}
+
+export interface Link {
+  source: Block;
+  target: Block;
+}
diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
index afd645d96..9422d8ee3 100644
--- a/packages/mermaid/src/diagrams/block/parser/block.jison
+++ b/packages/mermaid/src/diagrams/block/parser/block.jison
@@ -64,7 +64,7 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
 
 // Start of nodes with shapes and description
 "-)"                   { yy.getLogger().info('Lex: -)'); this.pushState('NODE');return 'NODE_D START'; }
-"(-"                   { yy.getLogger().info('Lex: (-'); this.pushState('NODE');return 'NODE_DSTART';           }
+"(-"                   { yy.getLogger().info('Lex: (-'); this.pushState('NODE');return 'NODE_DSTART'; }
 "))"                   { yy.getLogger().info('Lex: ))'); this.pushState('NODE');return 'NODE_DSTART';  }
 ")"                    { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART';      }
 "(("                   { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART'; }
@@ -177,8 +177,8 @@ statement
 	;
 
 nodeStatement
-  : nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) ');}
-  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1);}
+  : nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) '); yy.addBlock($1.id);}
+  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); yy.addBlock($1.id, $1.label, yy.typeStr2Type($1)); }
   ;
 
 columnsStatement
@@ -192,16 +192,16 @@ blockStatement
 
 node
   : NODE_ID
-  { yy.getLogger().info("Rule: node (NODE_ID seperator): ", $1); }
+  { yy.getLogger().info("Rule: node (NODE_ID seperator): ", $1); $$ = { id: $1 }; }
   |NODE_ID nodeShapeNLabel
-    { yy.getLogger().info("Rule: node (NODE_ID nodeShapeNLabel seperator): ", $1, $2); }
+    { yy.getLogger().info("Rule: node (NODE_ID nodeShapeNLabel seperator): ", $1, $2); $$ = { id: $1, label: $2.label, typeStr: $2.typeStr };}
   // |nodeShapeNLabel seperator
   // { yy.getLogger().info("Rule: node (nodeShapeNLabel seperator): ", $1, $2, $3); }
   ;
 
 nodeShapeNLabel
   :   NODE_DSTART STR NODE_DEND
-	      { yy.getLogger().info("Rule: nodeShapeNLabel: ", $1, $2, $3); $$ = { type: $1 + $3, descr: $2 }; }
+	      { yy.getLogger().info("Rule: nodeShapeNLabel: ", $1, $2, $3); $$ = { typeStr: $1 + $3, label: $2 }; }
   ;
 
 %%
diff --git a/packages/mermaid/src/diagrams/block/parser/block.spec.ts b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
index 75cd76b82..ded6db468 100644
--- a/packages/mermaid/src/diagrams/block/parser/block.spec.ts
+++ b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
@@ -3,8 +3,7 @@ import block from './block.jison';
 import db from '../blockDB.js';
 import { cleanupComments } from '../../../diagram-api/comments.js';
 import { prepareTextForParsing } from '../blockUtils.js';
-import * as fs from 'fs';
-import * as path from 'path';
+import { setConfig } from '../../../config.js';
 
 describe('Block diagram', function () {
   describe('when parsing an block diagram graph it should handle > ', function () {
@@ -20,6 +19,22 @@ describe('Block diagram', function () {
       `;
 
       block.parse(str);
+      const blocks = db.getBlocks();
+      expect(blocks.length).toBe(1);
+      expect(blocks[0].ID).toBe('id');
+      expect(blocks[0].label).toBe('id');
+    });
+    it('a node with a square shape and a label', async () => {
+      const str = `block-beta
+          id["A label"]
+          `;
+
+      block.parse(str);
+      const blocks = db.getBlocks();
+      expect(blocks.length).toBe(1);
+      expect(blocks[0].ID).toBe('id');
+      expect(blocks[0].label).toBe('A label');
+      expect(blocks[0].type).toBe('square');
     });
     it('a diagram with multiple nodes', async () => {
       const str = `block-beta
diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js
index 3852c4f92..8d0aec789 100644
--- a/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js
+++ b/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js
@@ -1,7 +1,7 @@
 import flowDb from '../flowDb.js';
 import flow from './flow.jison';
-import { setConfig } from '../../../config.js';
 import { cleanupComments } from '../../../diagram-api/comments.js';
+import { setConfig } from '../../../config.js';
 
 setConfig({
   securityLevel: 'strict',