diff --git a/.build/common.ts b/.build/common.ts index efd0e3a85..2497d443f 100644 --- a/.build/common.ts +++ b/.build/common.ts @@ -33,6 +33,11 @@ export const packageOptions = { packageName: 'mermaid-layout-elk', file: 'layouts.ts', }, + 'mermaid-layout-tidy-tree': { + name: 'mermaid-layout-tidy-tree', + packageName: 'mermaid-layout-tidy-tree', + file: 'index.ts', + }, examples: { name: 'mermaid-examples', packageName: 'examples', diff --git a/.changeset/clean-wolves-turn.md b/.changeset/clean-wolves-turn.md new file mode 100644 index 000000000..7a44c1c16 --- /dev/null +++ b/.changeset/clean-wolves-turn.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: Render newlines as spaces in class diagrams diff --git a/.changeset/deep-times-make.md b/.changeset/deep-times-make.md new file mode 100644 index 000000000..3f126736f --- /dev/null +++ b/.changeset/deep-times-make.md @@ -0,0 +1,5 @@ +--- +'mermaid': minor +--- + +Add IDs in architecture diagrams diff --git a/.changeset/four-eyes-wish.md b/.changeset/four-eyes-wish.md new file mode 100644 index 000000000..3bbbc1e47 --- /dev/null +++ b/.changeset/four-eyes-wish.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: Ensure edge label color is applied when using classDef with edge IDs diff --git a/.changeset/hungry-guests-drive.md b/.changeset/hungry-guests-drive.md new file mode 100644 index 000000000..1b0e0a07b --- /dev/null +++ b/.changeset/hungry-guests-drive.md @@ -0,0 +1,7 @@ +--- +'mermaid': minor +'@mermaid-js/layout-tidy-tree': minor +'@mermaid-js/layout-elk': minor +--- + +feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes diff --git a/.changeset/proud-colts-smell.md b/.changeset/proud-colts-smell.md new file mode 100644 index 000000000..610d69253 --- /dev/null +++ b/.changeset/proud-colts-smell.md @@ -0,0 +1,5 @@ +--- +'mermaid': minor +--- + +feat: Add IDs in architecture diagrams diff --git a/.changeset/revert-marked-dependency.md b/.changeset/revert-marked-dependency.md new file mode 100644 index 000000000..aded58871 --- /dev/null +++ b/.changeset/revert-marked-dependency.md @@ -0,0 +1,9 @@ +--- +'mermaid': patch +--- + +chore: revert marked dependency from ^15.0.7 to ^16.0.0 + +- Reverted marked package version to ^16.0.0 for better compatibility +- This is a dependency update that maintains API compatibility +- All tests pass with the updated version diff --git a/.cspell/mermaid-terms.txt b/.cspell/mermaid-terms.txt index b0cfa0a1d..45152a0ce 100644 --- a/.cspell/mermaid-terms.txt +++ b/.cspell/mermaid-terms.txt @@ -5,8 +5,10 @@ bmatrix braintree catmull compositTitleSize +cose curv doublecircle +elem elems gantt gitgraph diff --git a/.cspell/misc-terms.txt b/.cspell/misc-terms.txt index 1820e3c86..2906a02fa 100644 --- a/.cspell/misc-terms.txt +++ b/.cspell/misc-terms.txt @@ -1,4 +1,5 @@ BRANDES +Buzan circo handDrawn KOEPF diff --git a/.github/workflows/e2e-applitools.yml b/.github/workflows/e2e-applitools.yml index dd97b49e1..6aaa91eb8 100644 --- a/.github/workflows/e2e-applitools.yml +++ b/.github/workflows/e2e-applitools.yml @@ -23,9 +23,6 @@ env: jobs: e2e-applitools: runs-on: ubuntu-latest - container: - image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1 - options: --user 1001 steps: - if: ${{ ! env.USE_APPLI }} name: Warn if not using Applitools diff --git a/.github/workflows/e2e-timings.yml b/.github/workflows/e2e-timings.yml index 2bbfa8412..21dbda293 100644 --- a/.github/workflows/e2e-timings.yml +++ b/.github/workflows/e2e-timings.yml @@ -58,7 +58,7 @@ jobs: echo "EOF" >> $GITHUB_OUTPUT - name: Commit and create pull request - uses: peter-evans/create-pull-request@cb4d3bfce175d44325c6b7697f81e0afe8a79bdf + uses: peter-evans/create-pull-request@18e469570b1cf0dfc11d60ec121099f8ff3e617a with: add-paths: | cypress/timings.json diff --git a/.github/workflows/validate-lockfile.yml b/.github/workflows/validate-lockfile.yml index 6eb0a63ca..59a6df96d 100644 --- a/.github/workflows/validate-lockfile.yml +++ b/.github/workflows/validate-lockfile.yml @@ -35,7 +35,7 @@ jobs: # 2) No unwanted vitepress paths if grep -qF 'packages/mermaid/src/vitepress' pnpm-lock.yaml; then - issues+=("• Disallowed path 'packages/mermaid/src/vitepress' present. Run `rm -rf packages/mermaid/src/vitepress && pnpm install` to regenerate.") + issues+=("• Disallowed path 'packages/mermaid/src/vitepress' present. Run \`rm -rf packages/mermaid/src/vitepress && pnpm install\` to regenerate.") fi # 3) Lockfile only changes when package.json changes diff --git a/.gitignore b/.gitignore index 7448f2a81..7eb55d5cb 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ node_modules/ coverage/ .idea/ .pnpm-store/ +.instructions/ dist v8-compile-cache-0 diff --git a/cypress/integration/other/configuration.spec.js b/cypress/integration/other/configuration.spec.js index b48a197a4..a699e03a7 100644 --- a/cypress/integration/other/configuration.spec.js +++ b/cypress/integration/other/configuration.spec.js @@ -98,12 +98,12 @@ describe('Configuration', () => { it('should handle arrowMarkerAbsolute set to true', () => { renderGraph( `flowchart TD - A[Christmas] -->|Get money| B(Go shopping) - B --> C{Let me think} - C -->|One| D[Laptop] - C -->|Two| E[iPhone] - C -->|Three| F[fa:fa-car Car] - `, + A[Christmas] -->|Get money| B(Go shopping) + B --> C{Let me think} + C -->|One| D[Laptop] + C -->|Two| E[iPhone] + C -->|Three| F[fa:fa-car Car] + `, { arrowMarkerAbsolute: true, } @@ -113,8 +113,7 @@ describe('Configuration', () => { cy.get('path') .first() .should('have.attr', 'marker-end') - .should('exist') - .and('include', 'url(http\\:\\/\\/localhost'); + .and('include', 'url(http://localhost'); }); }); it('should not taint the initial configuration when using multiple directives', () => { diff --git a/cypress/integration/rendering/classDiagram.spec.js b/cypress/integration/rendering/classDiagram.spec.js index bd2a96b34..6cea402f8 100644 --- a/cypress/integration/rendering/classDiagram.spec.js +++ b/cypress/integration/rendering/classDiagram.spec.js @@ -524,5 +524,18 @@ describe('Class diagram', () => { `, {} ); + it('should handle an empty class body with empty braces', () => { + imgSnapshotTest( + ` classDiagram + class FooBase~T~ {} + class Bar { + +Zip + +Zap() + } + FooBase <|-- Ba + `, + { flowchart: { defaultRenderer: 'elk' } } + ); + }); }); }); diff --git a/cypress/integration/rendering/flowchart-elk.spec.js b/cypress/integration/rendering/flowchart-elk.spec.js index 312e1d5b4..fac4f3b4b 100644 --- a/cypress/integration/rendering/flowchart-elk.spec.js +++ b/cypress/integration/rendering/flowchart-elk.spec.js @@ -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('')); - verifyNumber(maxWidthValue, 380); + verifyNumber(maxWidthValue, 380, 15); }); }); 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); - verifyNumber(width, 380); + verifyNumber(width, 380, 15); expect(svg).to.not.have.attr('style'); }); }); diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index 8c6cde57a..5ef32c269 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -1186,4 +1186,17 @@ end imgSnapshotTest(graph, { htmlLabels: false }); }); }); + + it('V2 - 17: should apply class def colour to edge label', () => { + imgSnapshotTest( + ` graph LR + id1(Start) link@-- "Label" -->id2(Stop) + style id1 fill:#f9f,stroke:#333,stroke-width:4px + +class id2 myClass +classDef myClass fill:#bbf,stroke:#f66,stroke-width:2px,color:white,stroke-dasharray: 5 5 +class link myClass +` + ); + }); }); diff --git a/cypress/integration/rendering/mindmap-tidy-tree.spec.js b/cypress/integration/rendering/mindmap-tidy-tree.spec.js new file mode 100644 index 000000000..e111c281a --- /dev/null +++ b/cypress/integration/rendering/mindmap-tidy-tree.spec.js @@ -0,0 +1,79 @@ +import { imgSnapshotTest } from '../../helpers/util.ts'; + +describe('Mindmap Tidy Tree', () => { + it('1-tidy-tree: should render a simple mindmap without children', () => { + imgSnapshotTest( + ` --- + config: + layout: tidy-tree + --- + mindmap + root((mindmap)) + A + B + ` + ); + }); + it('2-tidy-tree: should render a simple mindmap', () => { + imgSnapshotTest( + ` --- + config: + layout: tidy-tree + --- + mindmap + root((mindmap is a long thing)) + A + B + C + D + ` + ); + }); + it('3-tidy-tree: should render a mindmap with different shapes', () => { + imgSnapshotTest( + ` --- + config: + layout: tidy-tree + --- + mindmap + root((mindmap)) + Origins + Long history + ::icon(fa fa-book) + Popularisation + British popular psychology author Tony Buzan + Research + On effectiveness<br/>and features + On Automatic creation + Uses + Creative techniques + Strategic planning + Argument mapping + Tools + id)I am a cloud( + id))I am a bang(( + Tools + ` + ); + }); + it('4-tidy-tree: should render a mindmap with children', () => { + imgSnapshotTest( + ` --- + config: + layout: tidy-tree + --- + mindmap + ((This is a mindmap)) + child1 + grandchild 1 + grandchild 2 + child2 + grandchild 3 + grandchild 4 + child3 + grandchild 5 + grandchild 6 + ` + ); + }); +}); diff --git a/cypress/integration/rendering/mindmap.spec.ts b/cypress/integration/rendering/mindmap.spec.ts index d76e58c56..e0409ed46 100644 --- a/cypress/integration/rendering/mindmap.spec.ts +++ b/cypress/integration/rendering/mindmap.spec.ts @@ -159,12 +159,10 @@ root }); it('square shape', () => { imgSnapshotTest( - ` -mindmap + `mindmap root[ The root - ] - `, + ]`, {}, undefined, shouldHaveRoot @@ -172,12 +170,10 @@ mindmap }); it('rounded rect shape', () => { imgSnapshotTest( - ` -mindmap + `mindmap root(( The root - )) - `, + ))`, {}, undefined, shouldHaveRoot @@ -185,12 +181,10 @@ mindmap }); it('circle shape', () => { imgSnapshotTest( - ` -mindmap + `mindmap root( The root - ) - `, + )`, {}, undefined, shouldHaveRoot @@ -198,10 +192,8 @@ mindmap }); it('default shape', () => { imgSnapshotTest( - ` -mindmap - The root - `, + `mindmap + The root`, {}, undefined, shouldHaveRoot @@ -209,12 +201,10 @@ mindmap }); it('adding children', () => { imgSnapshotTest( - ` -mindmap + `mindmap The root child1 - child2 - `, + child2`, {}, undefined, shouldHaveRoot @@ -222,13 +212,11 @@ mindmap }); it('adding grand children', () => { imgSnapshotTest( - ` -mindmap + `mindmap The root child1 child2 - child3 - `, + child3`, {}, undefined, shouldHaveRoot @@ -240,25 +228,21 @@ mindmap `mindmap id1[\`**Start** with a second line 😎\`] - id2[\`The dog in **the** hog... a *very long text* about it -Word!\`] -` + id2[\`The dog in **the** hog... a *very long text* about it Word!\`]` ); }); }); describe('Include char sequence "graph" in text (#6795)', () => { it('has a label with char sequence "graph"', () => { imgSnapshotTest( - ` - mindmap + ` mindmap root Photograph Waterfall Landscape Geography Mountains - Rocks - `, + Rocks`, { flowchart: { defaultRenderer: 'elk' } } ); }); diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index eb5528844..7ac7aeac8 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -32,26 +32,8 @@ href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap" rel="stylesheet" /> - - - + + +
++ --- + config: + layout: tidy-tree + --- + mindmap + root((mindmap)) + A + B ++
+ --- + config: + layout: dagre + --- + mindmap + root((mindmap)) + A + B ++
+ --- + config: + layout: elk + --- + mindmap + root((mindmap)) + A + B ++
+ --- + config: + layout: cose-bilkent + --- + mindmap + root((mindmap)) + A + B ++
+ --- + config: + layout: tidy-tree + --- + mindmap + root((mindmap is a long thing)) + A + B + C + D ++
+ --- + config: + layout: dagre + --- + mindmap + root((mindmap is a long thing)) + A + B + C + D ++
+ --- + config: + layout: elk + --- + mindmap + root((mindmap is a long thing)) + A + B + C + D ++
+ --- + config: + layout: cose-bilkent + --- + mindmap + root((mindmap is a long thing)) + A + B + C + D ++ +
+ --- + config: + layout: tidy-tree + --- + mindmap + root((mindmap)) + Origins + Long history + ::icon(fa fa-book) + Popularisation + British popular psychology author Tony Buzan + Research + On effectiveness<br/>and features + On Automatic creation + Uses + Creative techniques + Strategic planning + Argument mapping + Tools + id)I am a cloud( + id))I am a bang(( + Tools ++
+ --- + config: + layout: dagre + --- + mindmap + root((mindmap)) + Origins + Long history + ::icon(fa fa-book) + Popularisation + British popular psychology author Tony Buzan + Research + On effectiveness<br/>and features + On Automatic creation + Uses + Creative techniques + Strategic planning + Argument mapping + Tools + id)I am a cloud( + id))I am a bang(( + Tools ++
+ --- + config: + layout: elk + --- + mindmap + root((mindmap)) + Origins + Long history + ::icon(fa fa-book) + Popularisation + British popular psychology author Tony Buzan + Research + On effectiveness<br/>and features + On Automatic creation + Uses + Creative techniques + Strategic planning + Argument mapping + Tools + id)I am a cloud( + id))I am a bang(( + Tools ++
+ --- + config: + layout: cose-bilkent + --- + mindmap + root((mindmap)) + Origins + Long history + ::icon(fa fa-book) + Popularisation + British popular psychology author Tony Buzan + Research + On effectiveness<br/>and features + On Automatic creation + Uses + Creative techniques + Strategic planning + Argument mapping + Tools + id)I am a cloud( + id))I am a bang(( + Tools ++
+ --- + config: + layout: tidy-tree + --- + mindmap + root((mindmap)) + A + a + apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + b + c + d + B + apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + D + apa5[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + ++
+ --- + config: + layout: dagre + --- + mindmap + root((mindmap)) + A + a + apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + b + c + d + B + apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + D + apa5[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + ++
+ --- + config: + layout: elk + --- + mindmap + root((mindmap)) + A + a + apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + b + c + d + B + apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + D + apa5[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + ++
+ --- + config: + layout: cose-bilkent + --- + mindmap + root((mindmap)) + A + a + apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + b + c + d + B + apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + D + apa5[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] + ++ +
+ --- + config: + layout: tidy-tree + --- + mindmap + ((This is a mindmap)) + child1 + grandchild 1 + grandchild 2 + child2 + grandchild 3 + grandchild 4 + child3 + grandchild 5 + grandchild 6 + ++ +
+ --- + config: + layout: dagre + --- + mindmap + ((This is a mindmap)) + child1 + grandchild 1 + grandchild 2 + child2 + grandchild 3 + grandchild 4 + child3 + grandchild 5 + grandchild 6 + ++ +
+ --- + config: + layout: elk + --- + mindmap + ((This is a mindmap)) + child1 + grandchild 1 + grandchild 2 + child2 + grandchild 3 + grandchild 4 + child3 + grandchild 5 + grandchild 6 + ++ +
+ --- + config: + layout: cose-bilkent + --- + mindmap + ((This is a mindmap)) + child1 + grandchild 1 + grandchild 2 + child2 + grandchild 3 + grandchild 4 + child3 + grandchild 5 + grandchild 6 + ++ +