mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-29 01:44:08 +01:00
Compare commits
10 Commits
renovate/a
...
6623-add-i
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c40dd406d | ||
|
|
8dcddaf314 | ||
|
|
bd19523f5d | ||
|
|
6b64b92b6e | ||
|
|
41e3d2449a | ||
|
|
0386ed6b32 | ||
|
|
97481b4d11 | ||
|
|
b8b120939e | ||
|
|
71e4d62153 | ||
|
|
b867370f1b |
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Support edge animation in hand drawn look
|
||||
5
.changeset/bumpy-shrimps-stay.md
Normal file
5
.changeset/bumpy-shrimps-stay.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
---
|
||||
|
||||
feat: Add custom images and icons support for sequence diagram actors
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Resolved parsing error where direction TD was not recognized within subgraphs
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Correct viewBox casing and make SVGs responsive
|
||||
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
|
||||
---
|
||||
|
||||
fix: Improve participant parsing and prevent recursive loops on invalid syntax
|
||||
@@ -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: Resolve gantt chart crash due to invalid array length
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
---
|
||||
|
||||
feat: allow to put notes in namespaces on classDiagram
|
||||
@@ -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
|
||||
6
.github/workflows/autofix.yml
vendored
6
.github/workflows/autofix.yml
vendored
@@ -13,13 +13,13 @@ jobs:
|
||||
autofix:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
|
||||
6
.github/workflows/build-docs.yml
vendored
6
.github/workflows/build-docs.yml
vendored
@@ -18,12 +18,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
|
||||
2
.github/workflows/check-readme-in-sync.yml
vendored
2
.github/workflows/check-readme-in-sync.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Check for difference in README.md and docs/README.md
|
||||
run: |
|
||||
|
||||
12
.github/workflows/codeql.yml
vendored
12
.github/workflows/codeql.yml
vendored
@@ -26,17 +26,17 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ['javascript', 'actions']
|
||||
# CodeQL supports [ 'actions', 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
language: ['javascript']
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@d198d2fabf39a7f36b5ce57ce70d4942944f006e # v3.31.0
|
||||
uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
with:
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
languages: ${{ matrix.language }}
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
# 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)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@d198d2fabf39a7f36b5ce57ce70d4942944f006e # v3.31.0
|
||||
uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
|
||||
# ℹ️ 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
|
||||
@@ -62,4 +62,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@d198d2fabf39a7f36b5ce57ce70d4942944f006e # v3.31.0
|
||||
uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
|
||||
4
.github/workflows/dependency-review.yml
vendored
4
.github/workflows/dependency-review.yml
vendored
@@ -15,6 +15,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@40c09b7dc99638e5ddb0bfd91c1673effc064d8a # v4.8.1
|
||||
uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0
|
||||
|
||||
8
.github/workflows/e2e-applitools.yml
vendored
8
.github/workflows/e2e-applitools.yml
vendored
@@ -29,13 +29,13 @@ jobs:
|
||||
run: |
|
||||
echo "::error,title=Not using Applitools::APPLITOOLS_API_KEY is empty, disabling Applitools for this run."
|
||||
|
||||
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
|
||||
@@ -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"
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@e65cba2e7319696fc0fdc4d5a319b737aec4ba1c # v6.10.3
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
id: cypress
|
||||
with:
|
||||
start: pnpm run dev
|
||||
|
||||
12
.github/workflows/e2e-timings.yml
vendored
12
.github/workflows/e2e-timings.yml
vendored
@@ -20,19 +20,19 @@ jobs:
|
||||
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
|
||||
options: --user 1001
|
||||
steps:
|
||||
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
- name: Install dependencies
|
||||
uses: cypress-io/github-action@e65cba2e7319696fc0fdc4d5a319b737aec4ba1c # v6.10.3
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
with:
|
||||
runTests: false
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@e65cba2e7319696fc0fdc4d5a319b737aec4ba1c # v6.10.3
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
id: cypress
|
||||
with:
|
||||
install: false
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Commit and create pull request
|
||||
uses: peter-evans/create-pull-request@915d841dae6a4f191bb78faf61a257411d7be4d2
|
||||
uses: peter-evans/create-pull-request@18e469570b1cf0dfc11d60ec121099f8ff3e617a
|
||||
with:
|
||||
add-paths: |
|
||||
cypress/timings.json
|
||||
|
||||
26
.github/workflows/e2e.yml
vendored
26
.github/workflows/e2e.yml
vendored
@@ -37,15 +37,15 @@ jobs:
|
||||
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
|
||||
options: --user 1001
|
||||
steps:
|
||||
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
- name: Cache snapshots
|
||||
id: cache-snapshot
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||
with:
|
||||
path: ./cypress/snapshots
|
||||
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
|
||||
@@ -53,13 +53,13 @@ jobs:
|
||||
# If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots.
|
||||
- name: Switch to base branch
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ env.targetHash }}
|
||||
|
||||
- name: Install dependencies
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||
uses: cypress-io/github-action@e65cba2e7319696fc0fdc4d5a319b737aec4ba1c # v6.10.3
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
with:
|
||||
# just perform install
|
||||
runTests: false
|
||||
@@ -82,26 +82,26 @@ jobs:
|
||||
matrix:
|
||||
containers: [1, 2, 3, 4, 5]
|
||||
steps:
|
||||
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
|
||||
# These cached snapshots are downloaded, providing the reference snapshots.
|
||||
- name: Cache snapshots
|
||||
id: cache-snapshot
|
||||
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
uses: actions/cache/restore@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||
with:
|
||||
path: ./cypress/snapshots
|
||||
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
|
||||
|
||||
- name: Install dependencies
|
||||
uses: cypress-io/github-action@e65cba2e7319696fc0fdc4d5a319b737aec4ba1c # v6.10.3
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
with:
|
||||
runTests: false
|
||||
|
||||
@@ -117,7 +117,7 @@ jobs:
|
||||
# Install NPM dependencies, cache them correctly
|
||||
# and run all Cypress tests
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@e65cba2e7319696fc0fdc4d5a319b737aec4ba1c # v6.10.3
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
id: cypress
|
||||
with:
|
||||
install: false
|
||||
@@ -139,7 +139,7 @@ jobs:
|
||||
VITEST_COVERAGE: true
|
||||
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
|
||||
uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1
|
||||
# Run step only pushes to develop and pull_requests
|
||||
if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}}
|
||||
with:
|
||||
|
||||
6
.github/workflows/link-checker.yml
vendored
6
.github/workflows/link-checker.yml
vendored
@@ -29,17 +29,17 @@ jobs:
|
||||
# lychee only uses the GITHUB_TOKEN to avoid rate-limiting
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Restore lychee cache
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||
with:
|
||||
path: .lycheecache
|
||||
key: cache-lychee-${{ github.sha }}
|
||||
restore-keys: cache-lychee-
|
||||
|
||||
- name: Link Checker
|
||||
uses: lycheeverse/lychee-action@885c65f3dc543b57c898c8099f4e08c8afd178a2 # v2.6.1
|
||||
uses: lycheeverse/lychee-action@f613c4a64e50d792e0b31ec34bbcbba12263c6a6 # v2.3.0
|
||||
with:
|
||||
args: >-
|
||||
--config .github/lychee.toml
|
||||
|
||||
10
.github/workflows/lint.yml
vendored
10
.github/workflows/lint.yml
vendored
@@ -15,21 +15,21 @@ jobs:
|
||||
docker-lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0
|
||||
- uses: hadolint/hadolint-action@54c9adbab1582c2ef04b2016b760714a4bfde3cf # v3.1.0
|
||||
with:
|
||||
verbose: true
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
|
||||
2
.github/workflows/pr-labeler.yml
vendored
2
.github/workflows/pr-labeler.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Add "Sponsored by MermaidChart" label
|
||||
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
|
||||
6
.github/workflows/publish-docs.yml
vendored
6
.github/workflows/publish-docs.yml
vendored
@@ -23,12 +23,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
|
||||
@@ -9,14 +9,14 @@ jobs:
|
||||
publish-preview:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
|
||||
6
.github/workflows/release-preview.yml
vendored
6
.github/workflows/release-preview.yml
vendored
@@ -26,12 +26,12 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
|
||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -21,12 +21,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
- name: Create Release Pull Request or Publish to npm
|
||||
id: changesets
|
||||
uses: changesets/action@e0145edc7d9d8679003495b11f87bd8ef63c0cba # v1.5.3
|
||||
uses: changesets/action@c8bada60c408975afd1a20b3db81d6eee6789308 # v1.4.9
|
||||
with:
|
||||
version: pnpm changeset:version
|
||||
publish: pnpm changeset:publish
|
||||
|
||||
8
.github/workflows/scorecard.yml
vendored
8
.github/workflows/scorecard.yml
vendored
@@ -16,22 +16,22 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run analysis
|
||||
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
|
||||
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
publish_results: true
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
- name: Upload to code-scanning
|
||||
uses: github/codeql-action/upload-sarif@d198d2fabf39a7f36b5ce57ce70d4942944f006e # v3.31.0
|
||||
uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
8
.github/workflows/test.yml
vendored
8
.github/workflows/test.yml
vendored
@@ -9,13 +9,13 @@ jobs:
|
||||
unit-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
pnpm test:check:tsc
|
||||
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
|
||||
uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1
|
||||
# Run step only pushes to develop and pull_requests
|
||||
if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }}
|
||||
with:
|
||||
|
||||
6
.github/workflows/update-browserlist.yml
vendored
6
.github/workflows/update-browserlist.yml
vendored
@@ -8,8 +8,8 @@ jobs:
|
||||
update-browser-list:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- run: npx update-browserslist-db@latest
|
||||
- name: Commit changes
|
||||
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
message: 'chore: update browsers list'
|
||||
push: false
|
||||
- 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:
|
||||
branch: update-browserslist
|
||||
title: Update Browserslist
|
||||
|
||||
4
.github/workflows/validate-lockfile.yml
vendored
4
.github/workflows/validate-lockfile.yml
vendored
@@ -19,9 +19,9 @@ jobs:
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.19.5
|
||||
node-version: 20
|
||||
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Validate pnpm-lock.yaml entries
|
||||
id: validate # give this step an ID so we can reference its outputs
|
||||
|
||||
@@ -1 +1 @@
|
||||
22.21.0
|
||||
22.14.0
|
||||
|
||||
@@ -5,7 +5,7 @@ USER 0:0
|
||||
RUN corepack enable \
|
||||
&& corepack enable pnpm
|
||||
|
||||
RUN apk add --no-cache git~=2.43 \
|
||||
RUN apk add --no-cache git~=2.43.4 \
|
||||
&& git config --add --system safe.directory /mermaid
|
||||
|
||||
ENV NODE_OPTIONS="--max_old_space_size=8192"
|
||||
|
||||
@@ -6,7 +6,6 @@ interface CypressConfig {
|
||||
listUrl?: boolean;
|
||||
listId?: string;
|
||||
name?: string;
|
||||
screenshot?: boolean;
|
||||
}
|
||||
type CypressMermaidConfig = MermaidConfig & CypressConfig;
|
||||
|
||||
@@ -91,7 +90,7 @@ export const renderGraph = (
|
||||
|
||||
export const openURLAndVerifyRendering = (
|
||||
url: string,
|
||||
{ screenshot = true, ...options }: CypressMermaidConfig,
|
||||
options: CypressMermaidConfig,
|
||||
validation?: any
|
||||
): void => {
|
||||
const name: string = (options.name ?? cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
|
||||
@@ -99,15 +98,12 @@ export const openURLAndVerifyRendering = (
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('svg').should('be.visible');
|
||||
cy.get('svg').should('not.have.attr', 'viewbox');
|
||||
|
||||
if (validation) {
|
||||
cy.get('svg').should(validation);
|
||||
}
|
||||
|
||||
if (screenshot) {
|
||||
verifyScreenshot(name);
|
||||
}
|
||||
verifyScreenshot(name);
|
||||
};
|
||||
|
||||
export const verifyScreenshot = (name: string): void => {
|
||||
|
||||
@@ -562,20 +562,6 @@ class C13["With Città foreign language"]
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should add notes in namespaces', function () {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram
|
||||
note "This is a outer note"
|
||||
note for C1 "This is a outer note for C1"
|
||||
namespace Namespace1 {
|
||||
note "This is a inner note"
|
||||
note for C1 "This is a inner note for C1"
|
||||
class C1
|
||||
}
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render a simple class diagram with no members', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
|
||||
@@ -709,20 +709,6 @@ class C13["With Città foreign language"]
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should add notes in namespaces', function () {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram
|
||||
note "This is a outer note"
|
||||
note for C1 "This is a outer note for C1"
|
||||
namespace Namespace1 {
|
||||
note "This is a inner note"
|
||||
note for C1 "This is a inner note for C1"
|
||||
class C1
|
||||
}
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render a simple class diagram with no members', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
|
||||
@@ -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 }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1029,19 +1029,4 @@ graph TD
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('FDH49: should add edge animation', () => {
|
||||
renderGraph(
|
||||
`
|
||||
flowchart TD
|
||||
A(["Start"]) L_A_B_0@--> B{"Decision"}
|
||||
B --> C["Option A"] & D["Option B"]
|
||||
style C stroke-width:4px,stroke-dasharray: 5
|
||||
L_A_B_0@{ animation: slow }
|
||||
L_B_D_0@{ animation: fast }`,
|
||||
{ look: 'handDrawn', screenshot: false }
|
||||
);
|
||||
cy.get('path#L_A_B_0').should('have.class', 'edge-animation-slow');
|
||||
cy.get('path#L_B_D_0').should('have.class', 'edge-animation-fast');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -774,21 +774,6 @@ describe('Graph', () => {
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
it('40: should add edge animation', () => {
|
||||
renderGraph(
|
||||
`
|
||||
flowchart TD
|
||||
A(["Start"]) L_A_B_0@--> B{"Decision"}
|
||||
B --> C["Option A"] & D["Option B"]
|
||||
style C stroke-width:4px,stroke-dasharray: 5
|
||||
L_A_B_0@{ animation: slow }
|
||||
L_B_D_0@{ animation: fast }`,
|
||||
{ screenshot: false }
|
||||
);
|
||||
// Verify animation classes are applied to both edges
|
||||
cy.get('path#L_A_B_0').should('have.class', 'edge-animation-slow');
|
||||
cy.get('path#L_B_D_0').should('have.class', 'edge-animation-fast');
|
||||
});
|
||||
it('58: handle styling with style expressions', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
@@ -988,19 +973,4 @@ graph TD
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('70: should render a subgraph with direction TD', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
flowchart LR
|
||||
subgraph A
|
||||
direction TD
|
||||
a --> b
|
||||
end
|
||||
`,
|
||||
{
|
||||
fontFamily: 'courier',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -803,34 +803,4 @@ describe('Gantt diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should handle numeric timestamps with dateFormat x', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gantt
|
||||
title Process time profile (ms)
|
||||
dateFormat x
|
||||
axisFormat %L
|
||||
tickInterval 250millisecond
|
||||
|
||||
section Pipeline
|
||||
Parse JSON p1: 000, 120
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should handle numeric timestamps with dateFormat X', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gantt
|
||||
title Process time profile (ms)
|
||||
dateFormat X
|
||||
axisFormat %L
|
||||
tickInterval 250millisecond
|
||||
|
||||
section Pipeline
|
||||
Parse JSON p1: 000, 120
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
118
cypress/integration/rendering/sequenceDiagram-icon.spec.ts
Normal file
118
cypress/integration/rendering/sequenceDiagram-icon.spec.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util';
|
||||
|
||||
const looks = ['classic'] as const;
|
||||
|
||||
looks.forEach((look) => {
|
||||
describe(`SequenceDiagram icon participants in ${look} look`, () => {
|
||||
it(`single participant with icon`, () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "icon", icon: "fa:bell" }
|
||||
Note over Bob: Icon participant`;
|
||||
imgSnapshotTest(diagram, { look });
|
||||
});
|
||||
|
||||
it(`two participants, one icon and one normal`, () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "icon", icon: "fa:bell" }
|
||||
participant Alice
|
||||
Bob->>Alice: Hello`;
|
||||
imgSnapshotTest(diagram, { look });
|
||||
});
|
||||
|
||||
it(`two icon participants`, () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "icon", icon: "fa:bell" }
|
||||
participant Alice@{ type: "icon", icon: "fa:user" }
|
||||
Bob->>Alice: Hello
|
||||
Alice-->>Bob: Hi`;
|
||||
imgSnapshotTest(diagram, { look });
|
||||
});
|
||||
|
||||
it(`with markdown htmlLabels:true content`, () => {
|
||||
// html/markdown in messages/notes (participants themselves don't support label/form/w/h)
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "icon", icon: "fa:bell" }
|
||||
participant Alice
|
||||
Bob->>Alice: This is **bold** </br>and <strong>strong</strong>
|
||||
Note over Bob,Alice: Mixed <em>HTML</em> and **markdown**`;
|
||||
imgSnapshotTest(diagram, { look });
|
||||
});
|
||||
|
||||
it(`with markdown htmlLabels:false content`, () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "icon", icon: "fa:bell" }
|
||||
participant Alice
|
||||
Bob->>Alice: This is **bold** </br>and <strong>strong</strong>`;
|
||||
imgSnapshotTest(diagram, {
|
||||
look,
|
||||
htmlLabels: false,
|
||||
flowchart: { htmlLabels: false },
|
||||
});
|
||||
});
|
||||
|
||||
it(`with styles applied to participant`, () => {
|
||||
// style by participant id
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "icon", icon: "fa:bell" }
|
||||
participant Alice
|
||||
Bob->>Alice: Styled participant
|
||||
`;
|
||||
imgSnapshotTest(diagram, { look });
|
||||
});
|
||||
|
||||
it(`with classDef and class application`, () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "icon", icon: "fa:bell" }
|
||||
participant Alice
|
||||
Bob->>Alice: Classed participant
|
||||
`;
|
||||
imgSnapshotTest(diagram, { look });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Colored emoji icon tests (analogous to the flowchart colored icon tests), no direction line.
|
||||
describe('SequenceDiagram colored icon participant', () => {
|
||||
it('colored emoji icon without styles', () => {
|
||||
const icon = 'fluent-emoji:tropical-fish';
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "icon", icon: "${icon}" }
|
||||
Note over Bob: colored emoji icon
|
||||
`;
|
||||
imgSnapshotTest(diagram);
|
||||
});
|
||||
|
||||
it('colored emoji icon with styles', () => {
|
||||
const icon = 'fluent-emoji:tropical-fish';
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "icon", icon: "${icon}" }
|
||||
`;
|
||||
imgSnapshotTest(diagram);
|
||||
});
|
||||
});
|
||||
|
||||
// Mixed scenario: multiple interactions, still no direction line.
|
||||
describe('SequenceDiagram icon participant with multiple interactions', () => {
|
||||
const icon = 'fa:bell-slash';
|
||||
it('icon participant interacts with two normal participants', () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "icon", icon: "${icon}" }
|
||||
participant Alice
|
||||
participant Carol
|
||||
Bob->>Alice: Ping
|
||||
Alice-->>Bob: Pong
|
||||
Bob->>Carol: Notify
|
||||
Note right of Bob: Icon side note`;
|
||||
imgSnapshotTest(diagram);
|
||||
});
|
||||
});
|
||||
94
cypress/integration/rendering/sequenceDiagram-image.spec.ts
Normal file
94
cypress/integration/rendering/sequenceDiagram-image.spec.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util';
|
||||
|
||||
const looks = ['classic'] as const;
|
||||
|
||||
looks.forEach((look) => {
|
||||
describe(`SequenceDiagram image participants in ${look} look`, () => {
|
||||
it(`single participant with image`, () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
|
||||
Note over Bob: Image participant`;
|
||||
imgSnapshotTest(diagram, { look });
|
||||
});
|
||||
|
||||
it(`two participants, one image and one normal`, () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
|
||||
participant Alice
|
||||
Bob->>Alice: Hello`;
|
||||
imgSnapshotTest(diagram, { look });
|
||||
});
|
||||
|
||||
it(`two image participants`, () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
|
||||
participant Alice@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
|
||||
Bob->>Alice: Hello
|
||||
Alice-->>Bob: Hi`;
|
||||
imgSnapshotTest(diagram, { look });
|
||||
});
|
||||
|
||||
it(`with markdown htmlLabels:true content`, () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
|
||||
participant Alice
|
||||
Bob->>Alice: This is **bold** </br>and <strong>strong</strong>
|
||||
Note over Bob,Alice: Mixed <em>HTML</em> and **markdown**`;
|
||||
imgSnapshotTest(diagram, { look });
|
||||
});
|
||||
|
||||
it(`with markdown htmlLabels:false content`, () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
|
||||
participant Alice
|
||||
Bob->>Alice: This is **bold** </br>and <strong>strong</strong>`;
|
||||
imgSnapshotTest(diagram, {
|
||||
look,
|
||||
htmlLabels: false,
|
||||
flowchart: { htmlLabels: false },
|
||||
});
|
||||
});
|
||||
|
||||
it(`with styles applied to participant`, () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
|
||||
participant Alice
|
||||
Bob->>Alice: Styled participant
|
||||
`;
|
||||
imgSnapshotTest(diagram, { look });
|
||||
});
|
||||
|
||||
it(`with classDef and class application`, () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
|
||||
participant Alice
|
||||
Bob->>Alice: Classed participant
|
||||
`;
|
||||
imgSnapshotTest(diagram, { look });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Mixed scenario: multiple interactions, still no direction line.
|
||||
describe('SequenceDiagram image participant with multiple interactions', () => {
|
||||
const imageUrl = 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg';
|
||||
it('image participant interacts with two normal participants', () => {
|
||||
const diagram = `
|
||||
sequenceDiagram
|
||||
participant Bob@{ type: "image", "image": "${imageUrl}" }
|
||||
participant Alice
|
||||
participant Carol
|
||||
Bob->>Alice: Ping
|
||||
Alice-->>Bob: Pong
|
||||
Bob->>Carol: Notify
|
||||
Note right of Bob: Image side note`;
|
||||
imgSnapshotTest(diagram);
|
||||
});
|
||||
});
|
||||
@@ -655,126 +655,5 @@ describe('Sequence Diagram Special Cases', () => {
|
||||
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`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -110,48 +110,6 @@
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
Origins
|
||||
Long history
|
||||
::icon(fa fa-book)
|
||||
Popularisation
|
||||
British popular psychology author Tony Buzan
|
||||
Research
|
||||
On effectiveness<br/>and features
|
||||
On Automatic creation
|
||||
Uses
|
||||
Creative techniques
|
||||
Strategic planning
|
||||
Argument mapping
|
||||
Tools
|
||||
id)I am a cloud(
|
||||
id))I am a bang((
|
||||
Tools
|
||||
</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
|
||||
c1-->a2
|
||||
subgraph one
|
||||
|
||||
@@ -603,10 +603,6 @@
|
||||
</div>
|
||||
<div class="test">
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
theme: dark
|
||||
---
|
||||
classDiagram
|
||||
test ()--() test2
|
||||
</pre>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"lib": ["es2020", "dom"],
|
||||
"types": ["cypress", "node", "@argos-ci/cypress/support"],
|
||||
"types": ["cypress", "node", "@argos-ci/cypress/dist/support.d.ts"],
|
||||
"allowImportingTsExtensions": true,
|
||||
"noEmit": true
|
||||
},
|
||||
|
||||
@@ -184,7 +184,6 @@
|
||||
}
|
||||
Admin --> Report : generates
|
||||
</pre>
|
||||
<hr />
|
||||
<pre class="mermaid">
|
||||
classDiagram
|
||||
namespace Company.Project.Module {
|
||||
@@ -241,20 +240,6 @@
|
||||
Bike --> Square : "Logo Shape"
|
||||
|
||||
</pre>
|
||||
<hr />
|
||||
<pre class="mermaid">
|
||||
classDiagram
|
||||
note "This is a outer note"
|
||||
note for Class1 "This is a outer note for Class1"
|
||||
namespace ns {
|
||||
note "This is a inner note"
|
||||
note for Class1 "This is a inner note for Class1"
|
||||
class Class1
|
||||
class Class2
|
||||
}
|
||||
</pre>
|
||||
<hr />
|
||||
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
mermaid.initialize({
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
|
||||
@@ -17,7 +17,7 @@ services:
|
||||
- 9000:9000
|
||||
- 3333:3333
|
||||
cypress:
|
||||
image: cypress/included:14.5.4
|
||||
image: cypress/included:14.0.3
|
||||
stdin_open: true
|
||||
tty: true
|
||||
working_dir: /mermaid
|
||||
|
||||
@@ -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.
|
||||
|
||||
> **💡 Tip**
|
||||
> [Here is a GitHub document that gives an overview of the process](https://docs.github.com/en/get-started/quickstart/fork-a-repo).
|
||||
> **💡 Tip** > [Here is a GitHub document that gives an overview of the process](https://docs.github.com/en/get-started/quickstart/fork-a-repo).
|
||||
|
||||
```bash
|
||||
git clone git@github.com/your-fork/mermaid
|
||||
|
||||
@@ -33,8 +33,7 @@ mindmap
|
||||
|
||||
## Join the Development
|
||||
|
||||
> **💡 Tip**
|
||||
> **Check out our** [**detailed contribution guide**](./contributing.md).
|
||||
> **💡 Tip** > **Check out our** [**detailed contribution guide**](./contributing.md).
|
||||
|
||||
Where to start:
|
||||
|
||||
@@ -48,8 +47,7 @@ Where to start:
|
||||
|
||||
## A Question Or a Suggestion?
|
||||
|
||||
> **💡 Tip**
|
||||
> **Have a look at** [**how to open an issue**](./questions-and-suggestions.md).
|
||||
> **💡 Tip** > **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).
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
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
|
||||
- fontFamily
|
||||
- logLevel
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
# Interface: ParseOptions
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L88)
|
||||
Defined in: [packages/mermaid/src/types.ts:76](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L76)
|
||||
|
||||
## Properties
|
||||
|
||||
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mer
|
||||
|
||||
> `optional` **suppressErrors**: `boolean`
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:93](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L93)
|
||||
Defined in: [packages/mermaid/src/types.ts:81](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L81)
|
||||
|
||||
If `true`, parse will return `false` instead of throwing error when the diagram is invalid.
|
||||
The `parseError` function will not be called.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
# Interface: ParseResult
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L96)
|
||||
Defined in: [packages/mermaid/src/types.ts:84](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L84)
|
||||
|
||||
## Properties
|
||||
|
||||
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:96](https://github.com/mermaid-js/mer
|
||||
|
||||
> **config**: [`MermaidConfig`](MermaidConfig.md)
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:104](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L104)
|
||||
Defined in: [packages/mermaid/src/types.ts:92](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L92)
|
||||
|
||||
The config passed as YAML frontmatter or directives
|
||||
|
||||
@@ -28,6 +28,6 @@ The config passed as YAML frontmatter or directives
|
||||
|
||||
> **diagramType**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:100](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L100)
|
||||
Defined in: [packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L88)
|
||||
|
||||
The diagram type, e.g. 'flowchart', 'sequence', etc.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
# Interface: RenderResult
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:114](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L114)
|
||||
Defined in: [packages/mermaid/src/types.ts:102](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L102)
|
||||
|
||||
## Properties
|
||||
|
||||
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:114](https://github.com/mermaid-js/me
|
||||
|
||||
> `optional` **bindFunctions**: (`element`) => `void`
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:132](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L132)
|
||||
Defined in: [packages/mermaid/src/types.ts:120](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L120)
|
||||
|
||||
Bind function to be called after the svg has been inserted into the DOM.
|
||||
This is necessary for adding event listeners to the elements in the svg.
|
||||
@@ -45,7 +45,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
|
||||
|
||||
> **diagramType**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:122](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L122)
|
||||
Defined in: [packages/mermaid/src/types.ts:110](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L110)
|
||||
|
||||
The diagram type, e.g. 'flowchart', 'sequence', etc.
|
||||
|
||||
@@ -55,6 +55,6 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
|
||||
|
||||
> **svg**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:118](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L118)
|
||||
Defined in: [packages/mermaid/src/types.ts:106](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L106)
|
||||
|
||||
The svg code for the rendered graph.
|
||||
|
||||
@@ -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.
|
||||
|
||||
Official Mermaid Chart plugins:
|
||||
|
||||
- [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)
|
||||
- [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:
|
||||
|
||||
- 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)
|
||||
|
||||
- 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)
|
||||
|
||||
@@ -6,18 +6,6 @@
|
||||
|
||||
# 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)
|
||||
|
||||
7/15/2025 • 7 mins
|
||||
|
||||
@@ -194,7 +194,7 @@ architecture-beta
|
||||
## Icons
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -139,6 +139,7 @@ The following unfinished features are not supported in the short term.
|
||||
- [ ] Legend
|
||||
|
||||
- [x] System Context
|
||||
|
||||
- [x] Person(alias, label, ?descr, ?sprite, ?tags, $link)
|
||||
- [x] Person_Ext
|
||||
- [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] Container diagram
|
||||
|
||||
- [x] Container(alias, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
||||
- [x] ContainerDb
|
||||
- [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] Component diagram
|
||||
|
||||
- [x] Component(alias, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
||||
- [x] ComponentDb
|
||||
- [x] ComponentQueue
|
||||
@@ -169,15 +172,18 @@ The following unfinished features are not supported in the short term.
|
||||
- [x] ComponentQueue_Ext
|
||||
|
||||
- [x] Dynamic diagram
|
||||
|
||||
- [x] RelIndex(index, from, to, label, ?tags, $link)
|
||||
|
||||
- [x] Deployment diagram
|
||||
|
||||
- [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_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] Relationship Types
|
||||
|
||||
- [x] Rel(from, to, label, ?techn, ?descr, ?sprite, ?tags, $link)
|
||||
- [x] BiRel (bidirectional relationship)
|
||||
- [x] Rel_U, Rel_Up
|
||||
|
||||
@@ -21,7 +21,7 @@ title: Animal example
|
||||
classDiagram
|
||||
note "From Duck till Zebra"
|
||||
Animal <|-- Duck
|
||||
note for Duck "can fly<br>can swim<br>can dive<br>can help in debugging"
|
||||
note for Duck "can fly\ncan swim\ncan dive\ncan help in debugging"
|
||||
Animal <|-- Fish
|
||||
Animal <|-- Zebra
|
||||
Animal : +int age
|
||||
@@ -50,7 +50,7 @@ title: Animal example
|
||||
classDiagram
|
||||
note "From Duck till Zebra"
|
||||
Animal <|-- Duck
|
||||
note for Duck "can fly<br>can swim<br>can dive<br>can help in debugging"
|
||||
note for Duck "can fly\ncan swim\ncan dive\ncan help in debugging"
|
||||
Animal <|-- Fish
|
||||
Animal <|-- Zebra
|
||||
Animal : +int age
|
||||
|
||||
@@ -360,8 +360,7 @@ gantt
|
||||
weekday monday
|
||||
```
|
||||
|
||||
> **Warning**
|
||||
> `millisecond` and `second` support was added in v10.3.0
|
||||
> **Warning** > `millisecond` and `second` support was added in v10.3.0
|
||||
|
||||
## Output in compact mode
|
||||
|
||||
|
||||
@@ -194,6 +194,46 @@ sequenceDiagram
|
||||
Bob->>Alice: Queue response
|
||||
```
|
||||
|
||||
### Icon
|
||||
|
||||
If you want to use a custom icon for a participant, use the JSON configuration syntax as shown below. The `icon` value can be a FontAwesome icon name, emoji, or other supported icon identifier.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "icon", "icon": "fa:bell" }
|
||||
participant Bob
|
||||
Alice->>Bob: Icon participant
|
||||
Bob->>Alice: Response to icon
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "icon", "icon": "fa:bell" }
|
||||
participant Bob
|
||||
Alice->>Bob: Icon participant
|
||||
Bob->>Alice: Response to icon
|
||||
```
|
||||
|
||||
### Image
|
||||
|
||||
If you want to use a custom image for a participant, use the JSON configuration syntax as shown below. The `image` value should be a valid image URL.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
|
||||
participant Bob
|
||||
Alice->>Bob: Image participant
|
||||
Bob->>Alice: Response to image
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
|
||||
participant Bob
|
||||
Alice->>Bob: Image participant
|
||||
Bob->>Alice: Response to image
|
||||
```
|
||||
|
||||
### Aliases
|
||||
|
||||
The actor can have a convenient identifier and a descriptive label.
|
||||
@@ -329,11 +369,7 @@ Messages can be of two displayed either solid or with a dotted line.
|
||||
[Actor][Arrow][Actor]:Message text
|
||||
```
|
||||
|
||||
Lines can be solid or dotted, and can end with various types of arrowheads, crosses, or open arrows.
|
||||
|
||||
#### Supported Arrow Types
|
||||
|
||||
**Standard Arrow Types**
|
||||
There are ten types of arrows currently supported:
|
||||
|
||||
| Type | Description |
|
||||
| -------- | ---------------------------------------------------- |
|
||||
@@ -348,58 +384,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) |
|
||||
| `--)` | 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
|
||||
|
||||
It is possible to activate and deactivate an actor. (de)activation can be dedicated declarations:
|
||||
|
||||
62
package.json
62
package.json
@@ -4,7 +4,7 @@
|
||||
"version": "10.2.4",
|
||||
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@10.19.0+sha512.c9fc7236e92adf5c8af42fd5bf1612df99c2ceb62f27047032f4720b33f8eacdde311865e91c411f2774f618d82f320808ecb51718bfa82c060c4ba7c76a32b8",
|
||||
"packageManager": "pnpm@10.4.1+sha512.c753b6c3ad7afa13af388fa6d808035a008e30ea9993f58c6663e2bc5ff21679aa834db094987129aa4d488b86df57f7b634981b2f827cdcacc698cc0cfb88af",
|
||||
"keywords": [
|
||||
"diagram",
|
||||
"markdown",
|
||||
@@ -63,36 +63,36 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@applitools/eyes-cypress": "^3.56.2",
|
||||
"@argos-ci/cypress": "^6.1.3",
|
||||
"@applitools/eyes-cypress": "^3.44.9",
|
||||
"@argos-ci/cypress": "^5.0.2",
|
||||
"@changesets/changelog-github": "^0.5.1",
|
||||
"@changesets/cli": "^2.29.7",
|
||||
"@changesets/cli": "^2.27.12",
|
||||
"@cspell/eslint-plugin": "^8.19.4",
|
||||
"@cypress/code-coverage": "^3.14.6",
|
||||
"@cypress/code-coverage": "^3.12.49",
|
||||
"@eslint/js": "^9.26.0",
|
||||
"@rollup/plugin-typescript": "^12.3.0",
|
||||
"@types/cors": "^2.8.19",
|
||||
"@types/express": "^5.0.3",
|
||||
"@rollup/plugin-typescript": "^12.1.2",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "^5.0.0",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"@types/lodash": "^4.17.20",
|
||||
"@types/lodash": "^4.17.15",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"@types/node": "^22.18.6",
|
||||
"@types/node": "^22.13.5",
|
||||
"@types/rollup-plugin-visualizer": "^5.0.3",
|
||||
"@vitest/coverage-v8": "^3.2.4",
|
||||
"@vitest/spy": "^3.2.4",
|
||||
"@vitest/ui": "^3.2.4",
|
||||
"@vitest/coverage-v8": "^3.0.6",
|
||||
"@vitest/spy": "^3.0.6",
|
||||
"@vitest/ui": "^3.0.6",
|
||||
"ajv": "^8.17.1",
|
||||
"chokidar": "3.6.0",
|
||||
"concurrently": "^9.2.1",
|
||||
"concurrently": "^9.1.2",
|
||||
"cors": "^2.8.5",
|
||||
"cpy-cli": "^5.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"cspell": "^9.2.1",
|
||||
"cypress": "^14.5.4",
|
||||
"cspell": "^9.1.3",
|
||||
"cypress": "^14.5.1",
|
||||
"cypress-image-snapshot": "^4.0.1",
|
||||
"cypress-split": "^1.24.23",
|
||||
"esbuild": "^0.25.10",
|
||||
"cypress-split": "^1.24.14",
|
||||
"esbuild": "^0.25.0",
|
||||
"eslint": "^9.26.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-cypress": "^4.3.0",
|
||||
@@ -106,30 +106,30 @@
|
||||
"eslint-plugin-tsdoc": "^0.4.0",
|
||||
"eslint-plugin-unicorn": "^59.0.1",
|
||||
"express": "^5.1.0",
|
||||
"globals": "^16.4.0",
|
||||
"globby": "^14.1.0",
|
||||
"globals": "^16.0.0",
|
||||
"globby": "^14.0.2",
|
||||
"husky": "^9.1.7",
|
||||
"jest": "^30.2.0",
|
||||
"jest": "^30.0.4",
|
||||
"jison": "^0.4.18",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsdom": "^26.1.0",
|
||||
"langium-cli": "3.5.2",
|
||||
"lint-staged": "^16.2.6",
|
||||
"langium-cli": "3.3.0",
|
||||
"lint-staged": "^16.1.2",
|
||||
"markdown-table": "^3.0.4",
|
||||
"nyc": "^17.1.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-jsdoc": "^1.3.3",
|
||||
"prettier": "^3.5.2",
|
||||
"prettier-plugin-jsdoc": "^1.3.2",
|
||||
"rimraf": "^6.0.1",
|
||||
"rollup-plugin-visualizer": "^6.0.3",
|
||||
"start-server-and-test": "^2.1.2",
|
||||
"start-server-and-test": "^2.0.10",
|
||||
"tslib": "^2.8.1",
|
||||
"tsx": "^4.20.5",
|
||||
"typescript": "~5.9.3",
|
||||
"tsx": "^4.7.3",
|
||||
"typescript": "~5.7.3",
|
||||
"typescript-eslint": "^8.38.0",
|
||||
"vite": "^7.0.7",
|
||||
"vite-plugin-istanbul": "^7.2.0",
|
||||
"vitest": "^3.2.4"
|
||||
"vite": "^7.0.3",
|
||||
"vite-plugin-istanbul": "^7.0.0",
|
||||
"vitest": "^3.0.6"
|
||||
},
|
||||
"nyc": {
|
||||
"report-dir": "coverage/cypress"
|
||||
|
||||
@@ -37,12 +37,12 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^7.1.1",
|
||||
"@braintree/sanitize-url": "^7.0.4",
|
||||
"d3": "^7.9.0",
|
||||
"khroma": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^9.2.1",
|
||||
"concurrently": "^9.1.2",
|
||||
"mermaid": "workspace:*",
|
||||
"rimraf": "^6.0.1"
|
||||
},
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
# @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
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@mermaid-js/layout-elk",
|
||||
"version": "0.2.0",
|
||||
"version": "0.1.9",
|
||||
"description": "ELK layout engine for mermaid",
|
||||
"module": "dist/mermaid-layout-elk.core.mjs",
|
||||
"types": "dist/layouts.d.ts",
|
||||
@@ -30,14 +30,14 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"d3": "^7.9.0",
|
||||
"elkjs": "^0.11.0"
|
||||
"elkjs": "^0.9.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/d3": "^7.4.3",
|
||||
"mermaid": "workspace:^"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"mermaid": "^11.12.1"
|
||||
"mermaid": "^11.0.2"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
|
||||
@@ -67,22 +67,7 @@ export const render = async (
|
||||
|
||||
// Add the element to the DOM
|
||||
if (!node.isGroup) {
|
||||
// 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,
|
||||
};
|
||||
const child = node as NodeWithVertex;
|
||||
graph.children.push(child);
|
||||
nodeDb[node.id] = node;
|
||||
|
||||
@@ -165,7 +150,7 @@ export const render = async (
|
||||
domId: { node: () => any; attr: (arg0: string, arg1: string) => void };
|
||||
}) {
|
||||
if (node) {
|
||||
nodeDb[node.id] ??= {};
|
||||
nodeDb[node.id] = node;
|
||||
nodeDb[node.id].offset = {
|
||||
posX: node.x + relX,
|
||||
posY: node.y + relY,
|
||||
@@ -875,13 +860,11 @@ export const render = async (
|
||||
log.info('APA01 layout result:', JSON.stringify(g, null, 2));
|
||||
} catch (error) {
|
||||
log.error('APA01 ELK layout error:', error);
|
||||
log.error('APA01 elkGraph that caused error:', JSON.stringify(elkGraph, null, 2));
|
||||
throw error;
|
||||
}
|
||||
|
||||
// debugger;
|
||||
await drawNodes(0, 0, g.children, svg, subGraphsEl, 0);
|
||||
|
||||
g.edges?.map(
|
||||
(edge: {
|
||||
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",
|
||||
"version": "0.2.0",
|
||||
"version": "0.1.0",
|
||||
"description": "Tidy-tree layout engine for mermaid",
|
||||
"module": "dist/mermaid-layout-tidy-tree.core.mjs",
|
||||
"types": "dist/layouts.d.ts",
|
||||
@@ -38,7 +38,7 @@
|
||||
"mermaid": "workspace:^"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"mermaid": "^11.12.1"
|
||||
"mermaid": "^11.0.2"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@zenuml/core": "^3.41.4"
|
||||
"@zenuml/core": "^3.35.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mermaid": "workspace:^"
|
||||
|
||||
@@ -1,19 +1,5 @@
|
||||
# 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
|
||||
|
||||
### Minor Changes
|
||||
@@ -168,6 +154,7 @@
|
||||
### 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:
|
||||
|
||||
- Config
|
||||
- Init directive (%%{ init: { 'flowchart': { 'curve': '...' } } }%%)
|
||||
- LinkStyle command (linkStyle default interpolate ...)
|
||||
@@ -186,12 +173,14 @@
|
||||
### 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
|
||||
|
||||
- Incorrect label mapping for nodes when using `&`
|
||||
- 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
|
||||
|
||||
- [#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 hand drawn look
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"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.",
|
||||
"type": "module",
|
||||
"module": "./dist/mermaid.core.mjs",
|
||||
@@ -67,31 +67,31 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^7.1.1",
|
||||
"@iconify/utils": "^3.0.2",
|
||||
"@braintree/sanitize-url": "^7.0.4",
|
||||
"@iconify/utils": "^3.0.1",
|
||||
"@mermaid-js/parser": "workspace:^",
|
||||
"@types/d3": "^7.4.3",
|
||||
"cytoscape": "^3.33.1",
|
||||
"cytoscape": "^3.29.3",
|
||||
"cytoscape-cose-bilkent": "^4.1.0",
|
||||
"cytoscape-fcose": "^2.2.0",
|
||||
"d3": "^7.9.0",
|
||||
"d3-sankey": "^0.12.3",
|
||||
"dagre-d3-es": "7.0.11",
|
||||
"dayjs": "^1.11.18",
|
||||
"dayjs": "^1.11.13",
|
||||
"dompurify": "^3.2.5",
|
||||
"katex": "^0.16.22",
|
||||
"khroma": "^2.1.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"marked": "^16.4.1",
|
||||
"marked": "^16.0.0",
|
||||
"roughjs": "^4.6.6",
|
||||
"stylis": "^4.3.6",
|
||||
"ts-dedent": "^2.2.0",
|
||||
"uuid": "^11.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@adobe/jsonschema2md": "^8.0.5",
|
||||
"@adobe/jsonschema2md": "^8.0.2",
|
||||
"@iconify/types": "^2.0.0",
|
||||
"@types/cytoscape": "^3.31.0",
|
||||
"@types/cytoscape": "^3.21.9",
|
||||
"@types/cytoscape-fcose": "^2.2.4",
|
||||
"@types/d3-sankey": "^0.12.4",
|
||||
"@types/d3-scale": "^4.0.9",
|
||||
@@ -105,30 +105,30 @@
|
||||
"@types/stylis": "^4.2.7",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"ajv": "^8.17.1",
|
||||
"canvas": "^3.2.0",
|
||||
"canvas": "^3.1.0",
|
||||
"chokidar": "3.6.0",
|
||||
"concurrently": "^9.2.1",
|
||||
"concurrently": "^9.1.2",
|
||||
"csstree-validator": "^4.0.1",
|
||||
"globby": "^14.1.0",
|
||||
"globby": "^14.0.2",
|
||||
"jison": "^0.4.18",
|
||||
"js-base64": "^3.7.8",
|
||||
"js-base64": "^3.7.7",
|
||||
"jsdom": "^26.1.0",
|
||||
"json-schema-to-typescript": "^15.0.4",
|
||||
"micromatch": "^4.0.8",
|
||||
"path-browserify": "^1.0.1",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier": "^3.5.2",
|
||||
"remark": "^15.0.1",
|
||||
"remark-frontmatter": "^5.0.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"rimraf": "^6.0.1",
|
||||
"start-server-and-test": "^2.1.2",
|
||||
"type-fest": "^4.41.0",
|
||||
"typedoc": "^0.28.13",
|
||||
"typedoc-plugin-markdown": "^4.9.0",
|
||||
"typescript": "~5.9.3",
|
||||
"start-server-and-test": "^2.0.10",
|
||||
"type-fest": "^4.35.0",
|
||||
"typedoc": "^0.28.9",
|
||||
"typedoc-plugin-markdown": "^4.8.0",
|
||||
"typescript": "~5.7.3",
|
||||
"unist-util-flatmap": "^1.0.0",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"vitepress": "^1.6.4",
|
||||
"vitepress": "^1.0.2",
|
||||
"vitepress-plugin-search": "1.0.4-alpha.22"
|
||||
},
|
||||
"files": [
|
||||
|
||||
@@ -17,7 +17,6 @@ import type {
|
||||
ClassRelation,
|
||||
ClassNode,
|
||||
ClassNote,
|
||||
ClassNoteMap,
|
||||
ClassMap,
|
||||
NamespaceMap,
|
||||
NamespaceNode,
|
||||
@@ -34,16 +33,15 @@ const sanitizeText = (txt: string) => common.sanitizeText(txt, getConfig());
|
||||
|
||||
export class ClassDB implements DiagramDB {
|
||||
private relations: ClassRelation[] = [];
|
||||
private classes: ClassMap = new Map<string, ClassNode>();
|
||||
private classes = new Map<string, ClassNode>();
|
||||
private readonly styleClasses = new Map<string, StyleClass>();
|
||||
private notes: ClassNoteMap = new Map<string, ClassNote>();
|
||||
private notes: ClassNote[] = [];
|
||||
private interfaces: Interface[] = [];
|
||||
// private static classCounter = 0;
|
||||
private namespaces = new Map<string, NamespaceNode>();
|
||||
private namespaceCounter = 0;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
private functions: Function[] = [];
|
||||
private functions: any[] = [];
|
||||
|
||||
constructor() {
|
||||
this.functions.push(this.setupToolTips.bind(this));
|
||||
@@ -126,7 +124,7 @@ export class ClassDB implements DiagramDB {
|
||||
annotations: [],
|
||||
styles: [],
|
||||
domId: MERMAID_DOM_ID_PREFIX + name + '-' + classCounter,
|
||||
});
|
||||
} as ClassNode);
|
||||
|
||||
classCounter++;
|
||||
}
|
||||
@@ -157,12 +155,12 @@ export class ClassDB implements DiagramDB {
|
||||
|
||||
public clear() {
|
||||
this.relations = [];
|
||||
this.classes = new Map<string, ClassNode>();
|
||||
this.notes = new Map<string, ClassNote>();
|
||||
this.classes = new Map();
|
||||
this.notes = [];
|
||||
this.interfaces = [];
|
||||
this.functions = [];
|
||||
this.functions.push(this.setupToolTips.bind(this));
|
||||
this.namespaces = new Map<string, NamespaceNode>();
|
||||
this.namespaces = new Map();
|
||||
this.namespaceCounter = 0;
|
||||
this.direction = 'TB';
|
||||
commonClear();
|
||||
@@ -180,12 +178,7 @@ export class ClassDB implements DiagramDB {
|
||||
return this.relations;
|
||||
}
|
||||
|
||||
public getNote(id: string | number): ClassNote {
|
||||
const key = typeof id === 'number' ? `note${id}` : id;
|
||||
return this.notes.get(key)!;
|
||||
}
|
||||
|
||||
public getNotes(): ClassNoteMap {
|
||||
public getNotes() {
|
||||
return this.notes;
|
||||
}
|
||||
|
||||
@@ -286,19 +279,16 @@ export class ClassDB implements DiagramDB {
|
||||
}
|
||||
}
|
||||
|
||||
public addNote(text: string, className: string): string {
|
||||
const index = this.notes.size;
|
||||
public addNote(text: string, className: string) {
|
||||
const note = {
|
||||
id: `note${index}`,
|
||||
id: `note${this.notes.length}`,
|
||||
class: className,
|
||||
text: text,
|
||||
index: index,
|
||||
};
|
||||
this.notes.set(note.id, note);
|
||||
return note.id;
|
||||
this.notes.push(note);
|
||||
}
|
||||
|
||||
public cleanupLabel(label: string): string {
|
||||
public cleanupLabel(label: string) {
|
||||
if (label.startsWith(':')) {
|
||||
label = label.substring(1);
|
||||
}
|
||||
@@ -364,7 +354,7 @@ export class ClassDB implements DiagramDB {
|
||||
});
|
||||
}
|
||||
|
||||
public getTooltip(id: string, namespace?: string): string | undefined {
|
||||
public getTooltip(id: string, namespace?: string) {
|
||||
if (namespace && this.namespaces.has(namespace)) {
|
||||
return this.namespaces.get(namespace)!.classes.get(id)!.tooltip;
|
||||
}
|
||||
@@ -544,11 +534,10 @@ export class ClassDB implements DiagramDB {
|
||||
|
||||
this.namespaces.set(id, {
|
||||
id: id,
|
||||
classes: new Map<string, ClassNode>(),
|
||||
notes: new Map<string, ClassNote>(),
|
||||
children: new Map<string, NamespaceNode>(),
|
||||
classes: new Map(),
|
||||
children: {},
|
||||
domId: MERMAID_DOM_ID_PREFIX + id + '-' + this.namespaceCounter,
|
||||
});
|
||||
} as NamespaceNode);
|
||||
|
||||
this.namespaceCounter++;
|
||||
}
|
||||
@@ -566,23 +555,16 @@ export class ClassDB implements DiagramDB {
|
||||
*
|
||||
* @param id - ID of the namespace to add
|
||||
* @param classNames - IDs of the class to add
|
||||
* @param noteNames - IDs of the notes to add
|
||||
* @public
|
||||
*/
|
||||
public addClassesToNamespace(id: string, classNames: string[], noteNames: string[]) {
|
||||
public addClassesToNamespace(id: string, classNames: string[]) {
|
||||
if (!this.namespaces.has(id)) {
|
||||
return;
|
||||
}
|
||||
for (const name of classNames) {
|
||||
const { className } = this.splitClassNameAndType(name);
|
||||
const classNode = this.getClass(className);
|
||||
classNode.parent = id;
|
||||
this.namespaces.get(id)!.classes.set(className, classNode);
|
||||
}
|
||||
for (const noteName of noteNames) {
|
||||
const noteNode = this.getNote(noteName);
|
||||
noteNode.parent = id;
|
||||
this.namespaces.get(id)!.notes.set(noteName, noteNode);
|
||||
this.classes.get(className)!.parent = id;
|
||||
this.namespaces.get(id)!.classes.set(className, this.classes.get(className)!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,32 +617,36 @@ export class ClassDB implements DiagramDB {
|
||||
const edges: Edge[] = [];
|
||||
const config = getConfig();
|
||||
|
||||
for (const namespace of this.namespaces.values()) {
|
||||
const node: Node = {
|
||||
id: namespace.id,
|
||||
label: namespace.id,
|
||||
isGroup: true,
|
||||
padding: config.class!.padding ?? 16,
|
||||
// parent node must be one of [rect, roundedWithTitle, noteGroup, divider]
|
||||
shape: 'rect',
|
||||
cssStyles: [],
|
||||
look: config.look,
|
||||
};
|
||||
nodes.push(node);
|
||||
for (const namespaceKey of this.namespaces.keys()) {
|
||||
const namespace = this.namespaces.get(namespaceKey);
|
||||
if (namespace) {
|
||||
const node: Node = {
|
||||
id: namespace.id,
|
||||
label: namespace.id,
|
||||
isGroup: true,
|
||||
padding: config.class!.padding ?? 16,
|
||||
// parent node must be one of [rect, roundedWithTitle, noteGroup, divider]
|
||||
shape: 'rect',
|
||||
cssStyles: ['fill: none', 'stroke: black'],
|
||||
look: config.look,
|
||||
};
|
||||
nodes.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
for (const classNode of this.classes.values()) {
|
||||
const node: Node = {
|
||||
...classNode,
|
||||
type: undefined,
|
||||
isGroup: false,
|
||||
parentId: classNode.parent,
|
||||
look: config.look,
|
||||
};
|
||||
nodes.push(node);
|
||||
for (const classKey of this.classes.keys()) {
|
||||
const classNode = this.classes.get(classKey);
|
||||
if (classNode) {
|
||||
const node = classNode as unknown as Node;
|
||||
node.parentId = classNode.parent;
|
||||
node.look = config.look;
|
||||
nodes.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
for (const note of this.notes.values()) {
|
||||
let cnt = 0;
|
||||
for (const note of this.notes) {
|
||||
cnt++;
|
||||
const noteNode: Node = {
|
||||
id: note.id,
|
||||
label: note.text,
|
||||
@@ -674,15 +660,14 @@ export class ClassDB implements DiagramDB {
|
||||
`stroke: ${config.themeVariables.noteBorderColor}`,
|
||||
],
|
||||
look: config.look,
|
||||
parentId: note.parent,
|
||||
};
|
||||
nodes.push(noteNode);
|
||||
|
||||
const noteClassId = this.classes.get(note.class)?.id;
|
||||
const noteClassId = this.classes.get(note.class)?.id ?? '';
|
||||
|
||||
if (noteClassId) {
|
||||
const edge: Edge = {
|
||||
id: `edgeNote${note.index}`,
|
||||
id: `edgeNote${cnt}`,
|
||||
start: note.id,
|
||||
end: noteClassId,
|
||||
type: 'normal',
|
||||
@@ -712,7 +697,7 @@ export class ClassDB implements DiagramDB {
|
||||
nodes.push(interfaceNode);
|
||||
}
|
||||
|
||||
let cnt = 0;
|
||||
cnt = 0;
|
||||
for (const classRelation of this.relations) {
|
||||
cnt++;
|
||||
const edge: Edge = {
|
||||
|
||||
@@ -417,7 +417,7 @@ class C13["With Città foreign language"]
|
||||
note "This is a keyword: ${keyword}. It truly is."
|
||||
`;
|
||||
parser.parse(str);
|
||||
expect(classDb.getNote(0).text).toEqual(`This is a keyword: ${keyword}. It truly is.`);
|
||||
expect(classDb.getNotes()[0].text).toEqual(`This is a keyword: ${keyword}. It truly is.`);
|
||||
});
|
||||
|
||||
it.each(keywords)(
|
||||
@@ -427,7 +427,7 @@ class C13["With Città foreign language"]
|
||||
note "${keyword}"`;
|
||||
|
||||
parser.parse(str);
|
||||
expect(classDb.getNote(0).text).toEqual(`${keyword}`);
|
||||
expect(classDb.getNotes()[0].text).toEqual(`${keyword}`);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -441,7 +441,7 @@ class C13["With Città foreign language"]
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
expect(classDb.getNote(0).text).toEqual(`This is a keyword: ${keyword}. It truly is.`);
|
||||
expect(classDb.getNotes()[0].text).toEqual(`This is a keyword: ${keyword}. It truly is.`);
|
||||
});
|
||||
|
||||
it.each(keywords)(
|
||||
@@ -456,7 +456,7 @@ class C13["With Città foreign language"]
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
expect(classDb.getNote(0).text).toEqual(`${keyword}`);
|
||||
expect(classDb.getNotes()[0].text).toEqual(`${keyword}`);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import utils, { getEdgeId } from '../../utils.js';
|
||||
import { interpolateToCurve, getStylesFromArray } from '../../utils.js';
|
||||
import { setupGraphViewbox } from '../../setupGraphViewbox.js';
|
||||
import common from '../common/common.js';
|
||||
import type { ClassRelation, ClassMap, ClassNoteMap, NamespaceMap } from './classTypes.js';
|
||||
import type { ClassRelation, ClassNote, ClassMap, NamespaceMap } from './classTypes.js';
|
||||
import type { EdgeData } from '../../types.js';
|
||||
|
||||
const sanitizeText = (txt: string) => common.sanitizeText(txt, getConfig());
|
||||
@@ -65,9 +65,6 @@ export const addNamespaces = function (
|
||||
|
||||
g.setNode(vertex.id, node);
|
||||
addClasses(vertex.classes, g, _id, diagObj, vertex.id);
|
||||
const classes: ClassMap = diagObj.db.getClasses();
|
||||
const relations: ClassRelation[] = diagObj.db.getRelations();
|
||||
addNotes(vertex.notes, g, relations.length + 1, classes, vertex.id);
|
||||
|
||||
log.info('setNode', node);
|
||||
});
|
||||
@@ -147,74 +144,69 @@ export const addClasses = function (
|
||||
* @param classes - Classes
|
||||
*/
|
||||
export const addNotes = function (
|
||||
notes: ClassNoteMap,
|
||||
notes: ClassNote[],
|
||||
g: graphlib.Graph,
|
||||
startEdgeId: number,
|
||||
classes: ClassMap,
|
||||
parent?: string
|
||||
classes: ClassMap
|
||||
) {
|
||||
log.info(notes);
|
||||
|
||||
[...notes.values()]
|
||||
.filter((note) => note.parent === parent)
|
||||
.forEach(function (vertex) {
|
||||
const cssNoteStr = '';
|
||||
notes.forEach(function (note, i) {
|
||||
const vertex = note;
|
||||
|
||||
const styles = { labelStyle: '', style: '' };
|
||||
const cssNoteStr = '';
|
||||
|
||||
const vertexText = vertex.text;
|
||||
const styles = { labelStyle: '', style: '' };
|
||||
|
||||
const radius = 0;
|
||||
const shape = 'note';
|
||||
const node = {
|
||||
labelStyle: styles.labelStyle,
|
||||
shape: shape,
|
||||
labelText: sanitizeText(vertexText),
|
||||
noteData: vertex,
|
||||
rx: radius,
|
||||
ry: radius,
|
||||
class: cssNoteStr,
|
||||
style: styles.style,
|
||||
id: vertex.id,
|
||||
domId: vertex.id,
|
||||
tooltip: '',
|
||||
type: 'note',
|
||||
// TODO V10: Flowchart ? Keeping flowchart for backwards compatibility. Remove in next major release
|
||||
padding: getConfig().flowchart?.padding ?? getConfig().class?.padding,
|
||||
};
|
||||
g.setNode(vertex.id, node);
|
||||
log.info('setNode', node);
|
||||
const vertexText = vertex.text;
|
||||
|
||||
if (parent) {
|
||||
g.setParent(vertex.id, parent);
|
||||
}
|
||||
const radius = 0;
|
||||
const shape = 'note';
|
||||
const node = {
|
||||
labelStyle: styles.labelStyle,
|
||||
shape: shape,
|
||||
labelText: sanitizeText(vertexText),
|
||||
noteData: vertex,
|
||||
rx: radius,
|
||||
ry: radius,
|
||||
class: cssNoteStr,
|
||||
style: styles.style,
|
||||
id: vertex.id,
|
||||
domId: vertex.id,
|
||||
tooltip: '',
|
||||
type: 'note',
|
||||
// TODO V10: Flowchart ? Keeping flowchart for backwards compatibility. Remove in next major release
|
||||
padding: getConfig().flowchart?.padding ?? getConfig().class?.padding,
|
||||
};
|
||||
g.setNode(vertex.id, node);
|
||||
log.info('setNode', node);
|
||||
|
||||
if (!vertex.class || !classes.has(vertex.class)) {
|
||||
return;
|
||||
}
|
||||
const edgeId = startEdgeId + vertex.index;
|
||||
if (!vertex.class || !classes.has(vertex.class)) {
|
||||
return;
|
||||
}
|
||||
const edgeId = startEdgeId + i;
|
||||
|
||||
const edgeData: EdgeData = {
|
||||
id: `edgeNote${edgeId}`,
|
||||
//Set relationship style and line type
|
||||
classes: 'relation',
|
||||
pattern: 'dotted',
|
||||
// Set link type for rendering
|
||||
arrowhead: 'none',
|
||||
//Set edge extra labels
|
||||
startLabelRight: '',
|
||||
endLabelLeft: '',
|
||||
//Set relation arrow types
|
||||
arrowTypeStart: 'none',
|
||||
arrowTypeEnd: 'none',
|
||||
style: 'fill:none',
|
||||
labelStyle: '',
|
||||
curve: interpolateToCurve(conf.curve, curveLinear),
|
||||
};
|
||||
const edgeData: EdgeData = {
|
||||
id: `edgeNote${edgeId}`,
|
||||
//Set relationship style and line type
|
||||
classes: 'relation',
|
||||
pattern: 'dotted',
|
||||
// Set link type for rendering
|
||||
arrowhead: 'none',
|
||||
//Set edge extra labels
|
||||
startLabelRight: '',
|
||||
endLabelLeft: '',
|
||||
//Set relation arrow types
|
||||
arrowTypeStart: 'none',
|
||||
arrowTypeEnd: 'none',
|
||||
style: 'fill:none',
|
||||
labelStyle: '',
|
||||
curve: interpolateToCurve(conf.curve, curveLinear),
|
||||
};
|
||||
|
||||
// Add the edge to the graph
|
||||
g.setEdge(vertex.id, vertex.class, edgeData, edgeId);
|
||||
});
|
||||
// Add the edge to the graph
|
||||
g.setEdge(vertex.id, vertex.class, edgeData, edgeId);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -337,7 +329,7 @@ export const draw = async function (text: string, id: string, _version: string,
|
||||
const namespaces: NamespaceMap = diagObj.db.getNamespaces();
|
||||
const classes: ClassMap = diagObj.db.getClasses();
|
||||
const relations: ClassRelation[] = diagObj.db.getRelations();
|
||||
const notes: ClassNoteMap = diagObj.db.getNotes();
|
||||
const notes: ClassNote[] = diagObj.db.getNotes();
|
||||
log.info(relations);
|
||||
addNamespaces(namespaces, g, id, diagObj);
|
||||
addClasses(classes, g, id, diagObj);
|
||||
|
||||
@@ -206,7 +206,7 @@ export const draw = function (text, id, _version, diagObj) {
|
||||
);
|
||||
});
|
||||
|
||||
const notes = diagObj.db.getNotes().values();
|
||||
const notes = diagObj.db.getNotes();
|
||||
notes.forEach(function (note) {
|
||||
log.debug(`Adding note: ${JSON.stringify(note)}`);
|
||||
const node = svgDraw.drawNote(diagram, note, conf, diagObj);
|
||||
|
||||
@@ -5,7 +5,7 @@ export interface ClassNode {
|
||||
id: string;
|
||||
type: string;
|
||||
label: string;
|
||||
shape: 'classBox';
|
||||
shape: string;
|
||||
text: string;
|
||||
cssClasses: string;
|
||||
methods: ClassMember[];
|
||||
@@ -149,8 +149,6 @@ export interface ClassNote {
|
||||
id: string;
|
||||
class: string;
|
||||
text: string;
|
||||
index: number;
|
||||
parent?: string;
|
||||
}
|
||||
|
||||
export interface ClassRelation {
|
||||
@@ -179,7 +177,6 @@ export interface NamespaceNode {
|
||||
id: string;
|
||||
domId: string;
|
||||
classes: ClassMap;
|
||||
notes: ClassNoteMap;
|
||||
children: NamespaceMap;
|
||||
}
|
||||
|
||||
@@ -190,5 +187,4 @@ export interface StyleClass {
|
||||
}
|
||||
|
||||
export type ClassMap = Map<string, ClassNode>;
|
||||
export type ClassNoteMap = Map<string, ClassNote>;
|
||||
export type NamespaceMap = Map<string, NamespaceNode>;
|
||||
|
||||
@@ -275,8 +275,8 @@ statement
|
||||
;
|
||||
|
||||
namespaceStatement
|
||||
: namespaceIdentifier STRUCT_START classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $3[0], $3[1]); }
|
||||
| namespaceIdentifier STRUCT_START NEWLINE classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $4[0], $4[1]); }
|
||||
: namespaceIdentifier STRUCT_START classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $3); }
|
||||
| namespaceIdentifier STRUCT_START NEWLINE classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $4); }
|
||||
;
|
||||
|
||||
namespaceIdentifier
|
||||
@@ -284,12 +284,9 @@ namespaceIdentifier
|
||||
;
|
||||
|
||||
classStatements
|
||||
: classStatement {$$=[[$1], []]}
|
||||
| classStatement NEWLINE {$$=[[$1], []]}
|
||||
| classStatement NEWLINE classStatements {$3[0].unshift($1); $$=$3}
|
||||
| noteStatement {$$=[[], [$1]]}
|
||||
| noteStatement NEWLINE {$$=[[], [$1]]}
|
||||
| noteStatement NEWLINE classStatements {$3[1].unshift($1); $$=$3}
|
||||
: classStatement {$$=[$1]}
|
||||
| classStatement NEWLINE {$$=[$1]}
|
||||
| classStatement NEWLINE classStatements {$3.unshift($1); $$=$3}
|
||||
;
|
||||
|
||||
classStatement
|
||||
@@ -336,8 +333,8 @@ relationStatement
|
||||
;
|
||||
|
||||
noteStatement
|
||||
: NOTE_FOR className noteText { $$ = yy.addNote($3, $2); }
|
||||
| NOTE noteText { $$ = yy.addNote($2); }
|
||||
: NOTE_FOR className noteText { yy.addNote($3, $2); }
|
||||
| NOTE noteText { yy.addNote($2); }
|
||||
;
|
||||
|
||||
classDefStatement
|
||||
|
||||
@@ -13,30 +13,6 @@ const getStyles = (options) =>
|
||||
|
||||
}
|
||||
|
||||
.cluster-label text {
|
||||
fill: ${options.titleColor};
|
||||
}
|
||||
.cluster-label span {
|
||||
color: ${options.titleColor};
|
||||
}
|
||||
.cluster-label span p {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.cluster rect {
|
||||
fill: ${options.clusterBkg};
|
||||
stroke: ${options.clusterBorder};
|
||||
stroke-width: 1px;
|
||||
}
|
||||
|
||||
.cluster text {
|
||||
fill: ${options.titleColor};
|
||||
}
|
||||
|
||||
.cluster span {
|
||||
color: ${options.titleColor};
|
||||
}
|
||||
|
||||
.nodeLabel, .edgeLabel {
|
||||
color: ${options.classText};
|
||||
}
|
||||
|
||||
@@ -66,15 +66,12 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
||||
\}\| return 'ONE_OR_MORE';
|
||||
"one" return 'ONLY_ONE';
|
||||
"only one" return 'ONLY_ONE';
|
||||
[0-9]+\.[0-9]+ return 'DECIMAL_NUM';
|
||||
"1"(?=\s+[A-Za-z_"']) return 'ONLY_ONE';
|
||||
"1" return 'ENTITY_ONE';
|
||||
[0-9]+ return 'NUM';
|
||||
"1" return 'ONLY_ONE';
|
||||
\|\| return 'ONLY_ONE';
|
||||
o\| return 'ZERO_OR_ONE';
|
||||
o\{ return 'ZERO_OR_MORE';
|
||||
\|\{ return 'ONE_OR_MORE';
|
||||
u(?=[\.\-\|]) return 'MD_PARENT';
|
||||
\s*u return 'MD_PARENT';
|
||||
\.\. return 'NON_IDENTIFYING';
|
||||
\-\- return 'IDENTIFYING';
|
||||
"to" return 'IDENTIFYING';
|
||||
@@ -83,15 +80,13 @@ u(?=[\.\-\|]) return 'MD_PARENT';
|
||||
\-\. return 'NON_IDENTIFYING';
|
||||
<style>([^\x00-\x7F]|\w|\-|\*)+ return 'STYLE_TEXT';
|
||||
<style>';' return 'SEMI';
|
||||
([^\x00-\x7F]|\w|\-|\*|\.)+ return 'UNICODE_TEXT';
|
||||
([^\x00-\x7F]|\w|\-|\*)+ return 'UNICODE_TEXT';
|
||||
[0-9] return 'NUM';
|
||||
. return yytext[0];
|
||||
<<EOF>> return 'EOF';
|
||||
|
||||
/lex
|
||||
|
||||
%left 'ONLY_ONE'
|
||||
%left 'ZERO_OR_ONE' 'ZERO_OR_MORE' 'ONE_OR_MORE' 'MD_PARENT'
|
||||
|
||||
%start start
|
||||
%% /* language grammar */
|
||||
|
||||
@@ -233,9 +228,6 @@ styleComponent: STYLE_TEXT | NUM | COLON | BRKT;
|
||||
entityName
|
||||
: 'ENTITY_NAME' { $$ = $1.replace(/"/g, ''); }
|
||||
| 'UNICODE_TEXT' { $$ = $1; }
|
||||
| 'NUM' { $$ = $1; }
|
||||
| 'DECIMAL_NUM' { $$ = $1; }
|
||||
| 'ENTITY_ONE' { $$ = $1; }
|
||||
;
|
||||
|
||||
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
|
||||
}
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -140,7 +140,6 @@ that id.
|
||||
.*direction\s+BT[^\n]* return 'direction_bt';
|
||||
.*direction\s+RL[^\n]* return 'direction_rl';
|
||||
.*direction\s+LR[^\n]* return 'direction_lr';
|
||||
.*direction\s+TD[^\n]* return 'direction_td';
|
||||
|
||||
[^\s\"]+\@(?=[^\{\"]) { return 'LINK_ID'; }
|
||||
[0-9]+ return 'NUM';
|
||||
@@ -627,8 +626,6 @@ direction
|
||||
{ $$={stmt:'dir', value:'RL'};}
|
||||
| direction_lr
|
||||
{ $$={stmt:'dir', value:'LR'};}
|
||||
| direction_td
|
||||
{ $$={stmt:'dir', value:'TD'};}
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
@@ -309,21 +309,4 @@ describe('when parsing subgraphs', function () {
|
||||
expect(subgraphA.nodes).toContain('a');
|
||||
expect(subgraphA.nodes).not.toContain('c');
|
||||
});
|
||||
it('should correctly parse direction TD inside a subgraph', function () {
|
||||
const res = flow.parser.parse(`
|
||||
graph LR
|
||||
subgraph WithTD
|
||||
direction TD
|
||||
A1 --> A2
|
||||
end
|
||||
`);
|
||||
|
||||
const subgraphs = flow.parser.yy.getSubGraphs();
|
||||
expect(subgraphs.length).toBe(1);
|
||||
const subgraph = subgraphs[0];
|
||||
|
||||
expect(subgraph.dir).toBe('TD');
|
||||
expect(subgraph.nodes).toContain('A1');
|
||||
expect(subgraph.nodes).toContain('A2');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -268,9 +268,7 @@ const fixTaskDates = function (startTime, endTime, dateFormat, excludes, include
|
||||
|
||||
const getStartDate = function (prevTime, dateFormat, str) {
|
||||
str = str.trim();
|
||||
if ((dateFormat.trim() === 'x' || dateFormat.trim() === 'X') && /^\d+$/.test(str)) {
|
||||
return new Date(Number(str));
|
||||
}
|
||||
|
||||
// Test for after
|
||||
const afterRePattern = /^after\s+(?<ids>[\d\w- ]+)/;
|
||||
const afterStatement = afterRePattern.exec(str);
|
||||
|
||||
@@ -16,7 +16,7 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
|
||||
const svgWidth = bitWidth * bitsPerRow + 2;
|
||||
const svg: SVG = selectSvgElement(id);
|
||||
|
||||
svg.attr('viewBox', `0 0 ${svgWidth} ${svgHeight}`);
|
||||
svg.attr('viewbox', `0 0 ${svgWidth} ${svgHeight}`);
|
||||
configureSvgSize(svg, svgHeight, svgWidth, config.useMaxWidth);
|
||||
|
||||
for (const [word, packet] of words.entries()) {
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { Diagram } from '../../Diagram.js';
|
||||
import type { RadarDiagramConfig } from '../../config.type.js';
|
||||
import type { DiagramRenderer, DrawDefinition, SVG, SVGGroup } from '../../diagram-api/types.js';
|
||||
import { selectSvgElement } from '../../rendering-util/selectSvgElement.js';
|
||||
import { configureSvgSize } from '../../setupGraphViewbox.js';
|
||||
import type { RadarDB, RadarAxis, RadarCurve } from './types.js';
|
||||
|
||||
const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
|
||||
@@ -54,9 +53,11 @@ const drawFrame = (svg: SVG, config: Required<RadarDiagramConfig>): SVGGroup =>
|
||||
x: config.marginLeft + config.width / 2,
|
||||
y: config.marginTop + config.height / 2,
|
||||
};
|
||||
configureSvgSize(svg, totalHeight, totalWidth, config.useMaxWidth ?? true);
|
||||
|
||||
svg.attr('viewBox', `0 0 ${totalWidth} ${totalHeight}`);
|
||||
// Initialize the SVG
|
||||
svg
|
||||
.attr('viewbox', `0 0 ${totalWidth} ${totalHeight}`)
|
||||
.attr('width', totalWidth)
|
||||
.attr('height', totalHeight);
|
||||
// g element to center the radar chart
|
||||
return svg.append('g').attr('transform', `translate(${center.x}, ${center.y})`);
|
||||
};
|
||||
|
||||
@@ -32,14 +32,13 @@
|
||||
<CONFIG>[^\}]+ { return 'CONFIG_CONTENT'; }
|
||||
<CONFIG>\} { this.popState(); this.popState(); return 'CONFIG_END'; }
|
||||
<ID>[^\<->\->:\n,;@\s]+(?=\@\{) { yytext = yytext.trim(); return 'ACTOR'; }
|
||||
<ID>[^<>:\n,;@\s]+(?=\s+as\s) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; }
|
||||
<ID>[^<>:\n,;@]+(?=\s*[\n;#]|$) { yytext = yytext.trim(); this.popState(); return 'ACTOR'; }
|
||||
<ID>[^<>:\n,;@]*\<[^\n]* { this.popState(); return 'INVALID'; }
|
||||
<ID>[^\<->\->:\n,;@]+?([\-]*[^\<->\->:\n,;@]+?)*?(?=((?!\n)\s)+"as"(?!\n)\s|[#\n;]|$) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; }
|
||||
"box" { this.begin('LINE'); return 'box'; }
|
||||
"participant" { this.begin('ID'); return 'participant'; }
|
||||
"actor" { this.begin('ID'); return 'participant_actor'; }
|
||||
"create" return 'create';
|
||||
"destroy" { this.begin('ID'); return 'destroy'; }
|
||||
<ID>[^<\->\->:\n,;]+?([\-]*[^<\->\->:\n,;]+?)*?(?=((?!\n)\s)+"as"(?!\n)\s|[#\n;]|$) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; }
|
||||
<ALIAS>"as" { this.popState(); this.popState(); this.begin('LINE'); return 'AS'; }
|
||||
<ALIAS>(?:) { this.popState(); this.popState(); return 'NEWLINE'; }
|
||||
"loop" { this.begin('LINE'); return 'loop'; }
|
||||
@@ -79,7 +78,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
||||
"off" return 'off';
|
||||
"," return ',';
|
||||
";" 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 'BIDIRECTIONAL_SOLID_ARROW';
|
||||
"-->>" return 'DOTTED_ARROW';
|
||||
@@ -90,36 +89,10 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
||||
\-\-[x] return 'DOTTED_CROSS';
|
||||
\-[\)] return 'SOLID_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';
|
||||
":" return 'TXT';
|
||||
"+" return '+';
|
||||
"-" return '-';
|
||||
"()" return '()';
|
||||
<<EOF>> return 'NEWLINE';
|
||||
. return 'INVALID';
|
||||
|
||||
@@ -146,7 +119,6 @@ line
|
||||
: SPACE statement { $$ = $2 }
|
||||
| statement { $$ = $1 }
|
||||
| NEWLINE { $$=[]; }
|
||||
| INVALID { $$=[]; }
|
||||
;
|
||||
|
||||
box_section
|
||||
@@ -332,20 +304,6 @@ signal
|
||||
{ $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$2, msg:$5},
|
||||
{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
|
||||
{ $$ = [$1,$3,{type: 'addMessage', from:$1.actor, to:$3.actor, signalType:$2, msg:$4}]}
|
||||
;
|
||||
@@ -379,28 +337,7 @@ signaltype
|
||||
: SOLID_OPEN_ARROW { $$ = yy.LINETYPE.SOLID_OPEN; }
|
||||
| DOTTED_OPEN_ARROW { $$ = yy.LINETYPE.DOTTED_OPEN; }
|
||||
| SOLID_ARROW { $$ = yy.LINETYPE.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; }
|
||||
| BIDIRECTIONAL_SOLID_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_SOLID; }
|
||||
| DOTTED_ARROW { $$ = yy.LINETYPE.DOTTED; }
|
||||
| BIDIRECTIONAL_DOTTED_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_DOTTED; }
|
||||
| SOLID_CROSS { $$ = yy.LINETYPE.SOLID_CROSS; }
|
||||
@@ -413,4 +350,4 @@ text2
|
||||
: TXT {$$ = yy.parseMessage($1.trim().substring(1)) }
|
||||
;
|
||||
|
||||
%%
|
||||
%%
|
||||
|
||||
@@ -13,8 +13,7 @@ import {
|
||||
setAccTitle,
|
||||
setDiagramTitle,
|
||||
} from '../common/commonDb.js';
|
||||
import type { Actor, AddMessageParams, Box, Message, Note } from './types.js';
|
||||
import type { ParticipantMetaData } from '../../types.js';
|
||||
import type { Actor, AddMessageParams, Box, Message, Note, ParticipantMetaData } from './types.js';
|
||||
|
||||
interface SequenceState {
|
||||
prevActor?: string;
|
||||
@@ -64,30 +63,6 @@ const LINETYPE = {
|
||||
PAR_OVER_START: 32,
|
||||
BIDIRECTIONAL_SOLID: 33,
|
||||
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;
|
||||
|
||||
const ARROWTYPE = {
|
||||
@@ -110,6 +85,8 @@ export const PARTICIPANT_TYPE = {
|
||||
ENTITY: 'entity',
|
||||
PARTICIPANT: 'participant',
|
||||
QUEUE: 'queue',
|
||||
ICON: 'icon',
|
||||
IMAGE: 'image',
|
||||
} as const;
|
||||
|
||||
export class SequenceDB implements DiagramDB {
|
||||
@@ -210,6 +187,7 @@ export class SequenceDB implements DiagramDB {
|
||||
actorCnt: null,
|
||||
rectData: null,
|
||||
type: type ?? 'participant',
|
||||
doc: doc,
|
||||
});
|
||||
if (this.state.records.prevActor) {
|
||||
const prevActorInRecords = this.state.records.actors.get(this.state.records.prevActor);
|
||||
@@ -268,8 +246,7 @@ export class SequenceDB implements DiagramDB {
|
||||
idTo?: Message['to'],
|
||||
message?: { text: string; wrap: boolean },
|
||||
messageType?: number,
|
||||
activate = false,
|
||||
centralConnection?: number
|
||||
activate = false
|
||||
) {
|
||||
if (messageType === this.LINETYPE.ACTIVE_END) {
|
||||
const cnt = this.activationCount(idFrom ?? '');
|
||||
@@ -296,7 +273,6 @@ export class SequenceDB implements DiagramDB {
|
||||
wrap: message?.wrap ?? this.autoWrap(),
|
||||
type: messageType,
|
||||
activate,
|
||||
centralConnection: centralConnection ?? 0,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
@@ -589,12 +565,6 @@ export class SequenceDB implements DiagramDB {
|
||||
case 'activeStart':
|
||||
this.addSignal(param.actor, undefined, undefined, param.signalType);
|
||||
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':
|
||||
this.addSignal(param.actor, undefined, undefined, param.signalType);
|
||||
break;
|
||||
@@ -638,14 +608,7 @@ export class SequenceDB implements DiagramDB {
|
||||
this.state.records.lastDestroyed = undefined;
|
||||
}
|
||||
}
|
||||
this.addSignal(
|
||||
param.from,
|
||||
param.to,
|
||||
param.msg,
|
||||
param.signalType,
|
||||
param.activate,
|
||||
param.centralConnection
|
||||
);
|
||||
this.addSignal(param.from, param.to, param.msg, param.signalType, param.activate);
|
||||
break;
|
||||
case 'boxStart':
|
||||
this.addBox(param.boxData);
|
||||
|
||||
@@ -104,7 +104,6 @@ describe('more than one sequence diagram', () => {
|
||||
[
|
||||
{
|
||||
"activate": false,
|
||||
"centralConnection": 0,
|
||||
"from": "Alice",
|
||||
"id": "0",
|
||||
"message": "Hello Bob, how are you?",
|
||||
@@ -114,7 +113,6 @@ describe('more than one sequence diagram', () => {
|
||||
},
|
||||
{
|
||||
"activate": false,
|
||||
"centralConnection": 0,
|
||||
"from": "Bob",
|
||||
"id": "1",
|
||||
"message": "I am good thanks!",
|
||||
@@ -133,7 +131,6 @@ describe('more than one sequence diagram', () => {
|
||||
[
|
||||
{
|
||||
"activate": false,
|
||||
"centralConnection": 0,
|
||||
"from": "Alice",
|
||||
"id": "0",
|
||||
"message": "Hello Bob, how are you?",
|
||||
@@ -143,7 +140,6 @@ describe('more than one sequence diagram', () => {
|
||||
},
|
||||
{
|
||||
"activate": false,
|
||||
"centralConnection": 0,
|
||||
"from": "Bob",
|
||||
"id": "1",
|
||||
"message": "I am good thanks!",
|
||||
@@ -164,7 +160,6 @@ describe('more than one sequence diagram', () => {
|
||||
[
|
||||
{
|
||||
"activate": false,
|
||||
"centralConnection": 0,
|
||||
"from": "Alice",
|
||||
"id": "0",
|
||||
"message": "Hello John, how are you?",
|
||||
@@ -174,7 +169,6 @@ describe('more than one sequence diagram', () => {
|
||||
},
|
||||
{
|
||||
"activate": false,
|
||||
"centralConnection": 0,
|
||||
"from": "John",
|
||||
"id": "1",
|
||||
"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 () {
|
||||
let diagram;
|
||||
beforeEach(async function () {
|
||||
@@ -2312,36 +2058,6 @@ Bob->>Alice:Got it!
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
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', () => {
|
||||
it('should parse participants with different quote styles and whitespace', async () => {
|
||||
const diagram = await Diagram.fromText(`
|
||||
@@ -2609,17 +2325,74 @@ Bob->>Alice:Got it!
|
||||
expect(actors.get('E').type).toBe('entity');
|
||||
expect(actors.get('E').description).toBe('E');
|
||||
});
|
||||
it('should handle fail parsing when alias token causes conflicts in participant definition', async () => {
|
||||
let error = false;
|
||||
try {
|
||||
await Diagram.fromText(`
|
||||
});
|
||||
|
||||
describe('image and icon participant parsing', () => {
|
||||
it('should parse image participant with image URL', async () => {
|
||||
const diagram = await Diagram.fromText(`
|
||||
sequenceDiagram
|
||||
participant SAS MyServiceWithMoreThan20Chars <br> service decription
|
||||
`);
|
||||
} catch (e) {
|
||||
error = true;
|
||||
}
|
||||
expect(error).toBe(true);
|
||||
participant Bob@{ "type": "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
|
||||
Bob->>Bob: test
|
||||
`);
|
||||
const actors = diagram.db.getActors();
|
||||
expect(actors.get('Bob').type).toBe('image');
|
||||
expect(actors.get('Bob').doc.image).toBe(
|
||||
'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg'
|
||||
);
|
||||
});
|
||||
|
||||
it('should parse icon participant with icon name', async () => {
|
||||
const diagram = await Diagram.fromText(`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type": "icon", "icon": "fa:bell" }
|
||||
Alice->>Alice: test
|
||||
`);
|
||||
const actors = diagram.db.getActors();
|
||||
expect(actors.get('Alice').type).toBe('icon');
|
||||
expect(actors.get('Alice').doc.icon).toBe('fa:bell');
|
||||
});
|
||||
|
||||
it('should parse two image participants', async () => {
|
||||
const diagram = await Diagram.fromText(`
|
||||
sequenceDiagram
|
||||
participant Bob@{ "type": "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
|
||||
participant Alice@{ "type": "image", "image": "https://cdn.pixabay.com/photo/2016/11/29/09/32/animal-1867121_1280.jpg" }
|
||||
Bob->>Alice: Hello
|
||||
Alice-->>Bob: Hi
|
||||
`);
|
||||
const actors = diagram.db.getActors();
|
||||
expect(actors.get('Bob').type).toBe('image');
|
||||
expect(actors.get('Bob').doc.image).toBe(
|
||||
'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg'
|
||||
);
|
||||
expect(actors.get('Alice').type).toBe('image');
|
||||
expect(actors.get('Alice').doc.image).toBe(
|
||||
'https://cdn.pixabay.com/photo/2016/11/29/09/32/animal-1867121_1280.jpg'
|
||||
);
|
||||
});
|
||||
|
||||
it('should parse image participant with normal participant', async () => {
|
||||
const diagram = await Diagram.fromText(`
|
||||
sequenceDiagram
|
||||
participant Bob@{ "type": "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
|
||||
participant Alice
|
||||
Bob->>Alice: Hello
|
||||
`);
|
||||
const actors = diagram.db.getActors();
|
||||
expect(actors.get('Bob').type).toBe('image');
|
||||
expect(actors.get('Alice').type).toBe('participant');
|
||||
});
|
||||
|
||||
it('should parse icon participant with normal participant', async () => {
|
||||
const diagram = await Diagram.fromText(`
|
||||
sequenceDiagram
|
||||
participant Bob@{ "type": "icon", "icon": "fa:bell" }
|
||||
participant Alice
|
||||
Bob->>Alice: Hello
|
||||
`);
|
||||
const actors = diagram.db.getActors();
|
||||
expect(actors.get('Bob').type).toBe('icon');
|
||||
expect(actors.get('Alice').type).toBe('participant');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -282,49 +282,6 @@ const drawNote = async function (elem: any, noteModel: 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) => {
|
||||
return {
|
||||
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 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 textDims = utils.calculateTextDimensions(message, messageFont(conf));
|
||||
const textObj = svgDrawCommon.getTextObj();
|
||||
@@ -476,9 +433,6 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
||||
line.attr('y1', lineStartY);
|
||||
line.attr('x2', stopx);
|
||||
line.attr('y2', lineStartY);
|
||||
if (hasCentralConnection(msg, diagObj)) {
|
||||
drawCentralConnection(diagram, msg, msgModel, diagObj, startx, stopx, lineStartY);
|
||||
}
|
||||
}
|
||||
// Make an SVG Container
|
||||
// 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_POINT ||
|
||||
type === diagObj.db.LINETYPE.DOTTED_OPEN ||
|
||||
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
|
||||
type === diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED
|
||||
) {
|
||||
line.style('stroke-dasharray', '3, 3');
|
||||
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', 'none'); // handled by theme/css anyway
|
||||
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) {
|
||||
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_DOTTED;
|
||||
|
||||
const isReverseArrowType =
|
||||
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) {
|
||||
if (isBidirectional) {
|
||||
const SEQUENCE_NUMBER_RADIUS = 6;
|
||||
|
||||
if (startx < stopx) {
|
||||
@@ -599,7 +489,6 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
||||
} else {
|
||||
line.attr('x1', startx + SEQUENCE_NUMBER_RADIUS);
|
||||
}
|
||||
x = 3.5;
|
||||
}
|
||||
|
||||
diagram
|
||||
@@ -609,8 +498,7 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
||||
.attr('x2', startx)
|
||||
.attr('y2', lineStartY)
|
||||
.attr('stroke-width', 0)
|
||||
.attr('marker-start', 'url(' + url + '#sequencenumber)')
|
||||
.attr('transform', `translate(-${x}, 0)`);
|
||||
.attr('marker-start', 'url(' + url + '#sequencenumber)');
|
||||
|
||||
diagram
|
||||
.append('text')
|
||||
@@ -620,8 +508,7 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
||||
.attr('font-size', '12px')
|
||||
.attr('text-anchor', 'middle')
|
||||
.attr('class', 'sequenceNumber')
|
||||
.text(sequenceIndex)
|
||||
.attr('transform', `translate(-${x}, 0)`);
|
||||
.text(sequenceIndex);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -865,6 +752,8 @@ function adjustCreatedDestroyedData(
|
||||
PARTICIPANT_TYPE.CONTROL,
|
||||
PARTICIPANT_TYPE.ENTITY,
|
||||
PARTICIPANT_TYPE.DATABASE,
|
||||
PARTICIPANT_TYPE.ICON,
|
||||
PARTICIPANT_TYPE.IMAGE,
|
||||
];
|
||||
|
||||
// if it is a create message
|
||||
@@ -970,10 +859,6 @@ export const draw = async function (_text: string, id: string, _version: string,
|
||||
svgDraw.insertArrowCrossHead(diagram);
|
||||
svgDraw.insertArrowFilledHead(diagram);
|
||||
svgDraw.insertSequenceNumber(diagram);
|
||||
svgDraw.insertSolidTopArrowHead(diagram);
|
||||
svgDraw.insertSolidBottomArrowHead(diagram);
|
||||
svgDraw.insertStickTopArrowHead(diagram);
|
||||
svgDraw.insertStickBottomArrowHead(diagram);
|
||||
|
||||
/**
|
||||
* @param msg - The message to draw.
|
||||
@@ -1014,12 +899,6 @@ export const draw = async function (_text: string, id: string, _version: string,
|
||||
case diagObj.db.LINETYPE.ACTIVE_START:
|
||||
bounds.newActivation(msg, diagram, actors);
|
||||
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:
|
||||
activeEnd(msg, bounds.getVerticalPos());
|
||||
break;
|
||||
@@ -1178,7 +1057,7 @@ export const draw = async function (_text: string, id: string, _version: string,
|
||||
createdActors,
|
||||
destroyedActors
|
||||
);
|
||||
messagesToDraw.push({ messageModel: msgModel, lineStartY: lineStartY, msg });
|
||||
messagesToDraw.push({ messageModel: msgModel, lineStartY: lineStartY });
|
||||
bounds.models.addMessage(msgModel);
|
||||
} catch (e) {
|
||||
log.error('error while drawing message', e);
|
||||
@@ -1191,27 +1070,6 @@ export const draw = async function (_text: string, id: string, _version: string,
|
||||
diagObj.db.LINETYPE.SOLID_OPEN,
|
||||
diagObj.db.LINETYPE.DOTTED_OPEN,
|
||||
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.SOLID_CROSS,
|
||||
diagObj.db.LINETYPE.DOTTED_CROSS,
|
||||
@@ -1231,7 +1089,7 @@ export const draw = async function (_text: string, id: string, _version: string,
|
||||
await drawActors(diagram, actors, actorKeys, false);
|
||||
|
||||
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) {
|
||||
await drawActors(diagram, actors, actorKeys, true);
|
||||
@@ -1605,85 +1463,12 @@ const buildNoteModel = async function (msg, actors, diagObj) {
|
||||
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) {
|
||||
if (
|
||||
![
|
||||
diagObj.db.LINETYPE.SOLID_OPEN,
|
||||
diagObj.db.LINETYPE.DOTTED_OPEN,
|
||||
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.SOLID_CROSS,
|
||||
diagObj.db.LINETYPE.DOTTED_CROSS,
|
||||
@@ -1701,8 +1486,6 @@ const buildMessageModel = function (msg, actors, diagObj) {
|
||||
let startx = isArrowToRight ? fromRight : fromLeft;
|
||||
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.
|
||||
const isArrowToActivation = Math.abs(toLeft - toRight) > 2;
|
||||
|
||||
@@ -1736,30 +1519,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
|
||||
* This is not required for open arrows that don't have arrowheads
|
||||
*/
|
||||
if (
|
||||
![
|
||||
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)
|
||||
) {
|
||||
if (![diagObj.db.LINETYPE.SOLID_OPEN, diagObj.db.LINETYPE.DOTTED_OPEN].includes(msg.type)) {
|
||||
stopx += adjustValue(3);
|
||||
}
|
||||
|
||||
@@ -1767,14 +1527,9 @@ const buildMessageModel = function (msg, actors, diagObj) {
|
||||
* Shorten start position of bidirectional arrow to accommodate for second arrowhead
|
||||
*/
|
||||
if (
|
||||
[
|
||||
diagObj.db.LINETYPE.BIDIRECTIONAL_SOLID,
|
||||
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)
|
||||
[diagObj.db.LINETYPE.BIDIRECTIONAL_SOLID, diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED].includes(
|
||||
msg.type
|
||||
)
|
||||
) {
|
||||
startx -= adjustValue(3);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||
import * as configApi from '../../config.js';
|
||||
import { getIconSVG } from '../../rendering-util/icons.js';
|
||||
import { ZERO_WIDTH_SPACE, parseFontSize } from '../../utils.js';
|
||||
import common, {
|
||||
calculateMathMLDimensions,
|
||||
@@ -322,6 +323,89 @@ export const fixLifeLineHeights = (diagram, actors, actorKeys, conf) => {
|
||||
});
|
||||
};
|
||||
|
||||
const drawActorTypeIcon = async function (elem, actor, conf, isFooter) {
|
||||
const actorY = isFooter ? actor.stopy : actor.starty;
|
||||
const center = actor.x + actor.width / 2;
|
||||
const centerY = actorY + actor.height / 2;
|
||||
|
||||
const line = elem.append('g').lower();
|
||||
if (!isFooter) {
|
||||
actorCnt++;
|
||||
line
|
||||
.append('line')
|
||||
.attr('id', 'actor' + actorCnt)
|
||||
.attr('x1', center)
|
||||
.attr('y1', centerY + 25)
|
||||
.attr('x2', center)
|
||||
.attr('y2', 2000)
|
||||
.attr('class', 'actor-line')
|
||||
.attr('stroke-width', '0.5px')
|
||||
.attr('stroke', '#999')
|
||||
.attr('name', actor.name);
|
||||
actor.actorCnt = actorCnt;
|
||||
}
|
||||
|
||||
const actElem = elem.append('g');
|
||||
let cssClass = 'actor-icon';
|
||||
if (isFooter) {
|
||||
cssClass += ` ${BOTTOM_ACTOR_CLASS}`;
|
||||
} else {
|
||||
cssClass += ` ${TOP_ACTOR_CLASS}`;
|
||||
}
|
||||
|
||||
actElem.attr('class', cssClass);
|
||||
actElem.attr('name', actor.name);
|
||||
|
||||
// Define the size of the square and icon
|
||||
const iconSize = actor.width / 5;
|
||||
const squareX = center - iconSize / 2;
|
||||
const squareY = !isFooter ? actorY + 10 : actorY;
|
||||
|
||||
// Draw a square rectangle for the actor icon background
|
||||
|
||||
actElem
|
||||
.append('rect')
|
||||
.attr('x', squareX)
|
||||
.attr('y', squareY)
|
||||
.attr('width', iconSize)
|
||||
.attr('height', iconSize)
|
||||
.attr('rx', 3) // rounded corners, optional
|
||||
.attr('ry', 3)
|
||||
.attr('fill', 'none'); // light gray background or customize as needed
|
||||
|
||||
// Render icon SVG inside the rectangle
|
||||
const iconGroup = actElem.append('g').attr('transform', `translate(${squareX}, ${squareY})`);
|
||||
|
||||
iconGroup
|
||||
.append('svg')
|
||||
.attr('width', iconSize)
|
||||
.attr('height', iconSize)
|
||||
.html(
|
||||
`<g>${await getIconSVG(actor.doc.icon, {
|
||||
height: iconSize,
|
||||
width: iconSize,
|
||||
fallbackPrefix: '',
|
||||
})}</g>`
|
||||
);
|
||||
|
||||
// Add text label below icon
|
||||
_drawTextCandidateFunc(conf, hasKatex(actor.description))(
|
||||
actor.description,
|
||||
actElem,
|
||||
actor.x,
|
||||
actorY + (!isFooter ? 40 : 30), // positioning below the square icon
|
||||
actor.width,
|
||||
20,
|
||||
{ class: 'actor-icon-text' },
|
||||
conf
|
||||
);
|
||||
|
||||
const bounds = actElem.node().getBBox();
|
||||
actor.height = bounds.height + (conf.sequence?.labelBoxHeight ?? 0);
|
||||
|
||||
return actor.height;
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws an actor in the diagram with the attached line
|
||||
*
|
||||
@@ -414,6 +498,174 @@ const drawActorTypeParticipant = function (elem, actor, conf, isFooter) {
|
||||
|
||||
return height;
|
||||
};
|
||||
const drawActorTypeImage = async function (elem, actor, conf, isFooter) {
|
||||
const img = new Image();
|
||||
img.src = actor.doc.image ?? '';
|
||||
await img.decode();
|
||||
|
||||
const imageNaturalWidth = Number(img.naturalWidth.toString().replace('px', ''));
|
||||
const imageNaturalHeight = Number(img.naturalHeight.toString().replace('px', ''));
|
||||
|
||||
actor.doc.imageAspectRatio = imageNaturalWidth / imageNaturalHeight;
|
||||
|
||||
// Calculate image dimensions with proper sizing logic
|
||||
let imageWidth, imageHeight;
|
||||
|
||||
// Check if custom dimensions are provided and valid
|
||||
const hasValidCustomDimensions =
|
||||
actor.doc.height && actor.doc.height > 10 && actor.doc.width && actor.doc.width > 10;
|
||||
|
||||
if (hasValidCustomDimensions) {
|
||||
if (actor.doc.constraint === 'on') {
|
||||
// Maintain aspect ratio with constraint
|
||||
const customAspectRatio = imageNaturalWidth / imageNaturalHeight;
|
||||
|
||||
if (customAspectRatio > actor.doc.imageAspectRatio) {
|
||||
// Width is the limiting factor
|
||||
imageHeight = actor.doc.height;
|
||||
imageWidth = actor.doc.height * actor.doc.imageAspectRatio;
|
||||
} else {
|
||||
// Height is the limiting factor
|
||||
imageWidth = actor.doc.width;
|
||||
imageHeight = actor.doc.width / actor.doc.imageAspectRatio;
|
||||
}
|
||||
} else {
|
||||
// Use custom dimensions without maintaining aspect ratio
|
||||
imageWidth = actor.doc.width;
|
||||
imageHeight = actor.doc.height;
|
||||
}
|
||||
} else {
|
||||
// Use default sizing based on actor width
|
||||
const defaultImageSize = actor.width / 3.5;
|
||||
|
||||
// Ensure minimum and maximum sizes
|
||||
const minSize = 30;
|
||||
const maxSize = actor.width * 0.8;
|
||||
|
||||
if (actor.doc.imageAspectRatio >= 1) {
|
||||
// Landscape or square image
|
||||
imageWidth = Math.min(Math.max(defaultImageSize, minSize), maxSize);
|
||||
imageHeight = imageWidth / actor.doc.imageAspectRatio;
|
||||
} else {
|
||||
// Portrait image
|
||||
imageHeight = Math.min(Math.max(defaultImageSize, minSize), maxSize);
|
||||
imageWidth = imageHeight * actor.doc.imageAspectRatio;
|
||||
}
|
||||
|
||||
// Ensure the image doesn't exceed actor bounds
|
||||
if (imageWidth > actor.width * 0.9) {
|
||||
imageWidth = actor.width * 0.9;
|
||||
imageHeight = imageWidth / actor.doc.imageAspectRatio;
|
||||
}
|
||||
}
|
||||
|
||||
const actorY = isFooter ? actor.stopy : actor.starty;
|
||||
const center = actor.x + actor.width / 2;
|
||||
const centerY = actorY + imageHeight;
|
||||
|
||||
// Calculate positioning
|
||||
const squareX = center - imageWidth / 2;
|
||||
let squareY;
|
||||
|
||||
if (isFooter) {
|
||||
squareY = actorY + (imageHeight - imageHeight * 1);
|
||||
} else {
|
||||
squareY = actorY + 5;
|
||||
}
|
||||
|
||||
// Calculate text position based on image position and size
|
||||
const textY = !isFooter ? squareY + imageHeight : actorY + imageHeight; // Place text below image for header
|
||||
|
||||
// Draw actor line for non-footer elements
|
||||
const x = center;
|
||||
const y = centerY + (isFooter ? 0 : imageHeight / 2); // Adjust line start based on image height
|
||||
const line = elem.append('g').lower();
|
||||
if (!isFooter) {
|
||||
actorCnt++;
|
||||
line
|
||||
.append('line')
|
||||
.attr('id', 'actor' + actorCnt)
|
||||
.attr('x1', x)
|
||||
.attr('y1', y) // Adjust line start based on image height
|
||||
.attr('x2', center)
|
||||
.attr('y2', 2000)
|
||||
.attr('class', 'actor-line')
|
||||
.attr('stroke-width', '0.5px')
|
||||
.attr('stroke', '#999')
|
||||
.attr('name', actor.name);
|
||||
actor.actorCnt = actorCnt;
|
||||
}
|
||||
|
||||
const actElem = elem.append('g');
|
||||
let cssClass = 'actor-image';
|
||||
if (isFooter) {
|
||||
cssClass += ` ${BOTTOM_ACTOR_CLASS}`;
|
||||
} else {
|
||||
cssClass += ` ${TOP_ACTOR_CLASS}`;
|
||||
}
|
||||
|
||||
actElem.attr('class', cssClass);
|
||||
actElem.attr('name', actor.name);
|
||||
|
||||
// Draw background rectangle for the actor image
|
||||
actElem
|
||||
.append('rect')
|
||||
.attr('x', squareX)
|
||||
.attr('y', squareY)
|
||||
.attr('width', imageWidth)
|
||||
.attr('height', imageHeight)
|
||||
.attr('rx', 3)
|
||||
.attr('ry', 3)
|
||||
.attr('fill', 'white')
|
||||
.attr('stroke', '#ddd')
|
||||
.attr('stroke-width', '1px');
|
||||
|
||||
// Create clipping path for the image
|
||||
const clipId = `clip-actor-${actorCnt || 'footer'}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
actElem
|
||||
.append('defs')
|
||||
.append('clipPath')
|
||||
.attr('id', clipId)
|
||||
.append('rect')
|
||||
.attr('x', squareX)
|
||||
.attr('y', squareY)
|
||||
.attr('width', imageWidth)
|
||||
.attr('height', imageHeight)
|
||||
.attr('rx', 3)
|
||||
.attr('ry', 3);
|
||||
|
||||
// Render image inside the rectangle
|
||||
const imageGroup = actElem.append('g');
|
||||
|
||||
if (actor.doc.image) {
|
||||
imageGroup
|
||||
.append('image')
|
||||
.attr('x', squareX)
|
||||
.attr('y', squareY)
|
||||
.attr('width', imageWidth)
|
||||
.attr('height', imageHeight)
|
||||
.attr('href', img.src)
|
||||
.attr('preserveAspectRatio', actor.doc.constraint === 'on' ? 'xMidYMid meet' : 'none');
|
||||
}
|
||||
|
||||
// Add text label
|
||||
_drawTextCandidateFunc(conf, hasKatex(actor.description))(
|
||||
actor.description,
|
||||
actElem,
|
||||
actor.x,
|
||||
textY,
|
||||
actor.width,
|
||||
20,
|
||||
{ class: 'actor-image-text' },
|
||||
conf
|
||||
);
|
||||
|
||||
// Calculate final bounds and update actor height
|
||||
const bounds = actElem.node().getBBox();
|
||||
actor.height = bounds.height + (conf.sequence?.labelBoxHeight ?? 0);
|
||||
|
||||
return actor.height;
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws an actor in the diagram with the attached line
|
||||
@@ -1122,6 +1374,10 @@ export const drawActor = async function (elem, actor, conf, isFooter) {
|
||||
return await drawActorTypeCollections(elem, actor, conf, isFooter);
|
||||
case 'queue':
|
||||
return await drawActorTypeQueue(elem, actor, conf, isFooter);
|
||||
case 'icon':
|
||||
return await drawActorTypeIcon(elem, actor, conf, isFooter);
|
||||
case 'image':
|
||||
return await drawActorTypeImage(elem, actor, conf, isFooter);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1709,77 +1965,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 {
|
||||
drawRect,
|
||||
drawText,
|
||||
@@ -1802,8 +1987,4 @@ export default {
|
||||
getNoteRect,
|
||||
fixLifeLineHeights,
|
||||
sanitizeUrl,
|
||||
insertSolidTopArrowHead,
|
||||
insertSolidBottomArrowHead,
|
||||
insertStickTopArrowHead,
|
||||
insertStickBottomArrowHead,
|
||||
};
|
||||
|
||||
@@ -17,6 +17,9 @@ export interface Actor {
|
||||
actorCnt: number | null;
|
||||
rectData: unknown;
|
||||
type: string;
|
||||
doc?: ParticipantMetaData; // For documentation
|
||||
iconName?: string; // For icon type
|
||||
imgSrc?: string; // For img type
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
@@ -35,7 +38,6 @@ export interface Message {
|
||||
type?: number;
|
||||
activate?: boolean;
|
||||
placement?: string;
|
||||
centralConnection?: number;
|
||||
}
|
||||
|
||||
export interface AddMessageParams {
|
||||
@@ -51,8 +53,6 @@ export interface AddMessageParams {
|
||||
| 'destroyParticipant'
|
||||
| 'activeStart'
|
||||
| 'activeEnd'
|
||||
| 'centralConnection'
|
||||
| 'centralConnectionReverse'
|
||||
| 'addNote'
|
||||
| 'addLinks'
|
||||
| 'addALink'
|
||||
@@ -93,3 +93,20 @@ export interface Note {
|
||||
message: string;
|
||||
wrap: boolean;
|
||||
}
|
||||
|
||||
export interface ParticipantMetaData {
|
||||
type?:
|
||||
| 'actor'
|
||||
| 'participant'
|
||||
| 'boundary'
|
||||
| 'control'
|
||||
| 'entity'
|
||||
| 'database'
|
||||
| 'collections'
|
||||
| 'queue'
|
||||
| 'icon'
|
||||
| 'img';
|
||||
icon?: string;
|
||||
img?: string;
|
||||
form?: string;
|
||||
}
|
||||
|
||||
@@ -40,26 +40,105 @@ const openSourceFeatures: Feature[] = [
|
||||
{ iconUrl: '/icons/version-history.svg', featureName: 'Version history' },
|
||||
];
|
||||
|
||||
const editorColumns: EditorColumn[] = [
|
||||
{
|
||||
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=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 playgroundFeatures: Feature[] = [
|
||||
{ iconUrl: '/icons/public.svg', featureName: 'Diagram stored in URL' },
|
||||
{ iconUrl: '/icons/terminal.svg', featureName: 'Code editor' },
|
||||
{ iconUrl: '/icons/whiteboard.svg', featureName: 'Whiteboard' },
|
||||
];
|
||||
|
||||
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 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.
|
||||
|
||||
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
|
||||
- fontFamily
|
||||
- logLevel
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user