mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-28 08:34:43 +01:00
Compare commits
5 Commits
mindmap-no
...
fix-update
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f919ebafa | ||
|
|
a302ead548 | ||
|
|
918bcef6e6 | ||
|
|
fe6ddc89c3 | ||
|
|
2708b1c2f8 |
5
.changeset/clean-wolves-turn.md
Normal file
5
.changeset/clean-wolves-turn.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: Render newlines as spaces in class diagrams
|
||||||
5
.changeset/crazy-loops-matter.md
Normal file
5
.changeset/crazy-loops-matter.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: Handle arrows correctly when auto number is enabled
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'mermaid': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
chore: Fix mindmap rendering in docs and apply tidytree layout
|
|
||||||
5
.changeset/deep-times-make.md
Normal file
5
.changeset/deep-times-make.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add IDs in architecture diagrams
|
||||||
5
.changeset/hungry-baths-glow.md
Normal file
5
.changeset/hungry-baths-glow.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: Added support for new participant types (`actor`, `boundary`, `control`, `entity`, `database`, `collections`, `queue`) in `sequenceDiagram`.
|
||||||
7
.changeset/hungry-guests-drive.md
Normal file
7
.changeset/hungry-guests-drive.md
Normal file
@@ -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
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'mermaid': minor
|
|
||||||
---
|
|
||||||
|
|
||||||
feat: Add half-arrowheads (solid & stick) and central connection support
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'@mermaid': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: Mindmap breaking in ELK layout
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'mermaid': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix(er-diagram): prevent syntax error when using 'u', numbers, and decimals in node names
|
|
||||||
10
.github/workflows/codeql.yml
vendored
10
.github/workflows/codeql.yml
vendored
@@ -26,8 +26,8 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
language: ['javascript', 'actions']
|
language: ['javascript']
|
||||||
# CodeQL supports [ 'actions', 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21
|
uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||||
with:
|
with:
|
||||||
config-file: ./.github/codeql/codeql-config.yml
|
config-file: ./.github/codeql/codeql-config.yml
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
@@ -48,7 +48,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21
|
uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
@@ -62,4 +62,4 @@ jobs:
|
|||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21
|
uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||||
|
|||||||
2
.github/workflows/e2e-applitools.yml
vendored
2
.github/workflows/e2e-applitools.yml
vendored
@@ -53,7 +53,7 @@ jobs:
|
|||||||
args: -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH"
|
args: -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH"
|
||||||
|
|
||||||
- name: Cypress run
|
- name: Cypress run
|
||||||
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
|
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||||
id: cypress
|
id: cypress
|
||||||
with:
|
with:
|
||||||
start: pnpm run dev
|
start: pnpm run dev
|
||||||
|
|||||||
4
.github/workflows/e2e-timings.yml
vendored
4
.github/workflows/e2e-timings.yml
vendored
@@ -27,12 +27,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
|
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||||
with:
|
with:
|
||||||
runTests: false
|
runTests: false
|
||||||
|
|
||||||
- name: Cypress run
|
- name: Cypress run
|
||||||
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
|
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||||
id: cypress
|
id: cypress
|
||||||
with:
|
with:
|
||||||
install: false
|
install: false
|
||||||
|
|||||||
10
.github/workflows/e2e.yml
vendored
10
.github/workflows/e2e.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
|||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
- name: Cache snapshots
|
- name: Cache snapshots
|
||||||
id: cache-snapshot
|
id: cache-snapshot
|
||||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||||
with:
|
with:
|
||||||
path: ./cypress/snapshots
|
path: ./cypress/snapshots
|
||||||
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
|
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
|
||||||
@@ -59,7 +59,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||||
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
|
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||||
with:
|
with:
|
||||||
# just perform install
|
# just perform install
|
||||||
runTests: false
|
runTests: false
|
||||||
@@ -95,13 +95,13 @@ jobs:
|
|||||||
# These cached snapshots are downloaded, providing the reference snapshots.
|
# These cached snapshots are downloaded, providing the reference snapshots.
|
||||||
- name: Cache snapshots
|
- name: Cache snapshots
|
||||||
id: cache-snapshot
|
id: cache-snapshot
|
||||||
uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
uses: actions/cache/restore@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||||
with:
|
with:
|
||||||
path: ./cypress/snapshots
|
path: ./cypress/snapshots
|
||||||
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
|
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
|
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||||
with:
|
with:
|
||||||
runTests: false
|
runTests: false
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ jobs:
|
|||||||
# Install NPM dependencies, cache them correctly
|
# Install NPM dependencies, cache them correctly
|
||||||
# and run all Cypress tests
|
# and run all Cypress tests
|
||||||
- name: Cypress run
|
- name: Cypress run
|
||||||
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
|
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||||
id: cypress
|
id: cypress
|
||||||
with:
|
with:
|
||||||
install: false
|
install: false
|
||||||
|
|||||||
2
.github/workflows/link-checker.yml
vendored
2
.github/workflows/link-checker.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
|||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Restore lychee cache
|
- name: Restore lychee cache
|
||||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||||
with:
|
with:
|
||||||
path: .lycheecache
|
path: .lycheecache
|
||||||
key: cache-lychee-${{ github.sha }}
|
key: cache-lychee-${{ github.sha }}
|
||||||
|
|||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Create Release Pull Request or Publish to npm
|
- name: Create Release Pull Request or Publish to npm
|
||||||
id: changesets
|
id: changesets
|
||||||
uses: changesets/action@06245a4e0a36c064a573d4150030f5ec548e4fcc # v1.4.10
|
uses: changesets/action@c8bada60c408975afd1a20b3db81d6eee6789308 # v1.4.9
|
||||||
with:
|
with:
|
||||||
version: pnpm changeset:version
|
version: pnpm changeset:version
|
||||||
publish: pnpm changeset:publish
|
publish: pnpm changeset:publish
|
||||||
|
|||||||
6
.github/workflows/scorecard.yml
vendored
6
.github/workflows/scorecard.yml
vendored
@@ -20,18 +20,18 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Run analysis
|
- name: Run analysis
|
||||||
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
|
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
|
||||||
with:
|
with:
|
||||||
results_file: results.sarif
|
results_file: results.sarif
|
||||||
results_format: sarif
|
results_format: sarif
|
||||||
publish_results: true
|
publish_results: true
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
|
||||||
with:
|
with:
|
||||||
name: SARIF file
|
name: SARIF file
|
||||||
path: results.sarif
|
path: results.sarif
|
||||||
retention-days: 5
|
retention-days: 5
|
||||||
- name: Upload to code-scanning
|
- name: Upload to code-scanning
|
||||||
uses: github/codeql-action/upload-sarif@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21
|
uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
|
|||||||
2
.github/workflows/update-browserlist.yml
vendored
2
.github/workflows/update-browserlist.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
|||||||
message: 'chore: update browsers list'
|
message: 'chore: update browsers list'
|
||||||
push: false
|
push: false
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6
|
||||||
with:
|
with:
|
||||||
branch: update-browserslist
|
branch: update-browserslist
|
||||||
title: Update Browserslist
|
title: Update Browserslist
|
||||||
|
|||||||
@@ -369,92 +369,4 @@ ORDER ||--|{ LINE-ITEM : contains
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Special characters and numbers syntax', () => {
|
|
||||||
it('should render ER diagram with numeric entity names', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
erDiagram
|
|
||||||
1 ||--|| ORDER : places
|
|
||||||
ORDER ||--|{ 2 : contains
|
|
||||||
2 ||--o{ 3.5 : references
|
|
||||||
`,
|
|
||||||
{ logLevel: 1 }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render ER diagram with "u" character in entity names and cardinality', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
erDiagram
|
|
||||||
CUSTOMER ||--|| u : has
|
|
||||||
u ||--|| ORDER : places
|
|
||||||
PROJECT u--o{ TEAM_MEMBER : "parent"
|
|
||||||
`,
|
|
||||||
{ logLevel: 1 }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render ER diagram with decimal numbers in relationships', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
erDiagram
|
|
||||||
2.5 ||--|| 1.5 : has
|
|
||||||
CUSTOMER ||--o{ 3.14 : references
|
|
||||||
1.0 ||--|{ ORDER : contains
|
|
||||||
`,
|
|
||||||
{ logLevel: 1 }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render ER diagram with numeric entity names and attributes', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
erDiagram
|
|
||||||
1 {
|
|
||||||
string name
|
|
||||||
int value
|
|
||||||
}
|
|
||||||
1 ||--|| ORDER : places
|
|
||||||
ORDER {
|
|
||||||
float price
|
|
||||||
string description
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
{ logLevel: 1 }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render complex ER diagram with mixed special entity names', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
erDiagram
|
|
||||||
CUSTOMER ||--o{ 1 : places
|
|
||||||
1 ||--|{ u : contains
|
|
||||||
1.5
|
|
||||||
u ||--|| 2.5 : processes
|
|
||||||
2.5 {
|
|
||||||
string id
|
|
||||||
float value
|
|
||||||
}
|
|
||||||
u {
|
|
||||||
varchar(50) name
|
|
||||||
int count
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
{ logLevel: 1 }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('should render ER diagram with numeric entity names and attributes', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`erDiagram
|
|
||||||
PRODUCT ||--o{ ORDER-ITEM : has
|
|
||||||
1.5
|
|
||||||
u
|
|
||||||
1
|
|
||||||
`,
|
|
||||||
{ logLevel: 1 }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -655,126 +655,5 @@ describe('Sequence Diagram Special Cases', () => {
|
|||||||
expect(svg).to.not.have.attr('style');
|
expect(svg).to.not.have.attr('style');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Central Connection Rendering Tests', () => {
|
|
||||||
it('should render central connection circles on actor vertical lines', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
participant Charlie
|
|
||||||
Alice ()->>() Bob: Central connection
|
|
||||||
Bob ()-->> Charlie: Reverse central connection
|
|
||||||
Charlie ()<<-->>() Alice: Dual central connection`,
|
|
||||||
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render central connections with different arrow types', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
Alice ()->>() Bob: Solid open arrow
|
|
||||||
Alice ()-->>() Bob: Dotted open arrow
|
|
||||||
Alice ()-x() Bob: Solid cross
|
|
||||||
Alice ()--x() Bob: Dotted cross
|
|
||||||
Alice ()->() Bob: Solid arrow`,
|
|
||||||
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render central connections with bidirectional arrows', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
Alice ()<<->>() Bob: Bidirectional solid
|
|
||||||
Alice ()<<-->>() Bob: Bidirectional dotted`,
|
|
||||||
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render central connections with activations', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
participant Charlie
|
|
||||||
Alice ()->>() Bob: Activate Bob
|
|
||||||
activate Bob
|
|
||||||
Bob ()-->> Charlie: Message to Charlie
|
|
||||||
Bob ()->>() Alice: Response to Alice
|
|
||||||
deactivate Bob`,
|
|
||||||
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render central connections mixed with normal messages', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
participant Charlie
|
|
||||||
Alice ->> Bob: Normal message
|
|
||||||
Bob ()->>() Charlie: Central connection
|
|
||||||
Charlie -->> Alice: Normal dotted message
|
|
||||||
Alice ()<<-->>() Bob: Dual central connection
|
|
||||||
Bob -x Charlie: Normal cross message`,
|
|
||||||
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render central connections with notes', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
participant Charlie
|
|
||||||
Alice ()->>() Bob: Central connection
|
|
||||||
Note over Alice,Bob: Central connection note
|
|
||||||
Bob ()-->> Charlie: Reverse central connection
|
|
||||||
Note right of Charlie: Response note
|
|
||||||
Charlie ()<<-->>() Alice: Dual central connection`,
|
|
||||||
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render central connections with loops and alternatives', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
participant Charlie
|
|
||||||
loop Every minute
|
|
||||||
Alice ()->>() Bob: Central heartbeat
|
|
||||||
Bob ()-->> Charlie: Forward heartbeat
|
|
||||||
end
|
|
||||||
alt Success
|
|
||||||
Charlie ()<<-->>() Alice: Success response
|
|
||||||
else Failure
|
|
||||||
Charlie ()-x() Alice: Failure response
|
|
||||||
end`,
|
|
||||||
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render central connections with different participant types', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
actor Bob
|
|
||||||
participant Charlie@{"type":"boundary"}
|
|
||||||
participant David@{"type":"control"}
|
|
||||||
participant Eve@{"type":"entity"}
|
|
||||||
Alice ()->>() Bob: To actor
|
|
||||||
Bob ()-->> Charlie: To boundary
|
|
||||||
Charlie ()->>() David: To control
|
|
||||||
David ()<<-->>() Eve: To entity
|
|
||||||
Eve ()-x() Alice: Back to participant`,
|
|
||||||
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1053,167 +1053,4 @@ describe('Sequence diagram', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('render new arrow type', () => {
|
|
||||||
it('should render Solid half arrow top', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice -|\\ John: Hello John, how are you?
|
|
||||||
Alice-|\\ John: Hi Alice, I can hear you!
|
|
||||||
Alice -|\\ John: Test
|
|
||||||
`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('should render Solid half arrow bottom', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice-|/John: Hello John, how are you?
|
|
||||||
Alice-|/John: Hi Alice, I can hear you!
|
|
||||||
Alice-|/John: Test
|
|
||||||
`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render Stick half arrow top ', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice-\\\\John: Hello John, how are you?
|
|
||||||
Alice-\\\\John: Hi Alice, I can hear you!
|
|
||||||
Alice-\\\\John: Test
|
|
||||||
`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('should render Stick half arrow bottom ', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice-//John: Hello John, how are you?
|
|
||||||
Alice-//John: Hi Alice, I can hear you!
|
|
||||||
Alice-//John: Test
|
|
||||||
`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('should render Solid half arrow top reverse ', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice/|-John: Hello Alice, how are you?
|
|
||||||
Alice/|-John: Hi Alice, I can hear you!
|
|
||||||
Alice/|-John: Test
|
|
||||||
|
|
||||||
`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render Solid half arrow bottom reverse ', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`sequenceDiagram
|
|
||||||
Alice \\|- John: Hello Alice, how are you?
|
|
||||||
Alice \\|- John: Hi Alice, I can hear you!
|
|
||||||
Alice \\|- John: Test`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render Stick half arrow top reverse ', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice //-John: Hello Alice, how are you?
|
|
||||||
Alice //-John: Hi Alice, I can hear you!
|
|
||||||
Alice //-John: Test`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render Stick half arrow bottom reverse ', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice \\\\-John: Hello Alice, how are you?
|
|
||||||
Alice \\\\-John: Hi Alice, I can hear you!
|
|
||||||
Alice \\\\-John: Test`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render Solid half arrow top dotted', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice --|\\John: Hello John, how are you?
|
|
||||||
Alice --|\\John: Hi Alice, I can hear you!
|
|
||||||
Alice --|\\John: Test`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render Solid half arrow bottom dotted', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice --|/John: Hello John, how are you?
|
|
||||||
Alice --|/John: Hi Alice, I can hear you!
|
|
||||||
Alice --|/John: Test`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render Stick half arrow top dotted', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice--\\\\John: Hello John, how are you?
|
|
||||||
Alice--\\\\John: Hi Alice, I can hear you!
|
|
||||||
Alice--\\\\John: Test`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render Stick half arrow bottom dotted', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice--//John: Hello John, how are you?
|
|
||||||
Alice--//John: Hi Alice, I can hear you!
|
|
||||||
Alice--//John: Test`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render Solid half arrow top reverse dotted', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice/|--John: Hello Alice, how are you?
|
|
||||||
Alice/|--John: Hi Alice, I can hear you!
|
|
||||||
Alice/|--John: Test`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render Solid half arrow bottom reverse dotted', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice\\|--John: Hello Alice, how are you?
|
|
||||||
Alice\\|--John: Hi Alice, I can hear you!
|
|
||||||
Alice\\|--John: Test`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render Stick half arrow top reverse dotted ', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice//--John: Hello Alice, how are you?
|
|
||||||
Alice//--John: Hi Alice, I can hear you!
|
|
||||||
Alice//--John: Test`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render Stick half arrow bottom reverse dotted ', () => {
|
|
||||||
imgSnapshotTest(
|
|
||||||
`
|
|
||||||
sequenceDiagram
|
|
||||||
Alice\\\\--John: Hello Alice, how are you?
|
|
||||||
Alice\\\\--John: Hi Alice, I can hear you!
|
|
||||||
Alice\\\\--John: Test`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,14 +6,6 @@
|
|||||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
<style>
|
<style>
|
||||||
svg:not(svg svg) {
|
svg:not(svg svg) {
|
||||||
border: 2px solid darkred;
|
border: 2px solid darkred;
|
||||||
|
|||||||
@@ -110,48 +110,6 @@
|
|||||||
config:
|
config:
|
||||||
layout: elk
|
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
|
|
||||||
</pre>
|
|
||||||
<pre id="diagram4" class="mermaid">
|
|
||||||
---
|
|
||||||
config:
|
|
||||||
layout: elk
|
|
||||||
---
|
|
||||||
flowchart
|
|
||||||
aid0
|
|
||||||
</pre
|
|
||||||
>
|
|
||||||
<pre id="diagram4" class="mermaid">
|
|
||||||
---
|
|
||||||
config:
|
|
||||||
layout: elk
|
|
||||||
---
|
|
||||||
mindmap
|
|
||||||
aid0
|
|
||||||
|
|
||||||
</pre>
|
|
||||||
<pre id="diagram4" class="mermaid">
|
|
||||||
---
|
|
||||||
config:
|
|
||||||
layout: ogdc
|
|
||||||
---
|
|
||||||
flowchart-elk TB
|
flowchart-elk TB
|
||||||
c1-->a2
|
c1-->a2
|
||||||
subgraph one
|
subgraph one
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es2020",
|
"target": "es2020",
|
||||||
"lib": ["es2020", "dom"],
|
"lib": ["es2020", "dom"],
|
||||||
"types": ["cypress", "node", "@argos-ci/cypress/support"],
|
"types": ["cypress", "node", "@argos-ci/cypress/dist/support.d.ts"],
|
||||||
"allowImportingTsExtensions": true,
|
"allowImportingTsExtensions": true,
|
||||||
"noEmit": true
|
"noEmit": true
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
|
|||||||
@@ -29,8 +29,7 @@ In GitHub, you first [**fork a mermaid repository**](https://github.com/mermaid-
|
|||||||
|
|
||||||
Then you **clone** a copy to your local development machine (e.g. where you code) to make a copy with all the files to work with.
|
Then you **clone** a copy to your local development machine (e.g. where you code) to make a copy with all the files to work with.
|
||||||
|
|
||||||
> **💡 Tip**
|
> **💡 Tip** > [Here is a GitHub document that gives an overview of the process](https://docs.github.com/en/get-started/quickstart/fork-a-repo).
|
||||||
> [Here is a GitHub document that gives an overview of the process](https://docs.github.com/en/get-started/quickstart/fork-a-repo).
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone git@github.com/your-fork/mermaid
|
git clone git@github.com/your-fork/mermaid
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ mindmap
|
|||||||
|
|
||||||
## Join the Development
|
## Join the Development
|
||||||
|
|
||||||
> **💡 Tip**
|
> **💡 Tip** > **Check out our** [**detailed contribution guide**](./contributing.md).
|
||||||
> **Check out our** [**detailed contribution guide**](./contributing.md).
|
|
||||||
|
|
||||||
Where to start:
|
Where to start:
|
||||||
|
|
||||||
@@ -48,8 +47,7 @@ Where to start:
|
|||||||
|
|
||||||
## A Question Or a Suggestion?
|
## A Question Or a Suggestion?
|
||||||
|
|
||||||
> **💡 Tip**
|
> **💡 Tip** > **Have a look at** [**how to open an issue**](./questions-and-suggestions.md).
|
||||||
> **Have a look at** [**how to open an issue**](./questions-and-suggestions.md).
|
|
||||||
|
|
||||||
If you have faced a vulnerability [report it to us](./security.md).
|
If you have faced a vulnerability [report it to us](./security.md).
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ While directives allow you to change most of the default configuration settings,
|
|||||||
Mermaid basically supports two types of configuration options to be overridden by directives.
|
Mermaid basically supports two types of configuration options to be overridden by directives.
|
||||||
|
|
||||||
1. _General/Top Level configurations_ : These are the configurations that are available and applied to all the diagram. **Some of the most important top-level** configurations are:
|
1. _General/Top Level configurations_ : These are the configurations that are available and applied to all the diagram. **Some of the most important top-level** configurations are:
|
||||||
|
|
||||||
- theme
|
- theme
|
||||||
- fontFamily
|
- fontFamily
|
||||||
- logLevel
|
- logLevel
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
# Interface: LayoutData
|
# Interface: LayoutData
|
||||||
|
|
||||||
Defined in: [packages/mermaid/src/rendering-util/types.ts:169](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L169)
|
Defined in: [packages/mermaid/src/rendering-util/types.ts:168](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L168)
|
||||||
|
|
||||||
## Indexable
|
## Indexable
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ Defined in: [packages/mermaid/src/rendering-util/types.ts:169](https://github.co
|
|||||||
|
|
||||||
> **config**: [`MermaidConfig`](MermaidConfig.md)
|
> **config**: [`MermaidConfig`](MermaidConfig.md)
|
||||||
|
|
||||||
Defined in: [packages/mermaid/src/rendering-util/types.ts:172](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L172)
|
Defined in: [packages/mermaid/src/rendering-util/types.ts:171](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L171)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ Defined in: [packages/mermaid/src/rendering-util/types.ts:172](https://github.co
|
|||||||
|
|
||||||
> **edges**: `Edge`\[]
|
> **edges**: `Edge`\[]
|
||||||
|
|
||||||
Defined in: [packages/mermaid/src/rendering-util/types.ts:171](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L171)
|
Defined in: [packages/mermaid/src/rendering-util/types.ts:170](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L170)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -38,4 +38,4 @@ Defined in: [packages/mermaid/src/rendering-util/types.ts:171](https://github.co
|
|||||||
|
|
||||||
> **nodes**: `Node`\[]
|
> **nodes**: `Node`\[]
|
||||||
|
|
||||||
Defined in: [packages/mermaid/src/rendering-util/types.ts:170](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L170)
|
Defined in: [packages/mermaid/src/rendering-util/types.ts:169](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L169)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an accoun
|
|||||||
- **Plugins** - A plugin system for extending the functionality of Mermaid.
|
- **Plugins** - A plugin system for extending the functionality of Mermaid.
|
||||||
|
|
||||||
Official Mermaid Chart plugins:
|
Official Mermaid Chart plugins:
|
||||||
|
|
||||||
- [Mermaid Chart GPT](https://chatgpt.com/g/g-684cc36f30208191b21383b88650a45d-mermaid-chart-diagrams-and-charts)
|
- [Mermaid Chart GPT](https://chatgpt.com/g/g-684cc36f30208191b21383b88650a45d-mermaid-chart-diagrams-and-charts)
|
||||||
- [Confluence](https://marketplace.atlassian.com/apps/1234056/mermaid-chart-for-confluence?hosting=cloud&tab=overview)
|
- [Confluence](https://marketplace.atlassian.com/apps/1234056/mermaid-chart-for-confluence?hosting=cloud&tab=overview)
|
||||||
- [Jira](https://marketplace.atlassian.com/apps/1234810/mermaid-chart-for-jira?tab=overview&hosting=cloud)
|
- [Jira](https://marketplace.atlassian.com/apps/1234810/mermaid-chart-for-jira?tab=overview&hosting=cloud)
|
||||||
|
|||||||
@@ -35,11 +35,13 @@ The Mermaid Chart team is excited to introduce a new Visual Editor for Flowchart
|
|||||||
Learn more:
|
Learn more:
|
||||||
|
|
||||||
- Visual Editor For Flowcharts
|
- Visual Editor For Flowcharts
|
||||||
|
|
||||||
- [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-releases-new-visual-editor-for-flowcharts)
|
- [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-releases-new-visual-editor-for-flowcharts)
|
||||||
|
|
||||||
- [Demo video](https://www.youtube.com/watch?v=5aja0gijoO0)
|
- [Demo video](https://www.youtube.com/watch?v=5aja0gijoO0)
|
||||||
|
|
||||||
- Visual Editor For Sequence diagrams
|
- Visual Editor For Sequence diagrams
|
||||||
|
|
||||||
- [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-unveils-visual-editor-for-sequence-diagrams)
|
- [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-unveils-visual-editor-for-sequence-diagrams)
|
||||||
|
|
||||||
- [Demo video](https://youtu.be/imc2u5_N6Dc)
|
- [Demo video](https://youtu.be/imc2u5_N6Dc)
|
||||||
|
|||||||
@@ -6,18 +6,6 @@
|
|||||||
|
|
||||||
# Blog
|
# Blog
|
||||||
|
|
||||||
## [The Essential Guide to Mermaid Chart Plugin for VS Code \[08/2025\]](https://docs.mermaidchart.com/blog/posts/the-essential-guide-to-mermaid-chart-plugin-for-vs-code-08-2025)
|
|
||||||
|
|
||||||
9/9/2025 • 5 mins
|
|
||||||
|
|
||||||
Creating diagrams in VS Code has never been easier—the Mermaid VS Code plugin transforms text-based syntax into clear, professional visuals right inside your editor. With live previews, smart editing, and AI-powered diagram generation, it removes the friction from visualization so you can focus on coding.
|
|
||||||
|
|
||||||
## [How to Create Perfect Flowcharts Using AI in 2025 Step-by-Step Guide](https://docs.mermaidchart.com/blog/posts/how-to-create-perfect-flowcharts-using-ai-in-2025-step-by-step-guide)
|
|
||||||
|
|
||||||
7/22/2025 • 8 mins
|
|
||||||
|
|
||||||
In 2025, AI tools make creating flowcharts faster and easier than ever. With Mermaid’s AI flowchart generator, you can turn plain text into clear, accurate diagrams in seconds. This guide walks through how it works and how to get the most out of it for technical and business workflows alike.
|
|
||||||
|
|
||||||
## [Mermaid introduces the Visual Editor for Entity Relationship diagrams](https://docs.mermaidchart.com/blog/posts/mermaid-introduces-the-visual-editor-for-entity-relationship-diagrams)
|
## [Mermaid introduces the Visual Editor for Entity Relationship diagrams](https://docs.mermaidchart.com/blog/posts/mermaid-introduces-the-visual-editor-for-entity-relationship-diagrams)
|
||||||
|
|
||||||
7/15/2025 • 7 mins
|
7/15/2025 • 7 mins
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ architecture-beta
|
|||||||
## Icons
|
## Icons
|
||||||
|
|
||||||
By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`.
|
By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`.
|
||||||
Users can use any of the 200,000+ icons available in iconify.design, or add other custom icons, by [registering an icon pack](../config/icons.md).
|
Users can use any of the 200,000+ icons available in iconify.design, or [add custom icons](../config/icons.md).
|
||||||
|
|
||||||
After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack.
|
After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack.
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ The following unfinished features are not supported in the short term.
|
|||||||
- [ ] Legend
|
- [ ] Legend
|
||||||
|
|
||||||
- [x] System Context
|
- [x] System Context
|
||||||
|
|
||||||
- [x] Person(alias, label, ?descr, ?sprite, ?tags, $link)
|
- [x] Person(alias, label, ?descr, ?sprite, ?tags, $link)
|
||||||
- [x] Person_Ext
|
- [x] Person_Ext
|
||||||
- [x] System(alias, label, ?descr, ?sprite, ?tags, $link)
|
- [x] System(alias, label, ?descr, ?sprite, ?tags, $link)
|
||||||
@@ -152,6 +153,7 @@ The following unfinished features are not supported in the short term.
|
|||||||
- [x] System_Boundary
|
- [x] System_Boundary
|
||||||
|
|
||||||
- [x] Container diagram
|
- [x] Container diagram
|
||||||
|
|
||||||
- [x] Container(alias, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
- [x] Container(alias, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
||||||
- [x] ContainerDb
|
- [x] ContainerDb
|
||||||
- [x] ContainerQueue
|
- [x] ContainerQueue
|
||||||
@@ -161,6 +163,7 @@ The following unfinished features are not supported in the short term.
|
|||||||
- [x] Container_Boundary(alias, label, ?tags, $link)
|
- [x] Container_Boundary(alias, label, ?tags, $link)
|
||||||
|
|
||||||
- [x] Component diagram
|
- [x] Component diagram
|
||||||
|
|
||||||
- [x] Component(alias, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
- [x] Component(alias, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
||||||
- [x] ComponentDb
|
- [x] ComponentDb
|
||||||
- [x] ComponentQueue
|
- [x] ComponentQueue
|
||||||
@@ -169,15 +172,18 @@ The following unfinished features are not supported in the short term.
|
|||||||
- [x] ComponentQueue_Ext
|
- [x] ComponentQueue_Ext
|
||||||
|
|
||||||
- [x] Dynamic diagram
|
- [x] Dynamic diagram
|
||||||
|
|
||||||
- [x] RelIndex(index, from, to, label, ?tags, $link)
|
- [x] RelIndex(index, from, to, label, ?tags, $link)
|
||||||
|
|
||||||
- [x] Deployment diagram
|
- [x] Deployment diagram
|
||||||
|
|
||||||
- [x] Deployment_Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link)
|
- [x] Deployment_Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link)
|
||||||
- [x] Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link): short name of Deployment_Node()
|
- [x] Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link): short name of Deployment_Node()
|
||||||
- [x] Node_L(alias, label, ?type, ?descr, ?sprite, ?tags, $link): left aligned Node()
|
- [x] Node_L(alias, label, ?type, ?descr, ?sprite, ?tags, $link): left aligned Node()
|
||||||
- [x] Node_R(alias, label, ?type, ?descr, ?sprite, ?tags, $link): right aligned Node()
|
- [x] Node_R(alias, label, ?type, ?descr, ?sprite, ?tags, $link): right aligned Node()
|
||||||
|
|
||||||
- [x] Relationship Types
|
- [x] Relationship Types
|
||||||
|
|
||||||
- [x] Rel(from, to, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
- [x] Rel(from, to, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
||||||
- [x] BiRel (bidirectional relationship)
|
- [x] BiRel (bidirectional relationship)
|
||||||
- [x] Rel_U, Rel_Up
|
- [x] Rel_U, Rel_Up
|
||||||
|
|||||||
@@ -360,8 +360,7 @@ gantt
|
|||||||
weekday monday
|
weekday monday
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Warning**
|
> **Warning** > `millisecond` and `second` support was added in v10.3.0
|
||||||
> `millisecond` and `second` support was added in v10.3.0
|
|
||||||
|
|
||||||
## Output in compact mode
|
## Output in compact mode
|
||||||
|
|
||||||
|
|||||||
@@ -329,11 +329,7 @@ Messages can be of two displayed either solid or with a dotted line.
|
|||||||
[Actor][Arrow][Actor]:Message text
|
[Actor][Arrow][Actor]:Message text
|
||||||
```
|
```
|
||||||
|
|
||||||
Lines can be solid or dotted, and can end with various types of arrowheads, crosses, or open arrows.
|
There are ten types of arrows currently supported:
|
||||||
|
|
||||||
#### Supported Arrow Types
|
|
||||||
|
|
||||||
**Standard Arrow Types**
|
|
||||||
|
|
||||||
| Type | Description |
|
| Type | Description |
|
||||||
| -------- | ---------------------------------------------------- |
|
| -------- | ---------------------------------------------------- |
|
||||||
@@ -348,58 +344,6 @@ Lines can be solid or dotted, and can end with various types of arrowheads, cros
|
|||||||
| `-)` | Solid line with an open arrow at the end (async) |
|
| `-)` | Solid line with an open arrow at the end (async) |
|
||||||
| `--)` | Dotted line with a open arrow at the end (async) |
|
| `--)` | Dotted line with a open arrow at the end (async) |
|
||||||
|
|
||||||
**Half-Arrows (v\<MERMAID_RELEASE_VERSION>+)**
|
|
||||||
|
|
||||||
The following half-arrow types are supported for more expressive sequence diagrams. Both solid and dotted variants are available by increasing the number of dashes (`-` → `--`).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
| Type | Description |
|
|
||||||
| ------- | ---------------------------------------------------- |
|
|
||||||
| `-\|\` | Solid line with top half arrowhead |
|
|
||||||
| `--\|\` | Dotted line with top half arrowhead |
|
|
||||||
| `-\|/` | Solid line with bottom half arrowhead |
|
|
||||||
| `--\|/` | Dotted line with bottom half arrowhead |
|
|
||||||
| `/\|-` | Solid line with reverse top half arrowhead |
|
|
||||||
| `/\|--` | Dotted line with reverse top half arrowhead |
|
|
||||||
| `\\-` | Solid line with reverse bottom half arrowhead |
|
|
||||||
| `\\--` | Dotted line with reverse bottom half arrowhead |
|
|
||||||
| `-\\` | Solid line with top stick half arrowhead |
|
|
||||||
| `--\\` | Dotted line with top stick half arrowhead |
|
|
||||||
| `-//` | Solid line with bottom stick half arrowhead |
|
|
||||||
| `--//` | Dotted line with bottom stick half arrowhead |
|
|
||||||
| `//-` | Solid line with reverse top stick half arrowhead |
|
|
||||||
| `//--` | Dotted line with reverse top stick half arrowhead |
|
|
||||||
| `\\-` | Solid line with reverse bottom stick half arrowhead |
|
|
||||||
| `\\--` | Dotted line with reverse bottom stick half arrowhead |
|
|
||||||
|
|
||||||
## Central Connections (v\<MERMAID_RELEASE_VERSION>+)
|
|
||||||
|
|
||||||
Mermaid sequence diagrams support **central lifeline connections** using a `()`.
|
|
||||||
This is useful to represent messages or signals that connect to a central point, rather than from one actor directly to another.
|
|
||||||
|
|
||||||
To indicate a central connection, append `()` to the arrow syntax.
|
|
||||||
|
|
||||||
#### Basic Syntax
|
|
||||||
|
|
||||||
```mermaid-example
|
|
||||||
sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant John
|
|
||||||
Alice->>()John: Hello John
|
|
||||||
Alice()->>John: How are you?
|
|
||||||
John()->>()Alice: Great!
|
|
||||||
```
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant John
|
|
||||||
Alice->>()John: Hello John
|
|
||||||
Alice()->>John: How are you?
|
|
||||||
John()->>()Alice: Great!
|
|
||||||
```
|
|
||||||
|
|
||||||
## Activations
|
## Activations
|
||||||
|
|
||||||
It is possible to activate and deactivate an actor. (de)activation can be dedicated declarations:
|
It is possible to activate and deactivate an actor. (de)activation can be dedicated declarations:
|
||||||
|
|||||||
54
package.json
54
package.json
@@ -63,36 +63,36 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@applitools/eyes-cypress": "^3.55.2",
|
"@applitools/eyes-cypress": "^3.44.9",
|
||||||
"@argos-ci/cypress": "^6.1.1",
|
"@argos-ci/cypress": "^5.0.2",
|
||||||
"@changesets/changelog-github": "^0.5.1",
|
"@changesets/changelog-github": "^0.5.1",
|
||||||
"@changesets/cli": "^2.29.7",
|
"@changesets/cli": "^2.27.12",
|
||||||
"@cspell/eslint-plugin": "^8.19.4",
|
"@cspell/eslint-plugin": "^8.19.4",
|
||||||
"@cypress/code-coverage": "^3.14.6",
|
"@cypress/code-coverage": "^3.12.49",
|
||||||
"@eslint/js": "^9.26.0",
|
"@eslint/js": "^9.26.0",
|
||||||
"@rollup/plugin-typescript": "^12.1.4",
|
"@rollup/plugin-typescript": "^12.1.2",
|
||||||
"@types/cors": "^2.8.19",
|
"@types/cors": "^2.8.17",
|
||||||
"@types/express": "^5.0.3",
|
"@types/express": "^5.0.0",
|
||||||
"@types/js-yaml": "^4.0.9",
|
"@types/js-yaml": "^4.0.9",
|
||||||
"@types/jsdom": "^21.1.7",
|
"@types/jsdom": "^21.1.7",
|
||||||
"@types/lodash": "^4.17.20",
|
"@types/lodash": "^4.17.15",
|
||||||
"@types/mdast": "^4.0.4",
|
"@types/mdast": "^4.0.4",
|
||||||
"@types/node": "^22.18.6",
|
"@types/node": "^22.13.5",
|
||||||
"@types/rollup-plugin-visualizer": "^5.0.3",
|
"@types/rollup-plugin-visualizer": "^5.0.3",
|
||||||
"@vitest/coverage-v8": "^3.2.4",
|
"@vitest/coverage-v8": "^3.0.6",
|
||||||
"@vitest/spy": "^3.2.4",
|
"@vitest/spy": "^3.0.6",
|
||||||
"@vitest/ui": "^3.2.4",
|
"@vitest/ui": "^3.0.6",
|
||||||
"ajv": "^8.17.1",
|
"ajv": "^8.17.1",
|
||||||
"chokidar": "3.6.0",
|
"chokidar": "3.6.0",
|
||||||
"concurrently": "^9.2.1",
|
"concurrently": "^9.1.2",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"cpy-cli": "^5.0.0",
|
"cpy-cli": "^5.0.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"cspell": "^9.2.1",
|
"cspell": "^9.1.3",
|
||||||
"cypress": "^14.5.4",
|
"cypress": "^14.5.1",
|
||||||
"cypress-image-snapshot": "^4.0.1",
|
"cypress-image-snapshot": "^4.0.1",
|
||||||
"cypress-split": "^1.24.23",
|
"cypress-split": "^1.24.14",
|
||||||
"esbuild": "^0.25.10",
|
"esbuild": "^0.25.0",
|
||||||
"eslint": "^9.26.0",
|
"eslint": "^9.26.0",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-cypress": "^4.3.0",
|
"eslint-plugin-cypress": "^4.3.0",
|
||||||
@@ -106,30 +106,30 @@
|
|||||||
"eslint-plugin-tsdoc": "^0.4.0",
|
"eslint-plugin-tsdoc": "^0.4.0",
|
||||||
"eslint-plugin-unicorn": "^59.0.1",
|
"eslint-plugin-unicorn": "^59.0.1",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"globals": "^16.4.0",
|
"globals": "^16.0.0",
|
||||||
"globby": "^14.1.0",
|
"globby": "^14.0.2",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"jest": "^30.1.3",
|
"jest": "^30.0.4",
|
||||||
"jison": "^0.4.18",
|
"jison": "^0.4.18",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"jsdom": "^26.1.0",
|
"jsdom": "^26.1.0",
|
||||||
"langium-cli": "3.3.0",
|
"langium-cli": "3.3.0",
|
||||||
"lint-staged": "^16.1.6",
|
"lint-staged": "^16.1.2",
|
||||||
"markdown-table": "^3.0.4",
|
"markdown-table": "^3.0.4",
|
||||||
"nyc": "^17.1.0",
|
"nyc": "^17.1.0",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.5.2",
|
||||||
"prettier-plugin-jsdoc": "^1.3.3",
|
"prettier-plugin-jsdoc": "^1.3.2",
|
||||||
"rimraf": "^6.0.1",
|
"rimraf": "^6.0.1",
|
||||||
"rollup-plugin-visualizer": "^6.0.3",
|
"rollup-plugin-visualizer": "^6.0.3",
|
||||||
"start-server-and-test": "^2.1.2",
|
"start-server-and-test": "^2.0.10",
|
||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"tsx": "^4.20.5",
|
"tsx": "^4.7.3",
|
||||||
"typescript": "~5.7.3",
|
"typescript": "~5.7.3",
|
||||||
"typescript-eslint": "^8.38.0",
|
"typescript-eslint": "^8.38.0",
|
||||||
"vite": "^7.0.7",
|
"vite": "^7.0.3",
|
||||||
"vite-plugin-istanbul": "^7.0.0",
|
"vite-plugin-istanbul": "^7.0.0",
|
||||||
"vitest": "^3.2.4"
|
"vitest": "^3.0.6"
|
||||||
},
|
},
|
||||||
"nyc": {
|
"nyc": {
|
||||||
"report-dir": "coverage/cypress"
|
"report-dir": "coverage/cypress"
|
||||||
|
|||||||
@@ -37,12 +37,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@braintree/sanitize-url": "^7.1.1",
|
"@braintree/sanitize-url": "^7.0.4",
|
||||||
"d3": "^7.9.0",
|
"d3": "^7.9.0",
|
||||||
"khroma": "^2.1.0"
|
"khroma": "^2.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"concurrently": "^9.2.1",
|
"concurrently": "^9.1.2",
|
||||||
"mermaid": "workspace:*",
|
"mermaid": "workspace:*",
|
||||||
"rimraf": "^6.0.1"
|
"rimraf": "^6.0.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,16 +1,5 @@
|
|||||||
# @mermaid-js/layout-elk
|
# @mermaid-js/layout-elk
|
||||||
|
|
||||||
## 0.2.0
|
|
||||||
|
|
||||||
### Minor Changes
|
|
||||||
|
|
||||||
- [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes
|
|
||||||
|
|
||||||
### Patch Changes
|
|
||||||
|
|
||||||
- Updated dependencies [[`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800), [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20), [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05), [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8)]:
|
|
||||||
- mermaid@11.11.0
|
|
||||||
|
|
||||||
## 0.1.9
|
## 0.1.9
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@mermaid-js/layout-elk",
|
"name": "@mermaid-js/layout-elk",
|
||||||
"version": "0.2.0",
|
"version": "0.1.9",
|
||||||
"description": "ELK layout engine for mermaid",
|
"description": "ELK layout engine for mermaid",
|
||||||
"module": "dist/mermaid-layout-elk.core.mjs",
|
"module": "dist/mermaid-layout-elk.core.mjs",
|
||||||
"types": "dist/layouts.d.ts",
|
"types": "dist/layouts.d.ts",
|
||||||
|
|||||||
@@ -67,22 +67,7 @@ export const render = async (
|
|||||||
|
|
||||||
// Add the element to the DOM
|
// Add the element to the DOM
|
||||||
if (!node.isGroup) {
|
if (!node.isGroup) {
|
||||||
// const child = node as NodeWithVertex;
|
const child = node as NodeWithVertex;
|
||||||
const child: NodeWithVertex = {
|
|
||||||
id: node.id,
|
|
||||||
width: node.width,
|
|
||||||
height: node.height,
|
|
||||||
// Store the original node data for later use
|
|
||||||
label: node.label,
|
|
||||||
isGroup: node.isGroup,
|
|
||||||
shape: node.shape,
|
|
||||||
padding: node.padding,
|
|
||||||
cssClasses: node.cssClasses,
|
|
||||||
cssStyles: node.cssStyles,
|
|
||||||
look: node.look,
|
|
||||||
// Include parentId for subgraph processing
|
|
||||||
parentId: node.parentId,
|
|
||||||
};
|
|
||||||
graph.children.push(child);
|
graph.children.push(child);
|
||||||
nodeDb[node.id] = node;
|
nodeDb[node.id] = node;
|
||||||
|
|
||||||
@@ -165,7 +150,7 @@ export const render = async (
|
|||||||
domId: { node: () => any; attr: (arg0: string, arg1: string) => void };
|
domId: { node: () => any; attr: (arg0: string, arg1: string) => void };
|
||||||
}) {
|
}) {
|
||||||
if (node) {
|
if (node) {
|
||||||
nodeDb[node.id] ??= {};
|
nodeDb[node.id] = node;
|
||||||
nodeDb[node.id].offset = {
|
nodeDb[node.id].offset = {
|
||||||
posX: node.x + relX,
|
posX: node.x + relX,
|
||||||
posY: node.y + relY,
|
posY: node.y + relY,
|
||||||
@@ -875,13 +860,11 @@ export const render = async (
|
|||||||
log.info('APA01 layout result:', JSON.stringify(g, null, 2));
|
log.info('APA01 layout result:', JSON.stringify(g, null, 2));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error('APA01 ELK layout error:', error);
|
log.error('APA01 ELK layout error:', error);
|
||||||
log.error('APA01 elkGraph that caused error:', JSON.stringify(elkGraph, null, 2));
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// debugger;
|
// debugger;
|
||||||
await drawNodes(0, 0, g.children, svg, subGraphsEl, 0);
|
await drawNodes(0, 0, g.children, svg, subGraphsEl, 0);
|
||||||
|
|
||||||
g.edges?.map(
|
g.edges?.map(
|
||||||
(edge: {
|
(edge: {
|
||||||
sources: (string | number)[];
|
sources: (string | number)[];
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
# @mermaid-js/layout-tidy-tree
|
|
||||||
|
|
||||||
## 0.2.0
|
|
||||||
|
|
||||||
### Minor Changes
|
|
||||||
|
|
||||||
- [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes
|
|
||||||
|
|
||||||
### Patch Changes
|
|
||||||
|
|
||||||
- Updated dependencies [[`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800), [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20), [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05), [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8)]:
|
|
||||||
- mermaid@11.11.0
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@mermaid-js/layout-tidy-tree",
|
"name": "@mermaid-js/layout-tidy-tree",
|
||||||
"version": "0.2.0",
|
"version": "0.1.0",
|
||||||
"description": "Tidy-tree layout engine for mermaid",
|
"description": "Tidy-tree layout engine for mermaid",
|
||||||
"module": "dist/mermaid-layout-tidy-tree.core.mjs",
|
"module": "dist/mermaid-layout-tidy-tree.core.mjs",
|
||||||
"types": "dist/layouts.d.ts",
|
"types": "dist/layouts.d.ts",
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@zenuml/core": "^3.41.4"
|
"@zenuml/core": "^3.35.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mermaid": "workspace:^"
|
"mermaid": "workspace:^"
|
||||||
|
|||||||
@@ -1,19 +1,5 @@
|
|||||||
# mermaid
|
# mermaid
|
||||||
|
|
||||||
## 11.11.0
|
|
||||||
|
|
||||||
### Minor Changes
|
|
||||||
|
|
||||||
- [#6704](https://github.com/mermaid-js/mermaid/pull/6704) [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05) Thanks [@omkarht](https://github.com/omkarht)! - feat: Added support for new participant types (`actor`, `boundary`, `control`, `entity`, `database`, `collections`, `queue`) in `sequenceDiagram`.
|
|
||||||
|
|
||||||
- [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes
|
|
||||||
|
|
||||||
### Patch Changes
|
|
||||||
|
|
||||||
- [#6905](https://github.com/mermaid-js/mermaid/pull/6905) [`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Render newlines as spaces in class diagrams
|
|
||||||
|
|
||||||
- [#6886](https://github.com/mermaid-js/mermaid/pull/6886) [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Handle arrows correctly when auto number is enabled
|
|
||||||
|
|
||||||
## 11.10.0
|
## 11.10.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
@@ -168,6 +154,7 @@
|
|||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
- [#6408](https://github.com/mermaid-js/mermaid/pull/6408) [`ad65313`](https://github.com/mermaid-js/mermaid/commit/ad653138e16765d095613a6e5de86dc5e52ac8f0) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - fix: restore curve type configuration functionality for flowcharts. This fixes the issue where curve type settings were not being applied when configured through any of the following methods:
|
- [#6408](https://github.com/mermaid-js/mermaid/pull/6408) [`ad65313`](https://github.com/mermaid-js/mermaid/commit/ad653138e16765d095613a6e5de86dc5e52ac8f0) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - fix: restore curve type configuration functionality for flowcharts. This fixes the issue where curve type settings were not being applied when configured through any of the following methods:
|
||||||
|
|
||||||
- Config
|
- Config
|
||||||
- Init directive (%%{ init: { 'flowchart': { 'curve': '...' } } }%%)
|
- Init directive (%%{ init: { 'flowchart': { 'curve': '...' } } }%%)
|
||||||
- LinkStyle command (linkStyle default interpolate ...)
|
- LinkStyle command (linkStyle default interpolate ...)
|
||||||
@@ -186,12 +173,14 @@
|
|||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
- [#6187](https://github.com/mermaid-js/mermaid/pull/6187) [`7809b5a`](https://github.com/mermaid-js/mermaid/commit/7809b5a93fae127f45727071f5ff14325222c518) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Flowchart new syntax for node metadata bugs
|
- [#6187](https://github.com/mermaid-js/mermaid/pull/6187) [`7809b5a`](https://github.com/mermaid-js/mermaid/commit/7809b5a93fae127f45727071f5ff14325222c518) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Flowchart new syntax for node metadata bugs
|
||||||
|
|
||||||
- Incorrect label mapping for nodes when using `&`
|
- Incorrect label mapping for nodes when using `&`
|
||||||
- Syntax error when `}` with trailing spaces before new line
|
- Syntax error when `}` with trailing spaces before new line
|
||||||
|
|
||||||
- [#6136](https://github.com/mermaid-js/mermaid/pull/6136) [`ec0d9c3`](https://github.com/mermaid-js/mermaid/commit/ec0d9c389aa6018043187654044c1e0b5aa4f600) Thanks [@knsv](https://github.com/knsv)! - Adding support for animation of flowchart edges
|
- [#6136](https://github.com/mermaid-js/mermaid/pull/6136) [`ec0d9c3`](https://github.com/mermaid-js/mermaid/commit/ec0d9c389aa6018043187654044c1e0b5aa4f600) Thanks [@knsv](https://github.com/knsv)! - Adding support for animation of flowchart edges
|
||||||
|
|
||||||
- [#6373](https://github.com/mermaid-js/mermaid/pull/6373) [`05bdf0e`](https://github.com/mermaid-js/mermaid/commit/05bdf0e20e2629fe77513218fbd4e28e65f75882) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Upgrade Requirement and ER diagram to use the common renderer flow
|
- [#6373](https://github.com/mermaid-js/mermaid/pull/6373) [`05bdf0e`](https://github.com/mermaid-js/mermaid/commit/05bdf0e20e2629fe77513218fbd4e28e65f75882) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Upgrade Requirement and ER diagram to use the common renderer flow
|
||||||
|
|
||||||
- Added support for directions
|
- Added support for directions
|
||||||
- Added support for hand drawn look
|
- Added support for hand drawn look
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mermaid",
|
"name": "mermaid",
|
||||||
"version": "11.11.0",
|
"version": "11.10.0",
|
||||||
"description": "Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.",
|
"description": "Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"module": "./dist/mermaid.core.mjs",
|
"module": "./dist/mermaid.core.mjs",
|
||||||
@@ -67,29 +67,29 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@braintree/sanitize-url": "^7.1.1",
|
"@braintree/sanitize-url": "^7.0.4",
|
||||||
"@iconify/utils": "^3.0.2",
|
"@iconify/utils": "^3.0.1",
|
||||||
"@mermaid-js/parser": "workspace:^",
|
"@mermaid-js/parser": "workspace:^",
|
||||||
"@types/d3": "^7.4.3",
|
"@types/d3": "^7.4.3",
|
||||||
"cytoscape": "^3.33.1",
|
"cytoscape": "^3.29.3",
|
||||||
"cytoscape-cose-bilkent": "^4.1.0",
|
"cytoscape-cose-bilkent": "^4.1.0",
|
||||||
"cytoscape-fcose": "^2.2.0",
|
"cytoscape-fcose": "^2.2.0",
|
||||||
"d3": "^7.9.0",
|
"d3": "^7.9.0",
|
||||||
"d3-sankey": "^0.12.3",
|
"d3-sankey": "^0.12.3",
|
||||||
"dagre-d3-es": "7.0.11",
|
"dagre-d3-es": "7.0.11",
|
||||||
"dayjs": "^1.11.18",
|
"dayjs": "^1.11.13",
|
||||||
"dompurify": "^3.2.5",
|
"dompurify": "^3.2.5",
|
||||||
"katex": "^0.16.22",
|
"katex": "^0.16.22",
|
||||||
"khroma": "^2.1.0",
|
"khroma": "^2.1.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"marked": "^16.3.0",
|
"marked": "^16.0.0",
|
||||||
"roughjs": "^4.6.6",
|
"roughjs": "^4.6.6",
|
||||||
"stylis": "^4.3.6",
|
"stylis": "^4.3.6",
|
||||||
"ts-dedent": "^2.2.0",
|
"ts-dedent": "^2.2.0",
|
||||||
"uuid": "^11.1.0"
|
"uuid": "^11.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@adobe/jsonschema2md": "^8.0.5",
|
"@adobe/jsonschema2md": "^8.0.2",
|
||||||
"@iconify/types": "^2.0.0",
|
"@iconify/types": "^2.0.0",
|
||||||
"@types/cytoscape": "^3.21.9",
|
"@types/cytoscape": "^3.21.9",
|
||||||
"@types/cytoscape-fcose": "^2.2.4",
|
"@types/cytoscape-fcose": "^2.2.4",
|
||||||
@@ -105,30 +105,30 @@
|
|||||||
"@types/stylis": "^4.2.7",
|
"@types/stylis": "^4.2.7",
|
||||||
"@types/uuid": "^10.0.0",
|
"@types/uuid": "^10.0.0",
|
||||||
"ajv": "^8.17.1",
|
"ajv": "^8.17.1",
|
||||||
"canvas": "^3.2.0",
|
"canvas": "^3.1.0",
|
||||||
"chokidar": "3.6.0",
|
"chokidar": "3.6.0",
|
||||||
"concurrently": "^9.2.1",
|
"concurrently": "^9.1.2",
|
||||||
"csstree-validator": "^4.0.1",
|
"csstree-validator": "^4.0.1",
|
||||||
"globby": "^14.1.0",
|
"globby": "^14.0.2",
|
||||||
"jison": "^0.4.18",
|
"jison": "^0.4.18",
|
||||||
"js-base64": "^3.7.8",
|
"js-base64": "^3.7.7",
|
||||||
"jsdom": "^26.1.0",
|
"jsdom": "^26.1.0",
|
||||||
"json-schema-to-typescript": "^15.0.4",
|
"json-schema-to-typescript": "^15.0.4",
|
||||||
"micromatch": "^4.0.8",
|
"micromatch": "^4.0.8",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.5.2",
|
||||||
"remark": "^15.0.1",
|
"remark": "^15.0.1",
|
||||||
"remark-frontmatter": "^5.0.0",
|
"remark-frontmatter": "^5.0.0",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"rimraf": "^6.0.1",
|
"rimraf": "^6.0.1",
|
||||||
"start-server-and-test": "^2.1.2",
|
"start-server-and-test": "^2.0.10",
|
||||||
"type-fest": "^4.41.0",
|
"type-fest": "^4.35.0",
|
||||||
"typedoc": "^0.28.13",
|
"typedoc": "^0.28.9",
|
||||||
"typedoc-plugin-markdown": "^4.8.1",
|
"typedoc-plugin-markdown": "^4.8.0",
|
||||||
"typescript": "~5.7.3",
|
"typescript": "~5.7.3",
|
||||||
"unist-util-flatmap": "^1.0.0",
|
"unist-util-flatmap": "^1.0.0",
|
||||||
"unist-util-visit": "^5.0.0",
|
"unist-util-visit": "^5.0.0",
|
||||||
"vitepress": "^1.6.4",
|
"vitepress": "^1.0.2",
|
||||||
"vitepress-plugin-search": "1.0.4-alpha.22"
|
"vitepress-plugin-search": "1.0.4-alpha.22"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
@@ -66,15 +66,12 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
|||||||
\}\| return 'ONE_OR_MORE';
|
\}\| return 'ONE_OR_MORE';
|
||||||
"one" return 'ONLY_ONE';
|
"one" return 'ONLY_ONE';
|
||||||
"only one" return 'ONLY_ONE';
|
"only one" return 'ONLY_ONE';
|
||||||
[0-9]+\.[0-9]+ return 'DECIMAL_NUM';
|
"1" return 'ONLY_ONE';
|
||||||
"1"(?=\s+[A-Za-z_"']) return 'ONLY_ONE';
|
|
||||||
"1" return 'ENTITY_ONE';
|
|
||||||
[0-9]+ return 'NUM';
|
|
||||||
\|\| return 'ONLY_ONE';
|
\|\| return 'ONLY_ONE';
|
||||||
o\| return 'ZERO_OR_ONE';
|
o\| return 'ZERO_OR_ONE';
|
||||||
o\{ return 'ZERO_OR_MORE';
|
o\{ return 'ZERO_OR_MORE';
|
||||||
\|\{ return 'ONE_OR_MORE';
|
\|\{ return 'ONE_OR_MORE';
|
||||||
u(?=[\.\-\|]) return 'MD_PARENT';
|
\s*u return 'MD_PARENT';
|
||||||
\.\. return 'NON_IDENTIFYING';
|
\.\. return 'NON_IDENTIFYING';
|
||||||
\-\- return 'IDENTIFYING';
|
\-\- return 'IDENTIFYING';
|
||||||
"to" return 'IDENTIFYING';
|
"to" return 'IDENTIFYING';
|
||||||
@@ -83,15 +80,13 @@ u(?=[\.\-\|]) return 'MD_PARENT';
|
|||||||
\-\. return 'NON_IDENTIFYING';
|
\-\. return 'NON_IDENTIFYING';
|
||||||
<style>([^\x00-\x7F]|\w|\-|\*)+ return 'STYLE_TEXT';
|
<style>([^\x00-\x7F]|\w|\-|\*)+ return 'STYLE_TEXT';
|
||||||
<style>';' return 'SEMI';
|
<style>';' return 'SEMI';
|
||||||
([^\x00-\x7F]|\w|\-|\*|\.)+ return 'UNICODE_TEXT';
|
([^\x00-\x7F]|\w|\-|\*)+ return 'UNICODE_TEXT';
|
||||||
|
[0-9] return 'NUM';
|
||||||
. return yytext[0];
|
. return yytext[0];
|
||||||
<<EOF>> return 'EOF';
|
<<EOF>> return 'EOF';
|
||||||
|
|
||||||
/lex
|
/lex
|
||||||
|
|
||||||
%left 'ONLY_ONE'
|
|
||||||
%left 'ZERO_OR_ONE' 'ZERO_OR_MORE' 'ONE_OR_MORE' 'MD_PARENT'
|
|
||||||
|
|
||||||
%start start
|
%start start
|
||||||
%% /* language grammar */
|
%% /* language grammar */
|
||||||
|
|
||||||
@@ -233,9 +228,6 @@ styleComponent: STYLE_TEXT | NUM | COLON | BRKT;
|
|||||||
entityName
|
entityName
|
||||||
: 'ENTITY_NAME' { $$ = $1.replace(/"/g, ''); }
|
: 'ENTITY_NAME' { $$ = $1.replace(/"/g, ''); }
|
||||||
| 'UNICODE_TEXT' { $$ = $1; }
|
| 'UNICODE_TEXT' { $$ = $1; }
|
||||||
| 'NUM' { $$ = $1; }
|
|
||||||
| 'DECIMAL_NUM' { $$ = $1; }
|
|
||||||
| 'ENTITY_ONE' { $$ = $1; }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
attributes
|
attributes
|
||||||
|
|||||||
@@ -1001,90 +1001,4 @@ describe('when parsing ER diagram it...', function () {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('syntax fixes for special characters and numbers', function () {
|
|
||||||
describe('standalone entity names', function () {
|
|
||||||
it('should allow number "1" as standalone entity', function () {
|
|
||||||
erDiagram.parser.parse(`erDiagram\nCUSTOMER }|..|{ DELIVERY-ADDRESS : has\n1`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow character "u" as standalone entity', function () {
|
|
||||||
erDiagram.parser.parse(`erDiagram\nCUSTOMER }|..|{ DELIVERY-ADDRESS : has\nu`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow decimal numbers as standalone entities', function () {
|
|
||||||
erDiagram.parser.parse(`erDiagram\nCUSTOMER }|..|{ DELIVERY-ADDRESS : has\n2.5`);
|
|
||||||
erDiagram.parser.parse(`erDiagram\nCUSTOMER }|..|{ DELIVERY-ADDRESS : has\n1.5`);
|
|
||||||
erDiagram.parser.parse(`erDiagram\nCUSTOMER }|..|{ DELIVERY-ADDRESS : has\n0.1`);
|
|
||||||
erDiagram.parser.parse(`erDiagram\nCUSTOMER }|..|{ DELIVERY-ADDRESS : has\n99.99`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('entity names with attributes', function () {
|
|
||||||
it('should allow "u" as entity name with attributes', function () {
|
|
||||||
erDiagram.parser.parse(`erDiagram\nu {\nstring name\nint id\n}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow number "1" as entity name with attributes', function () {
|
|
||||||
erDiagram.parser.parse(`erDiagram\n1 {\nstring name\nint id\n}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow decimal numbers as entity names with attributes', function () {
|
|
||||||
erDiagram.parser.parse(`erDiagram\n2.5 {\nstring name\nint id\n}`);
|
|
||||||
erDiagram.parser.parse(`erDiagram\n1.5 {\nstring value\n}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('entity names in relationships', function () {
|
|
||||||
it('should allow "u" in relationships', function () {
|
|
||||||
erDiagram.parser.parse(`erDiagram\nCUSTOMER ||--|| u : has`);
|
|
||||||
erDiagram.parser.parse(`erDiagram\nu ||--|| ORDER : places`);
|
|
||||||
erDiagram.parser.parse(`erDiagram\nu ||--|| v : connects`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow numbers in relationships', function () {
|
|
||||||
erDiagram.parser.parse(`erDiagram\nCUSTOMER ||--|| 1 : has`);
|
|
||||||
erDiagram.parser.parse(`erDiagram\n1 ||--|| ORDER : places`);
|
|
||||||
erDiagram.parser.parse(`erDiagram\n1 ||--|| 2 : connects`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow decimal numbers in relationships', function () {
|
|
||||||
erDiagram.parser.parse(`erDiagram\nCUSTOMER ||--|| 2.5 : has`);
|
|
||||||
erDiagram.parser.parse(`erDiagram\n1.5 ||--|| ORDER : places`);
|
|
||||||
erDiagram.parser.parse(`erDiagram\n2.5 ||--|| 5.5 : connects`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('mixed scenarios', function () {
|
|
||||||
it('should handle complex diagram with special entity names', function () {
|
|
||||||
erDiagram.parser.parse(
|
|
||||||
`erDiagram
|
|
||||||
CUSTOMER ||--o{ 1 : places
|
|
||||||
1 ||--|{ u : contains
|
|
||||||
u {
|
|
||||||
string name
|
|
||||||
int quantity
|
|
||||||
}
|
|
||||||
"2.5" ||--|| ORDER : processes
|
|
||||||
ORDER {
|
|
||||||
int id
|
|
||||||
date created
|
|
||||||
}
|
|
||||||
`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle attributes with numbers in names (but not starting)', function () {
|
|
||||||
erDiagram.parser.parse(
|
|
||||||
`erDiagram
|
|
||||||
ENTITY {
|
|
||||||
string name1
|
|
||||||
int value2
|
|
||||||
float point3_5
|
|
||||||
}
|
|
||||||
`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,223 +0,0 @@
|
|||||||
import { log } from '../../logger.js';
|
|
||||||
import type { D3Selection } from '../../types.js';
|
|
||||||
import type { Node } from '../../rendering-util/types.js';
|
|
||||||
import { getIconSVG, isIconAvailable } from '../../rendering-util/icons.js';
|
|
||||||
|
|
||||||
export interface MindmapIconConfig {
|
|
||||||
iconSize: number;
|
|
||||||
iconPadding: number;
|
|
||||||
shapeType: 'circle' | 'rect' | 'rounded' | 'bang' | 'cloud' | 'hexagon' | 'default';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MindmapDimensions {
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
labelOffset: { x: number; y: number };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get icon configuration for different mindmap shape types
|
|
||||||
*/
|
|
||||||
export function getMindmapIconConfig(shapeType: string): MindmapIconConfig {
|
|
||||||
const baseConfig = {
|
|
||||||
iconSize: 30,
|
|
||||||
iconPadding: 15,
|
|
||||||
shapeType: shapeType as MindmapIconConfig['shapeType'],
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (shapeType) {
|
|
||||||
case 'bang':
|
|
||||||
return { ...baseConfig, iconPadding: 1 };
|
|
||||||
case 'rect':
|
|
||||||
case 'default':
|
|
||||||
return { ...baseConfig, iconPadding: 10 };
|
|
||||||
default:
|
|
||||||
return baseConfig;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate dimensions and label positioning for mindmap nodes with icons
|
|
||||||
*/
|
|
||||||
export function calculateMindmapDimensions(
|
|
||||||
node: Node,
|
|
||||||
bbox: any,
|
|
||||||
baseWidth: number,
|
|
||||||
baseHeight: number,
|
|
||||||
basePadding: number,
|
|
||||||
config: MindmapIconConfig
|
|
||||||
): MindmapDimensions {
|
|
||||||
const hasIcon = Boolean(node.icon);
|
|
||||||
|
|
||||||
if (!hasIcon) {
|
|
||||||
return {
|
|
||||||
width: baseWidth,
|
|
||||||
height: baseHeight,
|
|
||||||
labelOffset: { x: -bbox.width / 2, y: -bbox.height / 2 },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const { iconSize, iconPadding, shapeType } = config;
|
|
||||||
let width = baseWidth;
|
|
||||||
let height = baseHeight;
|
|
||||||
let labelXOffset = -bbox.width / 2;
|
|
||||||
const labelYOffset = -bbox.height / 2;
|
|
||||||
|
|
||||||
switch (shapeType) {
|
|
||||||
case 'circle': {
|
|
||||||
const totalWidthNeeded = bbox.width + iconSize + iconPadding * 2;
|
|
||||||
const minRadiusWithIcon = totalWidthNeeded / 2 + basePadding;
|
|
||||||
const radius = Math.max(baseWidth / 2, minRadiusWithIcon);
|
|
||||||
width = radius * 2;
|
|
||||||
height = radius * 2;
|
|
||||||
labelXOffset = -radius + iconSize + iconPadding;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'rect':
|
|
||||||
case 'rounded':
|
|
||||||
case 'default': {
|
|
||||||
const minWidthWithIcon = bbox.width + iconSize + iconPadding * 2 + basePadding * 2;
|
|
||||||
width = Math.max(baseWidth, minWidthWithIcon);
|
|
||||||
height = Math.max(baseHeight, iconSize + basePadding * 2);
|
|
||||||
|
|
||||||
const availableTextSpace = width - iconSize - iconPadding * 2;
|
|
||||||
labelXOffset = -width / 2 + iconSize + iconPadding + availableTextSpace / 2 - bbox.width / 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'bang':
|
|
||||||
case 'cloud': {
|
|
||||||
const minWidthWithIcon = bbox.width + iconSize + iconPadding * 2 + basePadding;
|
|
||||||
width = Math.max(baseWidth, minWidthWithIcon);
|
|
||||||
height = Math.max(baseHeight, iconSize + basePadding);
|
|
||||||
|
|
||||||
const availableTextSpace = width - iconSize - iconPadding * 2;
|
|
||||||
labelXOffset = -width / 2 + iconSize + iconPadding + availableTextSpace / 2 - bbox.width / 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
const minWidthWithIcon = bbox.width + iconSize + iconPadding * 2 + basePadding * 2;
|
|
||||||
width = Math.max(baseWidth, minWidthWithIcon);
|
|
||||||
height = Math.max(baseHeight, iconSize + basePadding * 2);
|
|
||||||
|
|
||||||
const availableTextSpace = width - iconSize - iconPadding * 2;
|
|
||||||
labelXOffset = -width / 2 + iconSize + iconPadding + availableTextSpace / 2 - bbox.width / 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
labelOffset: { x: labelXOffset, y: labelYOffset },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert mindmap icon into the shape SVG element
|
|
||||||
*/
|
|
||||||
export async function insertMindmapIcon(
|
|
||||||
parentElement: D3Selection<SVGGraphicsElement>,
|
|
||||||
node: Node,
|
|
||||||
config: MindmapIconConfig
|
|
||||||
): Promise<void> {
|
|
||||||
if (!node.icon) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { iconSize, iconPadding, shapeType } = config;
|
|
||||||
const section = node.section === undefined ? -1 : node.section;
|
|
||||||
|
|
||||||
let iconName = node.icon;
|
|
||||||
const isCssFormat = iconName.includes(' ');
|
|
||||||
|
|
||||||
if (isCssFormat) {
|
|
||||||
iconName = iconName.replace(' ', ':');
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (await isIconAvailable(iconName)) {
|
|
||||||
const iconSvg = await getIconSVG(
|
|
||||||
iconName,
|
|
||||||
{
|
|
||||||
height: iconSize,
|
|
||||||
width: iconSize,
|
|
||||||
},
|
|
||||||
{ class: 'label-icon' }
|
|
||||||
);
|
|
||||||
|
|
||||||
const iconElem = parentElement.append('g');
|
|
||||||
iconElem.html(`<g>${iconSvg}</g>`);
|
|
||||||
|
|
||||||
let iconX = 0;
|
|
||||||
let iconY = 0;
|
|
||||||
|
|
||||||
switch (shapeType) {
|
|
||||||
case 'circle': {
|
|
||||||
const nodeWidth = node.width || 100;
|
|
||||||
const radius = nodeWidth / 2;
|
|
||||||
iconX = -radius + iconSize / 2 + iconPadding;
|
|
||||||
iconY = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
const nodeWidth = node.width || 100;
|
|
||||||
iconX = -nodeWidth / 2 + iconSize / 2 + iconPadding;
|
|
||||||
iconY = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iconElem.attr('transform', `translate(${iconX}, ${iconY})`);
|
|
||||||
// Use currentColor to inherit label color - works for all shapes including bang
|
|
||||||
iconElem.attr('style', 'color: currentColor;');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
log.debug('SVG icon rendering failed, falling back to CSS:', error);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to CSS approach (original mindmap behavior)
|
|
||||||
const iconClass = isCssFormat ? node.icon : node.icon.replace(':', ' ');
|
|
||||||
|
|
||||||
let iconX = 0;
|
|
||||||
const iconY = -iconSize / 2;
|
|
||||||
|
|
||||||
switch (shapeType) {
|
|
||||||
case 'circle': {
|
|
||||||
const nodeWidth = node.width || 100;
|
|
||||||
const radius = nodeWidth / 2;
|
|
||||||
iconX = -radius + iconPadding;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
const nodeWidth = node.width || 100;
|
|
||||||
iconX = -nodeWidth / 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const icon = parentElement
|
|
||||||
.append('foreignObject')
|
|
||||||
.attr('height', `${iconSize}px`)
|
|
||||||
.attr('width', `${iconSize}px`)
|
|
||||||
.attr('x', iconX)
|
|
||||||
.attr('y', iconY)
|
|
||||||
.attr(
|
|
||||||
'style',
|
|
||||||
'text-align: center; display: flex; align-items: center; justify-content: center;'
|
|
||||||
);
|
|
||||||
|
|
||||||
icon
|
|
||||||
.append('div')
|
|
||||||
.attr('class', 'icon-container')
|
|
||||||
.attr(
|
|
||||||
'style',
|
|
||||||
'width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;'
|
|
||||||
)
|
|
||||||
.append('i')
|
|
||||||
.attr('class', `node-icon-${section} ${iconClass}`)
|
|
||||||
.attr('style', `font-size: ${iconSize}px;`);
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,6 @@ import type { LayoutData } from '../../rendering-util/types.js';
|
|||||||
import type { FilledMindMapNode } from './mindmapTypes.js';
|
import type { FilledMindMapNode } from './mindmapTypes.js';
|
||||||
import defaultConfig from '../../defaultConfig.js';
|
import defaultConfig from '../../defaultConfig.js';
|
||||||
import type { MindmapDB } from './mindmapDb.js';
|
import type { MindmapDB } from './mindmapDb.js';
|
||||||
import { getMindmapIconConfig, insertMindmapIcon } from './mindmapIconHelper.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the layout data with actual node dimensions after drawing
|
* Update the layout data with actual node dimensions after drawing
|
||||||
@@ -72,28 +71,6 @@ export const draw: DrawDefinition = async (text, id, _version, diagObj) => {
|
|||||||
|
|
||||||
// Use the unified rendering system
|
// Use the unified rendering system
|
||||||
await render(data4Layout, svg);
|
await render(data4Layout, svg);
|
||||||
const genericShapes = ['hexagon', 'rect', 'rounded', 'squareRect'];
|
|
||||||
const nodesWithIcons = data4Layout.nodes.filter(
|
|
||||||
(node) => node.icon && genericShapes.includes(node.shape || '')
|
|
||||||
);
|
|
||||||
|
|
||||||
if (nodesWithIcons.length > 0) {
|
|
||||||
for (const node of nodesWithIcons) {
|
|
||||||
const nodeId = node.domId || node.id;
|
|
||||||
const nodeElement = svg.select(`g[id="${nodeId}"]`);
|
|
||||||
|
|
||||||
if (!nodeElement.empty()) {
|
|
||||||
try {
|
|
||||||
const iconConfig = getMindmapIconConfig(node.shape || 'default');
|
|
||||||
await insertMindmapIcon(nodeElement, node, iconConfig);
|
|
||||||
} catch (error) {
|
|
||||||
log.warn(`Failed to add icon to ${nodeId}:`, error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.warn(`Could not find DOM element for node ${nodeId}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the view box and size of the svg element using config from data4Layout
|
// Setup the view box and size of the svg element using config from data4Layout
|
||||||
setupViewPortForSVG(
|
setupViewPortForSVG(
|
||||||
|
|||||||
@@ -67,9 +67,6 @@ const getStyles: DiagramStylesProvider = (options) =>
|
|||||||
.section-root span {
|
.section-root span {
|
||||||
color: ${options.gitBranchLabel0};
|
color: ${options.gitBranchLabel0};
|
||||||
}
|
}
|
||||||
.node-icon--1 {
|
|
||||||
color: ${options.gitBranchLabel0};
|
|
||||||
}
|
|
||||||
.section-2 span {
|
.section-2 span {
|
||||||
color: ${options.gitBranchLabel0};
|
color: ${options.gitBranchLabel0};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
|||||||
"off" return 'off';
|
"off" return 'off';
|
||||||
"," return ',';
|
"," return ',';
|
||||||
";" return 'NEWLINE';
|
";" return 'NEWLINE';
|
||||||
[^\/\\\+\()\+<\->\->:\n,;]+((?!(\-x|\-\-x|\-\)|\-\-\)|\-\|\\|\-\\|\-\/|\-\/\/|\-\|\/|\/\|\-|\\\|\-|\/\/\-|\\\\\-|\/\|\-|\-\-\|\\|\-\-|\(\)))[\-]*[^\+<\->\->:\n,;]+)* { yytext = yytext.trim(); return 'ACTOR'; } //final_4.11
|
[^+<\->\->:\n,;]+((?!(\-x|\-\-x|\-\)|\-\-\)))[\-]*[^\+<\->\->:\n,;]+)* { yytext = yytext.trim(); return 'ACTOR'; }
|
||||||
"->>" return 'SOLID_ARROW';
|
"->>" return 'SOLID_ARROW';
|
||||||
"<<->>" return 'BIDIRECTIONAL_SOLID_ARROW';
|
"<<->>" return 'BIDIRECTIONAL_SOLID_ARROW';
|
||||||
"-->>" return 'DOTTED_ARROW';
|
"-->>" return 'DOTTED_ARROW';
|
||||||
@@ -89,36 +89,10 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
|||||||
\-\-[x] return 'DOTTED_CROSS';
|
\-\-[x] return 'DOTTED_CROSS';
|
||||||
\-[\)] return 'SOLID_POINT';
|
\-[\)] return 'SOLID_POINT';
|
||||||
\-\-[\)] return 'DOTTED_POINT';
|
\-\-[\)] return 'DOTTED_POINT';
|
||||||
|
|
||||||
//normal-dotted
|
|
||||||
\-\-\|\\ return 'SOLID_ARROW_TOP_DOTTED';
|
|
||||||
\-\-\|\/ return 'SOLID_ARROW_BOTTOM_DOTTED';
|
|
||||||
\-\-\\\\ return 'STICK_ARROW_TOP_DOTTED';
|
|
||||||
\-\-\/\/ return 'STICK_ARROW_BOTTOM_DOTTED';
|
|
||||||
|
|
||||||
//reverse-dotted
|
|
||||||
\/\|\-\- return 'SOLID_ARROW_TOP_REVERSE_DOTTED';
|
|
||||||
\\\|\-\- return 'SOLID_ARROW_BOTTOM_REVERSE_DOTTED';
|
|
||||||
\/\/\-\- return 'STICK_ARROW_TOP_REVERSE_DOTTED';
|
|
||||||
\\\\\-\- return 'STICK_ARROW_BOTTOM_REVERSE_DOTTED';
|
|
||||||
|
|
||||||
//normal
|
|
||||||
\-\|\\ return 'SOLID_ARROW_TOP';
|
|
||||||
\-\|\/ return 'SOLID_ARROW_BOTTOM';
|
|
||||||
\-\\\\ return 'STICK_ARROW_TOP';
|
|
||||||
\-\/\/ return 'STICK_ARROW_BOTTOM';
|
|
||||||
|
|
||||||
//reverse
|
|
||||||
\/\|\- return 'SOLID_ARROW_TOP_REVERSE';
|
|
||||||
\\\|\- return 'SOLID_ARROW_BOTTOM_REVERSE';
|
|
||||||
\/\/\- return 'STICK_ARROW_TOP_REVERSE';
|
|
||||||
\\\\\- return 'STICK_ARROW_BOTTOM_REVERSE';
|
|
||||||
|
|
||||||
":"(?:(?:no)?wrap:)?[^#\n;]* return 'TXT';
|
":"(?:(?:no)?wrap:)?[^#\n;]* return 'TXT';
|
||||||
":" return 'TXT';
|
":" return 'TXT';
|
||||||
"+" return '+';
|
"+" return '+';
|
||||||
"-" return '-';
|
"-" return '-';
|
||||||
"()" return '()';
|
|
||||||
<<EOF>> return 'NEWLINE';
|
<<EOF>> return 'NEWLINE';
|
||||||
. return 'INVALID';
|
. return 'INVALID';
|
||||||
|
|
||||||
@@ -330,20 +304,6 @@ signal
|
|||||||
{ $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$2, msg:$5},
|
{ $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$2, msg:$5},
|
||||||
{type: 'activeEnd', signalType: yy.LINETYPE.ACTIVE_END, actor: $1.actor}
|
{type: 'activeEnd', signalType: yy.LINETYPE.ACTIVE_END, actor: $1.actor}
|
||||||
]}
|
]}
|
||||||
| actor signaltype '()' actor text2
|
|
||||||
{ $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$2, msg:$5, activate: true, centralConnection: yy.LINETYPE.CENTRAL_CONNECTION},
|
|
||||||
{type: 'centralConnection', signalType: yy.LINETYPE.CENTRAL_CONNECTION, actor: $4.actor, }
|
|
||||||
]}
|
|
||||||
|
|
||||||
| actor '()' signaltype actor text2
|
|
||||||
{ $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$3, msg:$5, activate: false, centralConnection: yy.LINETYPE.CENTRAL_CONNECTION_REVERSE},
|
|
||||||
{type: 'centralConnectionReverse', signalType: yy.LINETYPE.CENTRAL_CONNECTION_REVERSE, actor: $1.actor}
|
|
||||||
]}
|
|
||||||
| actor '()' signaltype '()' actor text2
|
|
||||||
{ $$ = [$1,$5,{type: 'addMessage', from:$1.actor, to:$5.actor, signalType:$3, msg:$6, activate: true, centralConnection: yy.LINETYPE.CENTRAL_CONNECTION_DUAL},
|
|
||||||
{type: 'centralConnection', signalType: yy.LINETYPE.CENTRAL_CONNECTION, actor: $5.actor, },
|
|
||||||
{type: 'centralConnectionReverse', signalType: yy.LINETYPE.CENTRAL_CONNECTION_REVERSE, actor: $1.actor}
|
|
||||||
]}
|
|
||||||
| actor signaltype actor text2
|
| actor signaltype actor text2
|
||||||
{ $$ = [$1,$3,{type: 'addMessage', from:$1.actor, to:$3.actor, signalType:$2, msg:$4}]}
|
{ $$ = [$1,$3,{type: 'addMessage', from:$1.actor, to:$3.actor, signalType:$2, msg:$4}]}
|
||||||
;
|
;
|
||||||
@@ -377,28 +337,7 @@ signaltype
|
|||||||
: SOLID_OPEN_ARROW { $$ = yy.LINETYPE.SOLID_OPEN; }
|
: SOLID_OPEN_ARROW { $$ = yy.LINETYPE.SOLID_OPEN; }
|
||||||
| DOTTED_OPEN_ARROW { $$ = yy.LINETYPE.DOTTED_OPEN; }
|
| DOTTED_OPEN_ARROW { $$ = yy.LINETYPE.DOTTED_OPEN; }
|
||||||
| SOLID_ARROW { $$ = yy.LINETYPE.SOLID; }
|
| SOLID_ARROW { $$ = yy.LINETYPE.SOLID; }
|
||||||
|
| BIDIRECTIONAL_SOLID_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_SOLID; }
|
||||||
| SOLID_ARROW_TOP { $$ = yy.LINETYPE.SOLID_TOP; }
|
|
||||||
| SOLID_ARROW_BOTTOM { $$ = yy.LINETYPE.SOLID_BOTTOM; }
|
|
||||||
| STICK_ARROW_TOP { $$ = yy.LINETYPE.STICK_TOP; }
|
|
||||||
| STICK_ARROW_BOTTOM { $$ = yy.LINETYPE.STICK_BOTTOM; }
|
|
||||||
|
|
||||||
| SOLID_ARROW_TOP_DOTTED { $$ = yy.LINETYPE.SOLID_TOP_DOTTED; }
|
|
||||||
| SOLID_ARROW_BOTTOM_DOTTED { $$ = yy.LINETYPE.SOLID_BOTTOM_DOTTED; }
|
|
||||||
| STICK_ARROW_TOP_DOTTED { $$ = yy.LINETYPE.STICK_TOP_DOTTED; }
|
|
||||||
| STICK_ARROW_BOTTOM_DOTTED { $$ = yy.LINETYPE.STICK_BOTTOM_DOTTED; }
|
|
||||||
|
|
||||||
| SOLID_ARROW_TOP_REVERSE { $$ = yy.LINETYPE.SOLID_ARROW_TOP_REVERSE; }
|
|
||||||
| SOLID_ARROW_BOTTOM_REVERSE { $$ = yy.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE; }
|
|
||||||
| STICK_ARROW_TOP_REVERSE { $$ = yy.LINETYPE.STICK_ARROW_TOP_REVERSE; }
|
|
||||||
| STICK_ARROW_BOTTOM_REVERSE { $$ = yy.LINETYPE.STICK_ARROW_BOTTOM_REVERSE; }
|
|
||||||
|
|
||||||
| SOLID_ARROW_TOP_REVERSE_DOTTED { $$ = yy.LINETYPE.SOLID_ARROW_TOP_REVERSE_DOTTED; }
|
|
||||||
| SOLID_ARROW_BOTTOM_REVERSE_DOTTED { $$ = yy.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE_DOTTED; }
|
|
||||||
| STICK_ARROW_TOP_REVERSE_DOTTED { $$ = yy.LINETYPE.STICK_ARROW_TOP_REVERSE_DOTTED; }
|
|
||||||
| STICK_ARROW_BOTTOM_REVERSE_DOTTED { $$ = yy.LINETYPE.STICK_ARROW_BOTTOM_REVERSE_DOTTED; }
|
|
||||||
|
|
||||||
| BIDIRECTIONAL_SOLID_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_SOLID; }
|
|
||||||
| DOTTED_ARROW { $$ = yy.LINETYPE.DOTTED; }
|
| DOTTED_ARROW { $$ = yy.LINETYPE.DOTTED; }
|
||||||
| BIDIRECTIONAL_DOTTED_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_DOTTED; }
|
| BIDIRECTIONAL_DOTTED_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_DOTTED; }
|
||||||
| SOLID_CROSS { $$ = yy.LINETYPE.SOLID_CROSS; }
|
| SOLID_CROSS { $$ = yy.LINETYPE.SOLID_CROSS; }
|
||||||
|
|||||||
@@ -64,30 +64,6 @@ const LINETYPE = {
|
|||||||
PAR_OVER_START: 32,
|
PAR_OVER_START: 32,
|
||||||
BIDIRECTIONAL_SOLID: 33,
|
BIDIRECTIONAL_SOLID: 33,
|
||||||
BIDIRECTIONAL_DOTTED: 34,
|
BIDIRECTIONAL_DOTTED: 34,
|
||||||
|
|
||||||
SOLID_TOP: 41,
|
|
||||||
SOLID_BOTTOM: 42,
|
|
||||||
STICK_TOP: 43,
|
|
||||||
STICK_BOTTOM: 44,
|
|
||||||
|
|
||||||
SOLID_ARROW_TOP_REVERSE: 45,
|
|
||||||
SOLID_ARROW_BOTTOM_REVERSE: 46,
|
|
||||||
STICK_ARROW_TOP_REVERSE: 47,
|
|
||||||
STICK_ARROW_BOTTOM_REVERSE: 48,
|
|
||||||
|
|
||||||
SOLID_TOP_DOTTED: 51,
|
|
||||||
SOLID_BOTTOM_DOTTED: 52,
|
|
||||||
STICK_TOP_DOTTED: 53,
|
|
||||||
STICK_BOTTOM_DOTTED: 54,
|
|
||||||
|
|
||||||
SOLID_ARROW_TOP_REVERSE_DOTTED: 55,
|
|
||||||
SOLID_ARROW_BOTTOM_REVERSE_DOTTED: 56,
|
|
||||||
STICK_ARROW_TOP_REVERSE_DOTTED: 57,
|
|
||||||
STICK_ARROW_BOTTOM_REVERSE_DOTTED: 58,
|
|
||||||
|
|
||||||
CENTRAL_CONNECTION: 59,
|
|
||||||
CENTRAL_CONNECTION_REVERSE: 60,
|
|
||||||
CENTRAL_CONNECTION_DUAL: 61,
|
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const ARROWTYPE = {
|
const ARROWTYPE = {
|
||||||
@@ -268,8 +244,7 @@ export class SequenceDB implements DiagramDB {
|
|||||||
idTo?: Message['to'],
|
idTo?: Message['to'],
|
||||||
message?: { text: string; wrap: boolean },
|
message?: { text: string; wrap: boolean },
|
||||||
messageType?: number,
|
messageType?: number,
|
||||||
activate = false,
|
activate = false
|
||||||
centralConnection?: number
|
|
||||||
) {
|
) {
|
||||||
if (messageType === this.LINETYPE.ACTIVE_END) {
|
if (messageType === this.LINETYPE.ACTIVE_END) {
|
||||||
const cnt = this.activationCount(idFrom ?? '');
|
const cnt = this.activationCount(idFrom ?? '');
|
||||||
@@ -296,7 +271,6 @@ export class SequenceDB implements DiagramDB {
|
|||||||
wrap: message?.wrap ?? this.autoWrap(),
|
wrap: message?.wrap ?? this.autoWrap(),
|
||||||
type: messageType,
|
type: messageType,
|
||||||
activate,
|
activate,
|
||||||
centralConnection: centralConnection ?? 0,
|
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -589,12 +563,6 @@ export class SequenceDB implements DiagramDB {
|
|||||||
case 'activeStart':
|
case 'activeStart':
|
||||||
this.addSignal(param.actor, undefined, undefined, param.signalType);
|
this.addSignal(param.actor, undefined, undefined, param.signalType);
|
||||||
break;
|
break;
|
||||||
case 'centralConnection':
|
|
||||||
this.addSignal(param.actor, undefined, undefined, param.signalType);
|
|
||||||
break;
|
|
||||||
case 'centralConnectionReverse':
|
|
||||||
this.addSignal(param.actor, undefined, undefined, param.signalType);
|
|
||||||
break;
|
|
||||||
case 'activeEnd':
|
case 'activeEnd':
|
||||||
this.addSignal(param.actor, undefined, undefined, param.signalType);
|
this.addSignal(param.actor, undefined, undefined, param.signalType);
|
||||||
break;
|
break;
|
||||||
@@ -638,14 +606,7 @@ export class SequenceDB implements DiagramDB {
|
|||||||
this.state.records.lastDestroyed = undefined;
|
this.state.records.lastDestroyed = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.addSignal(
|
this.addSignal(param.from, param.to, param.msg, param.signalType, param.activate);
|
||||||
param.from,
|
|
||||||
param.to,
|
|
||||||
param.msg,
|
|
||||||
param.signalType,
|
|
||||||
param.activate,
|
|
||||||
param.centralConnection
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case 'boxStart':
|
case 'boxStart':
|
||||||
this.addBox(param.boxData);
|
this.addBox(param.boxData);
|
||||||
|
|||||||
@@ -104,7 +104,6 @@ describe('more than one sequence diagram', () => {
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"activate": false,
|
"activate": false,
|
||||||
"centralConnection": 0,
|
|
||||||
"from": "Alice",
|
"from": "Alice",
|
||||||
"id": "0",
|
"id": "0",
|
||||||
"message": "Hello Bob, how are you?",
|
"message": "Hello Bob, how are you?",
|
||||||
@@ -114,7 +113,6 @@ describe('more than one sequence diagram', () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"activate": false,
|
"activate": false,
|
||||||
"centralConnection": 0,
|
|
||||||
"from": "Bob",
|
"from": "Bob",
|
||||||
"id": "1",
|
"id": "1",
|
||||||
"message": "I am good thanks!",
|
"message": "I am good thanks!",
|
||||||
@@ -133,7 +131,6 @@ describe('more than one sequence diagram', () => {
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"activate": false,
|
"activate": false,
|
||||||
"centralConnection": 0,
|
|
||||||
"from": "Alice",
|
"from": "Alice",
|
||||||
"id": "0",
|
"id": "0",
|
||||||
"message": "Hello Bob, how are you?",
|
"message": "Hello Bob, how are you?",
|
||||||
@@ -143,7 +140,6 @@ describe('more than one sequence diagram', () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"activate": false,
|
"activate": false,
|
||||||
"centralConnection": 0,
|
|
||||||
"from": "Bob",
|
"from": "Bob",
|
||||||
"id": "1",
|
"id": "1",
|
||||||
"message": "I am good thanks!",
|
"message": "I am good thanks!",
|
||||||
@@ -164,7 +160,6 @@ describe('more than one sequence diagram', () => {
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"activate": false,
|
"activate": false,
|
||||||
"centralConnection": 0,
|
|
||||||
"from": "Alice",
|
"from": "Alice",
|
||||||
"id": "0",
|
"id": "0",
|
||||||
"message": "Hello John, how are you?",
|
"message": "Hello John, how are you?",
|
||||||
@@ -174,7 +169,6 @@ describe('more than one sequence diagram', () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"activate": false,
|
"activate": false,
|
||||||
"centralConnection": 0,
|
|
||||||
"from": "John",
|
"from": "John",
|
||||||
"id": "1",
|
"id": "1",
|
||||||
"message": "I am good thanks!",
|
"message": "I am good thanks!",
|
||||||
@@ -187,254 +181,6 @@ describe('more than one sequence diagram', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Central Connection Parsing', () => {
|
|
||||||
describe('when parsing central connection syntax', () => {
|
|
||||||
it('should parse actor ()->>() actor syntax as CENTRAL_CONNECTION_DUAL', async () => {
|
|
||||||
const diagram = await Diagram.fromText(`
|
|
||||||
sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
Alice ()->>() Bob: Hello Bob, how are you?
|
|
||||||
`);
|
|
||||||
|
|
||||||
const messages = diagram.db.getMessages();
|
|
||||||
expect(messages).toHaveLength(3); // addMessage + centralConnection + centralConnectionReverse
|
|
||||||
|
|
||||||
// Find the actual message (type: 'addMessage')
|
|
||||||
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
|
|
||||||
expect(actualMessage).toMatchObject({
|
|
||||||
from: 'Alice',
|
|
||||||
to: 'Bob',
|
|
||||||
message: 'Hello Bob, how are you?',
|
|
||||||
centralConnection: 61, // CENTRAL_CONNECTION_DUAL
|
|
||||||
activate: true,
|
|
||||||
type: 0, // SOLID (based on test output)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse actor ()-->>() actor syntax as CENTRAL_CONNECTION_DUAL', async () => {
|
|
||||||
const diagram = await Diagram.fromText(`
|
|
||||||
sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
Alice ()-->>() Bob: Hello Bob, how are you?
|
|
||||||
`);
|
|
||||||
|
|
||||||
const messages = diagram.db.getMessages();
|
|
||||||
expect(messages).toHaveLength(3); // addMessage + centralConnection + centralConnectionReverse
|
|
||||||
|
|
||||||
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
|
|
||||||
expect(actualMessage).toMatchObject({
|
|
||||||
from: 'Alice',
|
|
||||||
to: 'Bob',
|
|
||||||
message: 'Hello Bob, how are you?',
|
|
||||||
centralConnection: 61, // CENTRAL_CONNECTION_DUAL
|
|
||||||
activate: true,
|
|
||||||
type: 1, // DOTTED (based on test output)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse actor ->>() actor syntax as CENTRAL_CONNECTION', async () => {
|
|
||||||
const diagram = await Diagram.fromText(`
|
|
||||||
sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
Alice ->>() Bob: Hello Bob, how are you?
|
|
||||||
`);
|
|
||||||
|
|
||||||
const messages = diagram.db.getMessages();
|
|
||||||
expect(messages).toHaveLength(2); // addMessage + centralConnection (no activation for this pattern)
|
|
||||||
|
|
||||||
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
|
|
||||||
expect(actualMessage).toMatchObject({
|
|
||||||
from: 'Alice',
|
|
||||||
to: 'Bob',
|
|
||||||
message: 'Hello Bob, how are you?',
|
|
||||||
centralConnection: 59, // CENTRAL_CONNECTION
|
|
||||||
activate: true,
|
|
||||||
type: 0, // SOLID (based on actual parsing)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse actor ()-->> actor syntax as CENTRAL_CONNECTION_REVERSE', async () => {
|
|
||||||
const diagram = await Diagram.fromText(`
|
|
||||||
sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
Alice ()-->> Bob: Hello Bob, how are you?
|
|
||||||
`);
|
|
||||||
|
|
||||||
const messages = diagram.db.getMessages();
|
|
||||||
expect(messages).toHaveLength(2); // addMessage + centralConnectionReverse
|
|
||||||
|
|
||||||
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
|
|
||||||
expect(actualMessage).toMatchObject({
|
|
||||||
from: 'Alice',
|
|
||||||
to: 'Bob',
|
|
||||||
message: 'Hello Bob, how are you?',
|
|
||||||
centralConnection: 60, // CENTRAL_CONNECTION_REVERSE
|
|
||||||
activate: false,
|
|
||||||
type: 1, // DOTTED (based on test output)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse actor ()->> actor syntax as CENTRAL_CONNECTION_REVERSE', async () => {
|
|
||||||
const diagram = await Diagram.fromText(`
|
|
||||||
sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
Alice ()->> Bob: Hello Bob, how are you?
|
|
||||||
`);
|
|
||||||
|
|
||||||
const messages = diagram.db.getMessages();
|
|
||||||
expect(messages).toHaveLength(2); // addMessage + centralConnectionReverse
|
|
||||||
|
|
||||||
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
|
|
||||||
expect(actualMessage).toMatchObject({
|
|
||||||
from: 'Alice',
|
|
||||||
to: 'Bob',
|
|
||||||
message: 'Hello Bob, how are you?',
|
|
||||||
centralConnection: 60, // CENTRAL_CONNECTION_REVERSE
|
|
||||||
activate: false,
|
|
||||||
type: 0, // SOLID (based on test output)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse actor ()<<-->>() actor syntax as CENTRAL_CONNECTION_DUAL', async () => {
|
|
||||||
const diagram = await Diagram.fromText(`
|
|
||||||
sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
Alice ()<<-->>() Bob: Hello Bob, how are you?
|
|
||||||
`);
|
|
||||||
|
|
||||||
const messages = diagram.db.getMessages();
|
|
||||||
expect(messages).toHaveLength(3); // addMessage + centralConnection + centralConnectionReverse
|
|
||||||
|
|
||||||
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
|
|
||||||
expect(actualMessage).toMatchObject({
|
|
||||||
from: 'Alice',
|
|
||||||
to: 'Bob',
|
|
||||||
message: 'Hello Bob, how are you?',
|
|
||||||
centralConnection: 61, // CENTRAL_CONNECTION_DUAL
|
|
||||||
activate: true,
|
|
||||||
type: 34, // BIDIRECTIONAL_DOTTED
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse actor ()<<->>() actor syntax as CENTRAL_CONNECTION_DUAL', async () => {
|
|
||||||
const diagram = await Diagram.fromText(`
|
|
||||||
sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
Alice ()<<->>() Bob: Hello Bob, how are you?
|
|
||||||
`);
|
|
||||||
|
|
||||||
const messages = diagram.db.getMessages();
|
|
||||||
expect(messages).toHaveLength(3); // addMessage + centralConnection + centralConnectionReverse
|
|
||||||
|
|
||||||
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
|
|
||||||
expect(actualMessage).toMatchObject({
|
|
||||||
from: 'Alice',
|
|
||||||
to: 'Bob',
|
|
||||||
message: 'Hello Bob, how are you?',
|
|
||||||
centralConnection: 61, // CENTRAL_CONNECTION_DUAL
|
|
||||||
activate: true,
|
|
||||||
type: 33, // BIDIRECTIONAL_SOLID
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle multiple central connection types in one diagram', async () => {
|
|
||||||
const diagram = await Diagram.fromText(`
|
|
||||||
sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
participant Charlie
|
|
||||||
Alice ()->>() Bob: Message 1
|
|
||||||
Bob ()-->> Charlie: Message 2
|
|
||||||
Charlie ()<<-->>() Alice: Message 3
|
|
||||||
`);
|
|
||||||
|
|
||||||
const messages = diagram.db.getMessages();
|
|
||||||
expect(messages).toHaveLength(8); // 3 addMessages + 5 central connection markers
|
|
||||||
|
|
||||||
// Filter to get only the actual messages
|
|
||||||
const actualMessages = messages.filter((msg) => msg.type !== undefined && msg.from && msg.to);
|
|
||||||
expect(actualMessages).toHaveLength(3);
|
|
||||||
|
|
||||||
expect(actualMessages[0]).toMatchObject({
|
|
||||||
from: 'Alice',
|
|
||||||
to: 'Bob',
|
|
||||||
centralConnection: 61, // CENTRAL_CONNECTION_DUAL (()->>())
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(actualMessages[1]).toMatchObject({
|
|
||||||
from: 'Bob',
|
|
||||||
to: 'Charlie',
|
|
||||||
centralConnection: 60, // CENTRAL_CONNECTION_REVERSE (()-->>)
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(actualMessages[2]).toMatchObject({
|
|
||||||
from: 'Charlie',
|
|
||||||
to: 'Alice',
|
|
||||||
centralConnection: 61, // CENTRAL_CONNECTION_DUAL (()<<-->>())
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle central connections with different arrow types', async () => {
|
|
||||||
const diagram = await Diagram.fromText(`
|
|
||||||
sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
Alice ()-x() Bob: Cross message
|
|
||||||
Alice ()--x() Bob: Dotted cross message
|
|
||||||
`);
|
|
||||||
|
|
||||||
const messages = diagram.db.getMessages();
|
|
||||||
expect(messages).toHaveLength(6); // 2 addMessages + 4 central connection markers
|
|
||||||
|
|
||||||
const actualMessages = messages.filter((msg) => msg.type !== undefined && msg.from && msg.to);
|
|
||||||
expect(actualMessages).toHaveLength(2);
|
|
||||||
|
|
||||||
expect(actualMessages[0]).toMatchObject({
|
|
||||||
from: 'Alice',
|
|
||||||
to: 'Bob',
|
|
||||||
centralConnection: 61, // CENTRAL_CONNECTION_DUAL (()-x())
|
|
||||||
type: 3, // SOLID_CROSS
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(actualMessages[1]).toMatchObject({
|
|
||||||
from: 'Alice',
|
|
||||||
to: 'Bob',
|
|
||||||
centralConnection: 61, // CENTRAL_CONNECTION_DUAL (()--x())
|
|
||||||
type: 4, // DOTTED_CROSS
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not break existing parsing without central connections', async () => {
|
|
||||||
const diagram = await Diagram.fromText(`
|
|
||||||
sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
Alice ->> Bob: Normal message
|
|
||||||
Bob -->> Alice: Normal dotted message
|
|
||||||
Alice -x Bob: Normal cross message
|
|
||||||
`);
|
|
||||||
|
|
||||||
const messages = diagram.db.getMessages();
|
|
||||||
expect(messages).toHaveLength(3);
|
|
||||||
|
|
||||||
messages.forEach((msg) => {
|
|
||||||
expect(msg.centralConnection).toBe(0); // No central connection
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(messages[0].type).toBe(0); // SOLID (based on actual parsing)
|
|
||||||
expect(messages[1].type).toBe(1); // DOTTED (based on actual parsing)
|
|
||||||
expect(messages[2].type).toBe(3); // SOLID_CROSS
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when parsing a sequenceDiagram', function () {
|
describe('when parsing a sequenceDiagram', function () {
|
||||||
let diagram;
|
let diagram;
|
||||||
beforeEach(async function () {
|
beforeEach(async function () {
|
||||||
@@ -2312,36 +2058,6 @@ Bob->>Alice:Got it!
|
|||||||
expect(messages[0].from).toBe('Alice');
|
expect(messages[0].from).toBe('Alice');
|
||||||
expect(messages[0].to).toBe('Bob');
|
expect(messages[0].to).toBe('Bob');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('1 should parse ', async () => {
|
|
||||||
const diagram = await Diagram.fromText(`
|
|
||||||
sequenceDiagram
|
|
||||||
actor Bob
|
|
||||||
actor Alice
|
|
||||||
Bob -|\\ Alice: Hello Alice, how are you?
|
|
||||||
Bob -|/ Alice: Hello Alice, how are you?
|
|
||||||
Bob -// Alice: Hello Alice, how are you?
|
|
||||||
Bob -\\\\ Alice: Hello Alice, how are you?
|
|
||||||
|
|
||||||
Bob \\|- Alice: Hello Alice, how are you?
|
|
||||||
Bob /|- Alice: Hello Alice, how are you?
|
|
||||||
Bob //- Alice: Hello Alice, how are you?
|
|
||||||
Bob \\\\- Alice: Hello Alice, how are you?
|
|
||||||
`);
|
|
||||||
|
|
||||||
const messages = diagram.db.getMessages();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('2 should parse ', async () => {
|
|
||||||
const diagram = await Diagram.fromText(`
|
|
||||||
sequenceDiagram
|
|
||||||
actor Bob
|
|
||||||
actor Alice
|
|
||||||
Alice ()<<->>() Bob: hey?
|
|
||||||
`);
|
|
||||||
|
|
||||||
const messages = diagram.db.getMessages();
|
|
||||||
});
|
|
||||||
describe('when parsing extended participant syntax', () => {
|
describe('when parsing extended participant syntax', () => {
|
||||||
it('should parse participants with different quote styles and whitespace', async () => {
|
it('should parse participants with different quote styles and whitespace', async () => {
|
||||||
const diagram = await Diagram.fromText(`
|
const diagram = await Diagram.fromText(`
|
||||||
|
|||||||
@@ -282,49 +282,6 @@ const drawNote = async function (elem: any, noteModel: NoteModel) {
|
|||||||
bounds.models.addNote(noteModel);
|
bounds.models.addNote(noteModel);
|
||||||
};
|
};
|
||||||
|
|
||||||
const drawCentralConnection = function (
|
|
||||||
elem: any,
|
|
||||||
msg: any,
|
|
||||||
msgModel: any,
|
|
||||||
diagObj: Diagram,
|
|
||||||
startx: number,
|
|
||||||
stopx: number,
|
|
||||||
lineStartY: number
|
|
||||||
) {
|
|
||||||
const actors = diagObj.db.getActors();
|
|
||||||
const fromActor = actors.get(msg.from);
|
|
||||||
const toActor = actors.get(msg.to);
|
|
||||||
const fromCenter = fromActor.x + fromActor.width / 2;
|
|
||||||
const toCenter = toActor.x + toActor.width / 2;
|
|
||||||
|
|
||||||
const g = elem.append('g');
|
|
||||||
|
|
||||||
const drawCircle = (cx: number) => {
|
|
||||||
g.append('circle')
|
|
||||||
.attr('cx', cx)
|
|
||||||
.attr('cy', lineStartY)
|
|
||||||
.attr('r', 5)
|
|
||||||
.attr('width', 10)
|
|
||||||
.attr('height', 10);
|
|
||||||
};
|
|
||||||
|
|
||||||
const { CENTRAL_CONNECTION, CENTRAL_CONNECTION_REVERSE, CENTRAL_CONNECTION_DUAL } =
|
|
||||||
diagObj.db.LINETYPE;
|
|
||||||
|
|
||||||
switch (msg.centralConnection) {
|
|
||||||
case CENTRAL_CONNECTION:
|
|
||||||
drawCircle(toCenter);
|
|
||||||
break;
|
|
||||||
case CENTRAL_CONNECTION_REVERSE:
|
|
||||||
drawCircle(fromCenter);
|
|
||||||
break;
|
|
||||||
case CENTRAL_CONNECTION_DUAL:
|
|
||||||
drawCircle(fromCenter);
|
|
||||||
drawCircle(toCenter);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const messageFont = (cnf) => {
|
const messageFont = (cnf) => {
|
||||||
return {
|
return {
|
||||||
fontFamily: cnf.messageFontFamily,
|
fontFamily: cnf.messageFontFamily,
|
||||||
@@ -410,7 +367,7 @@ async function boundMessage(_diagram, msgModel): Promise<number> {
|
|||||||
* @param lineStartY - The Y coordinate at which the message line starts
|
* @param lineStartY - The Y coordinate at which the message line starts
|
||||||
* @param diagObj - The diagram object.
|
* @param diagObj - The diagram object.
|
||||||
*/
|
*/
|
||||||
const drawMessage = async function (diagram, msgModel, lineStartY: number, diagObj: Diagram, msg) {
|
const drawMessage = async function (diagram, msgModel, lineStartY: number, diagObj: Diagram) {
|
||||||
const { startx, stopx, starty, message, type, sequenceIndex, sequenceVisible } = msgModel;
|
const { startx, stopx, starty, message, type, sequenceIndex, sequenceVisible } = msgModel;
|
||||||
const textDims = utils.calculateTextDimensions(message, messageFont(conf));
|
const textDims = utils.calculateTextDimensions(message, messageFont(conf));
|
||||||
const textObj = svgDrawCommon.getTextObj();
|
const textObj = svgDrawCommon.getTextObj();
|
||||||
@@ -476,9 +433,6 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
|||||||
line.attr('y1', lineStartY);
|
line.attr('y1', lineStartY);
|
||||||
line.attr('x2', stopx);
|
line.attr('x2', stopx);
|
||||||
line.attr('y2', lineStartY);
|
line.attr('y2', lineStartY);
|
||||||
if (hasCentralConnection(msg, diagObj)) {
|
|
||||||
drawCentralConnection(diagram, msg, msgModel, diagObj, startx, stopx, lineStartY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Make an SVG Container
|
// Make an SVG Container
|
||||||
// Draw the line
|
// Draw the line
|
||||||
@@ -487,15 +441,7 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
|||||||
type === diagObj.db.LINETYPE.DOTTED_CROSS ||
|
type === diagObj.db.LINETYPE.DOTTED_CROSS ||
|
||||||
type === diagObj.db.LINETYPE.DOTTED_POINT ||
|
type === diagObj.db.LINETYPE.DOTTED_POINT ||
|
||||||
type === diagObj.db.LINETYPE.DOTTED_OPEN ||
|
type === diagObj.db.LINETYPE.DOTTED_OPEN ||
|
||||||
type === diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED ||
|
type === diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED
|
||||||
type === diagObj.db.LINETYPE.SOLID_TOP_DOTTED ||
|
|
||||||
type === diagObj.db.LINETYPE.SOLID_BOTTOM_DOTTED ||
|
|
||||||
type === diagObj.db.LINETYPE.STICK_TOP_DOTTED ||
|
|
||||||
type === diagObj.db.LINETYPE.STICK_BOTTOM_DOTTED ||
|
|
||||||
type === diagObj.db.LINETYPE.SOLID_ARROW_TOP_REVERSE_DOTTED ||
|
|
||||||
type === diagObj.db.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE_DOTTED ||
|
|
||||||
type === diagObj.db.LINETYPE.STICK_ARROW_TOP_REVERSE_DOTTED ||
|
|
||||||
type === diagObj.db.LINETYPE.STICK_ARROW_BOTTOM_REVERSE_DOTTED
|
|
||||||
) {
|
) {
|
||||||
line.style('stroke-dasharray', '3, 3');
|
line.style('stroke-dasharray', '3, 3');
|
||||||
line.attr('class', 'messageLine1');
|
line.attr('class', 'messageLine1');
|
||||||
@@ -511,51 +457,6 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
|||||||
line.attr('stroke-width', 2);
|
line.attr('stroke-width', 2);
|
||||||
line.attr('stroke', 'none'); // handled by theme/css anyway
|
line.attr('stroke', 'none'); // handled by theme/css anyway
|
||||||
line.style('fill', 'none'); // remove any fill colour
|
line.style('fill', 'none'); // remove any fill colour
|
||||||
|
|
||||||
if (type === diagObj.db.LINETYPE.SOLID_TOP || type === diagObj.db.LINETYPE.SOLID_TOP_DOTTED) {
|
|
||||||
line.attr('marker-end', 'url(' + url + '#solidTopArrowHead)');
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
type === diagObj.db.LINETYPE.SOLID_BOTTOM ||
|
|
||||||
type === diagObj.db.LINETYPE.SOLID_BOTTOM_DOTTED
|
|
||||||
) {
|
|
||||||
line.attr('marker-end', 'url(' + url + '#solidBottomArrowHead)');
|
|
||||||
}
|
|
||||||
if (type === diagObj.db.LINETYPE.STICK_TOP || type === diagObj.db.LINETYPE.STICK_TOP_DOTTED) {
|
|
||||||
line.attr('marker-end', 'url(' + url + '#stickTopArrowHead)');
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
type === diagObj.db.LINETYPE.STICK_BOTTOM ||
|
|
||||||
type === diagObj.db.LINETYPE.STICK_BOTTOM_DOTTED
|
|
||||||
) {
|
|
||||||
line.attr('marker-end', 'url(' + url + '#stickBottomArrowHead)');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
type === diagObj.db.LINETYPE.SOLID_ARROW_TOP_REVERSE ||
|
|
||||||
type === diagObj.db.LINETYPE.SOLID_ARROW_TOP_REVERSE_DOTTED
|
|
||||||
) {
|
|
||||||
line.attr('marker-start', 'url(' + url + '#solidBottomArrowHead)');
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
type === diagObj.db.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE ||
|
|
||||||
type === diagObj.db.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE_DOTTED
|
|
||||||
) {
|
|
||||||
line.attr('marker-start', 'url(' + url + '#solidTopArrowHead)');
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
type === diagObj.db.LINETYPE.STICK_ARROW_TOP_REVERSE ||
|
|
||||||
type === diagObj.db.LINETYPE.STICK_ARROW_TOP_REVERSE_DOTTED
|
|
||||||
) {
|
|
||||||
line.attr('marker-start', 'url(' + url + '#stickBottomArrowHead)');
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
type === diagObj.db.LINETYPE.STICK_ARROW_BOTTOM_REVERSE ||
|
|
||||||
type === diagObj.db.LINETYPE.STICK_ARROW_BOTTOM_REVERSE_DOTTED
|
|
||||||
) {
|
|
||||||
line.attr('marker-start', 'url(' + url + '#stickTopArrowHead)');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === diagObj.db.LINETYPE.SOLID || type === diagObj.db.LINETYPE.DOTTED) {
|
if (type === diagObj.db.LINETYPE.SOLID || type === diagObj.db.LINETYPE.DOTTED) {
|
||||||
line.attr('marker-end', 'url(' + url + '#arrowhead)');
|
line.attr('marker-end', 'url(' + url + '#arrowhead)');
|
||||||
}
|
}
|
||||||
@@ -580,18 +481,7 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
|||||||
type === diagObj.db.LINETYPE.BIDIRECTIONAL_SOLID ||
|
type === diagObj.db.LINETYPE.BIDIRECTIONAL_SOLID ||
|
||||||
type === diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED;
|
type === diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED;
|
||||||
|
|
||||||
const isReverseArrowType =
|
if (isBidirectional) {
|
||||||
type === diagObj.db.LINETYPE.SOLID_ARROW_TOP_REVERSE ||
|
|
||||||
type === diagObj.db.LINETYPE.SOLID_ARROW_TOP_REVERSE_DOTTED ||
|
|
||||||
type === diagObj.db.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE ||
|
|
||||||
type === diagObj.db.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE_DOTTED ||
|
|
||||||
type === diagObj.db.LINETYPE.STICK_ARROW_TOP_REVERSE ||
|
|
||||||
type === diagObj.db.LINETYPE.STICK_ARROW_TOP_REVERSE_DOTTED ||
|
|
||||||
type === diagObj.db.LINETYPE.STICK_ARROW_BOTTOM_REVERSE ||
|
|
||||||
type === diagObj.db.LINETYPE.STICK_ARROW_BOTTOM_REVERSE_DOTTED;
|
|
||||||
|
|
||||||
let x = 0;
|
|
||||||
if (isBidirectional || isReverseArrowType) {
|
|
||||||
const SEQUENCE_NUMBER_RADIUS = 6;
|
const SEQUENCE_NUMBER_RADIUS = 6;
|
||||||
|
|
||||||
if (startx < stopx) {
|
if (startx < stopx) {
|
||||||
@@ -599,7 +489,6 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
|||||||
} else {
|
} else {
|
||||||
line.attr('x1', startx + SEQUENCE_NUMBER_RADIUS);
|
line.attr('x1', startx + SEQUENCE_NUMBER_RADIUS);
|
||||||
}
|
}
|
||||||
x = 3.5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
diagram
|
diagram
|
||||||
@@ -609,8 +498,7 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
|||||||
.attr('x2', startx)
|
.attr('x2', startx)
|
||||||
.attr('y2', lineStartY)
|
.attr('y2', lineStartY)
|
||||||
.attr('stroke-width', 0)
|
.attr('stroke-width', 0)
|
||||||
.attr('marker-start', 'url(' + url + '#sequencenumber)')
|
.attr('marker-start', 'url(' + url + '#sequencenumber)');
|
||||||
.attr('transform', `translate(-${x}, 0)`);
|
|
||||||
|
|
||||||
diagram
|
diagram
|
||||||
.append('text')
|
.append('text')
|
||||||
@@ -620,8 +508,7 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
|||||||
.attr('font-size', '12px')
|
.attr('font-size', '12px')
|
||||||
.attr('text-anchor', 'middle')
|
.attr('text-anchor', 'middle')
|
||||||
.attr('class', 'sequenceNumber')
|
.attr('class', 'sequenceNumber')
|
||||||
.text(sequenceIndex)
|
.text(sequenceIndex);
|
||||||
.attr('transform', `translate(-${x}, 0)`);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -970,10 +857,6 @@ export const draw = async function (_text: string, id: string, _version: string,
|
|||||||
svgDraw.insertArrowCrossHead(diagram);
|
svgDraw.insertArrowCrossHead(diagram);
|
||||||
svgDraw.insertArrowFilledHead(diagram);
|
svgDraw.insertArrowFilledHead(diagram);
|
||||||
svgDraw.insertSequenceNumber(diagram);
|
svgDraw.insertSequenceNumber(diagram);
|
||||||
svgDraw.insertSolidTopArrowHead(diagram);
|
|
||||||
svgDraw.insertSolidBottomArrowHead(diagram);
|
|
||||||
svgDraw.insertStickTopArrowHead(diagram);
|
|
||||||
svgDraw.insertStickBottomArrowHead(diagram);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param msg - The message to draw.
|
* @param msg - The message to draw.
|
||||||
@@ -1014,12 +897,6 @@ export const draw = async function (_text: string, id: string, _version: string,
|
|||||||
case diagObj.db.LINETYPE.ACTIVE_START:
|
case diagObj.db.LINETYPE.ACTIVE_START:
|
||||||
bounds.newActivation(msg, diagram, actors);
|
bounds.newActivation(msg, diagram, actors);
|
||||||
break;
|
break;
|
||||||
case diagObj.db.LINETYPE.CENTRAL_CONNECTION:
|
|
||||||
bounds.newActivation(msg, diagram, actors);
|
|
||||||
break;
|
|
||||||
case diagObj.db.LINETYPE.CENTRAL_CONNECTION_REVERSE:
|
|
||||||
bounds.newActivation(msg, diagram, actors);
|
|
||||||
break;
|
|
||||||
case diagObj.db.LINETYPE.ACTIVE_END:
|
case diagObj.db.LINETYPE.ACTIVE_END:
|
||||||
activeEnd(msg, bounds.getVerticalPos());
|
activeEnd(msg, bounds.getVerticalPos());
|
||||||
break;
|
break;
|
||||||
@@ -1178,7 +1055,7 @@ export const draw = async function (_text: string, id: string, _version: string,
|
|||||||
createdActors,
|
createdActors,
|
||||||
destroyedActors
|
destroyedActors
|
||||||
);
|
);
|
||||||
messagesToDraw.push({ messageModel: msgModel, lineStartY: lineStartY, msg });
|
messagesToDraw.push({ messageModel: msgModel, lineStartY: lineStartY });
|
||||||
bounds.models.addMessage(msgModel);
|
bounds.models.addMessage(msgModel);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error('error while drawing message', e);
|
log.error('error while drawing message', e);
|
||||||
@@ -1191,27 +1068,6 @@ export const draw = async function (_text: string, id: string, _version: string,
|
|||||||
diagObj.db.LINETYPE.SOLID_OPEN,
|
diagObj.db.LINETYPE.SOLID_OPEN,
|
||||||
diagObj.db.LINETYPE.DOTTED_OPEN,
|
diagObj.db.LINETYPE.DOTTED_OPEN,
|
||||||
diagObj.db.LINETYPE.SOLID,
|
diagObj.db.LINETYPE.SOLID,
|
||||||
|
|
||||||
diagObj.db.LINETYPE.SOLID_TOP,
|
|
||||||
diagObj.db.LINETYPE.SOLID_BOTTOM,
|
|
||||||
diagObj.db.LINETYPE.STICK_TOP,
|
|
||||||
diagObj.db.LINETYPE.STICK_BOTTOM,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.SOLID_TOP_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.SOLID_BOTTOM_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.STICK_TOP_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.STICK_BOTTOM_DOTTED,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_TOP_REVERSE,
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE,
|
|
||||||
diagObj.db.LINETYPE.STICK_ARROW_TOP_REVERSE,
|
|
||||||
diagObj.db.LINETYPE.STICK_ARROW_BOTTOM_REVERSE,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_TOP_REVERSE_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.STICK_ARROW_TOP_REVERSE_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.STICK_ARROW_BOTTOM_REVERSE_DOTTED,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.DOTTED,
|
diagObj.db.LINETYPE.DOTTED,
|
||||||
diagObj.db.LINETYPE.SOLID_CROSS,
|
diagObj.db.LINETYPE.SOLID_CROSS,
|
||||||
diagObj.db.LINETYPE.DOTTED_CROSS,
|
diagObj.db.LINETYPE.DOTTED_CROSS,
|
||||||
@@ -1231,7 +1087,7 @@ export const draw = async function (_text: string, id: string, _version: string,
|
|||||||
await drawActors(diagram, actors, actorKeys, false);
|
await drawActors(diagram, actors, actorKeys, false);
|
||||||
|
|
||||||
for (const e of messagesToDraw) {
|
for (const e of messagesToDraw) {
|
||||||
await drawMessage(diagram, e.messageModel, e.lineStartY, diagObj, e.msg);
|
await drawMessage(diagram, e.messageModel, e.lineStartY, diagObj);
|
||||||
}
|
}
|
||||||
if (conf.mirrorActors) {
|
if (conf.mirrorActors) {
|
||||||
await drawActors(diagram, actors, actorKeys, true);
|
await drawActors(diagram, actors, actorKeys, true);
|
||||||
@@ -1605,85 +1461,12 @@ const buildNoteModel = async function (msg, actors, diagObj) {
|
|||||||
return noteModel;
|
return noteModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Central connection positioning constants
|
|
||||||
const CENTRAL_CONNECTION_BASE_OFFSET = 4;
|
|
||||||
const CENTRAL_CONNECTION_BIDIRECTIONAL_OFFSET = 6;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a message has central connection
|
|
||||||
* @param msg - The message object
|
|
||||||
* @param diagObj - The diagram object containing LINETYPE constants
|
|
||||||
* @returns True if the message has any type of central connection
|
|
||||||
*/
|
|
||||||
const hasCentralConnection = function (msg, diagObj) {
|
|
||||||
const { CENTRAL_CONNECTION, CENTRAL_CONNECTION_REVERSE, CENTRAL_CONNECTION_DUAL } =
|
|
||||||
diagObj.db.LINETYPE;
|
|
||||||
return [CENTRAL_CONNECTION, CENTRAL_CONNECTION_REVERSE, CENTRAL_CONNECTION_DUAL].includes(
|
|
||||||
msg.centralConnection
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate the positioning offset for central connection arrows
|
|
||||||
* @param msg - The message object
|
|
||||||
* @param diagObj - The diagram object containing LINETYPE constants
|
|
||||||
* @param isArrowToRight - Whether the arrow is pointing to the right
|
|
||||||
* @returns The offset to apply to startx position
|
|
||||||
*/
|
|
||||||
const calculateCentralConnectionOffset = function (msg, diagObj, isArrowToRight) {
|
|
||||||
const {
|
|
||||||
CENTRAL_CONNECTION_REVERSE,
|
|
||||||
CENTRAL_CONNECTION_DUAL,
|
|
||||||
BIDIRECTIONAL_SOLID,
|
|
||||||
BIDIRECTIONAL_DOTTED,
|
|
||||||
} = diagObj.db.LINETYPE;
|
|
||||||
|
|
||||||
let offset = 0;
|
|
||||||
|
|
||||||
if (
|
|
||||||
msg.centralConnection === CENTRAL_CONNECTION_REVERSE ||
|
|
||||||
msg.centralConnection === CENTRAL_CONNECTION_DUAL
|
|
||||||
) {
|
|
||||||
offset += CENTRAL_CONNECTION_BASE_OFFSET;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
msg.centralConnection === CENTRAL_CONNECTION_DUAL &&
|
|
||||||
(msg.type === BIDIRECTIONAL_SOLID || msg.type === BIDIRECTIONAL_DOTTED)
|
|
||||||
) {
|
|
||||||
offset += isArrowToRight ? 0 : -CENTRAL_CONNECTION_BIDIRECTIONAL_OFFSET;
|
|
||||||
}
|
|
||||||
|
|
||||||
return offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildMessageModel = function (msg, actors, diagObj) {
|
const buildMessageModel = function (msg, actors, diagObj) {
|
||||||
if (
|
if (
|
||||||
![
|
![
|
||||||
diagObj.db.LINETYPE.SOLID_OPEN,
|
diagObj.db.LINETYPE.SOLID_OPEN,
|
||||||
diagObj.db.LINETYPE.DOTTED_OPEN,
|
diagObj.db.LINETYPE.DOTTED_OPEN,
|
||||||
diagObj.db.LINETYPE.SOLID,
|
diagObj.db.LINETYPE.SOLID,
|
||||||
|
|
||||||
diagObj.db.LINETYPE.SOLID_TOP,
|
|
||||||
diagObj.db.LINETYPE.SOLID_BOTTOM,
|
|
||||||
diagObj.db.LINETYPE.STICK_TOP,
|
|
||||||
diagObj.db.LINETYPE.STICK_BOTTOM,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.SOLID_TOP_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.SOLID_BOTTOM_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.STICK_TOP_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.STICK_BOTTOM_DOTTED,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_TOP_REVERSE,
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE,
|
|
||||||
diagObj.db.LINETYPE.STICK_ARROW_TOP_REVERSE,
|
|
||||||
diagObj.db.LINETYPE.STICK_ARROW_BOTTOM_REVERSE,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_TOP_REVERSE_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.STICK_ARROW_TOP_REVERSE_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.STICK_ARROW_BOTTOM_REVERSE_DOTTED,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.DOTTED,
|
diagObj.db.LINETYPE.DOTTED,
|
||||||
diagObj.db.LINETYPE.SOLID_CROSS,
|
diagObj.db.LINETYPE.SOLID_CROSS,
|
||||||
diagObj.db.LINETYPE.DOTTED_CROSS,
|
diagObj.db.LINETYPE.DOTTED_CROSS,
|
||||||
@@ -1701,8 +1484,6 @@ const buildMessageModel = function (msg, actors, diagObj) {
|
|||||||
let startx = isArrowToRight ? fromRight : fromLeft;
|
let startx = isArrowToRight ? fromRight : fromLeft;
|
||||||
let stopx = isArrowToRight ? toLeft : toRight;
|
let stopx = isArrowToRight ? toLeft : toRight;
|
||||||
|
|
||||||
// Apply central connection positioning adjustments
|
|
||||||
startx += calculateCentralConnectionOffset(msg, diagObj, isArrowToRight);
|
|
||||||
// As the line width is considered, the left and right values will be off by 2.
|
// As the line width is considered, the left and right values will be off by 2.
|
||||||
const isArrowToActivation = Math.abs(toLeft - toRight) > 2;
|
const isArrowToActivation = Math.abs(toLeft - toRight) > 2;
|
||||||
|
|
||||||
@@ -1736,30 +1517,7 @@ const buildMessageModel = function (msg, actors, diagObj) {
|
|||||||
* Shorten the length of arrow at the end and move the marker forward (using refX) to have a clean arrowhead
|
* Shorten the length of arrow at the end and move the marker forward (using refX) to have a clean arrowhead
|
||||||
* This is not required for open arrows that don't have arrowheads
|
* This is not required for open arrows that don't have arrowheads
|
||||||
*/
|
*/
|
||||||
if (
|
if (![diagObj.db.LINETYPE.SOLID_OPEN, diagObj.db.LINETYPE.DOTTED_OPEN].includes(msg.type)) {
|
||||||
![
|
|
||||||
diagObj.db.LINETYPE.SOLID_OPEN,
|
|
||||||
diagObj.db.LINETYPE.DOTTED_OPEN,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.STICK_TOP,
|
|
||||||
diagObj.db.LINETYPE.STICK_BOTTOM,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.STICK_TOP_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.STICK_BOTTOM_DOTTED,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_TOP_REVERSE_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE_DOTTED,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.STICK_ARROW_TOP_REVERSE,
|
|
||||||
diagObj.db.LINETYPE.STICK_ARROW_BOTTOM_REVERSE,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.STICK_ARROW_TOP_REVERSE_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.STICK_ARROW_BOTTOM_REVERSE_DOTTED,
|
|
||||||
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_TOP_REVERSE,
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE,
|
|
||||||
].includes(msg.type)
|
|
||||||
) {
|
|
||||||
stopx += adjustValue(3);
|
stopx += adjustValue(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1767,14 +1525,9 @@ const buildMessageModel = function (msg, actors, diagObj) {
|
|||||||
* Shorten start position of bidirectional arrow to accommodate for second arrowhead
|
* Shorten start position of bidirectional arrow to accommodate for second arrowhead
|
||||||
*/
|
*/
|
||||||
if (
|
if (
|
||||||
[
|
[diagObj.db.LINETYPE.BIDIRECTIONAL_SOLID, diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED].includes(
|
||||||
diagObj.db.LINETYPE.BIDIRECTIONAL_SOLID,
|
msg.type
|
||||||
diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED,
|
)
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_TOP_REVERSE_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE_DOTTED,
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_TOP_REVERSE,
|
|
||||||
diagObj.db.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE,
|
|
||||||
].includes(msg.type)
|
|
||||||
) {
|
) {
|
||||||
startx -= adjustValue(3);
|
startx -= adjustValue(3);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1709,77 +1709,6 @@ const _drawMenuItemTextCandidateFunc = (function () {
|
|||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup arrow head and define the marker. The result is appended to the svg.
|
|
||||||
*
|
|
||||||
* @param elem
|
|
||||||
*/
|
|
||||||
export const insertSolidTopArrowHead = function (elem) {
|
|
||||||
elem
|
|
||||||
.append('defs')
|
|
||||||
.append('marker')
|
|
||||||
.attr('id', 'solidTopArrowHead')
|
|
||||||
.attr('refX', 7.9)
|
|
||||||
.attr('refY', 7.25)
|
|
||||||
.attr('markerUnits', 'userSpaceOnUse')
|
|
||||||
.attr('markerWidth', 12)
|
|
||||||
.attr('markerHeight', 12)
|
|
||||||
.attr('orient', 'auto-start-reverse')
|
|
||||||
.append('path')
|
|
||||||
.attr('d', 'M 0 0 L 10 8 L 0 8 z'); // this is actual shape for arrowhead
|
|
||||||
};
|
|
||||||
|
|
||||||
export const insertSolidBottomArrowHead = function (elem) {
|
|
||||||
elem
|
|
||||||
.append('defs')
|
|
||||||
.append('marker')
|
|
||||||
.attr('id', 'solidBottomArrowHead')
|
|
||||||
.attr('refX', 7.9)
|
|
||||||
.attr('refY', 0.75)
|
|
||||||
.attr('markerUnits', 'userSpaceOnUse')
|
|
||||||
.attr('markerWidth', 12)
|
|
||||||
.attr('markerHeight', 12)
|
|
||||||
.attr('orient', 'auto-start-reverse')
|
|
||||||
.append('path')
|
|
||||||
.attr('d', 'M 0 0 L 10 0 L 0 8 z');
|
|
||||||
};
|
|
||||||
|
|
||||||
export const insertStickTopArrowHead = function (elem) {
|
|
||||||
elem
|
|
||||||
.append('defs')
|
|
||||||
.append('marker')
|
|
||||||
.attr('id', 'stickTopArrowHead')
|
|
||||||
.attr('refX', 7.5)
|
|
||||||
.attr('refY', 7)
|
|
||||||
.attr('markerUnits', 'userSpaceOnUse')
|
|
||||||
.attr('markerWidth', 12)
|
|
||||||
.attr('markerHeight', 12)
|
|
||||||
.attr('orient', 'auto-start-reverse')
|
|
||||||
.append('path')
|
|
||||||
.attr('d', 'M 0 0 L 7 7')
|
|
||||||
.attr('stroke', 'black')
|
|
||||||
.attr('stroke-width', 1.5)
|
|
||||||
.attr('fill', 'none');
|
|
||||||
};
|
|
||||||
|
|
||||||
export const insertStickBottomArrowHead = function (elem) {
|
|
||||||
elem
|
|
||||||
.append('defs')
|
|
||||||
.append('marker')
|
|
||||||
.attr('id', 'stickBottomArrowHead')
|
|
||||||
.attr('refX', 7.5)
|
|
||||||
.attr('refY', 0)
|
|
||||||
.attr('markerUnits', 'userSpaceOnUse')
|
|
||||||
.attr('markerWidth', 12)
|
|
||||||
.attr('markerHeight', 12)
|
|
||||||
.attr('orient', 'auto-start-reverse')
|
|
||||||
.append('path')
|
|
||||||
.attr('d', 'M 0 7 L 7 0')
|
|
||||||
.attr('stroke', 'black')
|
|
||||||
.attr('stroke-width', 1.5)
|
|
||||||
.attr('fill', 'none');
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
drawRect,
|
drawRect,
|
||||||
drawText,
|
drawText,
|
||||||
@@ -1802,8 +1731,4 @@ export default {
|
|||||||
getNoteRect,
|
getNoteRect,
|
||||||
fixLifeLineHeights,
|
fixLifeLineHeights,
|
||||||
sanitizeUrl,
|
sanitizeUrl,
|
||||||
insertSolidTopArrowHead,
|
|
||||||
insertSolidBottomArrowHead,
|
|
||||||
insertStickTopArrowHead,
|
|
||||||
insertStickBottomArrowHead,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ export interface Message {
|
|||||||
type?: number;
|
type?: number;
|
||||||
activate?: boolean;
|
activate?: boolean;
|
||||||
placement?: string;
|
placement?: string;
|
||||||
centralConnection?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AddMessageParams {
|
export interface AddMessageParams {
|
||||||
@@ -51,8 +50,6 @@ export interface AddMessageParams {
|
|||||||
| 'destroyParticipant'
|
| 'destroyParticipant'
|
||||||
| 'activeStart'
|
| 'activeStart'
|
||||||
| 'activeEnd'
|
| 'activeEnd'
|
||||||
| 'centralConnection'
|
|
||||||
| 'centralConnectionReverse'
|
|
||||||
| 'addNote'
|
| 'addNote'
|
||||||
| 'addLinks'
|
| 'addLinks'
|
||||||
| 'addALink'
|
| 'addALink'
|
||||||
|
|||||||
@@ -40,26 +40,105 @@ const openSourceFeatures: Feature[] = [
|
|||||||
{ iconUrl: '/icons/version-history.svg', featureName: 'Version history' },
|
{ iconUrl: '/icons/version-history.svg', featureName: 'Version history' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const editorColumns: EditorColumn[] = [
|
const playgroundFeatures: Feature[] = [
|
||||||
{
|
{ iconUrl: '/icons/public.svg', featureName: 'Diagram stored in URL' },
|
||||||
title: 'Mermaid Pro',
|
{ iconUrl: '/icons/terminal.svg', featureName: 'Code editor' },
|
||||||
description: 'Unlock AI and real-time collaboration',
|
{ iconUrl: '/icons/whiteboard.svg', featureName: 'Whiteboard' },
|
||||||
highlighted: true,
|
|
||||||
redBarText: 'Recommended',
|
|
||||||
proTrialButtonText: 'Start free trial',
|
|
||||||
proTrialUrl:
|
|
||||||
'https://www.mermaidchart.com/app/sign-up?utm_source=mermaid_js&utm_medium=2_editor_selection&utm_campaign=start_pro&redirect=%2Fapp%2Fuser%2Fbilling%2Fcheckout%3FisFromMermaid%3Dtrue',
|
|
||||||
features: mermaidChartFeatures,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Open Source',
|
|
||||||
description: 'Code only, no login',
|
|
||||||
buttonText: 'Start free',
|
|
||||||
redirectUrl: 'https://mermaid.live/edit',
|
|
||||||
features: openSourceFeatures,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const editorColumnVariants: EditorColumn[][] = [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
title: 'Playground',
|
||||||
|
description: 'Basic features, no login',
|
||||||
|
redirectUrl:
|
||||||
|
'https://www.mermaidchart.com/app/sign-up?utm_source=mermaid_js&utm_medium=3_editor_selection_A&utm_campaign=start_playground',
|
||||||
|
buttonText: 'Start free',
|
||||||
|
features: playgroundFeatures,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Free or Pro',
|
||||||
|
description: 'Advanced features, Free or Pro account',
|
||||||
|
proTrialUrl:
|
||||||
|
'https://www.mermaidchart.com/app/sign-up?utm_source=mermaid_js&utm_medium=3_editor_selection_A&utm_campaign=start_free',
|
||||||
|
proTrialButtonText: 'Start free',
|
||||||
|
highlighted: true,
|
||||||
|
redBarText: 'Best for collaboration',
|
||||||
|
features: mermaidChartFeatures,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Open Source',
|
||||||
|
description: 'Code only, no login',
|
||||||
|
redirectUrl: 'https://mermaid.live/edit',
|
||||||
|
buttonText: 'Start free',
|
||||||
|
features: openSourceFeatures,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
title: 'Mermaid Pro',
|
||||||
|
description: 'Unlock AI and real-time collaboration',
|
||||||
|
redirectUrl:
|
||||||
|
'https://www.mermaidchart.com/app/sign-up?utm_source=mermaid_js&utm_medium=editor_selection_B&utm_campaign=start_free',
|
||||||
|
buttonText: 'Start Free',
|
||||||
|
highlighted: true,
|
||||||
|
redBarText: 'Recommended',
|
||||||
|
proTrialButtonText: 'Start Pro trial',
|
||||||
|
proTrialUrl:
|
||||||
|
'https://www.mermaidchart.com/app/sign-up?utm_source=mermaid_js&utm_medium=editor_selection_B&utm_campaign=start_trial&redirect=%2Fapp%2Fuser%2Fbilling%2Fcheckout%3FisFromMermaid%3Dtrue',
|
||||||
|
features: mermaidChartFeatures,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Open Source',
|
||||||
|
description: 'Code only, no login',
|
||||||
|
buttonText: 'Start free',
|
||||||
|
redirectUrl: 'https://mermaid.live/edit',
|
||||||
|
isButtonMargined: true,
|
||||||
|
features: openSourceFeatures,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
title: 'Mermaid Pro',
|
||||||
|
description: 'Unlock AI and real-time collaboration',
|
||||||
|
highlighted: true,
|
||||||
|
redBarText: 'Recommended',
|
||||||
|
proTrialButtonText: 'Start free trial',
|
||||||
|
proTrialUrl:
|
||||||
|
'https://www.mermaidchart.com/app/sign-up?utm_source=mermaid_js&utm_medium=editor_selection_C&utm_campaign=start_trial&redirect=%2Fapp%2Fuser%2Fbilling%2Fcheckout%3FisFromMermaid%3Dtrue',
|
||||||
|
features: mermaidChartFeatures,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Open Source',
|
||||||
|
description: 'Code only, no login',
|
||||||
|
buttonText: 'Start free',
|
||||||
|
redirectUrl: 'https://mermaid.live/edit',
|
||||||
|
features: openSourceFeatures,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
title: 'Mermaid Pro',
|
||||||
|
description: 'Unlock AI and real-time collaboration',
|
||||||
|
highlighted: true,
|
||||||
|
redBarText: 'Recommended',
|
||||||
|
proTrialButtonText: 'Start free',
|
||||||
|
proTrialUrl:
|
||||||
|
'https://www.mermaidchart.com/app/sign-up?utm_source=mermaid_js&utm_medium=editor_selection_D&utm_campaign=start_free',
|
||||||
|
features: mermaidChartFeatures,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Open Source',
|
||||||
|
description: 'Code only, no login',
|
||||||
|
redirectUrl: 'https://mermaid.live/edit',
|
||||||
|
buttonText: 'Start free',
|
||||||
|
features: openSourceFeatures,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
const editorColumns = editorColumnVariants[Math.floor(Math.random() * editorColumnVariants.length)];
|
||||||
|
|
||||||
const isVisible = ref(false);
|
const isVisible = ref(false);
|
||||||
|
|
||||||
const handleMouseDown = (e: MouseEvent) => {
|
const handleMouseDown = (e: MouseEvent) => {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ While directives allow you to change most of the default configuration settings,
|
|||||||
Mermaid basically supports two types of configuration options to be overridden by directives.
|
Mermaid basically supports two types of configuration options to be overridden by directives.
|
||||||
|
|
||||||
1. _General/Top Level configurations_ : These are the configurations that are available and applied to all the diagram. **Some of the most important top-level** configurations are:
|
1. _General/Top Level configurations_ : These are the configurations that are available and applied to all the diagram. **Some of the most important top-level** configurations are:
|
||||||
|
|
||||||
- theme
|
- theme
|
||||||
- fontFamily
|
- fontFamily
|
||||||
- logLevel
|
- logLevel
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an accoun
|
|||||||
- **Plugins** - A plugin system for extending the functionality of Mermaid.
|
- **Plugins** - A plugin system for extending the functionality of Mermaid.
|
||||||
|
|
||||||
Official Mermaid Chart plugins:
|
Official Mermaid Chart plugins:
|
||||||
|
|
||||||
- [Mermaid Chart GPT](https://chatgpt.com/g/g-684cc36f30208191b21383b88650a45d-mermaid-chart-diagrams-and-charts)
|
- [Mermaid Chart GPT](https://chatgpt.com/g/g-684cc36f30208191b21383b88650a45d-mermaid-chart-diagrams-and-charts)
|
||||||
- [Confluence](https://marketplace.atlassian.com/apps/1234056/mermaid-chart-for-confluence?hosting=cloud&tab=overview)
|
- [Confluence](https://marketplace.atlassian.com/apps/1234056/mermaid-chart-for-confluence?hosting=cloud&tab=overview)
|
||||||
- [Jira](https://marketplace.atlassian.com/apps/1234810/mermaid-chart-for-jira?tab=overview&hosting=cloud)
|
- [Jira](https://marketplace.atlassian.com/apps/1234810/mermaid-chart-for-jira?tab=overview&hosting=cloud)
|
||||||
|
|||||||
@@ -33,11 +33,13 @@ The Mermaid Chart team is excited to introduce a new Visual Editor for Flowchart
|
|||||||
Learn more:
|
Learn more:
|
||||||
|
|
||||||
- Visual Editor For Flowcharts
|
- Visual Editor For Flowcharts
|
||||||
|
|
||||||
- [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-releases-new-visual-editor-for-flowcharts)
|
- [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-releases-new-visual-editor-for-flowcharts)
|
||||||
|
|
||||||
- [Demo video](https://www.youtube.com/watch?v=5aja0gijoO0)
|
- [Demo video](https://www.youtube.com/watch?v=5aja0gijoO0)
|
||||||
|
|
||||||
- Visual Editor For Sequence diagrams
|
- Visual Editor For Sequence diagrams
|
||||||
|
|
||||||
- [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-unveils-visual-editor-for-sequence-diagrams)
|
- [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-unveils-visual-editor-for-sequence-diagrams)
|
||||||
|
|
||||||
- [Demo video](https://youtu.be/imc2u5_N6Dc)
|
- [Demo video](https://youtu.be/imc2u5_N6Dc)
|
||||||
|
|||||||
@@ -1,17 +1,5 @@
|
|||||||
# Blog
|
# Blog
|
||||||
|
|
||||||
## [The Essential Guide to Mermaid Chart Plugin for VS Code [08/2025]](https://docs.mermaidchart.com/blog/posts/the-essential-guide-to-mermaid-chart-plugin-for-vs-code-08-2025)
|
|
||||||
|
|
||||||
9/9/2025 • 5 mins
|
|
||||||
|
|
||||||
Creating diagrams in VS Code has never been easier—the Mermaid VS Code plugin transforms text-based syntax into clear, professional visuals right inside your editor. With live previews, smart editing, and AI-powered diagram generation, it removes the friction from visualization so you can focus on coding.
|
|
||||||
|
|
||||||
## [How to Create Perfect Flowcharts Using AI in 2025 Step-by-Step Guide](https://docs.mermaidchart.com/blog/posts/how-to-create-perfect-flowcharts-using-ai-in-2025-step-by-step-guide)
|
|
||||||
|
|
||||||
7/22/2025 • 8 mins
|
|
||||||
|
|
||||||
In 2025, AI tools make creating flowcharts faster and easier than ever. With Mermaid’s AI flowchart generator, you can turn plain text into clear, accurate diagrams in seconds. This guide walks through how it works and how to get the most out of it for technical and business workflows alike.
|
|
||||||
|
|
||||||
## [Mermaid introduces the Visual Editor for Entity Relationship diagrams](https://docs.mermaidchart.com/blog/posts/mermaid-introduces-the-visual-editor-for-entity-relationship-diagrams)
|
## [Mermaid introduces the Visual Editor for Entity Relationship diagrams](https://docs.mermaidchart.com/blog/posts/mermaid-introduces-the-visual-editor-for-entity-relationship-diagrams)
|
||||||
|
|
||||||
7/15/2025 • 7 mins
|
7/15/2025 • 7 mins
|
||||||
|
|||||||
@@ -17,25 +17,25 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "^7.4.47",
|
"@mdi/font": "^7.4.47",
|
||||||
"@vueuse/core": "^13.9.0",
|
"@vueuse/core": "^13.1.0",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
"jiti": "^2.4.2",
|
"jiti": "^2.4.2",
|
||||||
"mermaid": "workspace:^",
|
"mermaid": "workspace:^",
|
||||||
"vue": "^3.5.21"
|
"vue": "^3.4.38"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@iconify-json/carbon": "^1.2.13",
|
"@iconify-json/carbon": "^1.1.37",
|
||||||
"@unocss/reset": "^66.5.1",
|
"@unocss/reset": "^66.0.0",
|
||||||
"@vite-pwa/vitepress": "^1.0.0",
|
"@vite-pwa/vitepress": "^1.0.0",
|
||||||
"@vitejs/plugin-vue": "^6.0.1",
|
"@vitejs/plugin-vue": "^6.0.0",
|
||||||
"fast-glob": "^3.3.3",
|
"fast-glob": "^3.3.3",
|
||||||
"https-localhost": "^4.7.1",
|
"https-localhost": "^4.7.1",
|
||||||
"pathe": "^2.0.3",
|
"pathe": "^2.0.3",
|
||||||
"unocss": "^66.5.1",
|
"unocss": "^66.4.2",
|
||||||
"unplugin-vue-components": "^28.4.1",
|
"unplugin-vue-components": "^28.4.0",
|
||||||
"vite": "^7.0.7",
|
"vite": "^7.0.0",
|
||||||
"vite-plugin-pwa": "^1.0.3",
|
"vite-plugin-pwa": "^1.0.0",
|
||||||
"vitepress": "1.6.4",
|
"vitepress": "1.6.3",
|
||||||
"workbox-window": "^7.3.0"
|
"workbox-window": "^7.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ architecture-beta
|
|||||||
## Icons
|
## Icons
|
||||||
|
|
||||||
By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`.
|
By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`.
|
||||||
Users can use any of the 200,000+ icons available in iconify.design, or add other custom icons, by [registering an icon pack](../config/icons.md).
|
Users can use any of the 200,000+ icons available in iconify.design, or [add custom icons](../config/icons.md).
|
||||||
|
|
||||||
After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack.
|
After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack.
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ The following unfinished features are not supported in the short term.
|
|||||||
- [ ] Legend
|
- [ ] Legend
|
||||||
|
|
||||||
- [x] System Context
|
- [x] System Context
|
||||||
|
|
||||||
- [x] Person(alias, label, ?descr, ?sprite, ?tags, $link)
|
- [x] Person(alias, label, ?descr, ?sprite, ?tags, $link)
|
||||||
- [x] Person_Ext
|
- [x] Person_Ext
|
||||||
- [x] System(alias, label, ?descr, ?sprite, ?tags, $link)
|
- [x] System(alias, label, ?descr, ?sprite, ?tags, $link)
|
||||||
@@ -96,6 +97,7 @@ The following unfinished features are not supported in the short term.
|
|||||||
- [x] System_Boundary
|
- [x] System_Boundary
|
||||||
|
|
||||||
- [x] Container diagram
|
- [x] Container diagram
|
||||||
|
|
||||||
- [x] Container(alias, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
- [x] Container(alias, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
||||||
- [x] ContainerDb
|
- [x] ContainerDb
|
||||||
- [x] ContainerQueue
|
- [x] ContainerQueue
|
||||||
@@ -105,6 +107,7 @@ The following unfinished features are not supported in the short term.
|
|||||||
- [x] Container_Boundary(alias, label, ?tags, $link)
|
- [x] Container_Boundary(alias, label, ?tags, $link)
|
||||||
|
|
||||||
- [x] Component diagram
|
- [x] Component diagram
|
||||||
|
|
||||||
- [x] Component(alias, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
- [x] Component(alias, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
||||||
- [x] ComponentDb
|
- [x] ComponentDb
|
||||||
- [x] ComponentQueue
|
- [x] ComponentQueue
|
||||||
@@ -113,15 +116,18 @@ The following unfinished features are not supported in the short term.
|
|||||||
- [x] ComponentQueue_Ext
|
- [x] ComponentQueue_Ext
|
||||||
|
|
||||||
- [x] Dynamic diagram
|
- [x] Dynamic diagram
|
||||||
|
|
||||||
- [x] RelIndex(index, from, to, label, ?tags, $link)
|
- [x] RelIndex(index, from, to, label, ?tags, $link)
|
||||||
|
|
||||||
- [x] Deployment diagram
|
- [x] Deployment diagram
|
||||||
|
|
||||||
- [x] Deployment_Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link)
|
- [x] Deployment_Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link)
|
||||||
- [x] Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link): short name of Deployment_Node()
|
- [x] Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link): short name of Deployment_Node()
|
||||||
- [x] Node_L(alias, label, ?type, ?descr, ?sprite, ?tags, $link): left aligned Node()
|
- [x] Node_L(alias, label, ?type, ?descr, ?sprite, ?tags, $link): left aligned Node()
|
||||||
- [x] Node_R(alias, label, ?type, ?descr, ?sprite, ?tags, $link): right aligned Node()
|
- [x] Node_R(alias, label, ?type, ?descr, ?sprite, ?tags, $link): right aligned Node()
|
||||||
|
|
||||||
- [x] Relationship Types
|
- [x] Relationship Types
|
||||||
|
|
||||||
- [x] Rel(from, to, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
- [x] Rel(from, to, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
||||||
- [x] BiRel (bidirectional relationship)
|
- [x] BiRel (bidirectional relationship)
|
||||||
- [x] Rel_U, Rel_Up
|
- [x] Rel_U, Rel_Up
|
||||||
|
|||||||
@@ -216,11 +216,7 @@ Messages can be of two displayed either solid or with a dotted line.
|
|||||||
[Actor][Arrow][Actor]:Message text
|
[Actor][Arrow][Actor]:Message text
|
||||||
```
|
```
|
||||||
|
|
||||||
Lines can be solid or dotted, and can end with various types of arrowheads, crosses, or open arrows.
|
There are ten types of arrows currently supported:
|
||||||
|
|
||||||
#### Supported Arrow Types
|
|
||||||
|
|
||||||
**Standard Arrow Types**
|
|
||||||
|
|
||||||
| Type | Description |
|
| Type | Description |
|
||||||
| -------- | ---------------------------------------------------- |
|
| -------- | ---------------------------------------------------- |
|
||||||
@@ -235,49 +231,6 @@ Lines can be solid or dotted, and can end with various types of arrowheads, cros
|
|||||||
| `-)` | Solid line with an open arrow at the end (async) |
|
| `-)` | Solid line with an open arrow at the end (async) |
|
||||||
| `--)` | Dotted line with a open arrow at the end (async) |
|
| `--)` | Dotted line with a open arrow at the end (async) |
|
||||||
|
|
||||||
**Half-Arrows (v<MERMAID_RELEASE_VERSION>+)**
|
|
||||||
|
|
||||||
The following half-arrow types are supported for more expressive sequence diagrams. Both solid and dotted variants are available by increasing the number of dashes (`-` → `--`).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
| Type | Description |
|
|
||||||
| ------- | ---------------------------------------------------- |
|
|
||||||
| `-\|\` | Solid line with top half arrowhead |
|
|
||||||
| `--\|\` | Dotted line with top half arrowhead |
|
|
||||||
| `-\|/` | Solid line with bottom half arrowhead |
|
|
||||||
| `--\|/` | Dotted line with bottom half arrowhead |
|
|
||||||
| `/\|-` | Solid line with reverse top half arrowhead |
|
|
||||||
| `/\|--` | Dotted line with reverse top half arrowhead |
|
|
||||||
| `\\-` | Solid line with reverse bottom half arrowhead |
|
|
||||||
| `\\--` | Dotted line with reverse bottom half arrowhead |
|
|
||||||
| `-\\` | Solid line with top stick half arrowhead |
|
|
||||||
| `--\\` | Dotted line with top stick half arrowhead |
|
|
||||||
| `-//` | Solid line with bottom stick half arrowhead |
|
|
||||||
| `--//` | Dotted line with bottom stick half arrowhead |
|
|
||||||
| `//-` | Solid line with reverse top stick half arrowhead |
|
|
||||||
| `//--` | Dotted line with reverse top stick half arrowhead |
|
|
||||||
| `\\-` | Solid line with reverse bottom stick half arrowhead |
|
|
||||||
| `\\--` | Dotted line with reverse bottom stick half arrowhead |
|
|
||||||
|
|
||||||
## Central Connections (v<MERMAID_RELEASE_VERSION>+)
|
|
||||||
|
|
||||||
Mermaid sequence diagrams support **central lifeline connections** using a `()`.
|
|
||||||
This is useful to represent messages or signals that connect to a central point, rather than from one actor directly to another.
|
|
||||||
|
|
||||||
To indicate a central connection, append `()` to the arrow syntax.
|
|
||||||
|
|
||||||
#### Basic Syntax
|
|
||||||
|
|
||||||
```mermaid-example
|
|
||||||
sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant John
|
|
||||||
Alice->>()John: Hello John
|
|
||||||
Alice()->>John: How are you?
|
|
||||||
John()->>()Alice: Great!
|
|
||||||
```
|
|
||||||
|
|
||||||
## Activations
|
## Activations
|
||||||
|
|
||||||
It is possible to activate and deactivate an actor. (de)activation can be dedicated declarations:
|
It is possible to activate and deactivate an actor. (de)activation can be dedicated declarations:
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ describe('when using mermaid and ', () => {
|
|||||||
[Error: Parse error on line 2:
|
[Error: Parse error on line 2:
|
||||||
...equenceDiagramAlice:->Bob: Hello Bob, h...
|
...equenceDiagramAlice:->Bob: Hello Bob, h...
|
||||||
----------------------^
|
----------------------^
|
||||||
Expecting '()', 'SOLID_OPEN_ARROW', 'DOTTED_OPEN_ARROW', 'SOLID_ARROW', 'SOLID_ARROW_TOP', 'SOLID_ARROW_BOTTOM', 'STICK_ARROW_TOP', 'STICK_ARROW_BOTTOM', 'SOLID_ARROW_TOP_DOTTED', 'SOLID_ARROW_BOTTOM_DOTTED', 'STICK_ARROW_TOP_DOTTED', 'STICK_ARROW_BOTTOM_DOTTED', 'SOLID_ARROW_TOP_REVERSE', 'SOLID_ARROW_BOTTOM_REVERSE', 'STICK_ARROW_TOP_REVERSE', 'STICK_ARROW_BOTTOM_REVERSE', 'SOLID_ARROW_TOP_REVERSE_DOTTED', 'SOLID_ARROW_BOTTOM_REVERSE_DOTTED', 'STICK_ARROW_TOP_REVERSE_DOTTED', 'STICK_ARROW_BOTTOM_REVERSE_DOTTED', 'BIDIRECTIONAL_SOLID_ARROW', 'DOTTED_ARROW', 'BIDIRECTIONAL_DOTTED_ARROW', 'SOLID_CROSS', 'DOTTED_CROSS', 'SOLID_POINT', 'DOTTED_POINT', got 'TXT']
|
Expecting 'SOLID_OPEN_ARROW', 'DOTTED_OPEN_ARROW', 'SOLID_ARROW', 'BIDIRECTIONAL_SOLID_ARROW', 'DOTTED_ARROW', 'BIDIRECTIONAL_DOTTED_ARROW', 'SOLID_CROSS', 'DOTTED_CROSS', 'SOLID_POINT', 'DOTTED_POINT', got 'TXT']
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,6 @@ import rough from 'roughjs';
|
|||||||
import type { D3Selection } from '../../../types.js';
|
import type { D3Selection } from '../../../types.js';
|
||||||
import { handleUndefinedAttr } from '../../../utils.js';
|
import { handleUndefinedAttr } from '../../../utils.js';
|
||||||
import type { Bounds, Point } from '../../../types.js';
|
import type { Bounds, Point } from '../../../types.js';
|
||||||
import {
|
|
||||||
calculateMindmapDimensions,
|
|
||||||
getMindmapIconConfig,
|
|
||||||
insertMindmapIcon,
|
|
||||||
} from '../../../diagrams/mindmap/mindmapIconHelper.js';
|
|
||||||
|
|
||||||
export async function bang<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
export async function bang<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
@@ -22,34 +17,20 @@ export async function bang<T extends SVGGraphicsElement>(parent: D3Selection<T>,
|
|||||||
getNodeClasses(node)
|
getNodeClasses(node)
|
||||||
);
|
);
|
||||||
|
|
||||||
const baseWidth = bbox.width + 10 * halfPadding;
|
const w = bbox.width + 10 * halfPadding;
|
||||||
const baseHeight = bbox.height + 8 * halfPadding;
|
const h = bbox.height + 8 * halfPadding;
|
||||||
|
const r = 0.15 * w;
|
||||||
const iconConfig = getMindmapIconConfig('bang');
|
const { cssStyles } = node;
|
||||||
const dimensions = calculateMindmapDimensions(
|
|
||||||
node,
|
|
||||||
bbox,
|
|
||||||
baseWidth,
|
|
||||||
baseHeight,
|
|
||||||
halfPadding,
|
|
||||||
iconConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
const w = dimensions.width;
|
|
||||||
const h = dimensions.height;
|
|
||||||
|
|
||||||
node.width = w;
|
|
||||||
node.height = h;
|
|
||||||
|
|
||||||
const minWidth = bbox.width + 20;
|
const minWidth = bbox.width + 20;
|
||||||
const minHeight = bbox.height + 20;
|
const minHeight = bbox.height + 20;
|
||||||
const effectiveWidth = Math.max(w, minWidth);
|
const effectiveWidth = Math.max(w, minWidth);
|
||||||
const effectiveHeight = Math.max(h, minHeight);
|
const effectiveHeight = Math.max(h, minHeight);
|
||||||
|
|
||||||
label.attr('transform', `translate(${dimensions.labelOffset.x}, ${dimensions.labelOffset.y})`);
|
label.attr('transform', `translate(${-bbox.width / 2}, ${-bbox.height / 2})`);
|
||||||
|
|
||||||
const r = 0.15 * effectiveWidth;
|
let bangElem;
|
||||||
const path = `M0 0
|
const path = `M0 0
|
||||||
a${r},${r} 1 0,0 ${effectiveWidth * 0.25},${-1 * effectiveHeight * 0.1}
|
a${r},${r} 1 0,0 ${effectiveWidth * 0.25},${-1 * effectiveHeight * 0.1}
|
||||||
a${r},${r} 1 0,0 ${effectiveWidth * 0.25},${0}
|
a${r},${r} 1 0,0 ${effectiveWidth * 0.25},${0}
|
||||||
a${r},${r} 1 0,0 ${effectiveWidth * 0.25},${0}
|
a${r},${r} 1 0,0 ${effectiveWidth * 0.25},${0}
|
||||||
@@ -69,16 +50,13 @@ export async function bang<T extends SVGGraphicsElement>(parent: D3Selection<T>,
|
|||||||
a${r},${r} 1 0,0 ${effectiveWidth * 0.1},${-1 * effectiveHeight * 0.33}
|
a${r},${r} 1 0,0 ${effectiveWidth * 0.1},${-1 * effectiveHeight * 0.33}
|
||||||
H0 V0 Z`;
|
H0 V0 Z`;
|
||||||
|
|
||||||
let bangElem;
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
const roughNode = rc.path(path, options);
|
const roughNode = rc.path(path, options);
|
||||||
bangElem = shapeSvg.insert(() => roughNode, ':first-child');
|
bangElem = shapeSvg.insert(() => roughNode, ':first-child');
|
||||||
bangElem
|
bangElem.attr('class', 'basic label-container').attr('style', handleUndefinedAttr(cssStyles));
|
||||||
.attr('class', 'basic label-container')
|
|
||||||
.attr('style', handleUndefinedAttr(node.cssStyles));
|
|
||||||
} else {
|
} else {
|
||||||
bangElem = shapeSvg
|
bangElem = shapeSvg
|
||||||
.insert('path', ':first-child')
|
.insert('path', ':first-child')
|
||||||
@@ -90,10 +68,6 @@ export async function bang<T extends SVGGraphicsElement>(parent: D3Selection<T>,
|
|||||||
// Translate the path (center the shape)
|
// Translate the path (center the shape)
|
||||||
bangElem.attr('transform', `translate(${-effectiveWidth / 2}, ${-effectiveHeight / 2})`);
|
bangElem.attr('transform', `translate(${-effectiveWidth / 2}, ${-effectiveHeight / 2})`);
|
||||||
|
|
||||||
if (node.icon) {
|
|
||||||
await insertMindmapIcon(shapeSvg, node, iconConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateNodeBounds(node, bangElem);
|
updateNodeBounds(node, bangElem);
|
||||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||||
return intersect.rect(bounds, point);
|
return intersect.rect(bounds, point);
|
||||||
|
|||||||
@@ -14,25 +14,9 @@ export async function circle<T extends SVGGraphicsElement>(
|
|||||||
) {
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
|
const { shapeSvg, bbox, halfPadding } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
const { shapeSvg, bbox, halfPadding, label } = await labelHelper(
|
|
||||||
parent,
|
|
||||||
node,
|
|
||||||
getNodeClasses(node)
|
|
||||||
);
|
|
||||||
|
|
||||||
const padding = options?.padding ?? halfPadding;
|
const padding = options?.padding ?? halfPadding;
|
||||||
|
|
||||||
const radius = bbox.width / 2 + padding;
|
const radius = bbox.width / 2 + padding;
|
||||||
|
|
||||||
node.width = radius * 2;
|
|
||||||
node.height = radius * 2;
|
|
||||||
|
|
||||||
const labelXOffset = -bbox.width / 2;
|
|
||||||
const labelYOffset = -bbox.height / 2;
|
|
||||||
if (node.icon) {
|
|
||||||
label.attr('transform', `translate(${labelXOffset}, ${labelYOffset})`);
|
|
||||||
}
|
|
||||||
let circleElem;
|
let circleElem;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,6 @@ import type { Node } from '../../types.js';
|
|||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import { getNodeClasses, labelHelper, updateNodeBounds } from './util.js';
|
import { getNodeClasses, labelHelper, updateNodeBounds } from './util.js';
|
||||||
import {
|
|
||||||
getMindmapIconConfig,
|
|
||||||
calculateMindmapDimensions,
|
|
||||||
insertMindmapIcon,
|
|
||||||
} from '../../../diagrams/mindmap/mindmapIconHelper.js';
|
|
||||||
|
|
||||||
export async function cloud<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
export async function cloud<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
@@ -22,26 +17,8 @@ export async function cloud<T extends SVGGraphicsElement>(parent: D3Selection<T>
|
|||||||
getNodeClasses(node)
|
getNodeClasses(node)
|
||||||
);
|
);
|
||||||
|
|
||||||
const baseWidth = bbox.width + 2 * halfPadding;
|
const w = bbox.width + 2 * halfPadding;
|
||||||
const baseHeight = bbox.height + 2 * halfPadding;
|
const h = bbox.height + 2 * halfPadding;
|
||||||
|
|
||||||
const iconConfig = getMindmapIconConfig('cloud');
|
|
||||||
const dimensions = calculateMindmapDimensions(
|
|
||||||
node,
|
|
||||||
bbox,
|
|
||||||
baseWidth,
|
|
||||||
baseHeight,
|
|
||||||
halfPadding,
|
|
||||||
iconConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
const w = dimensions.width;
|
|
||||||
const h = dimensions.height;
|
|
||||||
|
|
||||||
node.width = w;
|
|
||||||
node.height = h;
|
|
||||||
|
|
||||||
label.attr('transform', `translate(${dimensions.labelOffset.x}, ${dimensions.labelOffset.y})`);
|
|
||||||
|
|
||||||
// Cloud radii
|
// Cloud radii
|
||||||
const r1 = 0.15 * w;
|
const r1 = 0.15 * w;
|
||||||
@@ -84,13 +61,11 @@ export async function cloud<T extends SVGGraphicsElement>(parent: D3Selection<T>
|
|||||||
.attr('d', path);
|
.attr('d', path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label.attr('transform', `translate(${-bbox.width / 2}, ${-bbox.height / 2})`);
|
||||||
|
|
||||||
// Center the shape
|
// Center the shape
|
||||||
cloudElem.attr('transform', `translate(${-w / 2}, ${-h / 2})`);
|
cloudElem.attr('transform', `translate(${-w / 2}, ${-h / 2})`);
|
||||||
|
|
||||||
if (node.icon) {
|
|
||||||
await insertMindmapIcon(shapeSvg, node, iconConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateNodeBounds(node, cloudElem);
|
updateNodeBounds(node, cloudElem);
|
||||||
|
|
||||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||||
|
|||||||
@@ -3,11 +3,6 @@ import type { Node } from '../../types.js';
|
|||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { styles2String } from './handDrawnShapeStyles.js';
|
import { styles2String } from './handDrawnShapeStyles.js';
|
||||||
import { getNodeClasses, labelHelper, updateNodeBounds } from './util.js';
|
import { getNodeClasses, labelHelper, updateNodeBounds } from './util.js';
|
||||||
import {
|
|
||||||
getMindmapIconConfig,
|
|
||||||
calculateMindmapDimensions,
|
|
||||||
insertMindmapIcon,
|
|
||||||
} from '../../../diagrams/mindmap/mindmapIconHelper.js';
|
|
||||||
|
|
||||||
export async function defaultMindmapNode<T extends SVGGraphicsElement>(
|
export async function defaultMindmapNode<T extends SVGGraphicsElement>(
|
||||||
parent: D3Selection<T>,
|
parent: D3Selection<T>,
|
||||||
@@ -22,38 +17,22 @@ export async function defaultMindmapNode<T extends SVGGraphicsElement>(
|
|||||||
getNodeClasses(node)
|
getNodeClasses(node)
|
||||||
);
|
);
|
||||||
|
|
||||||
const baseWidth = bbox.width + 8 * halfPadding;
|
const w = bbox.width + 8 * halfPadding;
|
||||||
const baseHeight = bbox.height + 2 * halfPadding;
|
const h = bbox.height + 2 * halfPadding;
|
||||||
|
const rd = 5;
|
||||||
|
|
||||||
const iconConfig = getMindmapIconConfig('default');
|
const rectPath = `
|
||||||
const dimensions = calculateMindmapDimensions(
|
M${-w / 2} ${h / 2 - rd}
|
||||||
node,
|
v${-h + 2 * rd}
|
||||||
bbox,
|
q0,-${rd} ${rd},-${rd}
|
||||||
baseWidth,
|
h${w - 2 * rd}
|
||||||
baseHeight,
|
q${rd},0 ${rd},${rd}
|
||||||
halfPadding,
|
v${h - 2 * rd}
|
||||||
iconConfig
|
q0,${rd} -${rd},${rd}
|
||||||
);
|
h${-w + 2 * rd}
|
||||||
|
q-${rd},0 -${rd},-${rd}
|
||||||
const w = dimensions.width;
|
Z
|
||||||
const h = dimensions.height;
|
`;
|
||||||
|
|
||||||
node.width = w;
|
|
||||||
node.height = h;
|
|
||||||
|
|
||||||
label.attr('transform', `translate(${dimensions.labelOffset.x}, ${dimensions.labelOffset.y})`);
|
|
||||||
|
|
||||||
const RD = 5;
|
|
||||||
const rectPath = `M${-w / 2} ${h / 2 - RD}
|
|
||||||
v${-h + 2 * RD}
|
|
||||||
q0,-${RD} ${RD},-${RD}
|
|
||||||
h${w - 2 * RD}
|
|
||||||
q${RD},0 ${RD},${RD}
|
|
||||||
v${h - 2 * RD}
|
|
||||||
q0,${RD} -${RD},${RD}
|
|
||||||
h${-w + 2 * RD}
|
|
||||||
q-${RD},0 -${RD},-${RD}
|
|
||||||
Z`;
|
|
||||||
|
|
||||||
const bg = shapeSvg
|
const bg = shapeSvg
|
||||||
.append('path')
|
.append('path')
|
||||||
@@ -70,12 +49,9 @@ export async function defaultMindmapNode<T extends SVGGraphicsElement>(
|
|||||||
.attr('x2', w / 2)
|
.attr('x2', w / 2)
|
||||||
.attr('y2', h / 2);
|
.attr('y2', h / 2);
|
||||||
|
|
||||||
|
label.attr('transform', `translate(${-bbox.width / 2}, ${-bbox.height / 2})`);
|
||||||
shapeSvg.append(() => label.node());
|
shapeSvg.append(() => label.node());
|
||||||
|
|
||||||
if (node.icon) {
|
|
||||||
await insertMindmapIcon(shapeSvg, node, iconConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateNodeBounds(node, bg);
|
updateNodeBounds(node, bg);
|
||||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||||
return intersect.rect(bounds, point);
|
return intersect.rect(bounds, point);
|
||||||
|
|||||||
@@ -15,21 +15,11 @@ export async function drawRect<T extends SVGGraphicsElement>(
|
|||||||
) {
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
|
// console.log('IPI labelStyles:', labelStyles);
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
|
|
||||||
const totalWidth = Math.max(bbox.width + options.labelPaddingX * 2, node?.width || 0);
|
const totalWidth = Math.max(bbox.width + options.labelPaddingX * 2, node?.width || 0);
|
||||||
const totalHeight = Math.max(bbox.height + options.labelPaddingY * 2, node?.height || 0);
|
const totalHeight = Math.max(bbox.height + options.labelPaddingY * 2, node?.height || 0);
|
||||||
|
|
||||||
node.width = totalWidth;
|
|
||||||
node.height = totalHeight;
|
|
||||||
|
|
||||||
const labelXOffset = -bbox.width / 2;
|
|
||||||
|
|
||||||
const labelYOffset = -bbox.height / 2;
|
|
||||||
if (node.icon) {
|
|
||||||
label.attr('transform', `translate(${labelXOffset}, ${labelYOffset})`);
|
|
||||||
}
|
|
||||||
const x = -totalWidth / 2;
|
const x = -totalWidth / 2;
|
||||||
const y = -totalHeight / 2;
|
const y = -totalHeight / 2;
|
||||||
|
|
||||||
|
|||||||
@@ -26,22 +26,10 @@ export const createHexagonPathD = (
|
|||||||
export async function hexagon<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
export async function hexagon<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
|
||||||
|
|
||||||
const h = bbox.height + (node.padding ?? 0);
|
const h = bbox.height + (node.padding ?? 0);
|
||||||
const w = bbox.width + (node.padding ?? 0) * 2.5;
|
const w = bbox.width + (node.padding ?? 0) * 2.5;
|
||||||
|
|
||||||
node.width = w;
|
|
||||||
node.height = h;
|
|
||||||
|
|
||||||
const labelXOffset = -bbox.width / 2;
|
|
||||||
|
|
||||||
const labelYOffset = -bbox.height / 2;
|
|
||||||
|
|
||||||
if (node.icon) {
|
|
||||||
label.attr('transform', `translate(${labelXOffset}, ${labelYOffset})`);
|
|
||||||
}
|
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
@@ -86,6 +74,9 @@ export async function hexagon<T extends SVGGraphicsElement>(parent: D3Selection<
|
|||||||
polygon.selectChildren('path').attr('style', nodeStyles);
|
polygon.selectChildren('path').attr('style', nodeStyles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node.width = w;
|
||||||
|
node.height = h;
|
||||||
|
|
||||||
updateNodeBounds(node, polygon);
|
updateNodeBounds(node, polygon);
|
||||||
|
|
||||||
node.intersect = function (point) {
|
node.intersect = function (point) {
|
||||||
|
|||||||
@@ -1,57 +1,13 @@
|
|||||||
import type { Node } from '../../types.js';
|
import { circle } from './circle.js';
|
||||||
|
import type { Node, MindmapOptions } from '../../types.js';
|
||||||
import type { D3Selection } from '../../../types.js';
|
import type { D3Selection } from '../../../types.js';
|
||||||
import { getNodeClasses, labelHelper, updateNodeBounds } from './util.js';
|
|
||||||
import { styles2String } from './handDrawnShapeStyles.js';
|
|
||||||
import intersect from '../intersect/index.js';
|
|
||||||
import {
|
|
||||||
getMindmapIconConfig,
|
|
||||||
calculateMindmapDimensions,
|
|
||||||
insertMindmapIcon,
|
|
||||||
} from '../../../diagrams/mindmap/mindmapIconHelper.js';
|
|
||||||
|
|
||||||
export async function mindmapCircle<T extends SVGGraphicsElement>(
|
export async function mindmapCircle<T extends SVGGraphicsElement>(
|
||||||
parent: D3Selection<T>,
|
parent: D3Selection<T>,
|
||||||
node: Node
|
node: Node
|
||||||
) {
|
) {
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const options = {
|
||||||
const halfPadding = (node.padding ?? 0) / 2;
|
padding: node.padding ?? 0,
|
||||||
|
} as MindmapOptions;
|
||||||
const iconConfig = getMindmapIconConfig('circle');
|
return circle(parent, node, options);
|
||||||
const baseRadius = bbox.width / 2 + halfPadding;
|
|
||||||
const baseDiameter = baseRadius * 2;
|
|
||||||
|
|
||||||
const dimensions = calculateMindmapDimensions(
|
|
||||||
node,
|
|
||||||
bbox,
|
|
||||||
baseDiameter,
|
|
||||||
baseDiameter,
|
|
||||||
halfPadding,
|
|
||||||
iconConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
const radius = dimensions.width / 2;
|
|
||||||
node.width = dimensions.width;
|
|
||||||
node.height = dimensions.height;
|
|
||||||
|
|
||||||
label.attr('transform', `translate(${dimensions.labelOffset.x}, ${dimensions.labelOffset.y})`);
|
|
||||||
|
|
||||||
const circle = shapeSvg
|
|
||||||
.insert('circle', ':first-child')
|
|
||||||
.attr('r', radius)
|
|
||||||
.attr('class', 'basic label-container')
|
|
||||||
.attr('style', styles2String(node).nodeStyles);
|
|
||||||
|
|
||||||
shapeSvg.append(() => label.node());
|
|
||||||
|
|
||||||
if (node.icon) {
|
|
||||||
await insertMindmapIcon(shapeSvg, node, iconConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateNodeBounds(node, circle);
|
|
||||||
|
|
||||||
node.intersect = function (point) {
|
|
||||||
return intersect.circle(node, radius, point);
|
|
||||||
};
|
|
||||||
|
|
||||||
return shapeSvg;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } f
|
|||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.js';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import type { D3Selection } from '../../../types.js';
|
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates evenly spaced points along an elliptical arc connecting two points.
|
* Generates evenly spaced points along an elliptical arc connecting two points.
|
||||||
@@ -91,20 +91,13 @@ export async function roundedRect<T extends SVGGraphicsElement>(
|
|||||||
) {
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
|
|
||||||
const labelPaddingX = node?.padding ?? 0;
|
const labelPaddingX = node?.padding ?? 0;
|
||||||
const labelPaddingY = node?.padding ?? 0;
|
const labelPaddingY = node?.padding ?? 0;
|
||||||
|
|
||||||
const w = (node?.width ? node?.width : bbox.width) + labelPaddingX * 2;
|
const w = (node?.width ? node?.width : bbox.width) + labelPaddingX * 2;
|
||||||
const h = (node?.height ? node?.height : bbox.height) + labelPaddingY * 2;
|
const h = (node?.height ? node?.height : bbox.height) + labelPaddingY * 2;
|
||||||
|
|
||||||
const labelXOffset = -bbox.width / 2;
|
|
||||||
|
|
||||||
if (node.icon) {
|
|
||||||
label.attr('transform', `translate(${labelXOffset}, ${-bbox.height / 2})`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const radius = node.radius || 5;
|
const radius = node.radius || 5;
|
||||||
const taper = node.taper || 5; // Taper width for the rounded corners
|
const taper = node.taper || 5; // Taper width for the rounded corners
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|||||||
@@ -84,7 +84,6 @@ interface BaseNode {
|
|||||||
radius?: number;
|
radius?: number;
|
||||||
taper?: number;
|
taper?: number;
|
||||||
stroke?: string;
|
stroke?: string;
|
||||||
section?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -44,15 +44,18 @@ ValueConverter -->> Package: Return AST
|
|||||||
```
|
```
|
||||||
|
|
||||||
- When to override `TokenBuilder`?
|
- When to override `TokenBuilder`?
|
||||||
|
|
||||||
- To override keyword rules.
|
- To override keyword rules.
|
||||||
- To override terminal rules that need a custom function.
|
- To override terminal rules that need a custom function.
|
||||||
- To manually reorder the list of rules.
|
- To manually reorder the list of rules.
|
||||||
|
|
||||||
- When to override `Lexer`?
|
- When to override `Lexer`?
|
||||||
|
|
||||||
- To modify input before tokenizing.
|
- To modify input before tokenizing.
|
||||||
- To insert/modify tokens that cannot or have not been parsed.
|
- To insert/modify tokens that cannot or have not been parsed.
|
||||||
|
|
||||||
- When to override `LangiumParser`?
|
- When to override `LangiumParser`?
|
||||||
|
|
||||||
- To insert or modify attributes that can't be parsed.
|
- To insert or modify attributes that can't be parsed.
|
||||||
|
|
||||||
- When to override `ValueConverter`?
|
- When to override `ValueConverter`?
|
||||||
|
|||||||
@@ -1,19 +1,5 @@
|
|||||||
# mermaid
|
# mermaid
|
||||||
|
|
||||||
## 11.11.0
|
|
||||||
|
|
||||||
### Minor Changes
|
|
||||||
|
|
||||||
- [#6704](https://github.com/mermaid-js/mermaid/pull/6704) [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05) Thanks [@omkarht](https://github.com/omkarht)! - feat: Added support for new participant types (`actor`, `boundary`, `control`, `entity`, `database`, `collections`, `queue`) in `sequenceDiagram`.
|
|
||||||
|
|
||||||
- [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes
|
|
||||||
|
|
||||||
### Patch Changes
|
|
||||||
|
|
||||||
- [#6905](https://github.com/mermaid-js/mermaid/pull/6905) [`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Render newlines as spaces in class diagrams
|
|
||||||
|
|
||||||
- [#6886](https://github.com/mermaid-js/mermaid/pull/6886) [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Handle arrows correctly when auto number is enabled
|
|
||||||
|
|
||||||
## 11.10.0
|
## 11.10.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
@@ -168,6 +154,7 @@
|
|||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
- [#6408](https://github.com/mermaid-js/mermaid/pull/6408) [`ad65313`](https://github.com/mermaid-js/mermaid/commit/ad653138e16765d095613a6e5de86dc5e52ac8f0) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - fix: restore curve type configuration functionality for flowcharts. This fixes the issue where curve type settings were not being applied when configured through any of the following methods:
|
- [#6408](https://github.com/mermaid-js/mermaid/pull/6408) [`ad65313`](https://github.com/mermaid-js/mermaid/commit/ad653138e16765d095613a6e5de86dc5e52ac8f0) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - fix: restore curve type configuration functionality for flowcharts. This fixes the issue where curve type settings were not being applied when configured through any of the following methods:
|
||||||
|
|
||||||
- Config
|
- Config
|
||||||
- Init directive (%%{ init: { 'flowchart': { 'curve': '...' } } }%%)
|
- Init directive (%%{ init: { 'flowchart': { 'curve': '...' } } }%%)
|
||||||
- LinkStyle command (linkStyle default interpolate ...)
|
- LinkStyle command (linkStyle default interpolate ...)
|
||||||
@@ -186,12 +173,14 @@
|
|||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
- [#6187](https://github.com/mermaid-js/mermaid/pull/6187) [`7809b5a`](https://github.com/mermaid-js/mermaid/commit/7809b5a93fae127f45727071f5ff14325222c518) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Flowchart new syntax for node metadata bugs
|
- [#6187](https://github.com/mermaid-js/mermaid/pull/6187) [`7809b5a`](https://github.com/mermaid-js/mermaid/commit/7809b5a93fae127f45727071f5ff14325222c518) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Flowchart new syntax for node metadata bugs
|
||||||
|
|
||||||
- Incorrect label mapping for nodes when using `&`
|
- Incorrect label mapping for nodes when using `&`
|
||||||
- Syntax error when `}` with trailing spaces before new line
|
- Syntax error when `}` with trailing spaces before new line
|
||||||
|
|
||||||
- [#6136](https://github.com/mermaid-js/mermaid/pull/6136) [`ec0d9c3`](https://github.com/mermaid-js/mermaid/commit/ec0d9c389aa6018043187654044c1e0b5aa4f600) Thanks [@knsv](https://github.com/knsv)! - Adding support for animation of flowchart edges
|
- [#6136](https://github.com/mermaid-js/mermaid/pull/6136) [`ec0d9c3`](https://github.com/mermaid-js/mermaid/commit/ec0d9c389aa6018043187654044c1e0b5aa4f600) Thanks [@knsv](https://github.com/knsv)! - Adding support for animation of flowchart edges
|
||||||
|
|
||||||
- [#6373](https://github.com/mermaid-js/mermaid/pull/6373) [`05bdf0e`](https://github.com/mermaid-js/mermaid/commit/05bdf0e20e2629fe77513218fbd4e28e65f75882) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Upgrade Requirement and ER diagram to use the common renderer flow
|
- [#6373](https://github.com/mermaid-js/mermaid/pull/6373) [`05bdf0e`](https://github.com/mermaid-js/mermaid/commit/05bdf0e20e2629fe77513218fbd4e28e65f75882) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Upgrade Requirement and ER diagram to use the common renderer flow
|
||||||
|
|
||||||
- Added support for directions
|
- Added support for directions
|
||||||
- Added support for hand drawn look
|
- Added support for hand drawn look
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@mermaid-js/tiny",
|
"name": "@mermaid-js/tiny",
|
||||||
"version": "11.11.0",
|
"version": "11.10.0",
|
||||||
"description": "Tiny version of mermaid",
|
"description": "Tiny version of mermaid",
|
||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
"main": "./dist/mermaid.tiny.js",
|
"main": "./dist/mermaid.tiny.js",
|
||||||
|
|||||||
9885
pnpm-lock.yaml
generated
9885
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user