From 818cb2fd7665e9cc3b305bfe17de737f1b55ff16 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Fri, 5 Jan 2024 20:56:57 +0100 Subject: [PATCH] #3358 Adding support for style statements --- cypress/platform/knsv2.html | 38 ++++++++++++++----- .../mermaid/src/diagrams/block/blockDB.ts | 27 +++++++++++-- .../mermaid/src/diagrams/block/blockTypes.ts | 2 + .../src/diagrams/block/parser/block.jison | 15 +++++++- .../src/diagrams/block/renderHelpers.ts | 9 ++--- .../src/diagrams/flowchart/flowRenderer-v2.js | 2 +- packages/mermaid/src/mermaidAPI.ts | 1 - 7 files changed, 74 insertions(+), 20 deletions(-) diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index a6553304c..5dc87325c 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -72,18 +72,38 @@ block-beta
 block-beta
-      columns 3
+columns 3
+  space Browser space
+  space:3
+
+    A
+    B
+    C
+
+    space:3
+    space
+    db{{"This is the text in the box"}}
+
       classDef green fill:#9f6,stroke:#333,stroke-width:2px;
-      A
-      B
-      class A green
-    
-
-stateDiagram-v2
-      classDef green fill:#9f6,stroke:#333,stroke-width:2px;
-      A
+      style B fill:#f9F,stroke:#333,stroke-width:4px
       class A green
 
+      Browser --> A
+      Browser --> B
+      Browser --> C
+      A --> db
+      B --> db
+      C--> db
+
+      block
+        D
+        E
+      end
+    
+
+flowchart
+      B
+      style B fill:#f9F,stroke:#333,stroke-width:4px
     
 block-beta
diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
index 4a3a6a146..4ee5343fa 100644
--- a/packages/mermaid/src/diagrams/block/blockDB.ts
+++ b/packages/mermaid/src/diagrams/block/blockDB.ts
@@ -56,6 +56,20 @@ export const addStyleClass = function (id: string, styleAttributes = '') {
   }
 };
 
+/**
+ * Called when the parser comes across a (style) class definition
+ * @example classDef my-style fill:#f96;
+ *
+ * @param {string} id - the id of this (style) class
+ * @param  {string | null} styles - the string with 1 or more style attributes (each separated by a comma)
+ */
+export const addStyle2Node = function (id: string, styles = '') {
+  let foundBlock = blockDatabase[id];
+  if (styles !== undefined && styles !== null) {
+    foundBlock.styles = styles.split(STYLECLASS_SEP);
+  }
+};
+
 /**
  * Add a (style) class or css class to a state with the given id.
  * If the state isn't already in the list of known states, add it.
@@ -116,14 +130,21 @@ const populateBlockDatabase = (_blockList: Block[], parent: Block): void => {
   const children = [];
   for (const block of blockList) {
     if (block.type === 'classDef') {
-      console.log('abc88 classDef', block);
+      // console.log('abc88 classDef', block);
       addStyleClass(block.id, block.css);
       continue;
     }
     if (block.type === 'applyClass') {
-      console.log('abc88 applyClass', block);
+      // console.log('abc88 applyClass', block);
       // addStyleClass(block.id, block.css);
-      setCssClass(block.id, block.styleClass);
+      setCssClass(block.id, block?.styleClass || '');
+      continue;
+    }
+    if (block.type === 'applyStyles') {
+      console.log('abc88 applyStyles', block);
+      addStyle2Node(block.id, block.styles);
+      // addStyleClass(block.id, block.css);
+      // setCssClass(block.id, block.styles);
       continue;
     }
     if (block.type === 'column-setting') {
diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
index 241ad3934..0cee35e44 100644
--- a/packages/mermaid/src/diagrams/block/blockTypes.ts
+++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
@@ -30,6 +30,7 @@ export type BlockType =
   | 'doublecircle'
   | 'classDef'
   | 'applyClass'
+  | 'applyStyles'
   | 'composite';
 
 export interface Block {
@@ -57,6 +58,7 @@ export interface Block {
   directions?: string[];
   css?: string;
   styleClass?: string;
+  styles?: string[];
 }
 
 export interface Link {
diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
index 9228a3b8a..86faa1d84 100644
--- a/packages/mermaid/src/diagrams/block/parser/block.jison
+++ b/packages/mermaid/src/diagrams/block/parser/block.jison
@@ -23,6 +23,8 @@
 %x CLASS_STYLE
 %x CLASSDEF
 %x CLASSDEFID
+%x STYLE_STMNT
+%x STYLE_DEFINITION
 
 
 // as per section 6.1 of RFC 2234 [2]
@@ -53,7 +55,6 @@ CRLF \u000D\u000A
 [^"]*           { 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';
 "default"             return 'DEFAULT';
 "linkStyle"           return 'LINKSTYLE';
 "interpolate"         return 'INTERPOLATE';
@@ -67,6 +68,10 @@ space                  { yytext = '1'; yy.getLogger().info('COLUMNS (LEX)', yyte
 (\w+)+((","\s*\w+)*)     { this.popState(); this.pushState('CLASS_STYLE'); return 'CLASSENTITY_IDS' }
 [^\n]*             { this.popState(); return 'STYLECLASS' }
 
+"style"\s+      { this.pushState('STYLE_STMNT'); return 'style'; }
+(\w+)+((","\s*\w+)*)     { this.popState(); this.pushState('STYLE_DEFINITION'); return 'STYLE_ENTITY_IDS' }
+[^\n]*             { this.popState(); return 'STYLE_DEFINITION_DATA' }
+
 accTitle\s*":"\s*                                               { this.pushState("acc_title");return 'acc_title'; }
 (?!\n|;|#)*[^\n]*                                    { this.popState(); return "acc_title_value"; }
 accDescr\s*":"\s*                                               { this.pushState("acc_descr");return 'acc_descr'; }
@@ -208,6 +213,7 @@ statement
   | blockStatement
   | classDefStatement
   | cssClassStatement
+  | styleStatement
 	;
 
 nodeStatement
@@ -271,4 +277,11 @@ cssClassStatement
         }
     ;
 
+styleStatement
+    : style STYLE_ENTITY_IDS STYLE_DEFINITION_DATA {
+        console.log('abc88 apply class: id(s): ',$2, '  style class: ', $3);
+        $$={ type: 'applyStyles', id: $2.trim(), styles: $3.trim() };
+        }
+    ;
+
 %%
diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
index ebe88efdc..130f031ca 100644
--- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
+++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
@@ -16,10 +16,9 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
 
   let classStr = 'default';
   if ((vertex?.classes?.length || 0) > 0) {
-    console.log('abc88 vertex.classes', block.id, vertex?.classes);
     classStr = (vertex?.classes || []).join(' ');
   }
-  console.log('abc88 vertex.classes done');
+  console.log('abc88 vertex.classes styles', block.id, vertex?.styles);
   classStr = classStr + ' flowchart-label';
 
   // We create a SVG label, either by delegating to addHtmlLabel or manually
@@ -100,8 +99,8 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
       _shape = 'rect';
   }
 
-  // const styles = getStylesFromArray(vertex.styles);
-  const styles = getStylesFromArray([]);
+  const styles = getStylesFromArray(vertex?.styles || '');
+  // const styles = getStylesFromArray([]);
 
   // Use vertex id as text in the box if no text is provided by the graph definition
   const vertexText = vertex.label;
@@ -116,7 +115,7 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
     rx: radious,
     ry: radious,
     class: classStr,
-    style: styles.style,
+    style: styles.style, // + 'fill:#9f9;stroke:#333;stroke-width:4px;',
     id: vertex.id,
     directions: vertex.directions,
     // link: vertex.link,
diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
index 7c964b4e7..6f219f166 100644
--- a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
+++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
@@ -169,7 +169,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
       padding: getConfig().flowchart.padding,
     });
 
-    log.info('setNode', {
+    log.info('abc88 setNode', {
       labelStyle: styles.labelStyle,
       labelType: vertex.labelType,
       shape: _shape,
diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts
index 467f60c4e..80837fd34 100644
--- a/packages/mermaid/src/mermaidAPI.ts
+++ b/packages/mermaid/src/mermaidAPI.ts
@@ -513,7 +513,6 @@ const render = async function (
   const a11yTitle: string | undefined = diag.db.getAccTitle?.();
   const a11yDescr: string | undefined = diag.db.getAccDescription?.();
   addA11yInfo(diagramType, svgNode, a11yTitle, a11yDescr);
-
   // -------------------------------------------------------------------------------
   // Clean up SVG code
   root.select(`[id="${id}"]`).selectAll('foreignobject > *').attr('xmlns', XMLNS_XHTML_STD);