diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 41d9c4cff8..3574c35997 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -14,4 +14,5 @@ Make sure you
- [ ] :book: have read the [contribution guidelines](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md)
- [ ] :computer: have added unit/e2e tests (if appropriate)
+- [ ] :notebook: have added documentation (if appropriate)
- [ ] :bookmark: targeted `develop` branch
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 8ba06989d0..95e4256b1f 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -7,9 +7,10 @@ on:
- opened
- synchronize
- ready_for_review
+ workflow_dispatch:
permissions:
- contents: read
+ contents: write
jobs:
lint:
@@ -39,5 +40,19 @@ jobs:
run: pnpm run lint
- name: Verify Docs
+ id: verifyDocs
working-directory: ./packages/mermaid
+ continue-on-error: ${{ github.event_name == 'push' }}
run: pnpm run docs:verify
+
+ - name: Rebuild Docs
+ if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }}
+ working-directory: ./packages/mermaid
+ run: pnpm run docs:build
+
+ - name: Commit changes
+ uses: EndBug/add-and-commit@v9
+ if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }}
+ with:
+ message: 'Update docs'
+ add: 'docs/*'
diff --git a/.github/workflows/release-preview-publish.yml b/.github/workflows/release-preview-publish.yml
index 2b2ff559b2..5f4936ab68 100644
--- a/.github/workflows/release-preview-publish.yml
+++ b/.github/workflows/release-preview-publish.yml
@@ -10,22 +10,30 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - uses: pnpm/action-setup@v2
+
- name: Setup Node.js
uses: actions/setup-node@v3
with:
+ cache: pnpm
node-version: 18.x
- - name: Install Yarn
- run: npm i yarn --global
+
+ - name: Install Packages
+ run: |
+ pnpm install --frozen-lockfile
+ env:
+ CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Install Json
run: npm i json --global
- - name: Install Packages
- run: yarn install --frozen-lockfile
-
- name: Publish
+ working-directory: ./packages/mermaid
run: |
- PREVIEW_VERSION=8
+ PREVIEW_VERSION=$(git log --oneline "origin/$GITHUB_REF_NAME" ^"origin/master" | wc -l)
VERSION=$(echo ${{github.ref}} | tail -c +20)-preview.$PREVIEW_VERSION
echo $VERSION
npm version --no-git-tag-version --allow-same-version $VERSION
diff --git a/.vite/build.ts b/.vite/build.ts
index 1be46ad5ad..1261e375ba 100644
--- a/.vite/build.ts
+++ b/.vite/build.ts
@@ -146,7 +146,7 @@ const main = async () => {
};
if (watch) {
- build(getBuildConfig({ minify: false, watch, core: true, entryName: 'mermaid' }));
+ build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
if (!mermaidOnly) {
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-mindmap' }));
// build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
diff --git a/README.md b/README.md
index 059940a028..9a500283ce 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ English | [简体中文](./README.zh-CN.md)
**Thanks to all involved, people committing pull requests, people answering questions! 🙏**
-
+
## About
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 4bdbc4ae7d..6b3e28b192 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -10,7 +10,7 @@
**感谢所有参与进来提交 PR,解答疑问的人们! 🙏**
-
+
## 关于 Mermaid
diff --git a/__mocks__/c4Renderer.js b/__mocks__/c4Renderer.js
new file mode 100644
index 0000000000..576d5d8634
--- /dev/null
+++ b/__mocks__/c4Renderer.js
@@ -0,0 +1,21 @@
+/**
+ * Mocked C4Context diagram renderer
+ */
+
+import { vi } from 'vitest';
+
+export const drawPersonOrSystemArray = vi.fn();
+export const drawBoundary = vi.fn();
+
+export const setConf = vi.fn();
+
+export const draw = vi.fn().mockImplementation(() => {
+ return '';
+});
+
+export default {
+ drawPersonOrSystemArray,
+ drawBoundary,
+ setConf,
+ draw,
+};
diff --git a/__mocks__/classRenderer-v2.js b/__mocks__/classRenderer-v2.js
new file mode 100644
index 0000000000..1ad95806fc
--- /dev/null
+++ b/__mocks__/classRenderer-v2.js
@@ -0,0 +1,16 @@
+/**
+ * Mocked class diagram v2 renderer
+ */
+
+import { vi } from 'vitest';
+
+export const setConf = vi.fn();
+
+export const draw = vi.fn().mockImplementation(() => {
+ return '';
+});
+
+export default {
+ setConf,
+ draw,
+};
diff --git a/__mocks__/classRenderer.js b/__mocks__/classRenderer.js
new file mode 100644
index 0000000000..1c20de4b18
--- /dev/null
+++ b/__mocks__/classRenderer.js
@@ -0,0 +1,13 @@
+/**
+ * Mocked class diagram renderer
+ */
+
+import { vi } from 'vitest';
+
+export const draw = vi.fn().mockImplementation(() => {
+ return '';
+});
+
+export default {
+ draw,
+};
diff --git a/__mocks__/d3.ts b/__mocks__/d3.ts
index f90d93557b..af35020c57 100644
--- a/__mocks__/d3.ts
+++ b/__mocks__/d3.ts
@@ -1,79 +1,14 @@
// @ts-nocheck TODO: Fix TS
-import { vi } from 'vitest';
-
-const NewD3 = function () {
- /**
- *
- */
- function returnThis() {
- return this;
- }
- return {
- append: function () {
- return NewD3();
- },
- lower: returnThis,
- attr: returnThis,
- style: returnThis,
- text: returnThis,
- 0: {
- 0: {
- getBBox: function () {
- return {
- height: 10,
- width: 20,
- };
- },
- },
- },
- };
-};
+import { MockedD3 } from '../packages/mermaid/src/tests/MockedD3';
export const select = function () {
- return new NewD3();
+ return new MockedD3();
};
export const selectAll = function () {
- return new NewD3();
+ return new MockedD3();
};
export const curveBasis = 'basis';
export const curveLinear = 'linear';
export const curveCardinal = 'cardinal';
-
-export const MockD3 = (name, parent) => {
- const children = [];
- const elem = {
- get __children() {
- return children;
- },
- get __name() {
- return name;
- },
- get __parent() {
- return parent;
- },
- node() {
- return {
- getBBox() {
- return {
- x: 5,
- y: 10,
- height: 15,
- width: 20,
- };
- },
- };
- },
- };
- elem.append = (name) => {
- const mockElem = MockD3(name, elem);
- children.push(mockElem);
- return mockElem;
- };
- elem.lower = vi.fn(() => elem);
- elem.attr = vi.fn(() => elem);
- elem.text = vi.fn(() => elem);
- elem.style = vi.fn(() => elem);
- return elem;
-};
diff --git a/__mocks__/erRenderer.js b/__mocks__/erRenderer.js
new file mode 100644
index 0000000000..845d641f75
--- /dev/null
+++ b/__mocks__/erRenderer.js
@@ -0,0 +1,16 @@
+/**
+ * Mocked er diagram renderer
+ */
+
+import { vi } from 'vitest';
+
+export const setConf = vi.fn();
+
+export const draw = vi.fn().mockImplementation(() => {
+ return '';
+});
+
+export default {
+ setConf,
+ draw,
+};
diff --git a/__mocks__/flowRenderer-v2.js b/__mocks__/flowRenderer-v2.js
new file mode 100644
index 0000000000..89cc86031e
--- /dev/null
+++ b/__mocks__/flowRenderer-v2.js
@@ -0,0 +1,24 @@
+/**
+ * Mocked flow (flowchart) diagram v2 renderer
+ */
+
+import { vi } from 'vitest';
+
+export const setConf = vi.fn();
+export const addVertices = vi.fn();
+export const addEdges = vi.fn();
+export const getClasses = vi.fn().mockImplementation(() => {
+ return {};
+});
+
+export const draw = vi.fn().mockImplementation(() => {
+ return '';
+});
+
+export default {
+ setConf,
+ addVertices,
+ addEdges,
+ getClasses,
+ draw,
+};
diff --git a/__mocks__/ganttRenderer.js b/__mocks__/ganttRenderer.js
new file mode 100644
index 0000000000..9572498321
--- /dev/null
+++ b/__mocks__/ganttRenderer.js
@@ -0,0 +1,16 @@
+/**
+ * Mocked gantt diagram renderer
+ */
+
+import { vi } from 'vitest';
+
+export const setConf = vi.fn();
+
+export const draw = vi.fn().mockImplementation(() => {
+ return '';
+});
+
+export default {
+ setConf,
+ draw,
+};
diff --git a/__mocks__/gitGraphRenderer.js b/__mocks__/gitGraphRenderer.js
new file mode 100644
index 0000000000..1daa82ca4c
--- /dev/null
+++ b/__mocks__/gitGraphRenderer.js
@@ -0,0 +1,13 @@
+/**
+ * Mocked git (graph) diagram renderer
+ */
+
+import { vi } from 'vitest';
+
+export const draw = vi.fn().mockImplementation(() => {
+ return '';
+});
+
+export default {
+ draw,
+};
diff --git a/__mocks__/journeyRenderer.js b/__mocks__/journeyRenderer.js
new file mode 100644
index 0000000000..2bc77c0b10
--- /dev/null
+++ b/__mocks__/journeyRenderer.js
@@ -0,0 +1,15 @@
+/**
+ * Mocked pie (picChart) diagram renderer
+ */
+
+import { vi } from 'vitest';
+export const setConf = vi.fn();
+
+export const draw = vi.fn().mockImplementation(() => {
+ return '';
+});
+
+export default {
+ setConf,
+ draw,
+};
diff --git a/__mocks__/pieRenderer.js b/__mocks__/pieRenderer.js
new file mode 100644
index 0000000000..317c69901d
--- /dev/null
+++ b/__mocks__/pieRenderer.js
@@ -0,0 +1,13 @@
+/**
+ * Mocked pie (picChart) diagram renderer
+ */
+
+import { vi } from 'vitest';
+
+export const draw = vi.fn().mockImplementation(() => {
+ return '';
+});
+
+export default {
+ draw,
+};
diff --git a/__mocks__/requirementRenderer.js b/__mocks__/requirementRenderer.js
new file mode 100644
index 0000000000..48d8997ac1
--- /dev/null
+++ b/__mocks__/requirementRenderer.js
@@ -0,0 +1,13 @@
+/**
+ * Mocked requirement diagram renderer
+ */
+
+import { vi } from 'vitest';
+
+export const draw = vi.fn().mockImplementation(() => {
+ return '';
+});
+
+export default {
+ draw,
+};
diff --git a/__mocks__/sequenceRenderer.js b/__mocks__/sequenceRenderer.js
new file mode 100644
index 0000000000..11080c6bbf
--- /dev/null
+++ b/__mocks__/sequenceRenderer.js
@@ -0,0 +1,23 @@
+/**
+ * Mocked sequence diagram renderer
+ */
+
+import { vi } from 'vitest';
+
+export const bounds = vi.fn();
+export const drawActors = vi.fn();
+export const drawActorsPopup = vi.fn();
+
+export const setConf = vi.fn();
+
+export const draw = vi.fn().mockImplementation(() => {
+ return '';
+});
+
+export default {
+ bounds,
+ drawActors,
+ drawActorsPopup,
+ setConf,
+ draw,
+};
diff --git a/__mocks__/stateRenderer-v2.js b/__mocks__/stateRenderer-v2.js
new file mode 100644
index 0000000000..a2d103b50e
--- /dev/null
+++ b/__mocks__/stateRenderer-v2.js
@@ -0,0 +1,22 @@
+/**
+ * Mocked state diagram v2 renderer
+ */
+
+import { vi } from 'vitest';
+
+export const setConf = vi.fn();
+export const getClasses = vi.fn().mockImplementation(() => {
+ return {};
+});
+export const stateDomId = vi.fn().mockImplementation(() => {
+ return 'mocked-stateDiagram-stateDomId';
+});
+export const draw = vi.fn().mockImplementation(() => {
+ return '';
+});
+
+export default {
+ setConf,
+ getClasses,
+ draw,
+};
diff --git a/cSpell.json b/cSpell.json
index 64187e1ca5..49cb8ada14 100644
--- a/cSpell.json
+++ b/cSpell.json
@@ -14,6 +14,7 @@
"bilkent",
"bisheng",
"braintree",
+ "brkt",
"brolin",
"brotli",
"classdef",
@@ -60,13 +61,19 @@
"mindmaps",
"mitigations",
"mkdocs",
+ "mult",
"orlandoni",
"phpbb",
"plantuml",
"playfair",
+ "pnpm",
"podlite",
+ "quence",
"ranksep",
+ "rect",
+ "rects",
"redmine",
+ "roledescription",
"sandboxed",
"setupgraphviewbox",
"shiki",
@@ -76,7 +83,10 @@
"stylis",
"substate",
"sveidqvist",
+ "swimm",
"techn",
+ "teststr",
+ "textlength",
"treemap",
"ts-nocheck",
"tuleap",
diff --git a/cypress/integration/other/external-diagrams.spec.js b/cypress/integration/other/external-diagrams.spec.js
index 3a6c37e881..be69dfc982 100644
--- a/cypress/integration/other/external-diagrams.spec.js
+++ b/cypress/integration/other/external-diagrams.spec.js
@@ -1,13 +1,10 @@
+import { urlSnapshotTest } from '../../helpers/util';
+
describe('mermaid', () => {
describe('registerDiagram', () => {
it('should work on @mermaid-js/mermaid-mindmap and mermaid-example-diagram', () => {
const url = 'http://localhost:9000/external-diagrams-mindmap.html';
- cy.visit(url);
-
- cy.get('svg', {
- // may be a bit slower than normal, since vite might need to re-compile mermaid/mermaid-mindmap/mermaid-example-diagram
- timeout: 10000,
- }).matchImageSnapshot();
+ urlSnapshotTest(url, {}, false, false);
});
});
});
diff --git a/cypress/integration/other/ghsa.spec.js b/cypress/integration/other/ghsa.spec.js
index 5b168a8a8f..4fadc78554 100644
--- a/cypress/integration/other/ghsa.spec.js
+++ b/cypress/integration/other/ghsa.spec.js
@@ -7,4 +7,10 @@ describe('CSS injections', () => {
flowchart: { htmlLabels: false },
});
});
+ it('should not allow adding styletags affecting the page', () => {
+ urlSnapshotTest('http://localhost:9000/ghsa3.html', {
+ logLevel: 1,
+ flowchart: { htmlLabels: false },
+ });
+ });
});
diff --git a/cypress/integration/rendering/classDiagram-v2.spec.js b/cypress/integration/rendering/classDiagram-v2.spec.js
index f97458857e..9536a074dc 100644
--- a/cypress/integration/rendering/classDiagram-v2.spec.js
+++ b/cypress/integration/rendering/classDiagram-v2.spec.js
@@ -485,8 +485,7 @@ describe('Class diagram V2', () => {
classDiagram-v2
note "I love this diagram!\nDo you love it?"
class Class10 {
- < testThis element does not belong to the SVG but we can style it
+ Background should be yellow!!!
PAGE SHOULD NOT BE RED
+
-graph LR
- subgraph external
- inside
+flowchart LR
+ %% Actors
+ A
+ subgraph Sub
+ B --> C
end
- outside --> external
+
+ %% Accusations
+ A --L --> Sub
+
+ %% Offense
+ B --> A
+
-mindmap
- root
- child1((Circle))
- grandchild 1
- grandchild 2
- child2(Round rectangle)
- grandchild 3
- grandchild 4
- child3[Square]
- grandchild 5
- ::icon(mdi mdi-fire)
- gc6((grand
-
child 6))
- ::icon(mdi mdi-fire)
- gc7((grand
grand
child 8))
-
+ stateDiagram-v2
+
+ [*] --> S1
+ S1 --> S2: long line using
+
should work
+ S1 --> S3: long line using
should work
+ S1 --> S4: long line using \\nshould work
+
+
gantt
title Style today marker (vertical line should be 5px wide and half-transparent blue)
dateFormat YYYY-MM-DD
@@ -103,7 +104,7 @@
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
- theme: 'base',
+ theme: 'default',
startOnLoad: true,
logLevel: 0,
flowchart: {
@@ -114,10 +115,6 @@
useMaxWidth: false,
},
useMaxWidth: false,
- lazyLoadedDiagrams: [
- './mermaid-mindmap-detector.esm.mjs',
- './mermaid-example-diagram-detector.esm.mjs',
- ],
});
function callback() {
alert('It worked');
diff --git a/cypress/platform/knsv3.html b/cypress/platform/knsv3.html
index 0c1afadb72..e5ca66c87a 100644
--- a/cypress/platform/knsv3.html
+++ b/cypress/platform/knsv3.html
@@ -6,6 +6,10 @@
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
+
-
+
-flowchart TB;subgraph "number as labels";1;end;
-
-
-flowchart TB;a[APA];
-
-
-graph TD
- work --> sleep
- sleep --> work
- eat --> sleep
- work --> eat
-
-
-flowchart TD
- work --> sleep
- sleep --> work
- eat --> sleep
- work --> eat
-
-
- graph TB
- A
- B
- subgraph foo[Foo SubGraph]
- C
- D
- end
- subgraph bar[Bar SubGraph]
- E
- F
- end
- G
-
- A-->B
- B-->C
- C-->D
- B-->D
- D-->E
- E-->A
- E-->F
- F-->D
- F-->G
- B-->G
- G-->D
-
- style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred
- style bar fill:#999,stroke-width:2px,stroke:#0F0,color:blue
-
-
- graph TB
-%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
- A
- B
- subgraph foo[Foo SubGraph]
- C
- D
- end
- subgraph bar[Bar SubGraph]
- E
- F
- end
- G
+
-
+ graph TD
+ A["test"] --"
- A-->B
- B-->C
- C-->D
- B-->D
- D-->E
- E-->A
- E-->F
- F-->D
- F-->G
- B-->G
- G-->D
+
+
+
+
+
- style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred
- style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue
-
- graph TD
- A[Christmas] ==> D
- A[Christmas] -->|Get money| B(Go shopping)
- A[Christmas] ==> C
-
-
- graph TD
-%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
- A[Christmas] ==> D
- A[Christmas] -->|Get money| B(Go shopping)
- A[Christmas] ==> C
-
-
- flowchart TD
- A[Christmas] ==> D
- A[Christmas] -->|Get money| B(Go shopping)
- A[Christmas] ==> C
-
-
- flowchart TD
-%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
- A[Christmas] ==> D
- A[Christmas] -->|Get money| B(Go shopping)
- A[Christmas] ==> C
-
-
-flowchart LR
- a["Haiya"]---->b
-
-
-flowchart LR
-%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
- a["Haiya"]---->b
-
-
- flowchart TD
- A[Christmas] ==> D
- A[Christmas] -->|Get money| B(Go shopping)
- A[Christmas] ==> C
-
-
- flowchart TD
-%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
- A[Christmas] ==> D
- A[Christmas] -->|Get money| B(Go shopping)
- A[Christmas] ==> C
-
-
- %%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
-classDiagram-v2
- Class01 <|-- AveryLongClass : Cool
- <<interface>> Class01
- Class03 *-- Class04
- Class05 o-- Class06
- Class07 .. Class08
- Class09 --> C2 : Where am i?
- Class09 --* C3
- Class09 --|> Class07
- Class12 <|.. Class08
- Class11 ..>Class12
- Class07 : equals()
- Class07 : Object[] elementData
- Class01 : size()
- Class01 : int chimp
- Class01 : int gorilla
- Class01 : -int privateChimp
- Class01 : +int publicGorilla
- Class01 : #int protectedMarmoset
- Class08 <--> C2: Cool label
- class Class10 {
- <<service>>
- int id
- test()
- }
-
-
-classDiagram-v2
- Class01 <|-- AveryLongClass : Cool
- <<interface>> Class01
- Class03 *-- Class04
- Class05 o-- Class06
- Class07 .. Class08
- Class09 --> C2 : Where am i?
- Class09 --* C3
- Class09 --|> Class07
- Class12 <|.. Class08
- Class11 ..>Class12
- Class07 : equals()
- Class07 : Object[] elementData
- Class01 : size()
- Class01 : int chimp
- Class01 : int gorilla
- Class01 : -int privateChimp
- Class01 : +int publicGorilla
- Class01 : #int protectedMarmoset
- Class08 <--> C2: Cool label
- class Class10 {
- <<service>>
- int id
- test()
- }
-
-
-flowchart BT
- subgraph S1
- sub1 -->sub2
- end
- subgraph S2
- sub4
- end
- S1 --> S2
- sub1 --> sub4
-
-
+
+
+ erDiagram
+ "HOSPITAL" {
+ int id PK
+ int doctor_id FK
+ string address UK
+ string name
+ string phone_number
+ string fax_number
+ }
+
+
```
@@ -85,7 +85,7 @@ Example:
B-->D(fa:fa-spinner);