From 2dd6329872a2d509c40ff9be14aab4a48144a9e9 Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Wed, 29 Mar 2023 16:55:58 +0200 Subject: [PATCH 1/7] Define and export the Mermaid type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This represents the type of the default export. This is useful when it’s being passed around or declared as a global. --- packages/mermaid/src/mermaid.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/mermaid/src/mermaid.ts b/packages/mermaid/src/mermaid.ts index bd99877b6..4b02adb1c 100644 --- a/packages/mermaid/src/mermaid.ts +++ b/packages/mermaid/src/mermaid.ts @@ -392,7 +392,7 @@ const render = (id: string, text: string, container?: Element): Promise Date: Thu, 30 Mar 2023 22:08:50 +0530 Subject: [PATCH 2/7] fix(#4137): Cleanup comments before parsing --- docs/config/setup/modules/mermaidAPI.md | 2 +- packages/mermaid/src/Diagram.ts | 4 +- .../mermaid/src/diagram-api/comments.spec.ts | 70 +++++++++++++++++++ packages/mermaid/src/diagram-api/comments.ts | 8 +++ .../src/diagrams/er/parser/erDiagram.jison | 4 -- .../flowchart/parser/flow-comments.spec.js | 21 +++--- .../src/diagrams/flowchart/parser/flow.jison | 2 - .../diagrams/flowchart/parser/flow.spec.js | 3 +- packages/mermaid/src/mermaidAPI.ts | 3 - 9 files changed, 96 insertions(+), 21 deletions(-) create mode 100644 packages/mermaid/src/diagram-api/comments.spec.ts create mode 100644 packages/mermaid/src/diagram-api/comments.ts diff --git a/docs/config/setup/modules/mermaidAPI.md b/docs/config/setup/modules/mermaidAPI.md index b94fc8b94..4b8f57bd7 100644 --- a/docs/config/setup/modules/mermaidAPI.md +++ b/docs/config/setup/modules/mermaidAPI.md @@ -95,7 +95,7 @@ mermaid.initialize(config); #### Defined in -[mermaidAPI.ts:662](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L662) +[mermaidAPI.ts:659](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L659) ## Functions diff --git a/packages/mermaid/src/Diagram.ts b/packages/mermaid/src/Diagram.ts index 3010ce130..dd26d8de8 100644 --- a/packages/mermaid/src/Diagram.ts +++ b/packages/mermaid/src/Diagram.ts @@ -5,6 +5,7 @@ import { detectType, getDiagramLoader } from './diagram-api/detectType'; import { extractFrontMatter } from './diagram-api/frontmatter'; import { UnknownDiagramError } from './errors'; import { DetailedError } from './utils'; +import { cleanupComments } from './diagram-api/comments'; export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?: any) => void; @@ -43,7 +44,8 @@ export class Diagram { // Similarly, we can't do this in getDiagramFromText() because some code // calls diagram.db.clear(), which would reset anything set by // extractFrontMatter(). - this.parser.parse = (text: string) => originalParse(extractFrontMatter(text, this.db)); + this.parser.parse = (text: string) => + originalParse(cleanupComments(extractFrontMatter(text, this.db))); this.parser.parser.yy = this.db; if (diagram.init) { diagram.init(cnf); diff --git a/packages/mermaid/src/diagram-api/comments.spec.ts b/packages/mermaid/src/diagram-api/comments.spec.ts new file mode 100644 index 000000000..2435db0a0 --- /dev/null +++ b/packages/mermaid/src/diagram-api/comments.spec.ts @@ -0,0 +1,70 @@ +// tests to check that comments are removed + +import { cleanupComments } from './comments'; +import { describe, it, expect } from 'vitest'; + +describe('comments', () => { + it('should remove comments', () => { + const text = ` + +%% This is a comment +%% This is another comment +graph TD + A-->B +%% This is a comment +`; + expect(cleanupComments(text)).toMatchInlineSnapshot(` + " + + graph TD + A-->B + + " + `); + }); + + it('should keep init statements when removing comments', () => { + const text = ` +%% This is a comment + +%% This is another comment +%%{init: {'theme': 'forest'}}%% +%%{init: {'theme': 'space after ending'}}%% +graph TD + A-->B + + B-->C +%% This is a comment +`; + expect(cleanupComments(text)).toMatchInlineSnapshot(` + " + + %%{init: {'theme': 'forest'}}%% + %%{init: {'theme': 'space after ending'}}%% + graph TD + A-->B + + B-->C + + " + `); + }); + + it('should remove indented comments', () => { + const text = ` +%% This is a comment +graph TD + A-->B + %% This is a comment + C-->D +`; + expect(cleanupComments(text)).toMatchInlineSnapshot(` + " + graph TD + A-->B + + C-->D + " + `); + }); +}); diff --git a/packages/mermaid/src/diagram-api/comments.ts b/packages/mermaid/src/diagram-api/comments.ts new file mode 100644 index 000000000..19fafe15c --- /dev/null +++ b/packages/mermaid/src/diagram-api/comments.ts @@ -0,0 +1,8 @@ +/** + * Remove all lines starting with `%%` from the text that don't contain a `%%{` + * @param text - The text to remove comments from + * @returns cleaned text + */ +export const cleanupComments = (text: string): string => { + return text.replace(/^\s*%%(?!{)[^\n]+/gm, ''); +}; diff --git a/packages/mermaid/src/diagrams/er/parser/erDiagram.jison b/packages/mermaid/src/diagrams/er/parser/erDiagram.jison index d9f03c387..8ffa87c63 100644 --- a/packages/mermaid/src/diagrams/er/parser/erDiagram.jison +++ b/packages/mermaid/src/diagrams/er/parser/erDiagram.jison @@ -19,8 +19,6 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili ":" { this.popState(); this.begin('arg_directive'); return ':'; } \}\%\% { this.popState(); this.popState(); return 'close_directive'; } ((?:(?!\}\%\%).|\n)*) return 'arg_directive'; -\%%(?!\{)[^\n]* /* skip comments */ -[^\}]\%\%[^\n]* /* skip comments */ [\n]+ return 'NEWLINE'; \s+ /* skip whitespace */ [\s]+ return 'SPACE'; @@ -35,8 +33,6 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili [A-Za-z_][A-Za-z0-9\-_\[\]\(\)]* return 'ATTRIBUTE_WORD' \"[^"]*\" return 'COMMENT'; [\n]+ /* nothing */ -\%%(?!\{)[^\n]* /* skip comments in attribute block */ -[^\}]\%\%[^\n]* /* skip comments in attribute block */ "}" { this.popState(); return 'BLOCK_STOP'; } . return yytext[0]; diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-comments.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-comments.spec.js index 7aeed304c..cb1e4a923 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow-comments.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-comments.spec.js @@ -1,6 +1,7 @@ import flowDb from '../flowDb'; import flow from './flow'; import { setConfig } from '../../../config'; +import { cleanupComments } from '../../../diagram-api/comments'; setConfig({ securityLevel: 'strict', @@ -13,7 +14,7 @@ describe('[Comments] when parsing', () => { }); it('should handle comments', function () { - const res = flow.parser.parse('graph TD;\n%% Comment\n A-->B;'); + const res = flow.parser.parse(cleanupComments('graph TD;\n%% Comment\n A-->B;')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -28,7 +29,7 @@ describe('[Comments] when parsing', () => { }); it('should handle comments at the start', function () { - const res = flow.parser.parse('%% Comment\ngraph TD;\n A-->B;'); + const res = flow.parser.parse(cleanupComments('%% Comment\ngraph TD;\n A-->B;')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -43,7 +44,7 @@ describe('[Comments] when parsing', () => { }); it('should handle comments at the end', function () { - const res = flow.parser.parse('graph TD;\n A-->B\n %% Comment at the end\n'); + const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n %% Comment at the end\n')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -58,7 +59,7 @@ describe('[Comments] when parsing', () => { }); it('should handle comments at the end no trailing newline', function () { - const res = flow.parser.parse('graph TD;\n A-->B\n%% Comment'); + const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n%% Comment')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -73,7 +74,7 @@ describe('[Comments] when parsing', () => { }); it('should handle comments at the end many trailing newlines', function () { - const res = flow.parser.parse('graph TD;\n A-->B\n%% Comment\n\n\n'); + const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n%% Comment\n\n\n')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -88,7 +89,7 @@ describe('[Comments] when parsing', () => { }); it('should handle no trailing newlines', function () { - const res = flow.parser.parse('graph TD;\n A-->B'); + const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -103,7 +104,7 @@ describe('[Comments] when parsing', () => { }); it('should handle many trailing newlines', function () { - const res = flow.parser.parse('graph TD;\n A-->B\n\n'); + const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n\n')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -118,7 +119,7 @@ describe('[Comments] when parsing', () => { }); it('should handle a comment with blank rows in-between', function () { - const res = flow.parser.parse('graph TD;\n\n\n %% Comment\n A-->B;'); + const res = flow.parser.parse(cleanupComments('graph TD;\n\n\n %% Comment\n A-->B;')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -134,7 +135,9 @@ describe('[Comments] when parsing', () => { it('should handle a comment with mermaid flowchart code in them', function () { const res = flow.parser.parse( - 'graph TD;\n\n\n %% Test od>Odd shape]-->|Two line
edge comment|ro;\n A-->B;' + cleanupComments( + 'graph TD;\n\n\n %% Test od>Odd shape]-->|Two line
edge comment|ro;\n A-->B;' + ) ); const vert = flow.parser.yy.getVertices(); diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison index e2dad5881..0aeb30062 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison @@ -27,8 +27,6 @@ ":" { this.popState(); this.begin('arg_directive'); return ':'; } \}\%\% { this.popState(); this.popState(); return 'close_directive'; } ((?:(?!\}\%\%).|\n)*) return 'arg_directive'; -\%\%(?!\{)[^\n]* /* skip comments */ -[^\}]\%\%[^\n]* /* skip comments */ accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; } (?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; } accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; } diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js index 6b440da79..692e72f37 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js @@ -1,6 +1,7 @@ import flowDb from '../flowDb'; import flow from './flow'; import { setConfig } from '../../../config'; +import { cleanupComments } from '../../../diagram-api/comments'; setConfig({ securityLevel: 'strict', @@ -13,7 +14,7 @@ describe('parsing a flow chart', function () { }); it('should handle a trailing whitespaces after statements', function () { - const res = flow.parser.parse('graph TD;\n\n\n %% Comment\n A-->B; \n B-->C;'); + const res = flow.parser.parse(cleanupComments('graph TD;\n\n\n %% Comment\n A-->B; \n B-->C;')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index dba629477..1b440672a 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -399,9 +399,6 @@ const render = async function ( // clean up text CRLFs text = text.replace(/\r\n?/g, '\n'); // parser problems on CRLF ignore all CR and leave LF;; - // eslint-disable-next-line unicorn/better-regex - text = text.replace(/\s*%%[^{\ninit].*\n/gm, '\n'); // remove comments from text to avoid issues with parser - const idSelector = '#' + id; const iFrameID = 'i' + id; const iFrameID_selector = '#' + iFrameID; From 46ab6f46f2cdbe0993736c6b0d5bfc2415da9c89 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Thu, 30 Mar 2023 23:09:46 +0530 Subject: [PATCH 3/7] fix(#4256): Keep error diagram on screen --- .../integration/rendering/erDiagram.spec.js | 16 -------- .../rendering/errorDiagram.spec.js | 36 ++++++++++++++++++ demos/error.html | 38 +++++++++++++++++++ .../src/diagram-api/diagram-orchestration.ts | 6 ++- .../src/diagrams/error/errorDetector.ts | 20 ---------- .../src/diagrams/error/errorDiagram.ts | 2 + .../src/diagrams/error/errorRenderer.ts | 8 ++-- packages/mermaid/src/mermaidAPI.ts | 8 ++-- 8 files changed, 87 insertions(+), 47 deletions(-) create mode 100644 cypress/integration/rendering/errorDiagram.spec.js create mode 100644 demos/error.html delete mode 100644 packages/mermaid/src/diagrams/error/errorDetector.ts diff --git a/cypress/integration/rendering/erDiagram.spec.js b/cypress/integration/rendering/erDiagram.spec.js index df1fac0cd..faa511626 100644 --- a/cypress/integration/rendering/erDiagram.spec.js +++ b/cypress/integration/rendering/erDiagram.spec.js @@ -10,7 +10,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render an ER diagram with a recursive relationship', () => { @@ -23,7 +22,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render an ER diagram with multiple relationships between the same two entities', () => { @@ -35,7 +33,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render a cyclical ER diagram', () => { @@ -48,7 +45,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render a not-so-simple ER diagram', () => { @@ -66,7 +62,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render multiple ER diagrams', () => { @@ -85,7 +80,6 @@ describe('Entity Relationship Diagram', () => { ], { logLevel: 1 } ); - cy.get('svg'); }); it('should render an ER diagram with blank or empty labels', () => { @@ -98,7 +92,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render an ER diagrams when useMaxWidth is true (default)', () => { @@ -151,7 +144,6 @@ describe('Entity Relationship Diagram', () => { `, { er: { useMaxWidth: false } } ); - cy.get('svg'); }); it('should render entities with and without attributes', () => { @@ -164,7 +156,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render entities with generic and array attributes', () => { @@ -179,7 +170,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render entities with length in attributes type', () => { @@ -193,7 +183,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render entities and attributes with big and small entity names', () => { @@ -209,7 +198,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render entities with keys', () => { @@ -228,7 +216,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render entities with comments', () => { @@ -247,7 +234,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render entities with keys and comments', () => { @@ -267,7 +253,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render entities with aliases', () => { @@ -285,7 +270,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('1433: should render a simple ER diagram with a title', () => { diff --git a/cypress/integration/rendering/errorDiagram.spec.js b/cypress/integration/rendering/errorDiagram.spec.js new file mode 100644 index 000000000..89b8403a4 --- /dev/null +++ b/cypress/integration/rendering/errorDiagram.spec.js @@ -0,0 +1,36 @@ +import { imgSnapshotTest } from '../../helpers/util'; + +describe('Error Diagrams', () => { + it('should render a simple ER diagram', () => { + imgSnapshotTest( + ` + error + `, + { logLevel: 1 } + ); + }); + + it('should render error diagram for actual errors', () => { + imgSnapshotTest( + ` + flowchart TD + A[Christmas] --|Get money| B(Go shopping) + `, + { logLevel: 1 } + ); + }); + + it('should render error for wrong ER diagram', () => { + imgSnapshotTest( + ` + erDiagram + ATLAS-ORGANIZATION ||--|{ ATLAS-PROJECTS : "has many" + ATLAS-PROJECTS ||--|{ MONGODB-CLUSTERS : "has many" + ATLAS-PROJECTS ||--|{ ATLAS-TEAMS : "has many" + MONGODB-CLUSTERS ||..|{ + ATLAS-TEAMS ||..|{ + `, + { logLevel: 1 } + ); + }); +}); diff --git a/demos/error.html b/demos/error.html new file mode 100644 index 000000000..2d6d1b01f --- /dev/null +++ b/demos/error.html @@ -0,0 +1,38 @@ + + + + + + Error | Mermaid Quick Test Page + + + + +
+      erDiagram
+        ATLAS-ORGANIZATION ||--|{ ATLAS-PROJECTS : "has many"
+        ATLAS-PROJECTS ||--|{ MONGODB-CLUSTERS : "has many"
+        ATLAS-PROJECTS ||--|{ ATLAS-TEAMS : "has many"
+    
+
+      erDiagram
+        ATLAS-ORGANIZATION ||--|{ ATLAS-PROJECTS : "has many"
+        ATLAS-PROJECTS ||--|{ MONGODB-CLUSTERS : "has many"
+        ATLAS-PROJECTS ||--|{ ATLAS-TEAMS : "has many"
+        MONGODB-CLUSTERS ||..|{
+        ATLAS-TEAMS ||..|{
+    
+
+
+    flowchart TD
+      A[Christmas] -->|Get money| B(Go shopping)
+    
+
+    flowchart TD
+      A[Christmas] --|Get money| B(Go shopping)
+    
+ + + diff --git a/packages/mermaid/src/diagram-api/diagram-orchestration.ts b/packages/mermaid/src/diagram-api/diagram-orchestration.ts index 73bfcf084..a88a34f19 100644 --- a/packages/mermaid/src/diagram-api/diagram-orchestration.ts +++ b/packages/mermaid/src/diagram-api/diagram-orchestration.ts @@ -13,7 +13,7 @@ import classDiagramV2 from '../diagrams/class/classDetector-V2'; import state from '../diagrams/state/stateDetector'; import stateV2 from '../diagrams/state/stateDetector-V2'; import journey from '../diagrams/user-journey/journeyDetector'; -import error from '../diagrams/error/errorDetector'; +import errorDiagram from '../diagrams/error/errorDiagram'; import flowchartElk from '../diagrams/flowchart/elk/detector'; import timeline from '../diagrams/timeline/detector'; import mindmap from '../diagrams/mindmap/detector'; @@ -28,6 +28,9 @@ export const addDiagrams = () => { // This is added here to avoid race-conditions. // We could optimize the loading logic somehow. hasLoadedDiagrams = true; + registerDiagram('error', errorDiagram, (text) => { + return text.toLowerCase().trim() === 'error'; + }); registerDiagram( '---', // --- diagram type may appear if YAML front-matter is not parsed correctly @@ -57,7 +60,6 @@ export const addDiagrams = () => { ); // Ordering of detectors is important. The first one to return true will be used. registerLazyLoadedDiagrams( - error, c4, classDiagramV2, classDiagram, diff --git a/packages/mermaid/src/diagrams/error/errorDetector.ts b/packages/mermaid/src/diagrams/error/errorDetector.ts deleted file mode 100644 index 2bdcd7028..000000000 --- a/packages/mermaid/src/diagrams/error/errorDetector.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; - -const id = 'error'; - -const detector: DiagramDetector = (text) => { - return text.toLowerCase().trim() === 'error'; -}; - -const loader = async () => { - const { diagram } = await import('./errorDiagram'); - return { id, diagram }; -}; - -const plugin: ExternalDiagramDefinition = { - id, - detector, - loader, -}; - -export default plugin; diff --git a/packages/mermaid/src/diagrams/error/errorDiagram.ts b/packages/mermaid/src/diagrams/error/errorDiagram.ts index d081e1028..7b9f18c3b 100644 --- a/packages/mermaid/src/diagrams/error/errorDiagram.ts +++ b/packages/mermaid/src/diagrams/error/errorDiagram.ts @@ -19,3 +19,5 @@ export const diagram: DiagramDefinition = { // no op }, }; + +export default diagram; diff --git a/packages/mermaid/src/diagrams/error/errorRenderer.ts b/packages/mermaid/src/diagrams/error/errorRenderer.ts index 60877cb8d..046bcfdcf 100644 --- a/packages/mermaid/src/diagrams/error/errorRenderer.ts +++ b/packages/mermaid/src/diagrams/error/errorRenderer.ts @@ -4,15 +4,13 @@ import { select } from 'd3'; import { log } from '../../logger'; import { getErrorMessage } from '../../utils'; -let conf = {}; - /** * Merges the value of `conf` with the passed `cnf` * * @param cnf - Config to merge */ -export const setConf = function (cnf: any) { - conf = { ...conf, ...cnf }; +export const setConf = function () { + // no-op }; /** @@ -78,7 +76,7 @@ export const draw = (_text: string, id: string, mermaidVersion: string) => { .attr('y', 250) .attr('font-size', '150px') .style('text-anchor', 'middle') - .text('Syntax error in graph'); + .text('Syntax error in text'); g.append('text') // text label for the x axis .attr('class', 'error-text') .attr('x', 1250) diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index dba629477..520bf8b4e 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -534,6 +534,10 @@ const render = async function ( attachFunctions(); + if (parseEncounteredException) { + throw parseEncounteredException; + } + // ------------------------------------------------------------------------------- // Remove the temporary HTML element if appropriate const tmpElementSelector = isSandboxed ? iFrameID_selector : enclosingDivID_selector; @@ -542,10 +546,6 @@ const render = async function ( node.remove(); } - if (parseEncounteredException) { - throw parseEncounteredException; - } - return { svg: svgCode, bindFunctions: diag.db.bindFunctions, From 7739302ee80961f27a30d2c39d5494ca94fad54d Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Thu, 30 Mar 2023 23:28:41 +0530 Subject: [PATCH 4/7] fix uncaughexception in tests --- cypress/integration/rendering/errorDiagram.spec.js | 9 +++++++++ cypress/platform/viewer.js | 6 ++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/cypress/integration/rendering/errorDiagram.spec.js b/cypress/integration/rendering/errorDiagram.spec.js index 89b8403a4..e837565d3 100644 --- a/cypress/integration/rendering/errorDiagram.spec.js +++ b/cypress/integration/rendering/errorDiagram.spec.js @@ -1,6 +1,15 @@ import { imgSnapshotTest } from '../../helpers/util'; describe('Error Diagrams', () => { + beforeEach(() => { + cy.on('uncaught:exception', (err) => { + expect(err.message).to.include('Parse error'); + // return false to prevent the error from + // failing this test + return false; + }); + }); + it('should render a simple ER diagram', () => { imgSnapshotTest( ` diff --git a/cypress/platform/viewer.js b/cypress/platform/viewer.js index 2e1093519..99533192d 100644 --- a/cypress/platform/viewer.js +++ b/cypress/platform/viewer.js @@ -47,7 +47,6 @@ const contentLoaded = async function () { await mermaid2.registerExternalDiagrams([externalExample]); mermaid2.initialize(graphObj.mermaid); await mermaid2.run(); - markRendered(); } }; @@ -123,7 +122,6 @@ const contentLoadedApi = async function () { bindFunctions(div); } } - markRendered(); }; if (typeof document !== 'undefined') { @@ -135,10 +133,10 @@ if (typeof document !== 'undefined') { function () { if (this.location.href.match('xss.html')) { this.console.log('Using api'); - void contentLoadedApi(); + void contentLoadedApi().finally(markRendered); } else { this.console.log('Not using api'); - void contentLoaded(); + void contentLoaded().finally(markRendered); } }, false From d16894daf492acb50d028a089c50b6381d21fddf Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Fri, 31 Mar 2023 00:18:53 +0530 Subject: [PATCH 5/7] test: add space before init --- .../mermaid/src/diagram-api/comments.spec.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/mermaid/src/diagram-api/comments.spec.ts b/packages/mermaid/src/diagram-api/comments.spec.ts index 2435db0a0..4357b25c3 100644 --- a/packages/mermaid/src/diagram-api/comments.spec.ts +++ b/packages/mermaid/src/diagram-api/comments.spec.ts @@ -29,6 +29,7 @@ graph TD %% This is another comment %%{init: {'theme': 'forest'}}%% +%%{ init: {'theme': 'space before init'}}%% %%{init: {'theme': 'space after ending'}}%% graph TD A-->B @@ -37,17 +38,18 @@ graph TD %% This is a comment `; expect(cleanupComments(text)).toMatchInlineSnapshot(` - " + " - %%{init: {'theme': 'forest'}}%% - %%{init: {'theme': 'space after ending'}}%% - graph TD - A-->B + %%{init: {'theme': 'forest'}}%% + %%{ init: {'theme': 'space before init'}}%% + %%{init: {'theme': 'space after ending'}}%% + graph TD + A-->B - B-->C + B-->C - " - `); + " + `); }); it('should remove indented comments', () => { From 1945a629900c39877c4de123244c205e23509d3c Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Fri, 31 Mar 2023 00:25:33 +0530 Subject: [PATCH 6/7] fix: trimStart to text --- .../mermaid/src/diagram-api/comments.spec.ts | 22 +++++++++---------- packages/mermaid/src/diagram-api/comments.ts | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/mermaid/src/diagram-api/comments.spec.ts b/packages/mermaid/src/diagram-api/comments.spec.ts index 4357b25c3..366ba119c 100644 --- a/packages/mermaid/src/diagram-api/comments.spec.ts +++ b/packages/mermaid/src/diagram-api/comments.spec.ts @@ -14,13 +14,13 @@ graph TD %% This is a comment `; expect(cleanupComments(text)).toMatchInlineSnapshot(` - " + " - graph TD - A-->B + graph TD + A-->B - " - `); + " + `); }); it('should keep init statements when removing comments', () => { @@ -61,12 +61,12 @@ graph TD C-->D `; expect(cleanupComments(text)).toMatchInlineSnapshot(` - " - graph TD - A-->B + " + graph TD + A-->B - C-->D - " - `); + C-->D + " + `); }); }); diff --git a/packages/mermaid/src/diagram-api/comments.ts b/packages/mermaid/src/diagram-api/comments.ts index 19fafe15c..2ee6232de 100644 --- a/packages/mermaid/src/diagram-api/comments.ts +++ b/packages/mermaid/src/diagram-api/comments.ts @@ -4,5 +4,5 @@ * @returns cleaned text */ export const cleanupComments = (text: string): string => { - return text.replace(/^\s*%%(?!{)[^\n]+/gm, ''); + return text.trimStart().replace(/^\s*%%(?!{)[^\n]+/gm, ''); }; From 006da82470c59989f7ce93968e9f773d2b54d164 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Fri, 31 Mar 2023 00:35:56 +0530 Subject: [PATCH 7/7] fix: Remove comment line completely --- .../mermaid/src/diagram-api/comments.spec.ts | 44 ++++++++++++++----- packages/mermaid/src/diagram-api/comments.ts | 2 +- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/packages/mermaid/src/diagram-api/comments.spec.ts b/packages/mermaid/src/diagram-api/comments.spec.ts index 366ba119c..a2c896079 100644 --- a/packages/mermaid/src/diagram-api/comments.spec.ts +++ b/packages/mermaid/src/diagram-api/comments.spec.ts @@ -14,11 +14,8 @@ graph TD %% This is a comment `; expect(cleanupComments(text)).toMatchInlineSnapshot(` - " - - graph TD + "graph TD A-->B - " `); }); @@ -38,16 +35,13 @@ graph TD %% This is a comment `; expect(cleanupComments(text)).toMatchInlineSnapshot(` - " - - %%{init: {'theme': 'forest'}}%% + "%%{init: {'theme': 'forest'}}%% %%{ init: {'theme': 'space before init'}}%% %%{init: {'theme': 'space after ending'}}%% graph TD A-->B B-->C - " `); }); @@ -61,11 +55,39 @@ graph TD C-->D `; expect(cleanupComments(text)).toMatchInlineSnapshot(` + "graph TD + A-->B + C-->D " - graph TD - A-->B + `); + }); - C-->D + it('should remove empty newlines from start', () => { + const text = ` + + + + +%% This is a comment +graph TD + A-->B +`; + expect(cleanupComments(text)).toMatchInlineSnapshot(` + "graph TD + A-->B + " + `); + }); + + it('should remove comments at end of text with no newline', () => { + const text = ` +graph TD + A-->B +%% This is a comment`; + + expect(cleanupComments(text)).toMatchInlineSnapshot(` + "graph TD + A-->B " `); }); diff --git a/packages/mermaid/src/diagram-api/comments.ts b/packages/mermaid/src/diagram-api/comments.ts index 2ee6232de..be39b0a0f 100644 --- a/packages/mermaid/src/diagram-api/comments.ts +++ b/packages/mermaid/src/diagram-api/comments.ts @@ -4,5 +4,5 @@ * @returns cleaned text */ export const cleanupComments = (text: string): string => { - return text.trimStart().replace(/^\s*%%(?!{)[^\n]+/gm, ''); + return text.trimStart().replace(/^\s*%%(?!{)[^\n]+\n?/gm, ''); };