From 2c5d83fab3c7e0472ac9f6e51c4ece21a445af4d Mon Sep 17 00:00:00 2001 From: rhysd Date: Sun, 30 Apr 2023 00:32:40 +0900 Subject: [PATCH 01/21] Add `suppressErrorRendering` option to avoid inserting 'Syntax error' message in diagram --- packages/mermaid/src/config.type.ts | 1 + packages/mermaid/src/defaultConfig.ts | 8 ++++++++ packages/mermaid/src/mermaidAPI.ts | 5 ++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 545fdbbfb..207ca60d8 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -34,6 +34,7 @@ export interface MermaidConfig { dompurifyConfig?: DOMPurify.Config; wrap?: boolean; fontSize?: number; + suppressErrorRendering?: boolean; } // TODO: More configs needs to be moved in here diff --git a/packages/mermaid/src/defaultConfig.ts b/packages/mermaid/src/defaultConfig.ts index 9c6d6f46e..00c054358 100644 --- a/packages/mermaid/src/defaultConfig.ts +++ b/packages/mermaid/src/defaultConfig.ts @@ -152,6 +152,14 @@ const config: Partial = { */ deterministicIDSeed: undefined, + /** + * This option suppresses inserting 'Syntax error' message in diagram. This option is useful when + * you want to control how to handle syntax error in your application. + * + * Default value: false + */ + suppressErrorRendering: false, + /** The object containing configurations specific for flowcharts */ flowchart: { /** diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index 5e9d0ead6..b31378ce6 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -511,7 +511,9 @@ const render = async function ( try { await diag.renderer.draw(text, id, version, diag); } catch (e) { - errorRenderer.draw(text, id, version); + if (!config.suppressErrorRendering) { + errorRenderer.draw(text, id, version); + } throw e; } @@ -617,6 +619,7 @@ function addA11yInfo( * securityLevel: 'strict', * startOnLoad: true, * arrowMarkerAbsolute: false, + * suppressErrorRendering: false, * * er: { * diagramPadding: 20, From b4618f9ba1442d077caa7d99ae46466b40d65887 Mon Sep 17 00:00:00 2001 From: rhysd Date: Sun, 30 Apr 2023 22:29:53 +0900 Subject: [PATCH 02/21] Throw error when detecting diagram type failed and `suppressErrorRendering` is set --- packages/mermaid/src/mermaidAPI.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index b31378ce6..16421ba9b 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -476,6 +476,9 @@ const render = async function ( try { diag = await getDiagramFromText(text); } catch (error) { + if (config.suppressErrorRendering) { + throw error; + } diag = new Diagram('error'); parseEncounteredException = error; } From b09cdc0a180bc2e948bc046b9d1be793a1656eab Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Wed, 6 Sep 2023 12:59:02 +0530 Subject: [PATCH 03/21] chore: Add suppressErrorRendering to config --- packages/mermaid/src/config.type.ts | 5 +++++ packages/mermaid/src/schemas/config.schema.yaml | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 9ae4079b9..81dca5a00 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -158,6 +158,11 @@ export interface MermaidConfig { dompurifyConfig?: DOMPurifyConfiguration; wrap?: boolean; fontSize?: number; + /** + * Suppresses inserting 'Syntax error' diagram in the DOM. + * This is useful when you want to control how to handle syntax errors in your application. + * + */ suppressErrorRendering?: boolean; } /** diff --git a/packages/mermaid/src/schemas/config.schema.yaml b/packages/mermaid/src/schemas/config.schema.yaml index c0d239fb6..04aec01ef 100644 --- a/packages/mermaid/src/schemas/config.schema.yaml +++ b/packages/mermaid/src/schemas/config.schema.yaml @@ -217,6 +217,12 @@ properties: fontSize: type: number default: 16 + suppressErrorRendering: + type: boolean + default: false + description: | + Suppresses inserting 'Syntax error' diagram in the DOM. + This is useful when you want to control how to handle syntax errors in your application. $defs: # JSON Schema definition (maybe we should move these to a seperate file) BaseDiagramConfig: From 0480339272a21a397e3b16aff9b84aef38b3f4c3 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Wed, 6 Sep 2023 13:09:06 +0530 Subject: [PATCH 04/21] Add test --- .../integration/other/configuration.spec.js | 10 ++++++ cypress/platform/suppressError.html | 32 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 cypress/platform/suppressError.html diff --git a/cypress/integration/other/configuration.spec.js b/cypress/integration/other/configuration.spec.js index 7cbc5d105..5d5711459 100644 --- a/cypress/integration/other/configuration.spec.js +++ b/cypress/integration/other/configuration.spec.js @@ -126,4 +126,14 @@ describe('Configuration', () => { ); }); }); + + it('should not render error diagram if suppressErrorRendering is set', () => { + const url = 'http://localhost:9000/regression/issue-1874.html'; + cy.viewport(1440, 1024); + cy.visit(url); + cy.get('#test'); + cy.matchImageSnapshot( + 'configuration.spec-should-not-render-error-diagram-if-suppressErrorRendering-is-set' + ); + }); }); diff --git a/cypress/platform/suppressError.html b/cypress/platform/suppressError.html new file mode 100644 index 000000000..ab6cc323c --- /dev/null +++ b/cypress/platform/suppressError.html @@ -0,0 +1,32 @@ + + + + + + Mermaid Quick Test Page + + + +
+
+  flowchart
+      a[This should be visible]
+    
+
+  flowchart
+    a --< b
+    
+
+  flowchart
+      a[This should be visible, error diagram should not be visible above this]
+    
+
+ + + From 65dabeaf159508c5b40a445962b3069ff14b7f56 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Wed, 6 Sep 2023 13:15:04 +0530 Subject: [PATCH 05/21] Add test --- .../integration/other/configuration.spec.js | 28 +++++++++++++------ cypress/platform/suppressError.html | 6 ++-- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/cypress/integration/other/configuration.spec.js b/cypress/integration/other/configuration.spec.js index 5d5711459..51cbb0da5 100644 --- a/cypress/integration/other/configuration.spec.js +++ b/cypress/integration/other/configuration.spec.js @@ -127,13 +127,25 @@ describe('Configuration', () => { }); }); - it('should not render error diagram if suppressErrorRendering is set', () => { - const url = 'http://localhost:9000/regression/issue-1874.html'; - cy.viewport(1440, 1024); - cy.visit(url); - cy.get('#test'); - cy.matchImageSnapshot( - 'configuration.spec-should-not-render-error-diagram-if-suppressErrorRendering-is-set' - ); + describe('suppressErrorRendering', () => { + it('should not render error diagram if suppressErrorRendering is set', () => { + const url = 'http://localhost:9000/suppressError.html?suppressErrorRendering=true'; + cy.viewport(1440, 1024); + cy.visit(url); + cy.get('#test'); + cy.matchImageSnapshot( + 'configuration.spec-should-not-render-error-diagram-if-suppressErrorRendering-is-set' + ); + }); + + it('should render error diagram if suppressErrorRendering is not set', () => { + const url = 'http://localhost:9000/suppressError.html'; + cy.viewport(1440, 1024); + cy.visit(url); + cy.get('#test'); + cy.matchImageSnapshot( + 'configuration.spec-should-render-error-diagram-if-suppressErrorRendering-is-not-set' + ); + }); }); }); diff --git a/cypress/platform/suppressError.html b/cypress/platform/suppressError.html index ab6cc323c..bfaf76ed2 100644 --- a/cypress/platform/suppressError.html +++ b/cypress/platform/suppressError.html @@ -20,13 +20,15 @@ >
   flowchart
-      a[This should be visible, error diagram should not be visible above this]
+      a[This should be visible]
     
From 8b8b828cd1504adf80db8da0afefa0e71e037f3a Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Wed, 6 Sep 2023 13:19:08 +0530 Subject: [PATCH 06/21] docs: Rebuild --- docs/config/setup/modules/mermaidAPI.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/config/setup/modules/mermaidAPI.md b/docs/config/setup/modules/mermaidAPI.md index d5d4a1cbc..ae5a7dd36 100644 --- a/docs/config/setup/modules/mermaidAPI.md +++ b/docs/config/setup/modules/mermaidAPI.md @@ -42,6 +42,7 @@ const config = { securityLevel: 'strict', startOnLoad: true, arrowMarkerAbsolute: false, + suppressErrorRendering: false, er: { diagramPadding: 20, @@ -96,7 +97,7 @@ mermaid.initialize(config); #### Defined in -[mermaidAPI.ts:673](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L673) +[mermaidAPI.ts:679](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L679) ## Functions From 16c12a42c7892eb268e4afdc9e9cf589ce9138a4 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Thu, 14 Sep 2023 23:32:35 +0530 Subject: [PATCH 07/21] fix: Remove blank SVG --- docs/config/setup/modules/mermaidAPI.md | 2 +- packages/mermaid/src/mermaidAPI.ts | 26 +++++++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/docs/config/setup/modules/mermaidAPI.md b/docs/config/setup/modules/mermaidAPI.md index ae5a7dd36..25d2d6333 100644 --- a/docs/config/setup/modules/mermaidAPI.md +++ b/docs/config/setup/modules/mermaidAPI.md @@ -97,7 +97,7 @@ mermaid.initialize(config); #### Defined in -[mermaidAPI.ts:679](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L679) +[mermaidAPI.ts:685](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L685) ## Functions diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index e9ec3eca1..6a6b97735 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -420,6 +420,16 @@ const render = async function ( const enclosingDivID = 'd' + id; const enclosingDivID_selector = '#' + enclosingDivID; + const removeTempElements = () => { + // ------------------------------------------------------------------------------- + // Remove the temporary HTML element if appropriate + const tmpElementSelector = isSandboxed ? iFrameID_selector : enclosingDivID_selector; + const node = select(tmpElementSelector).node(); + if (node && 'remove' in node) { + node.remove(); + } + }; + let root: any = select('body'); const isSandboxed = config.securityLevel === SECURITY_LVL_SANDBOX; @@ -479,6 +489,7 @@ const render = async function ( diag = await getDiagramFromText(text); } catch (error) { if (config.suppressErrorRendering) { + removeTempElements(); throw error; } diag = new Diagram('error'); @@ -510,10 +521,11 @@ const render = async function ( try { await diag.renderer.draw(text, id, version, diag); } catch (e) { - if (!config.suppressErrorRendering) { - errorRenderer.draw(text, id, version); + if (config.suppressErrorRendering) { + removeTempElements(); + throw e; } - throw e; + errorRenderer.draw(text, id, version); } // This is the d3 node for the svg element @@ -549,13 +561,7 @@ const render = async function ( throw parseEncounteredException; } - // ------------------------------------------------------------------------------- - // Remove the temporary HTML element if appropriate - const tmpElementSelector = isSandboxed ? iFrameID_selector : enclosingDivID_selector; - const node = select(tmpElementSelector).node(); - if (node && 'remove' in node) { - node.remove(); - } + removeTempElements(); return { svg: svgCode, From 5f41b65af1bcc3f25645e32c3f722b914b425158 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Fri, 15 Sep 2023 08:41:12 +0530 Subject: [PATCH 08/21] chore: Add suppressErrorRendering to secure flags. Co-authored-by: Alois Klink --- cypress/platform/suppressError.html | 18 ++++++++++++++++++ .../mermaid/src/schemas/config.schema.yaml | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/cypress/platform/suppressError.html b/cypress/platform/suppressError.html index bfaf76ed2..19e8da22d 100644 --- a/cypress/platform/suppressError.html +++ b/cypress/platform/suppressError.html @@ -21,6 +21,24 @@
   flowchart
       a[This should be visible]
+    
+
+  ---
+  config:
+    suppressErrorRendering: true # This should not affect anything, as suppressErrorRendering is a secure config
+  ---
+  flowchart
+    a --< b
+    
+
+  ---
+  config:
+    suppressErrorRendering: false # This should not affect anything, as suppressErrorRendering is a secure config
+  ---
+  flowchart
+    a --< b
     
diff --git a/packages/mermaid/src/schemas/config.schema.yaml b/packages/mermaid/src/schemas/config.schema.yaml index 9f396e2b6..edda2feb1 100644 --- a/packages/mermaid/src/schemas/config.schema.yaml +++ b/packages/mermaid/src/schemas/config.schema.yaml @@ -155,7 +155,7 @@ properties: in the current `currentConfig`. This prevents malicious graph directives from overriding a site's default security. - default: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'] + default: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize', 'suppressErrorRendering'] type: array items: type: string From bd1e7a7c1322abaf1f74b3c40ab55dedb2e4d084 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Fri, 15 Sep 2023 08:42:12 +0530 Subject: [PATCH 09/21] fix: Retain default behavior when rendering errors cases Co-authored-by: Alois Klink --- docs/config/setup/modules/mermaidAPI.md | 2 +- packages/mermaid/src/mermaidAPI.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/config/setup/modules/mermaidAPI.md b/docs/config/setup/modules/mermaidAPI.md index 8cb03980d..e82327371 100644 --- a/docs/config/setup/modules/mermaidAPI.md +++ b/docs/config/setup/modules/mermaidAPI.md @@ -97,7 +97,7 @@ mermaid.initialize(config); #### Defined in -[mermaidAPI.ts:653](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L653) +[mermaidAPI.ts:654](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L654) ## Functions diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index 8eea34d88..a765abd52 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -491,9 +491,10 @@ const render = async function ( } catch (e) { if (config.suppressErrorRendering) { removeTempElements(); - throw e; + } else { + errorRenderer.draw(text, id, version); } - errorRenderer.draw(text, id, version); + throw e; } // This is the d3 node for the svg element From 56d339b8f0eadd77a7c951dcbbb132d02252985d Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Sat, 16 Sep 2023 13:33:28 +0530 Subject: [PATCH 10/21] fix: Race condition when running suppressError test. Co-authored-by: Alois Klink --- cypress/integration/other/configuration.spec.js | 13 ++++++++++++- cypress/platform/suppressError.html | 6 +++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cypress/integration/other/configuration.spec.js b/cypress/integration/other/configuration.spec.js index 51cbb0da5..3b6e12cf2 100644 --- a/cypress/integration/other/configuration.spec.js +++ b/cypress/integration/other/configuration.spec.js @@ -132,7 +132,17 @@ describe('Configuration', () => { const url = 'http://localhost:9000/suppressError.html?suppressErrorRendering=true'; cy.viewport(1440, 1024); cy.visit(url); - cy.get('#test'); + cy.window().should('have.property', 'rendered', true); + cy.get('#test') + .find('svg') + .should(($svg) => { + expect($svg).to.have.length(2); // all failing diagrams should not appear! + $svg.each((_index, svg) => { + expect(cy.$$(svg)).to.be.visible(); + // none of the diagrams should be error diagrams + expect($svg).to.not.contain('Syntax error'); + }); + }); cy.matchImageSnapshot( 'configuration.spec-should-not-render-error-diagram-if-suppressErrorRendering-is-set' ); @@ -142,6 +152,7 @@ describe('Configuration', () => { const url = 'http://localhost:9000/suppressError.html'; cy.viewport(1440, 1024); cy.visit(url); + cy.window().should('have.property', 'rendered', true); cy.get('#test'); cy.matchImageSnapshot( 'configuration.spec-should-render-error-diagram-if-suppressErrorRendering-is-not-set' diff --git a/cypress/platform/suppressError.html b/cypress/platform/suppressError.html index 19e8da22d..02591ce70 100644 --- a/cypress/platform/suppressError.html +++ b/cypress/platform/suppressError.html @@ -46,7 +46,11 @@ import mermaid from './mermaid.esm.mjs'; const shouldSuppress = new URLSearchParams(window.location.search).get('suppressErrorRendering') === 'true'; - mermaid.initialize({ startOnLoad: true, suppressErrorRendering: shouldSuppress }); + mermaid.initialize({ startOnLoad: false, suppressErrorRendering: shouldSuppress }); + await mermaid.run(); + if (window.Cypress) { + window.rendered = true; + } From 577f0ca5629af574712944d68be49ae5d901f970 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Sat, 16 Sep 2023 13:54:43 +0530 Subject: [PATCH 11/21] fix: Cypress test for Suppress Error --- .../integration/other/configuration.spec.js | 28 +++++++++++++------ cypress/platform/suppressError.html | 9 ++++-- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/cypress/integration/other/configuration.spec.js b/cypress/integration/other/configuration.spec.js index 3b6e12cf2..7f47b57e8 100644 --- a/cypress/integration/other/configuration.spec.js +++ b/cypress/integration/other/configuration.spec.js @@ -128,20 +128,24 @@ describe('Configuration', () => { }); describe('suppressErrorRendering', () => { + beforeEach(() => { + cy.on('uncaught:exception', (err, runnable) => { + return !err.message.includes('Parse error on line'); + }); + cy.viewport(1440, 1024); + }); + it('should not render error diagram if suppressErrorRendering is set', () => { const url = 'http://localhost:9000/suppressError.html?suppressErrorRendering=true'; - cy.viewport(1440, 1024); cy.visit(url); cy.window().should('have.property', 'rendered', true); cy.get('#test') .find('svg') .should(($svg) => { - expect($svg).to.have.length(2); // all failing diagrams should not appear! - $svg.each((_index, svg) => { - expect(cy.$$(svg)).to.be.visible(); - // none of the diagrams should be error diagrams - expect($svg).to.not.contain('Syntax error'); - }); + // all failing diagrams should not appear! + expect($svg).to.have.length(2); + // none of the diagrams should be error diagrams + expect($svg).to.not.contain('Syntax error'); }); cy.matchImageSnapshot( 'configuration.spec-should-not-render-error-diagram-if-suppressErrorRendering-is-set' @@ -150,10 +154,16 @@ describe('Configuration', () => { it('should render error diagram if suppressErrorRendering is not set', () => { const url = 'http://localhost:9000/suppressError.html'; - cy.viewport(1440, 1024); cy.visit(url); cy.window().should('have.property', 'rendered', true); - cy.get('#test'); + cy.get('#test') + .find('svg') + .should(($svg) => { + // all five diagrams should be rendered + expect($svg).to.have.length(5); + // some of the diagrams should be error diagrams + expect($svg).to.contain('Syntax error'); + }); cy.matchImageSnapshot( 'configuration.spec-should-render-error-diagram-if-suppressErrorRendering-is-not-set' ); diff --git a/cypress/platform/suppressError.html b/cypress/platform/suppressError.html index 02591ce70..347a82c79 100644 --- a/cypress/platform/suppressError.html +++ b/cypress/platform/suppressError.html @@ -47,9 +47,12 @@ const shouldSuppress = new URLSearchParams(window.location.search).get('suppressErrorRendering') === 'true'; mermaid.initialize({ startOnLoad: false, suppressErrorRendering: shouldSuppress }); - await mermaid.run(); - if (window.Cypress) { - window.rendered = true; + try { + await mermaid.run(); + } catch { + if (window.Cypress) { + window.rendered = true; + } } From 42561775319b1fc7393086976968cf4e3251f10f Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Fri, 26 Jan 2024 23:07:13 +0530 Subject: [PATCH 12/21] chore: Remove cy.viewport --- cypress/integration/other/configuration.spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/cypress/integration/other/configuration.spec.js b/cypress/integration/other/configuration.spec.js index b67782786..9fd081567 100644 --- a/cypress/integration/other/configuration.spec.js +++ b/cypress/integration/other/configuration.spec.js @@ -131,7 +131,6 @@ describe('Configuration', () => { cy.on('uncaught:exception', (err, runnable) => { return !err.message.includes('Parse error on line'); }); - cy.viewport(1440, 1024); }); it('should not render error diagram if suppressErrorRendering is set', () => { From f135a3a5e73d672e2d3f386bfffc0c8f6609c755 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Sat, 23 Mar 2024 15:07:21 +0530 Subject: [PATCH 13/21] chore: Add example page link in index --- demos/dev/example.html | 2 ++ demos/index.html | 1 + 2 files changed, 3 insertions(+) diff --git a/demos/dev/example.html b/demos/dev/example.html index 4ece7efa8..27d31e177 100644 --- a/demos/dev/example.html +++ b/demos/dev/example.html @@ -39,6 +39,8 @@ graph TB