diff --git a/.changeset/giant-steaks-argue.md b/.changeset/giant-steaks-argue.md deleted file mode 100644 index 0abefe3fc..000000000 --- a/.changeset/giant-steaks-argue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': minor ---- - -feat: Return parsed config from mermaid.parse diff --git a/.changeset/red-beans-cross.md b/.changeset/red-beans-cross.md deleted file mode 100644 index 3337d1189..000000000 --- a/.changeset/red-beans-cross.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': patch ---- - -fix: Replace $root with relative paths diff --git a/.changeset/rude-meals-invite.md b/.changeset/rude-meals-invite.md new file mode 100644 index 000000000..8d43692f8 --- /dev/null +++ b/.changeset/rude-meals-invite.md @@ -0,0 +1,5 @@ +--- +'mermaid': minor +--- + +New Flowchart Shapes (with new syntax) diff --git a/.changeset/slow-goats-act.md b/.changeset/slow-goats-act.md new file mode 100644 index 000000000..a21565ec3 --- /dev/null +++ b/.changeset/slow-goats-act.md @@ -0,0 +1,5 @@ +--- +'@mermaid-js/layout-elk': patch +--- + +chore: fix render types diff --git a/cypress/integration/rendering/flowchart-shape-alias.spec.ts b/cypress/integration/rendering/flowchart-shape-alias.spec.ts new file mode 100644 index 000000000..3e6d9092d --- /dev/null +++ b/cypress/integration/rendering/flowchart-shape-alias.spec.ts @@ -0,0 +1,134 @@ +import { imgSnapshotTest } from '../../helpers/util.ts'; + +const aliasSet1 = ['process', 'rect', 'proc', 'rectangle'] as const; + +const aliasSet2 = ['event', 'rounded'] as const; + +const aliasSet3 = ['stadium', 'pill', 'term'] as const; + +const aliasSet4 = ['fr', 'subproc', 'framed-rectangle', 'subroutine'] as const; + +const aliasSet5 = ['db', 'cylinder', 'cyl'] as const; + +const aliasSet6 = ['diam', 'decision', 'diamond'] as const; + +const aliasSet7 = ['hex', 'hexagon', 'prepare'] as const; + +const aliasSet8 = ['l-r', 'lean-right', 'in-out'] as const; + +const aliasSet9 = ['l-l', 'lean-left', 'out-in'] as const; + +const aliasSet10 = ['trap-b', 'trapezoid-bottom', 'priority', 'trapezoid'] as const; + +const aliasSet11 = ['trap-t', 'trapezoid-top', 'manual', 'inv-trapezoid'] as const; + +const aliasSet12 = ['dc', 'double-circle'] as const; + +const aliasSet13 = ['notched-rect', 'card', 'notch-rect'] as const; + +const aliasSet14 = ['lined-rect', 'lined-proc', 'shaded-proc'] as const; + +const aliasSet15 = ['sm-circ', 'small-circle', 'start'] as const; + +const aliasSet16 = ['framed-circle', 'stop'] as const; + +const aliasSet17 = ['fork', 'join', 'long-rect'] as const; + +const aliasSet18 = ['brace', 'comment', 'brace-l'] as const; + +const aliasSet19 = ['bolt', 'com-link', 'lightning-bolt'] as const; + +const aliasSet20 = ['we-rect', 'doc', 'wave-edge-rect', 'wave-edged-rectangle'] as const; + +const aliasSet21 = ['delay', 'half-rounded-rect'] as const; + +const aliasSet22 = ['t-cyl', 'das', 'tilted-cylinder'] as const; + +const aliasSet23 = ['l-cyl', 'disk', 'lined-cylinder'] as const; + +const aliasSet24 = ['cur-trap', 'disp', 'display', 'curved-trapezoid'] as const; + +const aliasSet25 = ['div-rect', 'div-proc', 'divided-rectangle'] as const; + +const aliasSet26 = ['sm-tri', 'extract', 'small-triangle', 'triangle'] as const; + +const aliasSet27 = ['win-pane', 'internal-storage', 'window-pane'] as const; + +const aliasSet28 = ['fc', 'junction', 'filled-circle'] as const; + +const aliasSet29 = ['lin-we-rect', 'lin-doc', 'lined-wave-edged-rect'] as const; + +const aliasSet30 = ['notch-pent', 'loop-limit', 'notched-pentagon'] as const; + +const aliasSet31 = ['flip-tri', 'manual-file', 'flipped-triangle'] as const; + +const aliasSet32 = ['sloped-rect', 'manual-input', 'sloped-rectangle'] as const; + +const aliasSet33 = ['mul-we-rect', 'mul-doc', 'multi-wave-edged-rectangle'] as const; + +const aliasSet34 = ['mul-rect', 'mul-proc', 'multi-rect'] as const; + +const aliasSet35 = ['flag', 'paper-tape'] as const; + +const aliasSet36 = ['bt-rect', 'stored-data', 'bow-tie-rect'] as const; + +const aliasSet37 = ['cross-circle', 'summary', 'crossed-circle'] as const; + +const aliasSet38 = ['tag-we-rect', 'tag-doc', 'tagged-wave-edged-rectangle'] as const; + +const aliasSet39 = ['tag-rect', 'tag-proc', 'tagged-rect'] as const; + +// Aggregate all alias sets into a single array +const aliasSets = [ + aliasSet1, + aliasSet2, + aliasSet3, + aliasSet4, + aliasSet5, + aliasSet6, + aliasSet7, + aliasSet8, + aliasSet9, + aliasSet10, + aliasSet11, + aliasSet12, + aliasSet13, + aliasSet14, + aliasSet15, + aliasSet16, + aliasSet17, + aliasSet18, + aliasSet19, + aliasSet20, + aliasSet21, + aliasSet22, + aliasSet23, + aliasSet24, + aliasSet25, + aliasSet26, + aliasSet27, + aliasSet28, + aliasSet29, + aliasSet30, + aliasSet31, + aliasSet32, + aliasSet33, + aliasSet34, + aliasSet35, + aliasSet36, + aliasSet37, + aliasSet38, + aliasSet39, +] as const; + +aliasSets.forEach((aliasSet) => { + describe(`Test ${aliasSet.join(',')} `, () => { + it(`All ${aliasSet.join(',')} should render same shape`, () => { + let flowchartCode = `flowchart \n`; + aliasSet.forEach((alias, index) => { + flowchartCode += ` n${index}@{ shape: ${alias}, label: "${alias}" }@\n`; + }); + imgSnapshotTest(flowchartCode); + }); + }); +}); diff --git a/cypress/integration/rendering/iconShape.spec.ts b/cypress/integration/rendering/iconShape.spec.ts new file mode 100644 index 000000000..9a01932fb --- /dev/null +++ b/cypress/integration/rendering/iconShape.spec.ts @@ -0,0 +1,121 @@ +import { imgSnapshotTest } from '../../helpers/util'; + +const looks = ['classic', 'handDrawn'] as const; +const directions = ['TB', 'BT', 'LR', 'RL'] as const; +const forms = [undefined, 'square', 'circle', 'rounded'] as const; +const labelPos = [undefined, 't', 'b'] as const; + +looks.forEach((look) => { + directions.forEach((direction) => { + forms.forEach((form) => { + labelPos.forEach((pos) => { + describe(`Test iconShape in ${form ? `${form} form,` : ''} ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => { + it(`without label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is a label for icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with very long label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is a very very very very very long long long label for icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:true`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold** and strong for icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:false`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold** and strong for icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { + look, + htmlLabels: false, + flowchart: { htmlLabels: false }, + }); + }); + + it(`with styles`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + flowchartCode += ` style nAA fill:#f9f,stroke:#333,stroke-width:4px \n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with classDef`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + flowchartCode += ` nAA:::customClazz\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + }); + }); + }); + }); +}); + +describe('Test iconShape with different h', () => { + it('with different h', () => { + let flowchartCode = `flowchart TB\n`; + const icon = 'fa:bell'; + const iconHeight = 64; + flowchartCode += ` nA --> nAA@{ icon: '${icon}', label: 'icon with different h', h: ${iconHeight} }@\n`; + imgSnapshotTest(flowchartCode); + }); +}); diff --git a/cypress/integration/rendering/imageShape.spec.ts b/cypress/integration/rendering/imageShape.spec.ts new file mode 100644 index 000000000..5f6d972cb --- /dev/null +++ b/cypress/integration/rendering/imageShape.spec.ts @@ -0,0 +1,98 @@ +import { imgSnapshotTest } from '../../helpers/util'; + +const looks = ['classic', 'handDrawn'] as const; +const directions = ['TB', 'BT', 'LR', 'RL'] as const; +const labelPos = [undefined, 't', 'b'] as const; + +looks.forEach((look) => { + directions.forEach((direction) => { + labelPos.forEach((pos) => { + describe(`Test imageShape in ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => { + it(`without label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', w: '100', h: '100' }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a label for image shape'`; + + flowchartCode += `, w: '100', h: '200'`; + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with very long label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a very very very very very long long long label for image shape'`; + + flowchartCode += `, w: '100', h: '250'`; + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:true`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold** and strong for image shape'`; + + flowchartCode += `, w: '550', h: '200'`; + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look, htmlLabels: true }); + }); + + it(`with markdown htmlLabels:false`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold** and strong for image shape'`; + flowchartCode += `, w: '250', h: '200'`; + + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { + look, + htmlLabels: false, + flowchart: { htmlLabels: false }, + }); + }); + + it(`with styles`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`; + flowchartCode += `, w: '550', h: '200'`; + + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + flowchartCode += ` style A fill:#f9f,stroke:#333,stroke-width:4px \n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with classDef`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#000000,stroke-dasharray: 5 5\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`; + + flowchartCode += `, w: '500', h: '550'`; + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + flowchartCode += ` A:::customClazz\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + }); + }); + }); +}); diff --git a/cypress/integration/rendering/newShapes.spec.ts b/cypress/integration/rendering/newShapes.spec.ts index 4e382f829..906a04da3 100644 --- a/cypress/integration/rendering/newShapes.spec.ts +++ b/cypress/integration/rendering/newShapes.spec.ts @@ -4,45 +4,53 @@ const looks = ['classic'] as const; const directions = ['TB'] as const; const newShapesSet1 = [ 'triangle', - 'slopedRect', - 'tiltedCylinder', - 'flippedTriangle', + 'sloped-rect', + 'tilted-cylinder', + 'flipped-triangle', 'hourglass', ] as const; const newShapesSet2 = [ - 'taggedRect', - 'multiRect', - 'lightningBolt', - 'filledCircle', - 'windowPane', + 'tagged-rect', + 'multi-rect', + 'lightning-bolt', + 'filled-circle', + 'window-pane', ] as const; const newShapesSet3 = [ - 'curvedTrapezoid', - 'bowTieRect', - 'waveEdgedRectangle', - 'dividedRectangle', - 'crossedCircle', + 'curved-trapezoid', + 'bow-tie-rect', + 'wave-edge-rect', + 'divided-rectangle', + 'crossed-circle', ] as const; const newShapesSet4 = [ - 'waveRectangle', - 'trapezoidalPentagon', - 'linedCylinder', - 'multiWaveEdgedRectangle', - 'halfRoundedRectangle', + 'wave-rectangle', + 'notched-pentagon', + 'lined-cylinder', + 'multi-wave-edged-rectangle', + 'half-rounded-rect', ] as const; const newShapesSet5 = [ - 'linedWaveEdgedRect', - 'taggedWaveEdgedRectangle', - 'curlyBraceLeft', - 'curvedTrapezoid', - 'waveRectangle', + 'lined-wave-edged-rect', + 'tagged-wave-edged-rectangle', + 'brace-l', + 'curved-trapezoid', + 'wave-rectangle', ] as const; +const newShapesSet6 = ['brace-r', 'braces'] as const; // Aggregate all shape sets into a single array -const newShapesSets = [newShapesSet2] as const; +const newShapesSets = [ + newShapesSet1, + newShapesSet2, + newShapesSet3, + newShapesSet4, + newShapesSet5, + newShapesSet6, +]; looks.forEach((look) => { directions.forEach((direction) => { diff --git a/cypress/platform/knsv-pos.html b/cypress/platform/knsv-pos.html index a39b2fd2d..34499a958 100644 --- a/cypress/platform/knsv-pos.html +++ b/cypress/platform/knsv-pos.html @@ -119,30 +119,24 @@ A S --> T: angrepp - T --> U: Apa - T --> V: Varg + T --> U + T --> V C D E `; - // code = ` - // stateDiagram - // A0 - // state subbe { - // subState - // B - // } - // C - // D - // E - // `; + code = ` + stateDiagram + T --> U + T --> V + `; let positions = { nodes: { S: { x: 0, y: 0 }, T: { x: 100, y: 100, width: 100, height: 100 }, - U: { x: 250, y: 160 }, + U: { x: 250, y: 260 }, V: { x: 300, y: 120 }, Z: { x: 300, y: 10, width: 160, height: 100 }, X: { x: 300, y: 20, width: 80, height: 60 }, @@ -167,7 +161,7 @@ { x: 150, y: 120 }, { x: 190.19453144073486, y: 120 }, { x: 190.19453144073486, y: 152.1556251525879 }, - { x: 230.38906288146973, y: 152.1556251525879 }, + { x: 250, y: 152.1556251525879 }, { x: 250, y: 160 }, ], }, @@ -182,11 +176,55 @@ }, }; - // positions = { - // nodes: {}, - // edges: {}, - // }; + positions = { + nodes: { + T: { + x: 37.964874267578125, + y: 24.99908971786499, + width: 38.10995101928711, + height: 25.998868942260742, + }, + U: { + x: 31.61321258544922, + y: 85.99644947052002, + width: 39.22151184082031, + height: 25.998876571655273, + }, + V: { + x: 105.83320808410645, + y: 85.99644947052002, + width: 39.22149658203125, + height: 25.998876571655273, + }, + }, + edges: { + edge0: { + points: [ + // { x: 37.61160659790039, y: 24 }, + { x: 31.61160659790039, y: 38 }, + { x: 31.61160659790039, y: 55.5 }, + { x: 31.61160659790039, y: 73 }, + ], + }, + edge1: { + points: [ + // { x: 37.61160659790039, y: 24 }, + { x: 44.31547546386719, y: 38 }, + { x: 44.31547546386719, y: 51.5 }, + { x: 45.487048339120996, y: 54.32842712474619 }, + { x: 48.31547546386719, y: 55.5 }, + { x: 101.83481979370117, y: 55.5 }, + { x: 104.66324691844736, y: 56.67157287525381 }, + { x: 105.83481979370117, y: 59.5 }, + { x: 105.83481979370117, y: 66.25 }, + { x: 105.83481979370117, y: 73 }, + ], + }, + }, + }; + + // console.log('positions:', positions); const { svg } = await mermaid.render('the-id-of-the-svg', code, undefined, positions); if (window?.calcIntersections) { console.log( diff --git a/cypress/platform/knsv-reset.html b/cypress/platform/knsv-reset.html new file mode 100644 index 000000000..a9e653da0 --- /dev/null +++ b/cypress/platform/knsv-reset.html @@ -0,0 +1,306 @@ + +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index a31e90611..1cd3282da 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -338,6 +338,39 @@ flowchart TD ++--- + title: hello2 + config: + look: neo + layout: dagre + elk: + nodePlacementStrategy: BRANDES_KOEPF +--- +flowchart + S + T + U + subgraph Z + subgraph X + Y[Ypsilon] + end + end + subgraph Q + Q1[Quintus] + end + A + + S -- angrepp --> T + T -- Apa --> U + T -- Varge --> V + C + D + E + + +
--- title: hello2 @@ -394,7 +427,7 @@ flowchart LR-
+flowchart TB c1-->a2 subgraph one @@ -432,7 +465,10 @@ flowchart TB window.callback = function () { alert('A callback was triggered'); }; - mermaid.initialize({ + function callback() { + alert('It worked'); + } + await mermaid.initialize({ // theme: 'base', // handDrawnSeed: 12, // look: 'handDrawn', @@ -455,10 +491,9 @@ flowchart TB fontSize: 12, logLevel: 3, securityLevel: 'loose', + callback, }); - function callback() { - alert('It worked'); - } + mermaid.parseError = function (err, hash) { console.error('In parse error:'); console.error(err); diff --git a/cypress/platform/saurabh.html b/cypress/platform/saurabh.html index aaa2bbc71..76c635084 100644 --- a/cypress/platform/saurabh.html +++ b/cypress/platform/saurabh.html @@ -1,54 +1,40 @@ - - - - - - - - - - - - - + } + + - --flowchart -A - B@{ shape: multiRect, label: "title aduwab whgdawhbd wajhdbawj" }@ - F@{ shape: multiRect, label: "title " }@ - G@{ shape: multiRect, label: "title \n duawd \n duawd \n duawd \n duawd" }@ - C - D - E - C -->B - B --> D - B --> E - F --> A - A --> F -+ ++ flowchart TD + B2@{ icon: "fa:bell", form: "square", label: "B2 agsyua duadu", pos: "t", h: 80 }@ + - - - + W --> B2 + X --> B2 + Y --> B2 + Z --> B2 + B2 --sas--> C + + +++ flowchart TB + A --test2--> B2@{ icon: "fa:bell", form: "rounded", label: "B2 aiduaid uyawduad uaduabd uyduadb", pos: "b" }@ + B2 --test--> C + D --> B2 --> E + style B2 fill:#f9f,stroke:#333,stroke-width:4px +++ flowchart BT + A --test2--> B2@{ icon: "fa:bell", form: "square", label: "B2", pos: "t", h: 40, w: 30 }@ + B2 --test--> C + D --> B2 --> E +++ flowchart BT + A --test2--> B2@{ icon: "fa:bell", label: "B2 awiugdawu uydgayuiwd wuydguy", pos: "b", h: 40, w: 30 }@ + B2 --test--> C +++ flowchart BT + A --test2--> B2@{ icon: "fa:bell", label: "B2 dawuygd ayuwgd uy", pos: "t", h: 40, w: 30 }@ + B2 --test--> C +++ flowchart TB + A --> B2@{ icon: "fa:bell", form: "circle", label: "test augfuyfavf ydvaubfuac", pos: "t", w: 200, h: 100 }@ --> C +++ flowchart TB + A --> B2@{ icon: "fa:bell", form: "circle", label: "test augfuyfavf ydvaubfuac", pos: "b", w: 200, h: 100 }@ --> C + D --> B2 --> E ++ +