diff --git a/cypress/integration/rendering/flowchart-elk.spec.js b/cypress/integration/rendering/flowchart-elk.spec.js index 414037651..68d8b3ce5 100644 --- a/cypress/integration/rendering/flowchart-elk.spec.js +++ b/cypress/integration/rendering/flowchart-elk.spec.js @@ -684,4 +684,149 @@ A --> B { titleTopMargin: 0 } ); }); + describe('Markdown strings flowchart-elk (#4220)', () => { + describe('html labels', () => { + it('With styling and classes', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart-elk LR + A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass + id1(Start)-->id2(Stop) + style id1 fill:#f9f,stroke:#333,stroke-width:4px + style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 + classDef someclass fill:#f96 +`, + { titleTopMargin: 0 } + ); + }); + it('With formatting in a node', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart-elk LR + a{"\`The **cat** in the hat\`"} -- 1o --> b + a -- 2o --> c + a -- 3o --> d + g --2i--> a + d --1i--> a + h --3i -->a + b --> d(The dog in the hog) + c --> d +`, + { titleTopMargin: 0 } + ); + }); + it('New line in node and formatted edge label', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart-elk LR +b("\`The dog in **the** hog.(1) +NL\`") --"\`1o **bold**\`"--> c +`, + { titleTopMargin: 0 } + ); + }); + it('Wrapping long text with a new line', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart-elk LR +b(\`The dog in **the** hog.(1).. a a a a *very long text* about it +Word! + +Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`) --> c + +`, + { titleTopMargin: 0 } + ); + }); + it('Sub graphs and markdown strings', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart-elk LR +subgraph "One" + a("\`The **cat** + in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}} +end +subgraph "\`**Two**\`" + c("\`The **cat** + in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog") +end + +`, + { titleTopMargin: 0 } + ); + }); + }); + + describe('svg text labels', () => { + it('With styling and classes', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart-elk LR + A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass + id1(Start)-->id2(Stop) + style id1 fill:#f9f,stroke:#333,stroke-width:4px + style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 + classDef someclass fill:#f96 +`, + { titleTopMargin: 0 } + ); + }); + it('With formatting in a node', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart-elk LR + a{"\`The **cat** in the hat\`"} -- 1o --> b + a -- 2o --> c + a -- 3o --> d + g --2i--> a + d --1i--> a + h --3i -->a + b --> d(The dog in the hog) + c --> d +`, + { titleTopMargin: 0 } + ); + }); + it('New line in node and formatted edge label', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart-elk LR +b("\`The dog in **the** hog.(1) +NL\`") --"\`1o **bold**\`"--> c +`, + { titleTopMargin: 0 } + ); + }); + it('Wrapping long text with a new line', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart-elk LR +b("\`The dog in **the** hog.(1).. a a a a *very long text* about it +Word! + +Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c + +`, + { titleTopMargin: 0 } + ); + }); + it('Sub graphs and markdown strings', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart-elk LR +subgraph "One" + a("\`The **cat** + in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}} +end +subgraph "\`**Two**\`" + c("\`The **cat** + in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog") +end + +`, + { titleTopMargin: 0 } + ); + }); + }); + }); }); diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index abdb22265..4513cc87d 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -685,4 +685,149 @@ A ~~~ B { titleTopMargin: 0 } ); }); + describe('Markdown strings flowchart (#4220)', () => { + describe('html labels', () => { + it('With styling and classes', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart LR + A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass + id1(Start)-->id2(Stop) + style id1 fill:#f9f,stroke:#333,stroke-width:4px + style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 + classDef someclass fill:#f96 +`, + { titleTopMargin: 0 } + ); + }); + it('With formatting in a node', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart LR + a{"\`The **cat** in the hat\`"} -- 1o --> b + a -- 2o --> c + a -- 3o --> d + g --2i--> a + d --1i--> a + h --3i -->a + b --> d(The dog in the hog) + c --> d +`, + { titleTopMargin: 0 } + ); + }); + it('New line in node and formatted edge label', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart LR +b("\`The dog in **the** hog.(1) +NL\`") --"\`1o **bold**\`"--> c +`, + { titleTopMargin: 0 } + ); + }); + it('Wrapping long text with a new line', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart LR +b("\`The dog in **the** hog.(1).. a a a a *very long text* about it +Word! + +Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c + +`, + { titleTopMargin: 0 } + ); + }); + it('Sub graphs and markdown strings', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart LR +subgraph "One" + a("\`The **cat** + in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}} +end +subgraph "\`**Two**\`" + c("\`The **cat** + in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog") +end + +`, + { titleTopMargin: 0 } + ); + }); + }); + + describe('svg text labels', () => { + it('With styling and classes', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart LR + A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass + id1(Start)-->id2(Stop) + style id1 fill:#f9f,stroke:#333,stroke-width:4px + style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 + classDef someclass fill:#f96 +`, + { titleTopMargin: 0 } + ); + }); + it('With formatting in a node', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart LR + a{"\`The **cat** in the hat\`"} -- 1o --> b + a -- 2o --> c + a -- 3o --> d + g --2i--> a + d --1i--> a + h --3i -->a + b --> d(The dog in the hog) + c --> d +`, + { titleTopMargin: 0 } + ); + }); + it('New line in node and formatted edge label', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart LR +b("\`The dog in **the** hog.(1) +NL\`") --"\`1o **bold**\`"--> c +`, + { titleTopMargin: 0 } + ); + }); + it('Wrapping long text with a new line', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart LR +b("\`The dog in **the** hog.(1).. a a a a *very long text* about it +Word! + +Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c + +`, + { titleTopMargin: 0 } + ); + }); + it('Sub graphs and markdown strings', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart LR +subgraph "One" + a("\`The **cat** + in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}} +end +subgraph "\`**Two**\`" + c("\`The **cat** + in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog") +end + +`, + { titleTopMargin: 0 } + ); + }); + }); + }); }); diff --git a/cypress/integration/rendering/mindmap.spec.ts b/cypress/integration/rendering/mindmap.spec.ts index 4663f6225..94b3f9ca0 100644 --- a/cypress/integration/rendering/mindmap.spec.ts +++ b/cypress/integration/rendering/mindmap.spec.ts @@ -223,5 +223,18 @@ mindmap shouldHaveRoot ); }); + describe('Markdown strings mindmaps (#4220)', () => { + it('Formatted label with linebreak and a wrapping label and emojis', () => { + imgSnapshotTest( + `mindmap + id1[\`**Start** with + a second line 😎\`] + id2[\`The dog in **the** hog... a *very long text* about it +Word!\`] +`, + { titleTopMargin: 0 } + ); + }); + }); /* The end */ }); diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index 4c160ca1b..08a4c0e68 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -58,91 +58,23 @@
-flowchart LR
-    A:::someclass --> B[`The **cat** in the hat`]:::someclass
-    id1(Start)-->id2(Stop)
-    style id1 fill:#f9f,stroke:#333,stroke-width:4px
-    style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
-    classDef someclass fill:#f96
-
-
-%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
-%%
-flowchart LR
-    A:::someclass --> B[`The **cat** in the hat`]:::someclass
-    id1(Start)-->id2(Stop)
-    style id1 fill:#f9f,stroke:#333,stroke-width:4px
-    style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
-    classDef someclass fill:#f96
-
-
-%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
-%%
-graph LR
-  a{`The **cat** in the hat`} -- 1o --> b
-  a -- 2o --> c
-  a -- 3o --> d
-  g --2i--> a
-  d --1i--> a
-  h --3i -->a
-  b --> d(The dog in the hog)
-  c --> d
-
-
-      %%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
-flowchart LR
-b(`The dog in **the** hog.(1)
-NL`) --`1o **bold**`--> c
-
-
-flowchart-elk LR
-b(`The dog in **the** hog.(1)
-NL`) --`1o **bold**`--> c
-
-
-flowchart-elk LR
-b(`The dog in **the** hog.(1).. a a a a *very long text* about it
-Word!
-
-Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. `) --> c
-
-
-      %%{init: {"flowchart": {"htmlLabels": true}} }%%
+      %%{init: {"flowchart": {"htmlLabels": false}} }%%
 flowchart-elk LR
 b(`The dog in **the** hog(2)... a a a a *very long text* about it
 Word!
 Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. `)
 
-
-      %%{init: {"flowchart": {"htmlLabels": false}} }%%
+    
 flowchart-elk LR
 b("The dog in the hog... a very
long text about it
Word!")
-
-      %%{init: {"flowchart": {"htmlLabels": true}} }%%
+    
 flowchart-elk LR
 b("The dog in the hog... a very
long text about it
Word!")
-
-flowchart-elk LR
-subgraph "One"
-  a(`The **cat**
-  in the hat`) -- "1o" --> b{{`The **dog** in the hog`}}
-end
-subgraph `**Two**`
-  c(`The **cat**
-  in the hat`) -- `1o **ipa**` --> d("The dog in the hog")
-end
-
-
+    
 mindmap
     id1[`**Start2**
     second line 😎 with long text that is wrapping to the next line`]
@@ -157,12 +89,12 @@ mindmap
     
 mindmap
-    id1[`**Start** with
-    a second line 😎`]
-      id2[`The dog in **the** hog... a *very long text* about it
-Word!`]
+    id1["`**Start** with
+    a second line 😎`"]
+      id2["`The dog in **the** hog... a *very long text* about it
+Word!`"]
     
-
+    
 %%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
 flowchart TB
   %% I could not figure out how to use double quotes in labels in Mermaid
@@ -218,7 +150,7 @@ flowchart TB
 

-
+    
 flowchart TB
   %% I could not figure out how to use double quotes in labels in Mermaid
   subgraph ibm[IBM Espresso CPU]
@@ -274,7 +206,7 @@ flowchart TB
     >
     
  -
+    
       flowchart LR
   B1 --be be--x B2
   B1 --bo bo--o B3
@@ -307,7 +239,7 @@ flowchart TB
   B6 --> B5
   
-
+    
 sequenceDiagram
     Customer->>+Stripe: Makes a payment request
     Stripe->>+Bank: Forwards the payment request to the bank
@@ -320,7 +252,7 @@ sequenceDiagram
     Customer->>+Merchant: Receives goods or services
         
-
+    
 mindmap
   root((mindmap))
     Origins
@@ -340,7 +272,7 @@ mindmap
       Mermaid
     

-
+    
   example-diagram
     
@@ -368,7 +300,7 @@ mindmap htmlLabels: false, // htmlLabels: true, }, - htmlLabels: false, + // htmlLabels: true, gantt: { useMaxWidth: false, }, diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-md-string.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-md-string.spec.js new file mode 100644 index 000000000..005d257e0 --- /dev/null +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-md-string.spec.js @@ -0,0 +1,64 @@ +import flowDb from '../flowDb'; +import flow from './flow'; +import { setConfig } from '../../../config'; + +setConfig({ + securityLevel: 'strict', +}); + +describe('parsing a flow chart with markdown strings', function () { + beforeEach(function () { + flow.parser.yy = flowDb; + flow.parser.yy.clear(); + }); + + it('mardown formatting in nodes and labels', function () { + const res = flow.parser.parse(`flowchart +A["\`The cat in **the** hat\`"]-- "\`The *bat* in the chat\`" -->B["The dog in the hog"] -- "The rat in the mat" -->C;`); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['A'].text).toBe('The cat in **the** hat'); + expect(vert['A'].labelType).toBe('markdown'); + expect(vert['B'].id).toBe('B'); + expect(vert['B'].text).toBe('The dog in the hog'); + expect(vert['B'].labelType).toBe('text'); + expect(edges.length).toBe(2); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow_point'); + expect(edges[0].text).toBe('The *bat* in the chat'); + expect(edges[0].labelType).toBe('markdown'); + expect(edges[1].start).toBe('B'); + expect(edges[1].end).toBe('C'); + expect(edges[1].type).toBe('arrow_point'); + expect(edges[1].text).toBe('The rat in the mat'); + expect(edges[1].labelType).toBe('text'); + }); + it('mardown formatting in subgraphs', function () { + const res = flow.parser.parse(`flowchart LR +subgraph "One" + a("\`The **cat** + in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}} +end +subgraph "\`**Two**\`" + c("\`The **cat** + in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog") +end`); + + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(2); + const subgraph = subgraphs[0]; + + expect(subgraph.nodes.length).toBe(2); + expect(subgraph.title).toBe('One'); + expect(subgraph.labelType).toBe('text'); + + const subgraph2 = subgraphs[1]; + expect(subgraph2.nodes.length).toBe(2); + expect(subgraph2.title).toBe('**Two**'); + expect(subgraph2.labelType).toBe('markdown'); + }); +}); diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison index dd82cff4d..19ab80b05 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison @@ -38,9 +38,9 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili [\}] { this.popState(); } [^\}]* return "acc_descr_multiline_value"; // .*[^\n]* { return "acc_descr_line"} -[`] { this.begin("md_string");} -[^`]+ { return "MD_STR";} -[`] { this.popState();} +["][`] { this.begin("md_string");} +[^`"]+ { return "MD_STR";} +[`]["] { this.popState();} ["] this.begin("string"); ["] this.popState(); [^"]* return "STR"; diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.js b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.js index c5b5fede1..a2a4def59 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.js +++ b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.js @@ -167,12 +167,15 @@ function positionNodes(cy) { export const draw = async (text, id, version, diagObj) => { const conf = getConfig(); + // console.log('Config: ', conf); + conf.htmlLabels = false; + // This is done only for throwing the error if the text is not valid. diagObj.db.clear(); // Parse the graph definition diagObj.parser.parse(text); - log.debug('Renering info diagram\n' + text); + log.debug('Renering mindmap diagram\n' + text, diagObj); const securityLevel = getConfig().securityLevel; // Handle root and Document for when rendering in sandbox mode diff --git a/packages/mermaid/src/diagrams/mindmap/parser/mindmap.jison b/packages/mermaid/src/diagrams/mindmap/parser/mindmap.jison index 41ee33c91..84a6191cf 100644 --- a/packages/mermaid/src/diagrams/mindmap/parser/mindmap.jison +++ b/packages/mermaid/src/diagrams/mindmap/parser/mindmap.jison @@ -42,9 +42,9 @@ // !(-\() return 'NODE_ID'; [^\(\[\n\-\)\{\}]+ return 'NODE_ID'; <> return 'EOF'; -[`] { this.begin("NSTR2");} -[^`]+ { return "NODE_DESCR";} -[`] { this.popState();} +["][`] { this.begin("NSTR2");} +[^`"]+ { return "NODE_DESCR";} +[`]["] { this.popState();} ["] { yy.getLogger().trace('Starting NSTR');this.begin("NSTR");} [^"]+ { yy.getLogger().trace('description:', yytext); return "NODE_DESCR";} ["] {this.popState();}