diff --git a/demos/classchart.html b/demos/classchart.html index 031f3b608f..b879618b62 100644 --- a/demos/classchart.html +++ b/demos/classchart.html @@ -17,10 +17,10 @@

Class diagram demos

----
-title: Demo Class Diagram
----
-		classDiagram
+    ---
+    title: Demo Class Diagram
+    ---
+    classDiagram
       accTitle: Demo Class Diagram
       accDescr: This class diagram show the abstract Animal class, and 3 classes that inherit from it: Duck, Fish, and Zebra.
 
diff --git a/demos/er.html b/demos/er.html
index a1c9e20069..34e06acf85 100644
--- a/demos/er.html
+++ b/demos/er.html
@@ -19,43 +19,42 @@
 
   
     
+      ---
+      title: This is a title
+      ---
+      erDiagram
+        %% title This is a title
+        %% accDescription Test a description
 
----
-title: This is a title
----
-erDiagram
-  %% title This is a title
-  %% accDescription Test a description
+        "Person . CUSTOMER"||--o{ ORDER : places
 
-  "Person . CUSTOMER"||--o{ ORDER : places
+        ORDER ||--|{ "€£LINE_ITEM ¥" : contains
 
-  ORDER ||--|{ "€£LINE_ITEM ¥" : contains
+        "Person . CUSTOMER" }|..|{ "Address//StreetAddress::[DELIVERY ADDRESS]" : uses
 
-  "Person . CUSTOMER" }|..|{ "Address//StreetAddress::[DELIVERY ADDRESS]" : uses
+        "Address//StreetAddress::[DELIVERY ADDRESS]" {
+          int customerID FK
+          string line1 "this is the first address line comment"
+          string line2
+          string city
+          string region
+          string state
+          string(5) postal_code
+          string country
+        }
 
-  "Address//StreetAddress::[DELIVERY ADDRESS]" {
-      int customerID FK
-      string line1 "this is the first address line comment"
-      string line2
-      string city
-      string region
-      string state
-      string(5) postal_code
-      string country
-      }
-
-      "a_~`!@#$^&*()-_=+[]{}|/;:'.?¡⁄™€£‹¢›∞fi§‡•°ª·º‚≠±œŒ∑„®†ˇ¥Á¨ˆˆØπ∏“«»åÅßÍ∂΃ϩ˙Ó∆Ô˚¬Ò…ÚæÆΩ¸≈π˛çÇ√◊∫ı˜µÂ≤¯≥˘÷¿" {
-        string name "this is an entity with an absurd name just to show characters that are now acceptable as long as the name is in double quotes"
-      }
+        "a_~`!@#$^&*()-_=+[]{}|/;:'.?¡⁄™€£‹¢›∞fi§‡•°ª·º‚≠±œŒ∑„®†ˇ¥Á¨ˆˆØπ∏“«»åÅßÍ∂΃ϩ˙Ó∆Ô˚¬Ò…ÚæÆΩ¸≈π˛çÇ√◊∫ı˜µÂ≤¯≥˘÷¿" {
+          string name "this is an entity with an absurd name just to show characters that are now acceptable as long as the name is in double quotes"
+        }
 
-      "€£LINE_ITEM ¥" {
-        int orderID FK
-        int currencyId FK
-        number price
-        number quantity
-        number adjustment
-        number final_price
-      }
+        "€£LINE_ITEM ¥" {
+          int orderID FK
+          int currencyId FK
+          number price
+          number quantity
+          number adjustment
+          number final_price
+        }
     

diff --git a/demos/flowchart.html b/demos/flowchart.html index 7251e586e5..60e6160c38 100644 --- a/demos/flowchart.html +++ b/demos/flowchart.html @@ -17,9 +17,9 @@

Comparison "graph vs. flowchart"

Sample 1

graph

----
-title: This is a complicated flow
----
+    ---
+    title: This is a complicated flow
+    ---
     graph LR
       accTitle: This is a complicated flow
       accDescr: This is the descriptoin for the complicated flow.
@@ -224,9 +224,9 @@ 

flowchart

Sample 2

graph

----
-title: What to buy
----
+    ---
+    title: What to buy
+    ---
     graph TD
       accTitle: What to buy
       accDescr: Options of what to buy with Christmas money
diff --git a/demos/git.html b/demos/git.html
index 99c53d7d0a..5e683152aa 100644
--- a/demos/git.html
+++ b/demos/git.html
@@ -16,9 +16,9 @@
   
     

Git diagram demo

----
-title: Simple Git diagram
----
+    ---
+    title: Simple Git diagram
+    ---
     gitGraph:
     options
     {
diff --git a/demos/journey.html b/demos/journey.html
index dadcfb13c0..96c89a2151 100644
--- a/demos/journey.html
+++ b/demos/journey.html
@@ -16,9 +16,9 @@
   
     

Journey diagram demo

----
-title: My working day 
----
+    ---
+    title: My working day 
+    ---
      journey
       accTitle: Very simple journey demo
       accDescr: 2 main sections: work and home, each with just a few tasks
diff --git a/demos/state.html b/demos/state.html
index 7aaa7516a9..1ab0461f3e 100644
--- a/demos/state.html
+++ b/demos/state.html
@@ -17,11 +17,11 @@
     

State diagram demos

Very simple showing change from State1 to State2

----
-title: Very simple diagram
----
-		stateDiagram
-		  accTitle: This is the accessible title
+    ---
+    title: Very simple diagram
+    ---
+    stateDiagram
+      accTitle: This is the accessible title
       accDescr:This is an accessible description
       State1 --> State2
     
@@ -47,13 +47,13 @@

And these are how they are applied:

----
-title: Very simple diagram
----
-		stateDiagram
+    ---
+    title: Very simple diagram
+    ---
+    stateDiagram
       direction TB
 
-		  accTitle: This is the accessible title
+      accTitle: This is the accessible title
       accDescr: This is an accessible description
 
       classDef notMoving fill:white
diff --git a/packages/mermaid/package.json b/packages/mermaid/package.json
index cd809fef13..802ffd237c 100644
--- a/packages/mermaid/package.json
+++ b/packages/mermaid/package.json
@@ -61,6 +61,7 @@
     "moment-mini": "^2.24.0",
     "non-layered-tidy-tree-layout": "^2.0.2",
     "stylis": "^4.1.2",
+    "ts-dedent": "^2.2.0",
     "uuid": "^9.0.0"
   },
   "devDependencies": {
diff --git a/packages/mermaid/src/diagram-api/diagram-orchestration.ts b/packages/mermaid/src/diagram-api/diagram-orchestration.ts
index a26edb3031..6c7ab69074 100644
--- a/packages/mermaid/src/diagram-api/diagram-orchestration.ts
+++ b/packages/mermaid/src/diagram-api/diagram-orchestration.ts
@@ -125,6 +125,33 @@ export const addDiagrams = () => {
     },
     (text) => text.toLowerCase().trim() === 'error'
   );
+  registerDiagram(
+    '---',
+    // --- diagram type may appear if YAML front-matter is not parsed correctly
+    {
+      db: {
+        clear: () => {
+          // Quite ok, clear needs to be there for --- to work as a regular diagram
+        },
+      },
+      styles: errorStyles, // should never be used
+      renderer: errorRenderer, // should never be used
+      parser: {
+        parser: { yy: {} },
+        parse: () => {
+          throw new Error(
+            'Diagrams beginning with --- are not valid. ' +
+              'If you were trying to use a YAML front-matter, please ensure that ' +
+              "you've correctly opened and closed the YAML front-matter with unindented `---` blocks"
+          );
+        },
+      },
+      init: () => null, // no op
+    },
+    (text) => {
+      return text.toLowerCase().trimStart().startsWith('---');
+    }
+  );
 
   registerDiagram(
     'c4',
diff --git a/packages/mermaid/src/mermaid.ts b/packages/mermaid/src/mermaid.ts
index 7a4d744e43..6217d514e7 100644
--- a/packages/mermaid/src/mermaid.ts
+++ b/packages/mermaid/src/mermaid.ts
@@ -2,6 +2,8 @@
  * Web page integration module for the mermaid framework. It uses the mermaidAPI for mermaid
  * functionality and to render the diagrams to svg code!
  */
+import dedent from 'ts-dedent';
+
 import { MermaidConfig } from './config.type';
 import { log } from './logger';
 import utils from './utils';
@@ -148,8 +150,7 @@ const initThrowsErrors = function (
     txt = element.innerHTML;
 
     // transforms the html to pure text
-    txt = utils
-      .entityDecode(txt)
+    txt = dedent(utils.entityDecode(txt)) // removes indentation, required for YAML parsing
       .trim()
       .replace(//gi, '
'); @@ -290,8 +291,7 @@ const initThrowsErrorsAsync = async function ( txt = element.innerHTML; // transforms the html to pure text - txt = utils - .entityDecode(txt) + txt = dedent(utils.entityDecode(txt)) // removes indentation, required for YAML parsing .trim() .replace(//gi, '
'); diff --git a/packages/mermaid/src/mermaidAPI.spec.ts b/packages/mermaid/src/mermaidAPI.spec.ts index d2fd49f34b..67138435ef 100644 --- a/packages/mermaid/src/mermaidAPI.spec.ts +++ b/packages/mermaid/src/mermaidAPI.spec.ts @@ -654,6 +654,19 @@ describe('mermaidAPI', function () { expect(mermaid.parseError).toEqual(undefined); expect(() => mermaidAPI.parse('this is not a mermaid diagram definition')).toThrow(); }); + it('throws for a nicer error for a invalid definition starting with `---`', function () { + expect(mermaid.parseError).toEqual(undefined); + expect(() => + mermaidAPI.parse(` + --- + title: a malformed YAML front-matter + `) + ).toThrow( + 'Diagrams beginning with --- are not valid. ' + + 'If you were trying to use a YAML front-matter, please ensure that ' + + "you've correctly opened and closed the YAML front-matter with unindented `---` blocks" + ); + }); it('does not throw for a valid definition', function () { expect(() => mermaidAPI.parse('graph TD;A--x|text including URL space|B;')).not.toThrow(); }); diff --git a/packages/mermaid/src/utils.spec.js b/packages/mermaid/src/utils.spec.js index e9a9fc7dcd..7ee6aa000c 100644 --- a/packages/mermaid/src/utils.spec.js +++ b/packages/mermaid/src/utils.spec.js @@ -239,9 +239,9 @@ Alice->Bob: hi`; const type = detectType(str); expect(type).toBe('gitGraph'); }); - it('should not allow frontmatter with leading spaces', function () { + it('should handle malformed frontmatter (with leading spaces) with `---` error graphtype', function () { const str = ' ---\ntitle: foo\n---\n gitGraph TB:\nbfs1:queue'; - expect(() => detectType(str)).toThrow('No diagram type detected for text'); + expect(detectType(str)).toBe('---'); }); }); describe('when finding substring in array ', function () { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 79fa35c732..ed90f56cd6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -193,6 +193,9 @@ importers: stylis: specifier: ^4.1.2 version: 4.1.2 + ts-dedent: + specifier: ^2.2.0 + version: 2.2.0 uuid: specifier: ^9.0.0 version: 9.0.0 @@ -3751,7 +3754,7 @@ packages: /axios/0.21.4_debug@4.3.2: resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} dependencies: - follow-redirects: 1.15.2_debug@4.3.2 + follow-redirects: 1.15.2 transitivePeerDependencies: - debug dev: true @@ -6500,7 +6503,7 @@ packages: resolution: {integrity: sha512-XGozTsMPYkm+6b5QL3Z9wQcJjNYxp0CYn3U1gO7dwD6PAqU1SVWZxI9CCg3z+ml3YfqdPnrBehaBrnH2AGKbNA==} dev: true - /follow-redirects/1.15.2_debug@4.3.2: + /follow-redirects/1.15.2: resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} peerDependencies: @@ -6508,8 +6511,6 @@ packages: peerDependenciesMeta: debug: optional: true - dependencies: - debug: 4.3.2 dev: true /foreground-child/2.0.0: @@ -7044,7 +7045,7 @@ packages: engines: {node: '>=8.0.0'} dependencies: eventemitter3: 4.0.7 - follow-redirects: 1.15.2_debug@4.3.2 + follow-redirects: 1.15.2 requires-port: 1.0.0 transitivePeerDependencies: - debug @@ -10745,6 +10746,11 @@ packages: resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} dev: true + /ts-dedent/2.2.0: + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} + dev: false + /ts-node/10.9.1_cbe7ovvae6zqfnmtgctpgpys54: resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true