diff --git a/codecov.yaml b/.github/codecov.yaml
similarity index 73%
rename from codecov.yaml
rename to .github/codecov.yaml
index b268d6680..3db0811ad 100644
--- a/codecov.yaml
+++ b/.github/codecov.yaml
@@ -1,6 +1,15 @@
+codecov:
+ branch: develop
+
comment:
layout: 'reach, diff, flags, files'
behavior: default
require_changes: false # if true: only post the comment if coverage changes
require_base: no # [yes :: must have a base report to post]
require_head: yes # [yes :: must have a head report to post]
+
+coverage:
+ status:
+ project:
+ default:
+ threshold: 2%
diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml
index f3e440fce..b25ff89cc 100644
--- a/.github/workflows/build-docs.yml
+++ b/.github/workflows/build-docs.yml
@@ -2,13 +2,13 @@ name: Build Vitepress docs
on:
pull_request:
+ merge_group:
permissions:
contents: read
jobs:
- # Build job
- build:
+ build-docs:
runs-on: ubuntu-latest
steps:
- name: Checkout
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 2a70b5901..eeb557ebb 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -2,6 +2,7 @@ name: Build
on:
push: {}
+ merge_group:
pull_request:
types:
- opened
@@ -12,7 +13,7 @@ permissions:
contents: read
jobs:
- build:
+ build-mermaid:
runs-on: ubuntu-latest
strategy:
matrix:
diff --git a/.github/workflows/check-readme-in-sync.yml b/.github/workflows/check-readme-in-sync.yml
index 13912e5b9..5a8ca319b 100644
--- a/.github/workflows/check-readme-in-sync.yml
+++ b/.github/workflows/check-readme-in-sync.yml
@@ -14,7 +14,7 @@ permissions:
contents: read
jobs:
- check:
+ check-readme:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml
index 396ff4e6e..9f9f316c4 100644
--- a/.github/workflows/checks.yml
+++ b/.github/workflows/checks.yml
@@ -1,15 +1,16 @@
on:
- push: {}
+ push:
+ merge_group:
pull_request:
types:
- opened
- synchronize
- ready_for_review
-name: Static analysis
+name: Static analysis on Test files
jobs:
- test:
+ check-tests:
runs-on: ubuntu-latest
name: check tests
if: github.repository_owner == 'mermaid-js'
diff --git a/.github/workflows/e2e-applitools.yml b/.github/workflows/e2e-applitools.yml
index 92f2f80b1..5b1943142 100644
--- a/.github/workflows/e2e-applitools.yml
+++ b/.github/workflows/e2e-applitools.yml
@@ -19,7 +19,7 @@ env:
USE_APPLI: ${{ secrets.APPLITOOLS_API_KEY && 'true' || '' }}
jobs:
- test:
+ e2e-applitools:
runs-on: ubuntu-latest
strategy:
matrix:
diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index 64637c5fb..c204d5872 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -1,12 +1,15 @@
name: E2E
-on: [push, pull_request]
+on:
+ push:
+ pull_request:
+ merge_group:
permissions:
contents: read
jobs:
- build:
+ e2e:
runs-on: ubuntu-latest
strategy:
fail-fast: false
@@ -49,7 +52,7 @@ jobs:
files: coverage/cypress/lcov.info
flags: e2e
name: mermaid-codecov
- fail_ci_if_error: true
+ fail_ci_if_error: false
verbose: true
- name: Upload Artifacts
uses: actions/upload-artifact@v3
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index d4bf4afe8..53b7f484d 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -1,7 +1,8 @@
name: Lint
on:
- push: {}
+ push:
+ merge_group:
pull_request:
types:
- opened
diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml
index b556c1b1d..f63e58750 100644
--- a/.github/workflows/publish-docs.yml
+++ b/.github/workflows/publish-docs.yml
@@ -19,7 +19,7 @@ concurrency:
jobs:
# Build job
- build:
+ build-docs:
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -48,11 +48,11 @@ jobs:
path: packages/mermaid/src/vitepress/.vitepress/dist
# Deployment job
- deploy:
+ deploy-docs:
environment:
name: github-pages
runs-on: ubuntu-latest
- needs: build
+ needs: build-docs
steps:
- name: Deploy to GitHub Pages
id: deployment
diff --git a/.github/workflows/release-preview-publish.yml b/.github/workflows/release-preview-publish.yml
index 5f4936ab6..221e3836e 100644
--- a/.github/workflows/release-preview-publish.yml
+++ b/.github/workflows/release-preview-publish.yml
@@ -6,7 +6,7 @@ on:
- 'release/**'
jobs:
- publish:
+ publish-preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 6bae6b71f..47b726bd1 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -1,12 +1,12 @@
name: Unit Tests
-on: [push, pull_request]
+on: [push, pull_request, merge_group]
permissions:
contents: read
jobs:
- build:
+ unit-test:
runs-on: ubuntu-latest
strategy:
matrix:
@@ -47,11 +47,5 @@ jobs:
files: ./coverage/vitest/lcov.info
flags: unit
name: mermaid-codecov
- fail_ci_if_error: true
+ fail_ci_if_error: false
verbose: true
- # Coveralls is throwing 500. Disabled for now.
- # - name: Upload Coverage to Coveralls
- # uses: coverallsapp/github-action@v2
- # with:
- # github-token: ${{ secrets.GITHUB_TOKEN }}
- # flag-name: unit
diff --git a/.github/workflows/update-browserlist.yml b/.github/workflows/update-browserlist.yml
index 4155ec988..813a400b3 100644
--- a/.github/workflows/update-browserlist.yml
+++ b/.github/workflows/update-browserlist.yml
@@ -5,7 +5,7 @@ on:
workflow_dispatch:
jobs:
- build:
+ update-browser-list:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
diff --git a/__mocks__/sankeyRenderer.js b/__mocks__/sankeyRenderer.js
new file mode 100644
index 000000000..76324c93f
--- /dev/null
+++ b/__mocks__/sankeyRenderer.js
@@ -0,0 +1,13 @@
+/**
+ * Mocked Sankey diagram renderer
+ */
+
+import { vi } from 'vitest';
+
+export const draw = vi.fn().mockImplementation(() => {
+ return '';
+});
+
+export default {
+ draw,
+};
diff --git a/cSpell.json b/cSpell.json
index ce761b884..ad225d1bc 100644
--- a/cSpell.json
+++ b/cSpell.json
@@ -109,6 +109,7 @@
"rehype",
"roledescription",
"sandboxed",
+ "sankey",
"setupgraphviewbox",
"shiki",
"sidharth",
diff --git a/cypress/integration/rendering/sankey.spec.ts b/cypress/integration/rendering/sankey.spec.ts
new file mode 100644
index 000000000..e334b898b
--- /dev/null
+++ b/cypress/integration/rendering/sankey.spec.ts
@@ -0,0 +1,144 @@
+import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
+
+describe('Sankey Diagram', () => {
+ it('should render a simple example', () => {
+ imgSnapshotTest(
+ `
+ sankey-beta
+
+ sourceNode,targetNode,10
+ `,
+ {}
+ );
+ });
+
+ describe('when given a linkColor', function () {
+ this.beforeAll(() => {
+ cy.wrap(
+ `sankey-beta
+ a,b,10
+ `
+ ).as('graph');
+ });
+
+ it('links should use hex color', function () {
+ renderGraph(this.graph, { sankey: { linkColor: '#636465' } });
+
+ cy.get('.link path').should((link) => {
+ expect(link.attr('stroke')).to.equal('#636465');
+ });
+ });
+
+ it('links should be the same color as source node', function () {
+ renderGraph(this.graph, { sankey: { linkColor: 'source' } });
+
+ cy.get('.link path').then((link) => {
+ cy.get('.node[id="node-1"] rect').should((node) =>
+ expect(link.attr('stroke')).to.equal(node.attr('fill'))
+ );
+ });
+ });
+
+ it('links should be the same color as target node', function () {
+ renderGraph(this.graph, { sankey: { linkColor: 'target' } });
+
+ cy.get('.link path').then((link) => {
+ cy.get('.node[id="node-2"] rect').should((node) =>
+ expect(link.attr('stroke')).to.equal(node.attr('fill'))
+ );
+ });
+ });
+
+ it('links must be gradient', function () {
+ renderGraph(this.graph, { sankey: { linkColor: 'gradient' } });
+
+ cy.get('.link path').should((link) => {
+ expect(link.attr('stroke')).to.equal('url(#linearGradient-3)');
+ });
+ });
+ });
+
+ describe('when given a nodeAlignment', function () {
+ this.beforeAll(() => {
+ cy.wrap(
+ `
+ sankey-beta
+
+ a,b,8
+ b,c,8
+ c,d,8
+ d,e,8
+
+ x,c,4
+ c,y,4
+ `
+ ).as('graph');
+ });
+
+ this.afterEach(() => {
+ cy.get('.node[id="node-1"]').should((node) => {
+ expect(node.attr('x')).to.equal('0');
+ });
+ cy.get('.node[id="node-2"]').should((node) => {
+ expect(node.attr('x')).to.equal('100');
+ });
+ cy.get('.node[id="node-3"]').should((node) => {
+ expect(node.attr('x')).to.equal('200');
+ });
+ cy.get('.node[id="node-4"]').should((node) => {
+ expect(node.attr('x')).to.equal('300');
+ });
+ cy.get('.node[id="node-5"]').should((node) => {
+ expect(node.attr('x')).to.equal('400');
+ });
+ });
+
+ it('should justify nodes', function () {
+ renderGraph(this.graph, {
+ sankey: { nodeAlignment: 'justify', width: 410, useMaxWidth: false },
+ });
+ cy.get('.node[id="node-6"]').should((node) => {
+ expect(node.attr('x')).to.equal('0');
+ });
+ cy.get('.node[id="node-7"]').should((node) => {
+ expect(node.attr('x')).to.equal('400');
+ });
+ });
+
+ it('should align nodes left', function () {
+ renderGraph(this.graph, {
+ sankey: { nodeAlignment: 'left', width: 410, useMaxWidth: false },
+ });
+ cy.get('.node[id="node-6"]').should((node) => {
+ expect(node.attr('x')).to.equal('0');
+ });
+ cy.get('.node[id="node-7"]').should((node) => {
+ expect(node.attr('x')).to.equal('300');
+ });
+ });
+
+ it('should align nodes right', function () {
+ renderGraph(this.graph, {
+ sankey: { nodeAlignment: 'right', width: 410, useMaxWidth: false },
+ });
+ cy.get('.node[id="node-6"]').should((node) => {
+ expect(node.attr('x')).to.equal('100');
+ });
+ cy.get('.node[id="node-7"]').should((node) => {
+ expect(node.attr('x')).to.equal('400');
+ });
+ });
+
+ it('should center nodes', function () {
+ renderGraph(this.graph, {
+ sankey: { nodeAlignment: 'center', width: 410, useMaxWidth: false },
+ });
+ cy.get('.node[id="node-6"]').should((node) => {
+ expect(node.attr('x')).to.equal('100');
+ });
+ cy.get('.node[id="node-7"]').should((node) => {
+ expect(node.attr('x')).to.equal('300');
+ });
+ });
+ });
+});
diff --git a/cypress/integration/rendering/sequencediagram.spec.js b/cypress/integration/rendering/sequencediagram.spec.js
index 185cc4133..7d36c1ff1 100644
--- a/cypress/integration/rendering/sequencediagram.spec.js
+++ b/cypress/integration/rendering/sequencediagram.spec.js
@@ -156,6 +156,81 @@ context('Sequence diagram', () => {
`
);
});
+ it('should render a sequence diagram with basic actor creation and destruction', () => {
+ imgSnapshotTest(
+ `
+ sequenceDiagram
+ Alice ->> Bob: Hello Bob, how are you ?
+ Bob ->> Alice: Fine, thank you. And you?
+ create participant Polo
+ Alice ->> Polo: Hi Polo!
+ create actor Ola1 as Ola
+ Polo ->> Ola1: Hiii
+ Ola1 ->> Alice: Hi too
+ destroy Ola1
+ Alice --x Ola1: Bye!
+ Alice ->> Bob: And now?
+ create participant Ola2 as Ola
+ Alice ->> Ola2: Hello again
+ destroy Alice
+ Alice --x Ola2: Bye for me!
+ destroy Bob
+ Ola2 --> Bob: The end
+ `
+ );
+ });
+ it('should render a sequence diagram with actor creation and destruction coupled with backgrounds, loops and notes', () => {
+ imgSnapshotTest(
+ `
+ sequenceDiagram
+ accTitle: test the accTitle
+ accDescr: Test a description
+
+ participant Alice
+ participant Bob
+ autonumber 10 10
+ rect rgb(200, 220, 100)
+ rect rgb(200, 255, 200)
+
+ Alice ->> Bob: Hello Bob, how are you?
+ create participant John as John
Second Line
+ Bob-->>John: How about you John?
+ end
+
+ Bob--x Alice: I am good thanks!
+ Bob-x John: I am good thanks!
+ Note right of John: John thinks a long
long time, so long
that the text does
not fit on a row.
+
+ Bob-->Alice: Checking with John...
+ Note over John:wrap: John looks like he's still thinking, so Bob prods him a bit.
+ Bob-x John: Hey John - we're still waiting to know
how you're doing
+ Note over John:nowrap: John's trying hard not to break his train of thought.
+ destroy John
+ Bob-x John: John! Cmon!
+ Note over John: After a few more moments, John
finally snaps out of it.
+ end
+
+ autonumber off
+ alt either this
+ create actor Lola
+ Alice->>+Lola: Yes
+ Lola-->>-Alice: OK
+ else or this
+ autonumber
+ Alice->>Lola: No
+ else or this will happen
+ Alice->Lola: Maybe
+ end
+ autonumber 200
+ par this happens in parallel
+ destroy Bob
+ Alice -->> Bob: Parallel message 1
+ and
+ Alice -->> Lola: Parallel message 2
+ end
+ `
+ );
+ });
context('font settings', () => {
it('should render different note fonts when configured', () => {
imgSnapshotTest(
diff --git a/demos/index.html b/demos/index.html
index 391042182..24c4fbf3b 100644
--- a/demos/index.html
+++ b/demos/index.html
@@ -75,6 +75,9 @@