diff --git a/.changeset/bright-ads-exist.md b/.changeset/bright-ads-exist.md new file mode 100644 index 000000000..ef2f76f4c --- /dev/null +++ b/.changeset/bright-ads-exist.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +Fixes for consistent edge id creation & handling edge cases for animate edge feature diff --git a/.changeset/chatty-elephants-warn.md b/.changeset/chatty-elephants-warn.md new file mode 100644 index 000000000..225047ece --- /dev/null +++ b/.changeset/chatty-elephants-warn.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +Fix for issue #6195 - allowing @ signs inside node labels diff --git a/.changeset/chilly-years-cheat.md b/.changeset/chilly-years-cheat.md new file mode 100644 index 000000000..e665af75b --- /dev/null +++ b/.changeset/chilly-years-cheat.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each class diagram diff --git a/.changeset/dull-tips-cough.md b/.changeset/dull-tips-cough.md new file mode 100644 index 000000000..1f5179417 --- /dev/null +++ b/.changeset/dull-tips-cough.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: revert state db to resolve getData returning empty nodes and edges diff --git a/.changeset/great-ghosts-rule.md b/.changeset/great-ghosts-rule.md new file mode 100644 index 000000000..f11c6e2a9 --- /dev/null +++ b/.changeset/great-ghosts-rule.md @@ -0,0 +1,8 @@ +--- +'mermaid': minor +--- + +Flowchart new syntax for node metadata bugs + +- Incorrect label mapping for nodes when using `&` +- Syntax error when `}` with trailing spaces before new line diff --git a/.changeset/grumpy-cheetahs-deliver.md b/.changeset/grumpy-cheetahs-deliver.md new file mode 100644 index 000000000..fa6736d42 --- /dev/null +++ b/.changeset/grumpy-cheetahs-deliver.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +`mermaidAPI.getDiagramFromText()` now returns a new db instance on each call for state diagrams diff --git a/.changeset/heavy-moose-mix.md b/.changeset/heavy-moose-mix.md new file mode 100644 index 000000000..c02d62446 --- /dev/null +++ b/.changeset/heavy-moose-mix.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +Added versioning to StateDB and updated tests and diagrams to use it. diff --git a/.changeset/new-kiwis-listen.md b/.changeset/new-kiwis-listen.md new file mode 100644 index 000000000..24306573c --- /dev/null +++ b/.changeset/new-kiwis-listen.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each flowchart diff --git a/.changeset/stupid-dots-do.md b/.changeset/stupid-dots-do.md new file mode 100644 index 000000000..594fa9536 --- /dev/null +++ b/.changeset/stupid-dots-do.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: Gantt, Sankey and User Journey diagram are now able to pick font-family from mermaid config. diff --git a/.changeset/witty-crews-smell.md b/.changeset/witty-crews-smell.md new file mode 100644 index 000000000..4213083f2 --- /dev/null +++ b/.changeset/witty-crews-smell.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +`mermaidAPI.getDiagramFromText()` now returns a new different db for each state diagram diff --git a/.cspell/libraries.txt b/.cspell/libraries.txt index 73a2dceeb..185d284f7 100644 --- a/.cspell/libraries.txt +++ b/.cspell/libraries.txt @@ -26,6 +26,7 @@ dompurify elkjs fcose fontawesome +Forgejo Foswiki Gitea graphlib diff --git a/.github/lychee.toml b/.github/lychee.toml index 288ab054a..5070c3d50 100644 --- a/.github/lychee.toml +++ b/.github/lychee.toml @@ -47,7 +47,10 @@ exclude = [ "https://(www.)?drupal.org", # Swimm returns 404, eventhough the link is valid -"https://docs.swimm.io" +"https://docs.swimm.io", + +# Timeout +"https://huehive.co" ] # Exclude all private IPs from checking. diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index 13b913c11..7280278d2 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -42,4 +42,4 @@ jobs: working-directory: ./packages/mermaid run: pnpm run docs:build - - uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c # main + - uses: autofix-ci/action@551dded8c6cc8a1054039c8bc0b8b48c51dfc6ef # main diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 47adbdae1..4922da76f 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -28,6 +28,8 @@ env: ) || github.event.before }} + RUN_VISUAL_TEST: >- + ${{ github.repository == 'mermaid-js/mermaid' && (github.event_name != 'pull_request' || !startsWith(github.head_ref, 'renovate/')) }} jobs: cache: runs-on: ubuntu-latest @@ -43,9 +45,8 @@ jobs: node-version-file: '.node-version' - name: Cache snapshots id: cache-snapshot - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 with: - save-always: true path: ./cypress/snapshots key: ${{ runner.os }}-snapshots-${{ env.targetHash }} @@ -94,7 +95,7 @@ jobs: # These cached snapshots are downloaded, providing the reference snapshots. - name: Cache snapshots id: cache-snapshot - uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache/restore@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 with: path: ./cypress/snapshots key: ${{ runner.os }}-snapshots-${{ env.targetHash }} @@ -125,18 +126,17 @@ jobs: browser: chrome # Disable recording if we don't have an API key # e.g. if this action was run from a fork - record: ${{ secrets.CYPRESS_RECORD_KEY != '' }} + record: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY != '' }} env: - CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} - VITEST_COVERAGE: true + ARGOS_PARALLEL: ${{ env.RUN_VISUAL_TEST == 'true' }} + ARGOS_PARALLEL_TOTAL: ${{ env.RUN_VISUAL_TEST == 'true' && strategy.job-total || 1 }} + ARGOS_PARALLEL_INDEX: ${{ env.RUN_VISUAL_TEST == 'true' && matrix.containers || 1 }} CYPRESS_COMMIT: ${{ github.sha }} - ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }} - ARGOS_PARALLEL: true - ARGOS_PARALLEL_TOTAL: ${{ strategy.job-total }} - ARGOS_PARALLEL_INDEX: ${{ matrix.containers }} + CYPRESS_RECORD_KEY: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY || ''}} SPLIT: ${{ strategy.job-total }} SPLIT_INDEX: ${{ strategy.job-index }} SPLIT_FILE: 'cypress/timings.json' + VITEST_COVERAGE: true - name: Upload Coverage to Codecov uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 diff --git a/.github/workflows/link-checker.yml b/.github/workflows/link-checker.yml index 0a2b74dfe..d2f5d7744 100644 --- a/.github/workflows/link-checker.yml +++ b/.github/workflows/link-checker.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Restore lychee cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 with: path: .lycheecache key: cache-lychee-${{ github.sha }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index ce20af54d..5b4fdc342 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -26,7 +26,7 @@ jobs: results_format: sarif publish_results: true - name: Upload artifact - uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: SARIF file path: results.sarif diff --git a/README.md b/README.md index 456747132..047f8254c 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,10 @@ In our release process we rely heavily on visual regression tests using [applito +## Mermaid AI Bot + +[Mermaid](https://codeparrot.ai/oracle?owner=mermaid-js&repo=mermaid) Bot will help you understand this repository better. You can ask for code examples, installation guide, debugging help and much more. + ## Examples **The following are some examples of the diagrams, charts and graphs that can be made using Mermaid. Click here to jump into the [text syntax](https://mermaid.js.org/intro/syntax-reference.html).** @@ -253,6 +257,34 @@ pie ### Git graph [experimental - live editor] +``` +gitGraph + commit + commit + branch develop + checkout develop + commit + commit + checkout main + merge develop + commit + commit +``` + +```mermaid +gitGraph + commit + commit + branch develop + checkout develop + commit + commit + checkout main + merge develop + commit + commit +``` + ### Bar chart (using gantt chart) [docs - live editor] ``` @@ -435,7 +467,7 @@ A quick note from Knut Sveidqvist: > > _Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017._ > -> _Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!_ +> _Thank you to the ever-growing list of [contributors](https://github.com/mermaid-js/mermaid/graphs/contributors) that brought the project this far!_ --- diff --git a/README.zh-CN.md b/README.zh-CN.md index 942f54bff..a3046ab54 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -358,7 +358,7 @@ _很不幸的是,鱼与熊掌不可兼得,在这个场景下它意味着在 > _特别感谢 [d3](https://d3js.org/) 和 [dagre-d3](https://github.com/cpettitt/dagre-d3) 这两个优秀的项目,它们提供了图形布局和绘图工具库!_ > _同样感谢 [js-sequence-diagram](https://bramp.github.io/js-sequence-diagrams) 提供了时序图语法的使用。 感谢 Jessica Peter 提供了甘特图渲染的灵感。_ > _感谢 [Tyler Long](https://github.com/tylerlong) 从 2017 年四月开始成为了项目的合作者。_ > -> _感谢越来越多的 [贡献者们](https://github.com/knsv/mermaid/graphs/contributors),没有你们,就没有这个项目的今天!_ +> _感谢越来越多的 [贡献者们](https://github.com/mermaid-js/mermaid/graphs/contributors),没有你们,就没有这个项目的今天!_ --- diff --git a/cypress.config.ts b/cypress.config.ts index b0257b9b2..d077ba915 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -23,12 +23,10 @@ export default eyesPlugin( }); // copy any needed variables from process.env to config.env config.env.useAppli = process.env.USE_APPLI ? true : false; - config.env.useArgos = !!process.env.CI; + config.env.useArgos = process.env.RUN_VISUAL_TEST === 'true'; if (config.env.useArgos) { - registerArgosTask(on, config, { - token: 'fc3a35cf5200db928d65b2047861582d9444032b', - }); + registerArgosTask(on, config); } else { addMatchImageSnapshotPlugin(on, config); } diff --git a/cypress/helpers/util.ts b/cypress/helpers/util.ts index 52da4a72e..81b7036af 100644 --- a/cypress/helpers/util.ts +++ b/cypress/helpers/util.ts @@ -132,3 +132,10 @@ export const verifyScreenshot = (name: string): void => { cy.matchImageSnapshot(name); } }; + +export const verifyNumber = (value: number, expected: number, deltaPercent = 10): void => { + expect(value).to.be.within( + expected * (1 - deltaPercent / 100), + expected * (1 + deltaPercent / 100) + ); +}; diff --git a/cypress/integration/rendering/flowchart-elk.spec.js b/cypress/integration/rendering/flowchart-elk.spec.js index 38bfe6440..c31df1181 100644 --- a/cypress/integration/rendering/flowchart-elk.spec.js +++ b/cypress/integration/rendering/flowchart-elk.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; +import { imgSnapshotTest, renderGraph, verifyNumber } from '../../helpers/util.ts'; describe('Flowchart ELK', () => { it('1-elk: should render a simple flowchart', () => { @@ -109,7 +109,7 @@ describe('Flowchart ELK', () => { const style = svg.attr('style'); expect(style).to.match(/^max-width: [\d.]+px;$/); const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); - expect(maxWidthValue).to.be.within(230 * 0.95, 230 * 1.05); + verifyNumber(maxWidthValue, 380); }); }); it('8-elk: should render a flowchart when useMaxWidth is false', () => { @@ -128,7 +128,7 @@ describe('Flowchart ELK', () => { const width = parseFloat(svg.attr('width')); // use within because the absolute value can be slightly different depending on the environment ±5% // expect(height).to.be.within(446 * 0.95, 446 * 1.05); - expect(width).to.be.within(230 * 0.95, 230 * 1.05); + verifyNumber(width, 380); expect(svg).to.not.have.attr('style'); }); }); @@ -692,7 +692,7 @@ A --> B {} ); cy.get('svg').should((svg) => { - const edges = svg.querySelectorAll('.edges > path'); + const edges = svg[0].querySelectorAll('.edges > path'); edges.forEach((edge) => { expect(edge).to.have.class('flowchart-link'); }); @@ -739,7 +739,7 @@ NL\`") --"\`1o **bold**\`"--> c { flowchart: { titleTopMargin: 0 } } ); }); - it('Wrapping long text with a new line', () => { + it.skip('Wrapping long text with a new line', () => { imgSnapshotTest( `%%{init: {"flowchart": {"htmlLabels": true}} }%% flowchart-elk LR @@ -841,7 +841,7 @@ end { flowchart: { titleTopMargin: 0 } } ); }); - it('Sub graphs and markdown strings', () => { + it('Sub graphs', () => { imgSnapshotTest( `--- config: diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index 66452f4b2..4322500df 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -1076,4 +1076,41 @@ end ); }); }); + describe('New @ sytax for node metadata edge cases', () => { + it('should be possible to use @ syntax to add labels on multi nodes', () => { + imgSnapshotTest( + `flowchart TB + n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"} + `, + {} + ); + }); + it('should be possible to use @ syntax to add labels with trail spaces and &', () => { + imgSnapshotTest( + `flowchart TB + n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"} + `, + {} + ); + }); + it('should be possible to use @ syntax to add labels with trail spaces', () => { + imgSnapshotTest( + `flowchart TB + n2["label for n2"] + n4@{ label: "labe for n4"} + n5@{ label: "labe for n5"} + `, + {} + ); + }); + it('should be possible to use @ syntax to add labels with trail spaces and edge/link', () => { + imgSnapshotTest( + `flowchart TD + A["A"] --> B["for B"] & C@{ label: "for c"} & E@{label : "for E"} + D@{label: "for D"} + `, + {} + ); + }); + }); }); diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index 1e8a51140..3a437850d 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -78,9 +78,11 @@ font-family: monospace; font-size: 72px; } + pre { width: 100%; } + /* tspan { font-size: 6px !important; } */ @@ -103,16 +105,20 @@ -
+    
       flowchart LR
-        A --> B
+        AB["apa@apa@"] --> B(("`apa@apa`"))
+    
+
+      flowchart
+        D(("for D"))
     
       flowchart LR
         A e1@==> B
         e1@{ animate: true}
     
-
+    
 flowchart LR
   A e1@--> B
   classDef animate stroke-width:2,stroke-dasharray:10\,8,stroke-dashoffset:-180,animation: edge-animation-frame 6s linear infinite, stroke-linecap: round
@@ -126,7 +132,7 @@ flowchart LR
   class e1 animate
     

Mermaid - edge-animation-slow

-
+    
 flowchart LR
   A e1@--> B
 e1@{ animation: fast}
@@ -428,7 +434,10 @@ kanban
       window.callback = function () {
         alert('A callback was triggered');
       };
-      mermaid.initialize({
+      function callback() {
+        alert('It worked');
+      }
+      await mermaid.initialize({
         // theme: 'base',
         // theme: 'default',
         // theme: 'forest',
@@ -440,9 +449,11 @@ kanban
         // layout: 'fixed',
         // htmlLabels: false,
         flowchart: { titleTopMargin: 10 },
+
         // fontFamily: 'Caveat',
         // fontFamily: 'Kalam',
         // fontFamily: 'courier',
+        fontFamily: 'arial',
         sequence: {
           actorFontFamily: 'courier',
           noteFontFamily: 'courier',
@@ -454,10 +465,9 @@ kanban
         fontSize: 12,
         logLevel: 0,
         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 89b314e68..cdb711fb7 100644
--- a/cypress/platform/saurabh.html
+++ b/cypress/platform/saurabh.html
@@ -62,56 +62,23 @@
 
   
     
-      flowchart LR
-      A@{ icon: "fa:window-minimize", form: circle }
-      E@{ icon: "fa:window-minimize", form: circle }
-      B@{ icon: "fa:bell", form: circle }
-      B2@{ icon: "fa:bell", form: circle }
-      C@{ icon: "fa:address-book",  form: square  }
-      D@{ icon: "fa:star-half",  form: square  }
-      A --> E
-      B --> B2
-
+      flowchart
+          A --> A
+          subgraph B
+            B1 --> B1
+          end
+          subgraph C
+            subgraph C1
+              C2 --> C2
+              subgraph D
+                D1 --> D1
+              end
+              D --> D
+            end
+            C1 --> C1
+          end
 
     
-
-      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
-