mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-26 01:14:09 +02:00
Compare commits
201 Commits
mermaid@11
...
saurabh/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0518e9cfd7 | ||
|
|
f43e35039f | ||
|
|
dbf885b077 | ||
|
|
ad2f17205a | ||
|
|
98fe7a6e03 | ||
|
|
5857953d51 | ||
|
|
34a12103d0 | ||
|
|
46b8a75199 | ||
|
|
1dca45a76d | ||
|
|
d1d5bd14f6 | ||
|
|
974867a089 | ||
|
|
52532a7801 | ||
|
|
6eb56b9363 | ||
|
|
f7c91a72cb | ||
|
|
c53e044559 | ||
|
|
d846a8c65a | ||
|
|
c3ba23a4e9 | ||
|
|
c688c387a0 | ||
|
|
300fb85a73 | ||
|
|
9c6e554153 | ||
|
|
b5c78b7225 | ||
|
|
da6361f652 | ||
|
|
167fef5cff | ||
|
|
3233c63fc0 | ||
|
|
1182aaaf4d | ||
|
|
b78c061a8f | ||
|
|
ebfcf3ea07 | ||
|
|
62edea6b33 | ||
|
|
72eda9ce52 | ||
|
|
cfd84e54d5 | ||
|
|
cfe710f42b | ||
|
|
fe6f05eec9 | ||
|
|
548256507d | ||
|
|
d8ebf7a136 | ||
|
|
a758b24b75 | ||
|
|
88abf46fc3 | ||
|
|
2eeba0e999 | ||
|
|
397684fe49 | ||
|
|
bc1f769f13 | ||
|
|
f6592235a2 | ||
|
|
57805dafa4 | ||
|
|
3b92f979e3 | ||
|
|
7a7e4b4e6f | ||
|
|
c5843bee23 | ||
|
|
ada42b892c | ||
|
|
62f9261c4e | ||
|
|
a19b42f3c2 | ||
|
|
9f90f4f23a | ||
|
|
451c886f50 | ||
|
|
0a1a112605 | ||
|
|
348401c4f4 | ||
|
|
8145199203 | ||
|
|
f408e938d4 | ||
|
|
af6e2b4cb6 | ||
|
|
7a4a52b50a | ||
|
|
ee05d8588f | ||
|
|
58175f647e | ||
|
|
6ca8f46d37 | ||
|
|
b2dfbb6ffd | ||
|
|
ffa7804af0 | ||
|
|
f454865b97 | ||
|
|
d83b1a5dbc | ||
|
|
d07f85e6ac | ||
|
|
a79c0f4c00 | ||
|
|
4a19740aea | ||
|
|
4dbaa2b5d6 | ||
|
|
9cad3c7aea | ||
|
|
56d66cdabc | ||
|
|
a0e5408850 | ||
|
|
d155e414a0 | ||
|
|
8dd0e7a794 | ||
|
|
5e9c887385 | ||
|
|
fdb8ae5b53 | ||
|
|
e2de55202f | ||
|
|
b4043840ca | ||
|
|
8f3e17e386 | ||
|
|
4e950e7256 | ||
|
|
de3e381ccf | ||
|
|
b2fde76753 | ||
|
|
b5587d8b87 | ||
|
|
9b75aeb224 | ||
|
|
993858cdc8 | ||
|
|
f4e1f07412 | ||
|
|
09e0de6053 | ||
|
|
9a50bf5237 | ||
|
|
5747009c8f | ||
|
|
dc513ec211 | ||
|
|
5f58d4f7b0 | ||
|
|
3536ceb5d3 | ||
|
|
7ed33a91c0 | ||
|
|
f8bf03d365 | ||
|
|
4202ee521a | ||
|
|
0e25fd42f9 | ||
|
|
feee5d1c8c | ||
|
|
ab6d92c544 | ||
|
|
d27d4abab7 | ||
|
|
3162cff7a9 | ||
|
|
9681a27b31 | ||
|
|
ba534985ec | ||
|
|
edc1ae1e0c | ||
|
|
c00f3fb090 | ||
|
|
74a56fc58a | ||
|
|
08ffbb61e9 | ||
|
|
232e60c8cb | ||
|
|
cd9ca76e39 | ||
|
|
c13d988392 | ||
|
|
15ffe2021a | ||
|
|
4fbc19e0d7 | ||
|
|
2b8998fdd1 | ||
|
|
202ef31071 | ||
|
|
b09f2e836a | ||
|
|
6a814a0d91 | ||
|
|
b07bb9b3ff | ||
|
|
5120ed09ab | ||
|
|
61f3fc5ede | ||
|
|
90bbf90a83 | ||
|
|
92efc24283 | ||
|
|
1c45df4567 | ||
|
|
1575a93136 | ||
|
|
bde653b1c2 | ||
|
|
e9e663ffa3 | ||
|
|
963efa64c7 | ||
|
|
e2e5101005 | ||
|
|
6ea13cded3 | ||
|
|
c063b92cc9 | ||
|
|
304f133227 | ||
|
|
54a0dd0af6 | ||
|
|
ab5b7694c6 | ||
|
|
eb76dfb1ca | ||
|
|
28d7ec092c | ||
|
|
84b03f3a08 | ||
|
|
f9ac9867c1 | ||
|
|
ee6fb83265 | ||
|
|
46c16c963b | ||
|
|
32a68d489e | ||
|
|
7bbebff583 | ||
|
|
c432aec2f6 | ||
|
|
64237fbaa7 | ||
|
|
7ba415dad1 | ||
|
|
7f47678862 | ||
|
|
127bac1147 | ||
|
|
9a90d795ca | ||
|
|
f7fe8f2f59 | ||
|
|
1d9c2aab8d | ||
|
|
8fba9c1236 | ||
|
|
04800ff677 | ||
|
|
5d3d1047a4 | ||
|
|
0f08c3bc9c | ||
|
|
7809b5a93f | ||
|
|
ef9bb53e67 | ||
|
|
3e32332814 | ||
|
|
e1aab25144 | ||
|
|
c8697301ee | ||
|
|
fcb1de915b | ||
|
|
e345294658 | ||
|
|
9936099e25 | ||
|
|
59352ad4d8 | ||
|
|
ba70f15de5 | ||
|
|
e70b069576 | ||
|
|
28bab4a323 | ||
|
|
6cc31b7453 | ||
|
|
29ca1504dd | ||
|
|
16d2251e43 | ||
|
|
bc2cc61240 | ||
|
|
6836e9c7a8 | ||
|
|
8dc016e7f9 | ||
|
|
3cad7984a3 | ||
|
|
f5bae98098 | ||
|
|
0695893e30 | ||
|
|
9ef6090c8c | ||
|
|
ec0d9c389a | ||
|
|
323b07a2e4 | ||
|
|
c153d0455f | ||
|
|
9b00f1f2fb | ||
|
|
a055ff7db3 | ||
|
|
d032723a47 | ||
|
|
daf83f596d | ||
|
|
df636c6d0a | ||
|
|
64554a6c60 | ||
|
|
becadf0a7d | ||
|
|
54d485f173 | ||
|
|
b4f5b8ddaf | ||
|
|
cb5c1ae367 | ||
|
|
b29081d4e8 | ||
|
|
654097c438 | ||
|
|
1e672868c4 | ||
|
|
bff32827b5 | ||
|
|
65f9b29b86 | ||
|
|
b4879d13b8 | ||
|
|
95964b5487 | ||
|
|
4e17da0a30 | ||
|
|
2a91849a38 | ||
|
|
082de76eef | ||
|
|
570ae78b15 | ||
|
|
885ac6f947 | ||
|
|
193fdb225e | ||
|
|
7cbd80af33 | ||
|
|
16c448b89b | ||
|
|
cb0a4703bd | ||
|
|
8cb1c68166 | ||
|
|
d752240efc |
5
.changeset/angry-bags-brake.md
Normal file
5
.changeset/angry-bags-brake.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: architecture diagrams no longer grow to extreme heights due to conflicting alignments
|
||||
5
.changeset/bright-ads-exist.md
Normal file
5
.changeset/bright-ads-exist.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
Fixes for consistent edge id creation & handling edge cases for animate edge feature
|
||||
5
.changeset/chatty-elephants-warn.md
Normal file
5
.changeset/chatty-elephants-warn.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
Fix for issue #6195 - allowing @ signs inside node labels
|
||||
5
.changeset/chilly-years-cheat.md
Normal file
5
.changeset/chilly-years-cheat.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each class diagram
|
||||
5
.changeset/dull-tips-cough.md
Normal file
5
.changeset/dull-tips-cough.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: revert state db to resolve getData returning empty nodes and edges
|
||||
8
.changeset/great-ghosts-rule.md
Normal file
8
.changeset/great-ghosts-rule.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
---
|
||||
|
||||
Flowchart new syntax for node metadata bugs
|
||||
|
||||
- Incorrect label mapping for nodes when using `&`
|
||||
- Syntax error when `}` with trailing spaces before new line
|
||||
5
.changeset/grumpy-cheetahs-deliver.md
Normal file
5
.changeset/grumpy-cheetahs-deliver.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
`mermaidAPI.getDiagramFromText()` now returns a new db instance on each call for state diagrams
|
||||
5
.changeset/heavy-moose-mix.md
Normal file
5
.changeset/heavy-moose-mix.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
Added versioning to StateDB and updated tests and diagrams to use it.
|
||||
5
.changeset/many-brooms-promise.md
Normal file
5
.changeset/many-brooms-promise.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
---
|
||||
|
||||
Adding support for animation of flowchart edges
|
||||
5
.changeset/new-kiwis-listen.md
Normal file
5
.changeset/new-kiwis-listen.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each flowchart
|
||||
5
.changeset/silver-olives-marry.md
Normal file
5
.changeset/silver-olives-marry.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each sequence diagram. Added unique IDs for messages.
|
||||
5
.changeset/stupid-dots-do.md
Normal file
5
.changeset/stupid-dots-do.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Gantt, Sankey and User Journey diagram are now able to pick font-family from mermaid config.
|
||||
5
.changeset/weak-trees-perform.md
Normal file
5
.changeset/weak-trees-perform.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: `getDirection` and `setDirection` in `stateDb` refactored to return and set actual direction
|
||||
5
.changeset/witty-crews-smell.md
Normal file
5
.changeset/witty-crews-smell.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
`mermaidAPI.getDiagramFromText()` now returns a new different db for each state diagram
|
||||
@@ -26,6 +26,7 @@ dompurify
|
||||
elkjs
|
||||
fcose
|
||||
fontawesome
|
||||
Forgejo
|
||||
Foswiki
|
||||
Gitea
|
||||
graphlib
|
||||
|
||||
5
.github/lychee.toml
vendored
5
.github/lychee.toml
vendored
@@ -47,7 +47,10 @@ exclude = [
|
||||
"https://(www.)?drupal.org",
|
||||
|
||||
# Swimm returns 404, eventhough the link is valid
|
||||
"https://docs.swimm.io"
|
||||
"https://docs.swimm.io",
|
||||
|
||||
# Timeout
|
||||
"https://huehive.co"
|
||||
]
|
||||
|
||||
# Exclude all private IPs from checking.
|
||||
|
||||
2
.github/workflows/autofix.yml
vendored
2
.github/workflows/autofix.yml
vendored
@@ -42,4 +42,4 @@ jobs:
|
||||
working-directory: ./packages/mermaid
|
||||
run: pnpm run docs:build
|
||||
|
||||
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c # main
|
||||
- uses: autofix-ci/action@551dded8c6cc8a1054039c8bc0b8b48c51dfc6ef # main
|
||||
|
||||
6
.github/workflows/codeql.yml
vendored
6
.github/workflows/codeql.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
|
||||
uses: github/codeql-action/init@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
|
||||
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@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
|
||||
uses: github/codeql-action/autobuild@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
|
||||
|
||||
# ℹ️ 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@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
|
||||
uses: github/codeql-action/analyze@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
|
||||
|
||||
2
.github/workflows/dependency-review.yml
vendored
2
.github/workflows/dependency-review.yml
vendored
@@ -17,4 +17,4 @@ jobs:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4
|
||||
uses: actions/dependency-review-action@a6993e2c61fd5dc440b409aa1d6904921c5e1894 # v4.3.5
|
||||
|
||||
4
.github/workflows/e2e-timings.yml
vendored
4
.github/workflows/e2e-timings.yml
vendored
@@ -26,11 +26,11 @@ jobs:
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
- name: Install dependencies
|
||||
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
|
||||
uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8
|
||||
with:
|
||||
runTests: false
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
|
||||
uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8
|
||||
id: cypress
|
||||
with:
|
||||
install: false
|
||||
|
||||
26
.github/workflows/e2e.yml
vendored
26
.github/workflows/e2e.yml
vendored
@@ -28,6 +28,8 @@ env:
|
||||
) ||
|
||||
github.event.before
|
||||
}}
|
||||
RUN_VISUAL_TEST: >-
|
||||
${{ github.repository == 'mermaid-js/mermaid' && (github.event_name != 'pull_request' || !startsWith(github.head_ref, 'renovate/')) }}
|
||||
jobs:
|
||||
cache:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -43,9 +45,8 @@ jobs:
|
||||
node-version-file: '.node-version'
|
||||
- name: Cache snapshots
|
||||
id: cache-snapshot
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||
with:
|
||||
save-always: true
|
||||
path: ./cypress/snapshots
|
||||
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
|
||||
|
||||
@@ -58,7 +59,7 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
|
||||
uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8
|
||||
with:
|
||||
# just perform install
|
||||
runTests: false
|
||||
@@ -94,13 +95,13 @@ jobs:
|
||||
# These cached snapshots are downloaded, providing the reference snapshots.
|
||||
- name: Cache snapshots
|
||||
id: cache-snapshot
|
||||
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
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@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
|
||||
uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8
|
||||
with:
|
||||
runTests: false
|
||||
|
||||
@@ -116,7 +117,7 @@ jobs:
|
||||
# Install NPM dependencies, cache them correctly
|
||||
# and run all Cypress tests
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
|
||||
uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8
|
||||
id: cypress
|
||||
with:
|
||||
install: false
|
||||
@@ -125,18 +126,17 @@ jobs:
|
||||
browser: chrome
|
||||
# Disable recording if we don't have an API key
|
||||
# e.g. if this action was run from a fork
|
||||
record: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
||||
record: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY != '' }}
|
||||
env:
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
VITEST_COVERAGE: true
|
||||
ARGOS_PARALLEL: ${{ env.RUN_VISUAL_TEST == 'true' }}
|
||||
ARGOS_PARALLEL_TOTAL: ${{ env.RUN_VISUAL_TEST == 'true' && strategy.job-total || 1 }}
|
||||
ARGOS_PARALLEL_INDEX: ${{ env.RUN_VISUAL_TEST == 'true' && matrix.containers || 1 }}
|
||||
CYPRESS_COMMIT: ${{ github.sha }}
|
||||
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
|
||||
ARGOS_PARALLEL: true
|
||||
ARGOS_PARALLEL_TOTAL: ${{ strategy.job-total }}
|
||||
ARGOS_PARALLEL_INDEX: ${{ matrix.containers }}
|
||||
CYPRESS_RECORD_KEY: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY || ''}}
|
||||
SPLIT: ${{ strategy.job-total }}
|
||||
SPLIT_INDEX: ${{ strategy.job-index }}
|
||||
SPLIT_FILE: 'cypress/timings.json'
|
||||
VITEST_COVERAGE: true
|
||||
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
|
||||
|
||||
2
.github/workflows/link-checker.yml
vendored
2
.github/workflows/link-checker.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
|
||||
- name: Restore lychee cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||
with:
|
||||
path: .lycheecache
|
||||
key: cache-lychee-${{ github.sha }}
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
- name: Create Release Pull Request or Publish to npm
|
||||
id: changesets
|
||||
uses: changesets/action@3de3850952bec538fde60aac71731376e57b9b57 # v1.4.8
|
||||
uses: changesets/action@c8bada60c408975afd1a20b3db81d6eee6789308 # v1.4.9
|
||||
with:
|
||||
version: pnpm changeset:version
|
||||
publish: pnpm changeset:publish
|
||||
|
||||
4
.github/workflows/scorecard.yml
vendored
4
.github/workflows/scorecard.yml
vendored
@@ -26,12 +26,12 @@ jobs:
|
||||
results_format: sarif
|
||||
publish_results: true
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
- name: Upload to code-scanning
|
||||
uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
|
||||
uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
34
README.md
34
README.md
@@ -95,6 +95,10 @@ In our release process we rely heavily on visual regression tests using [applito
|
||||
|
||||
<!-- </Main description> -->
|
||||
|
||||
## Mermaid AI Bot
|
||||
|
||||
[Mermaid](https://codeparrot.ai/oracle?owner=mermaid-js&repo=mermaid) Bot will help you understand this repository better. You can ask for code examples, installation guide, debugging help and much more.
|
||||
|
||||
## Examples
|
||||
|
||||
**The following are some examples of the diagrams, charts and graphs that can be made using Mermaid. Click here to jump into the [text syntax](https://mermaid.js.org/intro/syntax-reference.html).**
|
||||
@@ -253,6 +257,34 @@ pie
|
||||
|
||||
### Git graph [experimental - <a href="https://mermaid.live/edit#pako:eNqNkMFugzAMhl8F-VyVAR1tOW_aA-zKxSSGRCMJCk6lCvHuNZPKZdM0n-zf3_8r8QIqaIIGMqnB8kfEybQ--y4VnLP8-9RF9Mpkmm40hmlnDKmvkPiH_kfS7nFo_VN0FAf6XwocQGgxa_nGsm1bYEOOWmik1dRjGrmF1q-Cpkkj07u2HCI0PY4zHQATh8-7V9BwTPSE3iwOEd1OjQE1iWkBvk_bzQY7s0Sq4Hs7bHqKo8iGeZqbPN_WR7mpSd1RHpvPVhuMbG7XOq_L-oJlRfW5wteq0qorrpe-PBW9Pr8UJcK6rg-BLYPQ">live editor</a>]
|
||||
|
||||
```
|
||||
gitGraph
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
```
|
||||
|
||||
```mermaid
|
||||
gitGraph
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
```
|
||||
|
||||
### Bar chart (using gantt chart) [<a href="https://mermaid.js.org/syntax/gantt.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNptkU1vhCAQhv8KIenNugiI4rkf6bmXpvEyFVxJFDYyNt1u9r8X63Z7WQ9m5pknLzieaBeMpQ3dg0dsPUkPOhwteXZIXmJcbCT3xMAxkuh8Z8kIEclyMIB209fqKcwTICFvG4IvFy_oLrZ-g9F26ILfQgvNFN94VaRXQ1iWqpumZBcu1J8p1E1TXDx59eQNr5LyEqjJn6hv5QnGNlxevZJmdLLpy5xJSzut45biYCfb0iaVxvawjNjS1p-TCguG16PvaIPzYjO67e3BwX6GiTY9jPFKH43DMF_hGMDY1J4oHg-_f8hFTJFd8L3br3yZx4QHxENsdrt1nO8dDstH3oVpF50ZYMbhU6ud4qoGLqyqBJRCmO6j0HXPZdGbihUc6Pmc0QP49xD-b5X69ZQv2gjO81IwzWqhC1lKrjJ6pA3nVS7SMiVjrKirWlYp5fs3osgrWeo00lorLWvOzz8JVbXm">live editor</a>]
|
||||
|
||||
```
|
||||
@@ -435,7 +467,7 @@ A quick note from Knut Sveidqvist:
|
||||
>
|
||||
> _Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017._
|
||||
>
|
||||
> _Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!_
|
||||
> _Thank you to the ever-growing list of [contributors](https://github.com/mermaid-js/mermaid/graphs/contributors) that brought the project this far!_
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -358,7 +358,7 @@ _很不幸的是,鱼与熊掌不可兼得,在这个场景下它意味着在
|
||||
|
||||
> _特别感谢 [d3](https://d3js.org/) 和 [dagre-d3](https://github.com/cpettitt/dagre-d3) 这两个优秀的项目,它们提供了图形布局和绘图工具库!_ > _同样感谢 [js-sequence-diagram](https://bramp.github.io/js-sequence-diagrams) 提供了时序图语法的使用。 感谢 Jessica Peter 提供了甘特图渲染的灵感。_ > _感谢 [Tyler Long](https://github.com/tylerlong) 从 2017 年四月开始成为了项目的合作者。_
|
||||
>
|
||||
> _感谢越来越多的 [贡献者们](https://github.com/knsv/mermaid/graphs/contributors),没有你们,就没有这个项目的今天!_
|
||||
> _感谢越来越多的 [贡献者们](https://github.com/mermaid-js/mermaid/graphs/contributors),没有你们,就没有这个项目的今天!_
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -23,12 +23,10 @@ export default eyesPlugin(
|
||||
});
|
||||
// copy any needed variables from process.env to config.env
|
||||
config.env.useAppli = process.env.USE_APPLI ? true : false;
|
||||
config.env.useArgos = !!process.env.CI;
|
||||
config.env.useArgos = process.env.RUN_VISUAL_TEST === 'true';
|
||||
|
||||
if (config.env.useArgos) {
|
||||
registerArgosTask(on, config, {
|
||||
token: 'fc3a35cf5200db928d65b2047861582d9444032b',
|
||||
});
|
||||
registerArgosTask(on, config);
|
||||
} else {
|
||||
addMatchImageSnapshotPlugin(on, config);
|
||||
}
|
||||
|
||||
@@ -132,3 +132,10 @@ export const verifyScreenshot = (name: string): void => {
|
||||
cy.matchImageSnapshot(name);
|
||||
}
|
||||
};
|
||||
|
||||
export const verifyNumber = (value: number, expected: number, deltaPercent = 10): void => {
|
||||
expect(value).to.be.within(
|
||||
expected * (1 - deltaPercent / 100),
|
||||
expected * (1 + deltaPercent / 100)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -171,6 +171,58 @@ describe.skip('architecture diagram', () => {
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('should render an architecture diagram with a resonable height', () => {
|
||||
imgSnapshotTest(
|
||||
`architecture-beta
|
||||
group federated(cloud)[Federated Environment]
|
||||
service server1(server)[System] in federated
|
||||
service edge(server)[Edge Device] in federated
|
||||
server1:R -- L:edge
|
||||
|
||||
group on_prem(cloud)[Hub]
|
||||
service firewall(server)[Firewall Device] in on_prem
|
||||
service server(server)[Server] in on_prem
|
||||
firewall:R -- L:server
|
||||
|
||||
service db1(database)[db1] in on_prem
|
||||
service db2(database)[db2] in on_prem
|
||||
service db3(database)[db3] in on_prem
|
||||
service db4(database)[db4] in on_prem
|
||||
service db5(database)[db5] in on_prem
|
||||
service db6(database)[db6] in on_prem
|
||||
|
||||
junction mid in on_prem
|
||||
server:B -- T:mid
|
||||
|
||||
junction 1Leftofmid in on_prem
|
||||
1Leftofmid:R -- L:mid
|
||||
1Leftofmid:B -- T:db1
|
||||
|
||||
junction 2Leftofmid in on_prem
|
||||
2Leftofmid:R -- L:1Leftofmid
|
||||
2Leftofmid:B -- T:db2
|
||||
|
||||
junction 3Leftofmid in on_prem
|
||||
3Leftofmid:R -- L:2Leftofmid
|
||||
3Leftofmid:B -- T:db3
|
||||
|
||||
junction 1RightOfMid in on_prem
|
||||
mid:R -- L:1RightOfMid
|
||||
1RightOfMid:B -- T:db4
|
||||
|
||||
junction 2RightOfMid in on_prem
|
||||
1RightOfMid:R -- L:2RightOfMid
|
||||
2RightOfMid:B -- T:db5
|
||||
|
||||
junction 3RightOfMid in on_prem
|
||||
2RightOfMid:R -- L:3RightOfMid
|
||||
3RightOfMid:B -- T:db6
|
||||
|
||||
edge:R -- L:firewall
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Skipped as the layout is not deterministic, and causes issues in E2E tests.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
import { imgSnapshotTest, renderGraph, verifyNumber } from '../../helpers/util.ts';
|
||||
|
||||
describe('Flowchart ELK', () => {
|
||||
it('1-elk: should render a simple flowchart', () => {
|
||||
@@ -109,7 +109,7 @@ describe('Flowchart ELK', () => {
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
expect(maxWidthValue).to.be.within(230 * 0.95, 230 * 1.05);
|
||||
verifyNumber(maxWidthValue, 380);
|
||||
});
|
||||
});
|
||||
it('8-elk: should render a flowchart when useMaxWidth is false', () => {
|
||||
@@ -128,7 +128,7 @@ describe('Flowchart ELK', () => {
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
expect(width).to.be.within(230 * 0.95, 230 * 1.05);
|
||||
verifyNumber(width, 380);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
@@ -692,7 +692,7 @@ A --> B
|
||||
{}
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const edges = svg.querySelectorAll('.edges > path');
|
||||
const edges = svg[0].querySelectorAll('.edges > path');
|
||||
edges.forEach((edge) => {
|
||||
expect(edge).to.have.class('flowchart-link');
|
||||
});
|
||||
@@ -739,7 +739,7 @@ NL\`") --"\`1o **bold**\`"--> c
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('Wrapping long text with a new line', () => {
|
||||
it.skip('Wrapping long text with a new line', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
|
||||
flowchart-elk LR
|
||||
@@ -841,7 +841,7 @@ end
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('Sub graphs and markdown strings', () => {
|
||||
it('Sub graphs', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
@@ -900,6 +900,153 @@ flowchart LR
|
||||
n7@{ shape: rect}
|
||||
n8@{ shape: rect}
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('6088-1: should handle diamond shape intersections', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
subgraph S2
|
||||
subgraph s1["APA"]
|
||||
D{"Use the editor"}
|
||||
end
|
||||
|
||||
|
||||
D -- Mermaid js --> I{"fa:fa-code Text"}
|
||||
D --> I
|
||||
D --> I
|
||||
|
||||
end
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('6088-2: should handle diamond shape intersections', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
a
|
||||
subgraph s0["APA"]
|
||||
subgraph s8["APA"]
|
||||
subgraph s1["APA"]
|
||||
D{"X"}
|
||||
E[Q]
|
||||
end
|
||||
subgraph s3["BAPA"]
|
||||
F[Q]
|
||||
I
|
||||
end
|
||||
D --> I
|
||||
D --> I
|
||||
D --> I
|
||||
|
||||
I{"X"}
|
||||
end
|
||||
end
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('6088-3: should handle diamond shape intersections', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
a
|
||||
D{"Use the editor"}
|
||||
|
||||
D -- Mermaid js --> I{"fa:fa-code Text"}
|
||||
D-->I
|
||||
D-->I
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('6088-4: should handle diamond shape intersections', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
subgraph s1["Untitled subgraph"]
|
||||
n1["Evaluate"]
|
||||
n2["Option 1"]
|
||||
n3["Option 2"]
|
||||
n4["fa:fa-car Option 3"]
|
||||
end
|
||||
subgraph s2["Untitled subgraph"]
|
||||
n5["Evaluate"]
|
||||
n6["Option 1"]
|
||||
n7["Option 2"]
|
||||
n8["fa:fa-car Option 3"]
|
||||
end
|
||||
A["Start"] -- Some text --> B("Continue")
|
||||
B --> C{"Evaluate"}
|
||||
C -- One --> D["Option 1"]
|
||||
C -- Two --> E["Option 2"]
|
||||
C -- Three --> F["fa:fa-car Option 3"]
|
||||
n1 -- One --> n2
|
||||
n1 -- Two --> n3
|
||||
n1 -- Three --> n4
|
||||
n5 -- One --> n6
|
||||
n5 -- Two --> n7
|
||||
n5 -- Three --> n8
|
||||
n1@{ shape: diam}
|
||||
n2@{ shape: rect}
|
||||
n3@{ shape: rect}
|
||||
n4@{ shape: rect}
|
||||
n5@{ shape: diam}
|
||||
n6@{ shape: rect}
|
||||
n7@{ shape: rect}
|
||||
n8@{ shape: rect}
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('6088-5: should handle diamond shape intersections', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
A{A} --> B & C
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('6088-6: should handle diamond shape intersections', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
A{A} --> B & C
|
||||
subgraph "subbe"
|
||||
A
|
||||
end
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
|
||||
@@ -1076,4 +1076,41 @@ end
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('New @ sytax for node metadata edge cases', () => {
|
||||
it('should be possible to use @ syntax to add labels on multi nodes', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TB
|
||||
n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should be possible to use @ syntax to add labels with trail spaces and &', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TB
|
||||
n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should be possible to use @ syntax to add labels with trail spaces', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TB
|
||||
n2["label for n2"]
|
||||
n4@{ label: "labe for n4"}
|
||||
n5@{ label: "labe for n5"}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should be possible to use @ syntax to add labels with trail spaces and edge/link', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TD
|
||||
A["A"] --> B["for B"] & C@{ label: "for c"} & E@{label : "for E"}
|
||||
D@{label: "for D"}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
@@ -78,45 +78,116 @@
|
||||
font-family: monospace;
|
||||
font-size: 72px;
|
||||
}
|
||||
|
||||
pre {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* tspan {
|
||||
font-size: 6px !important;
|
||||
} */
|
||||
/* .flowchart-link {
|
||||
stroke-dasharray: 4, 4 !important;
|
||||
animation: flow 1s linear infinite;
|
||||
animation: dashdraw 4.93282s linear infinite;
|
||||
stroke-width: 2px !important;
|
||||
} */
|
||||
|
||||
@keyframes dashdraw {
|
||||
from {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*stroke-width:2;stroke-dasharray:10.000000,9.865639;stroke-dashoffset:-198.656393;animation: 4.932820s linear infinite;*/
|
||||
/* stroke-width:2;stroke-dasharray:10.000000,9.865639;stroke-dashoffset:-198.656393;animation: dashdraw 4.932820s linear infinite;*/
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
AB["apa@apa@"] --> B(("`apa@apa`"))
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart
|
||||
D(("for D"))
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
A e1@==> B
|
||||
e1@{ animate: true}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
A e1@--> B
|
||||
classDef animate stroke-width:2,stroke-dasharray:10\,8,stroke-dashoffset:-180,animation: edge-animation-frame 6s linear infinite, stroke-linecap: round
|
||||
class e1 animate
|
||||
</pre>
|
||||
<h2>infinite</h2>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
A e1@--> B
|
||||
classDef animate stroke-dasharray: 9\,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||
class e1 animate
|
||||
</pre>
|
||||
<h2>Mermaid - edge-animation-slow</h2>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
A e1@--> B
|
||||
e1@{ animation: fast}
|
||||
</pre>
|
||||
<h2>Mermaid - edge-animation-fast</h2>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
A e1@--> B
|
||||
classDef animate stroke-dasharray: 1000,stroke-dashoffset: 1000,animation: dash 10s linear;
|
||||
class e1 edge-animation-fast
|
||||
</pre>
|
||||
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
|
||||
info </pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
subgraph s1["Untitled subgraph"]
|
||||
n1["Evaluate"]
|
||||
n2["Option 1"]
|
||||
n3["Option 2"]
|
||||
n4["fa:fa-car Option 3"]
|
||||
end
|
||||
n1 -- One --> n2
|
||||
n1 -- Two --> n3
|
||||
n1 -- Three --> n4
|
||||
n5
|
||||
n1@{ shape: diam}
|
||||
n2@{ shape: rect}
|
||||
n3@{ shape: rect}
|
||||
n4@{ shape: rect}
|
||||
A["Start"] -- Some text --> B("Continue")
|
||||
B --> C{"Evaluate"}
|
||||
C -- One --> D["Option 1"]
|
||||
C -- Two --> E["Option 2"]
|
||||
C -- Three --> F["fa:fa-car Option 3"]
|
||||
|
||||
flowchart LR
|
||||
a
|
||||
subgraph s0["APA"]
|
||||
subgraph s8["APA"]
|
||||
subgraph s1["APA"]
|
||||
D{"X"}
|
||||
E[Q]
|
||||
end
|
||||
subgraph s3["BAPA"]
|
||||
F[Q]
|
||||
I
|
||||
end
|
||||
D --> I
|
||||
D --> I
|
||||
D --> I
|
||||
|
||||
I{"X"}
|
||||
end
|
||||
end
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
a
|
||||
D{"Use the editor"}
|
||||
|
||||
D -- Mermaid js --> I{"fa:fa-code Text"}
|
||||
D-->I
|
||||
D-->I
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -185,6 +256,18 @@ flowchart LR
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
A{A} --> B & C
|
||||
subgraph "subbe"
|
||||
A
|
||||
end
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
n2@{ shape: rect}
|
||||
n3@{ shape: rect}
|
||||
@@ -351,7 +434,10 @@ kanban
|
||||
window.callback = function () {
|
||||
alert('A callback was triggered');
|
||||
};
|
||||
mermaid.initialize({
|
||||
function callback() {
|
||||
alert('It worked');
|
||||
}
|
||||
await mermaid.initialize({
|
||||
// theme: 'base',
|
||||
// theme: 'default',
|
||||
// theme: 'forest',
|
||||
@@ -363,9 +449,11 @@ kanban
|
||||
// layout: 'fixed',
|
||||
// htmlLabels: false,
|
||||
flowchart: { titleTopMargin: 10 },
|
||||
|
||||
// fontFamily: 'Caveat',
|
||||
// fontFamily: 'Kalam',
|
||||
// fontFamily: 'courier',
|
||||
fontFamily: 'arial',
|
||||
sequence: {
|
||||
actorFontFamily: 'courier',
|
||||
noteFontFamily: 'courier',
|
||||
@@ -377,10 +465,9 @@ kanban
|
||||
fontSize: 12,
|
||||
logLevel: 0,
|
||||
securityLevel: 'loose',
|
||||
callback,
|
||||
});
|
||||
function callback() {
|
||||
alert('It worked');
|
||||
}
|
||||
|
||||
mermaid.parseError = function (err, hash) {
|
||||
console.error('In parse error:');
|
||||
console.error(err);
|
||||
|
||||
@@ -62,56 +62,23 @@
|
||||
|
||||
<body style="display: flex; gap: 2rem; flex-direction: row">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
A@{ icon: "fa:window-minimize", form: circle }
|
||||
E@{ icon: "fa:window-minimize", form: circle }
|
||||
B@{ icon: "fa:bell", form: circle }
|
||||
B2@{ icon: "fa:bell", form: circle }
|
||||
C@{ icon: "fa:address-book", form: square }
|
||||
D@{ icon: "fa:star-half", form: square }
|
||||
A --> E
|
||||
B --> B2
|
||||
|
||||
flowchart
|
||||
A --> A
|
||||
subgraph B
|
||||
B1 --> B1
|
||||
end
|
||||
subgraph C
|
||||
subgraph C1
|
||||
C2 --> C2
|
||||
subgraph D
|
||||
D1 --> D1
|
||||
end
|
||||
D --> D
|
||||
end
|
||||
C1 --> C1
|
||||
end
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart TB
|
||||
A --test2--> B2@{ icon: "fa:bell", form: "rounded", label: "B2 aiduaid uyawduad uaduabd uyduadb", pos: "b" }
|
||||
B2 --test--> C
|
||||
D --> B2 --> E
|
||||
style B2 fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram43" class="mermaid2">
|
||||
flowchart BT
|
||||
A --test2--> B2@{ icon: "fa:bell", form: "square", label: "B2", pos: "t", h: 40, w: 30 }
|
||||
B2 --test--> C
|
||||
D --> B2 --> E
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart BT
|
||||
A --test2--> B2@{ icon: "fa:bell", label: "B2 awiugdawu uydgayuiwd wuydguy", pos: "b", h: 40, w: 30 }
|
||||
B2 --test--> C
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram43" class="mermaid2">
|
||||
flowchart BT
|
||||
A --test2--> B2@{ icon: "fa:bell", label: "B2 dawuygd ayuwgd uy", pos: "t", h: 40, w: 30 }
|
||||
B2 --test--> C
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram6" class="mermaid2">
|
||||
flowchart TB
|
||||
A --> B2@{ icon: "fa:bell", form: "circle", label: "test augfuyfavf ydvaubfuac", pos: "t", w: 200, h: 100 } --> C
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram6" class="mermaid2">
|
||||
flowchart TB
|
||||
A --> B2@{ icon: "fa:bell", form: "circle", label: "test augfuyfavf ydvaubfuac", pos: "b", w: 200, h: 100 } --> C
|
||||
D --> B2 --> E
|
||||
</pre
|
||||
>
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
import layouts from './mermaid-layout-elk.esm.mjs';
|
||||
|
||||
@@ -39,8 +39,8 @@ graph TB
|
||||
|
||||
<script type="module">
|
||||
import mermaid from '/mermaid.esm.mjs';
|
||||
import flowchartELK from '/mermaid-flowchart-elk.esm.mjs';
|
||||
await mermaid.registerExternalDiagrams([flowchartELK]);
|
||||
import layouts from '/mermaid-layout-elk.esm.mjs';
|
||||
mermaid.registerLayoutLoaders(layouts);
|
||||
async function render(str) {
|
||||
const { svg } = await mermaid.render('dynamic', str);
|
||||
document.getElementById('dynamicDiagram').innerHTML = svg;
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
1. [How to add title to flowchart?](https://github.com/knsv/mermaid/issues/556#issuecomment-363182217)
|
||||
1. [How to add title to flowchart?](https://github.com/mermaid-js/mermaid/issues/556#issuecomment-363182217)
|
||||
2. [How to specify custom CSS file?](https://github.com/mermaidjs/mermaid.cli/pull/24#issuecomment-373402785)
|
||||
3. [How to fix tooltip misplacement issue?](https://github.com/knsv/mermaid/issues/542#issuecomment-3343564621)
|
||||
4. [How to specify gantt diagram xAxis format?](https://github.com/knsv/mermaid/issues/269#issuecomment-373229136)
|
||||
5. [How to bind an event?](https://github.com/knsv/mermaid/issues/372)
|
||||
6. [How to add newline in the text?](https://github.com/knsv/mermaid/issues/384#issuecomment-281339381)
|
||||
7. [How to have special characters in link text?](https://github.com/knsv/mermaid/issues/407#issuecomment-329944735)
|
||||
8. [How to change Flowchart curve style?](https://github.com/knsv/mermaid/issues/580#issuecomment-373929046)
|
||||
3. [How to fix tooltip misplacement issue?](https://github.com/mermaid-js/mermaid/issues/542#issuecomment-3343564621)
|
||||
4. [How to specify gantt diagram xAxis format?](https://github.com/mermaid-js/mermaid/issues/269#issuecomment-373229136)
|
||||
5. [How to bind an event?](https://github.com/mermaid-js/mermaid/issues/372)
|
||||
6. [How to add newline in the text?](https://github.com/mermaid-js/mermaid/issues/384#issuecomment-281339381)
|
||||
7. [How to have special characters in link text?](https://github.com/mermaid-js/mermaid/issues/407#issuecomment-329944735)
|
||||
8. [How to change Flowchart curve style?](https://github.com/mermaid-js/mermaid/issues/580#issuecomment-373929046)
|
||||
9. [How to create a Flowchart end-Node that says "End"](https://github.com/mermaid-js/mermaid/issues/1444#issuecomment-639528897)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/rendering-util/types.ts:144](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L144)
|
||||
[packages/mermaid/src/rendering-util/types.ts:148](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L148)
|
||||
|
||||
---
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/rendering-util/types.ts:143](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L143)
|
||||
[packages/mermaid/src/rendering-util/types.ts:147](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L147)
|
||||
|
||||
---
|
||||
|
||||
@@ -40,4 +40,4 @@
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/rendering-util/types.ts:142](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L142)
|
||||
[packages/mermaid/src/rendering-util/types.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L146)
|
||||
|
||||
@@ -19,4 +19,4 @@ The `parseError` function will not be called.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/types.ts:59](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L59)
|
||||
[packages/mermaid/src/types.ts:64](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L64)
|
||||
|
||||
@@ -18,7 +18,7 @@ The config passed as YAML frontmatter or directives
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/types.ts:70](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L70)
|
||||
[packages/mermaid/src/types.ts:75](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L75)
|
||||
|
||||
---
|
||||
|
||||
@@ -30,4 +30,4 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/types.ts:66](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L66)
|
||||
[packages/mermaid/src/types.ts:71](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L71)
|
||||
|
||||
@@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/types.ts:98](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L98)
|
||||
[packages/mermaid/src/types.ts:103](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L103)
|
||||
|
||||
---
|
||||
|
||||
@@ -51,7 +51,7 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L88)
|
||||
[packages/mermaid/src/types.ts:93](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L93)
|
||||
|
||||
---
|
||||
|
||||
@@ -63,4 +63,4 @@ The svg code for the rendered graph.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/types.ts:84](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L84)
|
||||
[packages/mermaid/src/types.ts:89](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L89)
|
||||
|
||||
BIN
docs/ecosystem/img/python-mermaid-integration-updated.png
Normal file
BIN
docs/ecosystem/img/python-mermaid-integration-updated.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 256 KiB |
@@ -44,6 +44,7 @@ To add an integration to this list, see the [Integrations - create page](./integ
|
||||
- [Deepdwn](https://billiam.itch.io/deepdwn) ✅
|
||||
- [Doctave](https://www.doctave.com/) ✅
|
||||
- [Mermaid in Markdown code blocks](https://docs.doctave.com/components/mermaid) ✅
|
||||
- [Forgejo](https://forgejo.org/) ✅
|
||||
- [GitBook](https://gitbook.com)
|
||||
- [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid)
|
||||
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
|
||||
@@ -99,8 +100,7 @@ Blogging frameworks and platforms
|
||||
- [Nextra](https://nextra.site/)
|
||||
- [Mermaid](https://nextra.site/docs/guide/mermaid)
|
||||
- [WordPress](https://wordpress.org)
|
||||
- [WordPress Markdown Editor](https://wordpress.org/plugins/wp-githuber-md)
|
||||
- [WP-ReliableMD](https://wordpress.org/plugins/wp-reliablemd/)
|
||||
- [MerPRess](https://wordpress.org/plugins/merpress/)
|
||||
|
||||
### CMS/ECM
|
||||
|
||||
|
||||
@@ -52,28 +52,33 @@ Examples are provided in [Getting Started](../intro/getting-started.md)
|
||||
|
||||
[K8s.dev blog: Improve your documentation with Mermaid.js diagrams](https://www.kubernetes.dev/blog/2021/12/01/improve-your-documentation-with-mermaid.js-diagrams/)
|
||||
|
||||
## Jupyter Integration with mermaid-js
|
||||
## Jupyter / Python Integration with mermaid-js
|
||||
|
||||
Here's an example of Python integration with mermaid-js which uses the mermaid.ink service, that displays the graph in a Jupyter notebook.
|
||||
Here's an example of Python integration with mermaid-js which uses the mermaid.ink service, that displays the graph in a Jupyter notebook and save it as _.png_ image with the stated resolution (in this example, `dpi=1200`).
|
||||
|
||||
```python
|
||||
import base64
|
||||
import io, requests
|
||||
from IPython.display import Image, display
|
||||
from PIL import Image as im
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def mm(graph):
|
||||
graphbytes = graph.encode("utf8")
|
||||
base64_bytes = base64.urlsafe_b64encode(graphbytes)
|
||||
base64_string = base64_bytes.decode("ascii")
|
||||
display(Image(url="https://mermaid.ink/img/" + base64_string))
|
||||
img = im.open(io.BytesIO(requests.get('https://mermaid.ink/img/' + base64_string).content))
|
||||
plt.imshow(img)
|
||||
plt.axis('off') # allow to hide axis
|
||||
plt.savefig('image.png', dpi=1200)
|
||||
|
||||
mm("""
|
||||
graph LR;
|
||||
A--> B & C & D;
|
||||
B--> A & E;
|
||||
C--> A & E;
|
||||
D--> A & E;
|
||||
E--> B & C & D;
|
||||
A--> B & C & D
|
||||
B--> A & E
|
||||
C--> A & E
|
||||
D--> A & E
|
||||
E--> B & C & D
|
||||
""")
|
||||
```
|
||||
|
||||
@@ -81,4 +86,4 @@ graph LR;
|
||||
|
||||

|
||||
|
||||
<!--- cspell:ignore Elle Jaoude Neurodiverse graphbytes --->
|
||||
<!--- cspell:ignore Elle Jaoude Neurodiverse graphbytes imshow savefig --->
|
||||
|
||||
@@ -49,7 +49,7 @@ For a more detailed introduction to Mermaid and some of its more basic uses, loo
|
||||
|
||||
🌐 [CDN](https://www.jsdelivr.com/package/npm/mermaid) | 📖 [Documentation](https://mermaidjs.github.io) | 🙌 [Contribution](../community/contributing.md) | 🔌 [Plug-Ins](../ecosystem/integrations-community.md)
|
||||
|
||||
> 🖖 Keep a steady pulse: mermaid needs more Collaborators, [Read More](https://github.com/knsv/mermaid/issues/866).
|
||||
> 🖖 Keep a steady pulse: mermaid needs more Collaborators, [Read More](https://github.com/mermaid-js/mermaid/issues/866).
|
||||
|
||||
:trophy: **Mermaid was nominated and won the [JS Open Source Awards (2019)](https://osawards.com/javascript/#nominees) in the category "The most exciting use of technology"!!!**
|
||||
|
||||
@@ -453,7 +453,7 @@ A quick note from Knut Sveidqvist:
|
||||
>
|
||||
> _Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017._
|
||||
>
|
||||
> _Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!_
|
||||
> _Thank you to the ever-growing list of [contributors](https://github.com/mermaid-js/mermaid/graphs/contributors) that brought the project this far!_
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1183,6 +1183,91 @@ flowchart TB
|
||||
B --> D
|
||||
```
|
||||
|
||||
### Attaching an ID to Edges
|
||||
|
||||
Mermaid now supports assigning IDs to edges, similar to how IDs and metadata can be attached to nodes. This feature lays the groundwork for more advanced styling, classes, and animation capabilities on edges.
|
||||
|
||||
**Syntax:**
|
||||
|
||||
To give an edge an ID, prepend the edge syntax with the ID followed by an `@` character. For example:
|
||||
|
||||
```mermaid-example
|
||||
flowchart LR
|
||||
A e1@–> B
|
||||
```
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A e1@–> B
|
||||
```
|
||||
|
||||
In this example, `e1` is the ID of the edge connecting `A` to `B`. You can then use this ID in later definitions or style statements, just like with nodes.
|
||||
|
||||
### Turning an Animation On
|
||||
|
||||
Once you have assigned an ID to an edge, you can turn on animations for that edge by defining the edge’s properties:
|
||||
|
||||
```mermaid-example
|
||||
flowchart LR
|
||||
A e1@==> B
|
||||
e1@{ animate: true }
|
||||
```
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A e1@==> B
|
||||
e1@{ animate: true }
|
||||
```
|
||||
|
||||
This tells Mermaid that the edge `e1` should be animated.
|
||||
|
||||
### Selecting Type of Animation
|
||||
|
||||
In the initial version, two animation speeds are supported: `fast` and `slow`. Selecting a specific animation type is a shorthand for enabling animation and setting the animation speed in one go.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```mermaid-example
|
||||
flowchart LR
|
||||
A e1@–> B
|
||||
e1@{ animation: fast }
|
||||
```
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A e1@–> B
|
||||
e1@{ animation: fast }
|
||||
```
|
||||
|
||||
This is equivalent to `{ animate: true, animation: fast }`.
|
||||
|
||||
### Using classDef Statements for Animations
|
||||
|
||||
You can also animate edges by assigning a class to them and then defining animation properties in a `classDef` statement. For example:
|
||||
|
||||
```mermaid-example
|
||||
flowchart LR
|
||||
A e1@–> B
|
||||
classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||
class e1 animate
|
||||
```
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A e1@–> B
|
||||
classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||
class e1 animate
|
||||
```
|
||||
|
||||
In this snippet:
|
||||
|
||||
- `e1@-->` creates an edge with ID `e1`.
|
||||
- `classDef animate` defines a class named `animate` with styling and animation properties.
|
||||
- `class e1 animate` applies the `animate` class to the edge `e1`.
|
||||
|
||||
**Note on Escaping Commas:**
|
||||
When setting the `stroke-dasharray` property, remember to escape commas as `\,` since commas are used as delimiters in Mermaid’s style definitions.
|
||||
|
||||
## New arrow types
|
||||
|
||||
There are new types of arrows supported:
|
||||
@@ -1707,8 +1792,7 @@ graph LR
|
||||
```
|
||||
|
||||
For a full list of available curves, including an explanation of custom curves, refer to
|
||||
the [Shapes](https://github.com/d3/d3-shape/blob/main/README.md#curves) documentation in the
|
||||
[d3-shape](https://github.com/d3/d3-shape/) project.
|
||||
the [Shapes](https://d3js.org/d3-shape/curve) documentation in the [d3-shape](https://github.com/d3/d3-shape/) project.
|
||||
|
||||
### Styling a node
|
||||
|
||||
|
||||
@@ -500,7 +500,7 @@ mermaid.ganttConfig = {
|
||||
sectionFontSize: 24, // Font size for sections
|
||||
numberSectionStyles: 1, // The number of alternating section styles
|
||||
axisFormat: '%d/%m', // Date/time format of the axis
|
||||
tickInterval: '1 week', // Axis ticks
|
||||
tickInterval: '1week', // Axis ticks
|
||||
topAxis: true, // When this flag is set, date labels will be added to the top of the chart
|
||||
displayMode: 'compact', // Turns compact mode on
|
||||
weekday: 'sunday', // On which day a week-based interval should start
|
||||
|
||||
@@ -86,7 +86,7 @@ todo[Todo]
|
||||
|
||||
## Configuration Options
|
||||
|
||||
You can customize the Kanban diagram using a configuration block at the beginning of your markdown file. This is useful for setting global settings like a base URL for tickets. Currently there is one configuration option for kanban diagrams tacketBaseUrl. This can be set as in the the following example:
|
||||
You can customize the Kanban diagram using a configuration block at the beginning of your markdown file. This is useful for setting global settings like a base URL for tickets. Currently there is one configuration option for kanban diagrams `ticketBaseUrl`. This can be set as in the the following example:
|
||||
|
||||
```yaml
|
||||
---
|
||||
|
||||
@@ -18,7 +18,7 @@ timeline
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook
|
||||
: Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
```
|
||||
|
||||
@@ -28,7 +28,7 @@ timeline
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook
|
||||
: Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
```
|
||||
|
||||
@@ -67,7 +67,7 @@ timeline
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
```
|
||||
|
||||
@@ -76,7 +76,7 @@ timeline
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
```
|
||||
|
||||
@@ -198,7 +198,7 @@ However, if there is no section defined, then we have two possibilities:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
|
||||
```
|
||||
@@ -208,7 +208,7 @@ However, if there is no section defined, then we have two possibilities:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
|
||||
```
|
||||
@@ -239,7 +239,7 @@ let us look at same example, where we have disabled the multiColor option.
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
|
||||
```
|
||||
@@ -250,7 +250,7 @@ let us look at same example, where we have disabled the multiColor option.
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
|
||||
```
|
||||
@@ -278,7 +278,7 @@ Now let's override the default values for the `cScale0` to `cScale2` variables:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
2007 : Tumblr
|
||||
2008 : Instagram
|
||||
@@ -296,7 +296,7 @@ Now let's override the default values for the `cScale0` to `cScale2` variables:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
2007 : Tumblr
|
||||
2008 : Instagram
|
||||
@@ -329,7 +329,7 @@ Let's put them to use, and see how our sample diagram looks in different themes:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
2007 : Tumblr
|
||||
2008 : Instagram
|
||||
@@ -342,7 +342,7 @@ Let's put them to use, and see how our sample diagram looks in different themes:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
2007 : Tumblr
|
||||
2008 : Instagram
|
||||
@@ -357,7 +357,7 @@ Let's put them to use, and see how our sample diagram looks in different themes:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
2007 : Tumblr
|
||||
2008 : Instagram
|
||||
@@ -370,7 +370,7 @@ Let's put them to use, and see how our sample diagram looks in different themes:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
2007 : Tumblr
|
||||
2008 : Instagram
|
||||
@@ -385,7 +385,7 @@ Let's put them to use, and see how our sample diagram looks in different themes:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
2007 : Tumblr
|
||||
2008 : Instagram
|
||||
@@ -398,7 +398,7 @@ Let's put them to use, and see how our sample diagram looks in different themes:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
2007 : Tumblr
|
||||
2008 : Instagram
|
||||
@@ -413,7 +413,7 @@ Let's put them to use, and see how our sample diagram looks in different themes:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
2007 : Tumblr
|
||||
2008 : Instagram
|
||||
@@ -426,7 +426,7 @@ Let's put them to use, and see how our sample diagram looks in different themes:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
2007 : Tumblr
|
||||
2008 : Instagram
|
||||
@@ -441,7 +441,7 @@ Let's put them to use, and see how our sample diagram looks in different themes:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
2007 : Tumblr
|
||||
2008 : Instagram
|
||||
@@ -454,7 +454,7 @@ Let's put them to use, and see how our sample diagram looks in different themes:
|
||||
title History of Social Media Platform
|
||||
2002 : LinkedIn
|
||||
2004 : Facebook : Google
|
||||
2005 : Youtube
|
||||
2005 : YouTube
|
||||
2006 : Twitter
|
||||
2007 : Tumblr
|
||||
2008 : Instagram
|
||||
|
||||
@@ -137,7 +137,6 @@ export default tseslint.config(
|
||||
'unicorn/no-instanceof-array': 'error',
|
||||
'unicorn/no-typeof-undefined': 'error',
|
||||
'unicorn/no-unnecessary-await': 'error',
|
||||
'unicorn/no-unsafe-regex': 'warn',
|
||||
'unicorn/no-useless-promise-resolve-reject': 'error',
|
||||
'unicorn/prefer-array-find': 'error',
|
||||
'unicorn/prefer-array-flat-map': 'error',
|
||||
|
||||
11
package.json
11
package.json
@@ -92,10 +92,10 @@
|
||||
"cypress": "^13.14.1",
|
||||
"cypress-image-snapshot": "^4.0.1",
|
||||
"cypress-split": "^1.24.0",
|
||||
"esbuild": "^0.21.5",
|
||||
"esbuild": "^0.25.0",
|
||||
"eslint": "^9.4.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-cypress": "^3.3.0",
|
||||
"eslint-config-prettier": "^10.0.0",
|
||||
"eslint-plugin-cypress": "^4.0.0",
|
||||
"eslint-plugin-html": "^8.1.1",
|
||||
"eslint-plugin-jest": "^28.6.0",
|
||||
"eslint-plugin-jsdoc": "^50.0.0",
|
||||
@@ -103,8 +103,8 @@
|
||||
"eslint-plugin-lodash": "^8.0.0",
|
||||
"eslint-plugin-markdown": "^5.0.0",
|
||||
"eslint-plugin-no-only-tests": "^3.1.0",
|
||||
"eslint-plugin-tsdoc": "^0.3.0",
|
||||
"eslint-plugin-unicorn": "^56.0.0",
|
||||
"eslint-plugin-tsdoc": "^0.4.0",
|
||||
"eslint-plugin-unicorn": "^57.0.0",
|
||||
"express": "^4.19.1",
|
||||
"globals": "^15.4.0",
|
||||
"globby": "^14.0.1",
|
||||
@@ -123,6 +123,7 @@
|
||||
"rimraf": "^5.0.5",
|
||||
"rollup-plugin-visualizer": "^5.12.0",
|
||||
"start-server-and-test": "^2.0.3",
|
||||
"tslib": "^2.8.1",
|
||||
"tsx": "^4.7.1",
|
||||
"typescript": "~5.4.5",
|
||||
"typescript-eslint": "^8.0.0-alpha.34",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @mermaid-js/layout-elk
|
||||
|
||||
## 0.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6090](https://github.com/mermaid-js/mermaid/pull/6090) [`654097c`](https://github.com/mermaid-js/mermaid/commit/654097c43801b2d606bc3d2bef8c6fbc3301e9e4) Thanks [@knsv](https://github.com/knsv)! - fix: Updated offset calculations for diamond shape when handling intersections
|
||||
|
||||
## 0.1.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@mermaid-js/layout-elk",
|
||||
"version": "0.1.6",
|
||||
"version": "0.1.7",
|
||||
"description": "ELK layout engine for mermaid",
|
||||
"module": "dist/mermaid-layout-elk.core.mjs",
|
||||
"types": "dist/layouts.d.ts",
|
||||
|
||||
@@ -705,14 +705,11 @@ export const render = async (
|
||||
bounds: { x: any; y: any; width: any; height: any; padding: any },
|
||||
isDiamond: boolean
|
||||
) => {
|
||||
log.debug('UIO cutPathAtIntersect Points:', _points, 'node:', bounds, 'isDiamond', isDiamond);
|
||||
log.debug('APA18 cutPathAtIntersect Points:', _points, 'node:', bounds, 'isDiamond', isDiamond);
|
||||
const points: any[] = [];
|
||||
let lastPointOutside = _points[0];
|
||||
let isInside = false;
|
||||
_points.forEach((point: any) => {
|
||||
// const node = clusterDb[edge.toCluster].node;
|
||||
log.debug(' checking point', point, bounds);
|
||||
|
||||
// check if point is inside the boundary rect
|
||||
if (!outsideNode(bounds, point) && !isInside) {
|
||||
// First point inside the rect found
|
||||
@@ -906,7 +903,7 @@ export const render = async (
|
||||
|
||||
const offset = calcOffset(sourceId, targetId, parentLookupDb);
|
||||
log.debug(
|
||||
'offset',
|
||||
'APA18 offset',
|
||||
offset,
|
||||
sourceId,
|
||||
' ==> ',
|
||||
@@ -971,29 +968,22 @@ export const render = async (
|
||||
}
|
||||
if (startNode.shape === 'diamond' || startNode.shape === 'diam') {
|
||||
edge.points.unshift({
|
||||
x: startNode.x + startNode.width / 2 + offset.x,
|
||||
y: startNode.y + startNode.height / 2 + offset.y,
|
||||
x: startNode.offset.posX + startNode.width / 2,
|
||||
y: startNode.offset.posY + startNode.height / 2,
|
||||
});
|
||||
}
|
||||
if (endNode.shape === 'diamond' || endNode.shape === 'diam') {
|
||||
const x = endNode.x + endNode.width / 2 + offset.x;
|
||||
// Add a point at the center of the diamond
|
||||
if (
|
||||
Math.abs(edge.points[edge.points.length - 1].y - endNode.y - offset.y) > 0.01 ||
|
||||
Math.abs(edge.points[edge.points.length - 1].x - x) > 0.001
|
||||
) {
|
||||
edge.points.push({
|
||||
x: endNode.x + endNode.width / 2 + offset.x,
|
||||
y: endNode.y + endNode.height / 2 + offset.y,
|
||||
});
|
||||
}
|
||||
edge.points.push({
|
||||
x: endNode.offset.posX + endNode.width / 2,
|
||||
y: endNode.offset.posY + endNode.height / 2,
|
||||
});
|
||||
}
|
||||
|
||||
edge.points = cutPathAtIntersect(
|
||||
edge.points.reverse(),
|
||||
{
|
||||
x: startNode.x + startNode.width / 2 + offset.x,
|
||||
y: startNode.y + startNode.height / 2 + offset.y,
|
||||
x: startNode.offset.posX + startNode.width / 2,
|
||||
y: startNode.offset.posY + startNode.height / 2,
|
||||
width: sw,
|
||||
height: startNode.height,
|
||||
padding: startNode.padding,
|
||||
@@ -1004,8 +994,8 @@ export const render = async (
|
||||
edge.points = cutPathAtIntersect(
|
||||
edge.points,
|
||||
{
|
||||
x: endNode.x + ew / 2 + endNode.offset.x,
|
||||
y: endNode.y + endNode.height / 2 + endNode.offset.y,
|
||||
x: endNode.offset.posX + endNode.width / 2,
|
||||
y: endNode.offset.posY + endNode.height / 2,
|
||||
width: ew,
|
||||
height: endNode.height,
|
||||
padding: endNode.padding,
|
||||
|
||||
@@ -230,7 +230,7 @@ const ConfigWarning = {
|
||||
} as const;
|
||||
|
||||
type ConfigWarningStrings = keyof typeof ConfigWarning;
|
||||
const issuedWarnings: { [key in ConfigWarningStrings]?: boolean } = {};
|
||||
const issuedWarnings: Partial<Record<ConfigWarningStrings, boolean>> = {};
|
||||
const issueWarning = (warning: ConfigWarningStrings) => {
|
||||
if (issuedWarnings[warning]) {
|
||||
return;
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
setDiagramTitle,
|
||||
} from '../common/commonDb.js';
|
||||
import type {
|
||||
ArchitectureAlignment,
|
||||
ArchitectureDB,
|
||||
ArchitectureDirectionPair,
|
||||
ArchitectureDirectionPairMap,
|
||||
@@ -25,6 +26,7 @@ import type {
|
||||
ArchitectureState,
|
||||
} from './architectureTypes.js';
|
||||
import {
|
||||
getArchitectureDirectionAlignment,
|
||||
getArchitectureDirectionPair,
|
||||
isArchitectureDirection,
|
||||
isArchitectureJunction,
|
||||
@@ -211,12 +213,18 @@ const addEdge = function ({
|
||||
const getEdges = (): ArchitectureEdge[] => state.records.edges;
|
||||
|
||||
/**
|
||||
* Returns the current diagram's adjacency list & spatial map.
|
||||
* Returns the current diagram's adjacency list, spatial map, & group alignments.
|
||||
* If they have not been created, run the algorithms to generate them.
|
||||
* @returns
|
||||
*/
|
||||
const getDataStructures = () => {
|
||||
if (state.records.dataStructures === undefined) {
|
||||
// Tracks how groups are aligned with one another. Generated while creating the adj list
|
||||
const groupAlignments: Record<
|
||||
string,
|
||||
Record<string, Exclude<ArchitectureAlignment, 'bend'>>
|
||||
> = {};
|
||||
|
||||
// Create an adjacency list of the diagram to perform BFS on
|
||||
// Outer reduce applied on all services
|
||||
// Inner reduce applied on the edges for a service
|
||||
@@ -224,6 +232,19 @@ const getDataStructures = () => {
|
||||
Record<string, ArchitectureDirectionPairMap>
|
||||
>((prevOuter, [id, service]) => {
|
||||
prevOuter[id] = service.edges.reduce<ArchitectureDirectionPairMap>((prevInner, edge) => {
|
||||
// track the direction groups connect to one another
|
||||
const lhsGroupId = getNode(edge.lhsId)?.in;
|
||||
const rhsGroupId = getNode(edge.rhsId)?.in;
|
||||
if (lhsGroupId && rhsGroupId && lhsGroupId !== rhsGroupId) {
|
||||
const alignment = getArchitectureDirectionAlignment(edge.lhsDir, edge.rhsDir);
|
||||
if (alignment !== 'bend') {
|
||||
groupAlignments[lhsGroupId] ??= {};
|
||||
groupAlignments[lhsGroupId][rhsGroupId] = alignment;
|
||||
groupAlignments[rhsGroupId] ??= {};
|
||||
groupAlignments[rhsGroupId][lhsGroupId] = alignment;
|
||||
}
|
||||
}
|
||||
|
||||
if (edge.lhsId === id) {
|
||||
// source is LHS
|
||||
const pair = getArchitectureDirectionPair(edge.lhsDir, edge.rhsDir);
|
||||
@@ -245,6 +266,7 @@ const getDataStructures = () => {
|
||||
// Configuration for the initial pass of BFS
|
||||
const firstId = Object.keys(adjList)[0];
|
||||
const visited = { [firstId]: 1 };
|
||||
// If a key is present in this object, it has not been visited
|
||||
const notVisited = Object.keys(adjList).reduce(
|
||||
(prev, id) => (id === firstId ? prev : { ...prev, [id]: 1 }),
|
||||
{} as Record<string, number>
|
||||
@@ -283,6 +305,7 @@ const getDataStructures = () => {
|
||||
state.records.dataStructures = {
|
||||
adjList,
|
||||
spatialMaps,
|
||||
groupAlignments,
|
||||
};
|
||||
}
|
||||
return state.records.dataStructures;
|
||||
|
||||
@@ -12,7 +12,9 @@ import { setupGraphViewbox } from '../../setupGraphViewbox.js';
|
||||
import { getConfigField } from './architectureDb.js';
|
||||
import { architectureIcons } from './architectureIcons.js';
|
||||
import type {
|
||||
ArchitectureAlignment,
|
||||
ArchitectureDataStructures,
|
||||
ArchitectureGroupAlignments,
|
||||
ArchitectureJunction,
|
||||
ArchitectureSpatialMap,
|
||||
EdgeSingular,
|
||||
@@ -149,25 +151,91 @@ function addEdges(edges: ArchitectureEdge[], cy: cytoscape.Core) {
|
||||
});
|
||||
}
|
||||
|
||||
function getAlignments(spatialMaps: ArchitectureSpatialMap[]): fcose.FcoseAlignmentConstraint {
|
||||
function getAlignments(
|
||||
db: ArchitectureDB,
|
||||
spatialMaps: ArchitectureSpatialMap[],
|
||||
groupAlignments: ArchitectureGroupAlignments
|
||||
): fcose.FcoseAlignmentConstraint {
|
||||
/**
|
||||
* Flattens the alignment object so nodes in different groups will be in the same alignment array IFF their groups don't connect in a conflicting alignment
|
||||
*
|
||||
* i.e., two groups which connect horizontally should not have nodes with vertical alignments to one another
|
||||
*
|
||||
* See: #5952
|
||||
*
|
||||
* @param alignmentObj - alignment object with the outer key being the row/col # and the inner key being the group name mapped to the nodes on that axis in the group
|
||||
* @param alignmentDir - alignment direction
|
||||
* @returns flattened alignment object with an arbitrary key mapping to nodes in the same row/col
|
||||
*/
|
||||
const flattenAlignments = (
|
||||
alignmentObj: Record<number, Record<string, string[]>>,
|
||||
alignmentDir: ArchitectureAlignment
|
||||
): Record<string, string[]> => {
|
||||
return Object.entries(alignmentObj).reduce(
|
||||
(prev, [dir, alignments]) => {
|
||||
// prev is the mapping of x/y coordinate to an array of the nodes in that row/column
|
||||
let cnt = 0;
|
||||
const arr = Object.entries(alignments); // [group name, array of nodes within the group on axis dir]
|
||||
if (arr.length === 1) {
|
||||
// If only one group exists in the row/column, we don't need to do anything else
|
||||
prev[dir] = arr[0][1];
|
||||
return prev;
|
||||
}
|
||||
for (let i = 0; i < arr.length - 1; i++) {
|
||||
for (let j = i + 1; j < arr.length; j++) {
|
||||
const [aGroupId, aNodeIds] = arr[i];
|
||||
const [bGroupId, bNodeIds] = arr[j];
|
||||
const alignment = groupAlignments[aGroupId]?.[bGroupId]; // Get how the two groups are intended to align (undefined if they aren't)
|
||||
|
||||
if (alignment === alignmentDir) {
|
||||
// If the intended alignment between the two groups is the same as the alignment we are parsing
|
||||
prev[dir] ??= [];
|
||||
prev[dir] = [...prev[dir], ...aNodeIds, ...bNodeIds]; // add the node ids of both groups to the axis array in prev
|
||||
} else if (aGroupId === 'default' || bGroupId === 'default') {
|
||||
// If either of the groups are in the default space (not in a group), use the same behavior as above
|
||||
prev[dir] ??= [];
|
||||
prev[dir] = [...prev[dir], ...aNodeIds, ...bNodeIds];
|
||||
} else {
|
||||
// Otherwise, the nodes in the two groups are not intended to align
|
||||
const keyA = `${dir}-${cnt++}`;
|
||||
prev[keyA] = aNodeIds;
|
||||
const keyB = `${dir}-${cnt++}`;
|
||||
prev[keyB] = bNodeIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return prev;
|
||||
},
|
||||
{} as Record<string, string[]>
|
||||
);
|
||||
};
|
||||
|
||||
const alignments = spatialMaps.map((spatialMap) => {
|
||||
const horizontalAlignments: Record<number, string[]> = {};
|
||||
const verticalAlignments: Record<number, string[]> = {};
|
||||
const horizontalAlignments: Record<number, Record<string, string[]>> = {};
|
||||
const verticalAlignments: Record<number, Record<string, string[]>> = {};
|
||||
|
||||
// Group service ids in an object with their x and y coordinate as the key
|
||||
Object.entries(spatialMap).forEach(([id, [x, y]]) => {
|
||||
if (!horizontalAlignments[y]) {
|
||||
horizontalAlignments[y] = [];
|
||||
}
|
||||
if (!verticalAlignments[x]) {
|
||||
verticalAlignments[x] = [];
|
||||
}
|
||||
horizontalAlignments[y].push(id);
|
||||
verticalAlignments[x].push(id);
|
||||
const nodeGroup = db.getNode(id)?.in ?? 'default';
|
||||
|
||||
horizontalAlignments[y] ??= {};
|
||||
horizontalAlignments[y][nodeGroup] ??= [];
|
||||
horizontalAlignments[y][nodeGroup].push(id);
|
||||
|
||||
verticalAlignments[x] ??= {};
|
||||
verticalAlignments[x][nodeGroup] ??= [];
|
||||
verticalAlignments[x][nodeGroup].push(id);
|
||||
});
|
||||
|
||||
// Merge the values of each object into a list if the inner list has at least 2 elements
|
||||
return {
|
||||
horiz: Object.values(horizontalAlignments).filter((arr) => arr.length > 1),
|
||||
vert: Object.values(verticalAlignments).filter((arr) => arr.length > 1),
|
||||
horiz: Object.values(flattenAlignments(horizontalAlignments, 'horizontal')).filter(
|
||||
(arr) => arr.length > 1
|
||||
),
|
||||
vert: Object.values(flattenAlignments(verticalAlignments, 'vertical')).filter(
|
||||
(arr) => arr.length > 1
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -244,7 +312,8 @@ function layoutArchitecture(
|
||||
junctions: ArchitectureJunction[],
|
||||
groups: ArchitectureGroup[],
|
||||
edges: ArchitectureEdge[],
|
||||
{ spatialMaps }: ArchitectureDataStructures
|
||||
db: ArchitectureDB,
|
||||
{ spatialMaps, groupAlignments }: ArchitectureDataStructures
|
||||
): Promise<cytoscape.Core> {
|
||||
return new Promise((resolve) => {
|
||||
const renderEl = select('body').append('div').attr('id', 'cy').attr('style', 'display:none');
|
||||
@@ -318,9 +387,8 @@ function layoutArchitecture(
|
||||
addServices(services, cy);
|
||||
addJunctions(junctions, cy);
|
||||
addEdges(edges, cy);
|
||||
|
||||
// Use the spatial map to create alignment arrays for fcose
|
||||
const alignmentConstraint = getAlignments(spatialMaps);
|
||||
const alignmentConstraint = getAlignments(db, spatialMaps, groupAlignments);
|
||||
|
||||
// Create the relative constraints for fcose by using an inverse of the spatial map and performing BFS on it
|
||||
const relativePlacementConstraint = getRelativeConstraints(spatialMaps);
|
||||
@@ -454,7 +522,7 @@ export const draw: DrawDefinition = async (text, id, _version, diagObj: Diagram)
|
||||
await drawServices(db, servicesElem, services);
|
||||
drawJunctions(db, servicesElem, junctions);
|
||||
|
||||
const cy = await layoutArchitecture(services, junctions, groups, edges, ds);
|
||||
const cy = await layoutArchitecture(services, junctions, groups, edges, db, ds);
|
||||
|
||||
await drawEdges(edgesElem, cy);
|
||||
await drawGroups(groupElem, cy);
|
||||
|
||||
@@ -7,6 +7,8 @@ import type cytoscape from 'cytoscape';
|
||||
| Architecture Diagram Types |
|
||||
\*=======================================*/
|
||||
|
||||
export type ArchitectureAlignment = 'vertical' | 'horizontal' | 'bend';
|
||||
|
||||
export type ArchitectureDirection = 'L' | 'R' | 'T' | 'B';
|
||||
export type ArchitectureDirectionX = Extract<ArchitectureDirection, 'L' | 'R'>;
|
||||
export type ArchitectureDirectionY = Extract<ArchitectureDirection, 'T' | 'B'>;
|
||||
@@ -104,9 +106,7 @@ export const isValidArchitectureDirectionPair = function (
|
||||
return x !== 'LL' && x !== 'RR' && x !== 'TT' && x !== 'BB';
|
||||
};
|
||||
|
||||
export type ArchitectureDirectionPairMap = {
|
||||
[key in ArchitectureDirectionPair]?: string;
|
||||
};
|
||||
export type ArchitectureDirectionPairMap = Partial<Record<ArchitectureDirectionPair, string>>;
|
||||
|
||||
/**
|
||||
* Creates a pair of the directions of each side of an edge. This function should be used instead of manually creating it to ensure that the source is always the first character.
|
||||
@@ -170,6 +170,18 @@ export const getArchitectureDirectionXYFactors = function (
|
||||
}
|
||||
};
|
||||
|
||||
export const getArchitectureDirectionAlignment = function (
|
||||
a: ArchitectureDirection,
|
||||
b: ArchitectureDirection
|
||||
): ArchitectureAlignment {
|
||||
if (isArchitectureDirectionXY(a, b)) {
|
||||
return 'bend';
|
||||
} else if (isArchitectureDirectionX(a)) {
|
||||
return 'horizontal';
|
||||
}
|
||||
return 'vertical';
|
||||
};
|
||||
|
||||
export interface ArchitectureStyleOptions {
|
||||
archEdgeColor: string;
|
||||
archEdgeArrowColor: string;
|
||||
@@ -249,9 +261,27 @@ export interface ArchitectureDB extends DiagramDB {
|
||||
|
||||
export type ArchitectureAdjacencyList = Record<string, ArchitectureDirectionPairMap>;
|
||||
export type ArchitectureSpatialMap = Record<string, number[]>;
|
||||
|
||||
/**
|
||||
* Maps the direction that groups connect from.
|
||||
*
|
||||
* **Outer key**: ID of group A
|
||||
*
|
||||
* **Inner key**: ID of group B
|
||||
*
|
||||
* **Value**: 'vertical' or 'horizontal'
|
||||
*
|
||||
* Note: tmp[groupA][groupB] == tmp[groupB][groupA]
|
||||
*/
|
||||
export type ArchitectureGroupAlignments = Record<
|
||||
string,
|
||||
Record<string, Exclude<ArchitectureAlignment, 'bend'>>
|
||||
>;
|
||||
|
||||
export interface ArchitectureDataStructures {
|
||||
adjList: ArchitectureAdjacencyList;
|
||||
spatialMaps: ArchitectureSpatialMap[];
|
||||
groupAlignments: ArchitectureGroupAlignments;
|
||||
}
|
||||
|
||||
export interface ArchitectureState extends Record<string, unknown> {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,11 @@
|
||||
import { parser } from './parser/classDiagram.jison';
|
||||
import classDb from './classDb.js';
|
||||
import { ClassDB } from './classDb.js';
|
||||
|
||||
describe('class diagram, ', function () {
|
||||
describe('when parsing data from a classDiagram it', function () {
|
||||
let classDb;
|
||||
beforeEach(function () {
|
||||
classDb = new ClassDB();
|
||||
parser.yy = classDb;
|
||||
parser.yy.clear();
|
||||
});
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import type { DiagramDefinition } from '../../diagram-api/types.js';
|
||||
// @ts-ignore: JISON doesn't support types
|
||||
import parser from './parser/classDiagram.jison';
|
||||
import db from './classDb.js';
|
||||
import { ClassDB } from './classDb.js';
|
||||
import styles from './styles.js';
|
||||
import renderer from './classRenderer-v3-unified.js';
|
||||
|
||||
export const diagram: DiagramDefinition = {
|
||||
parser,
|
||||
db,
|
||||
get db() {
|
||||
return new ClassDB();
|
||||
},
|
||||
renderer,
|
||||
styles,
|
||||
init: (cnf) => {
|
||||
@@ -15,6 +17,5 @@ export const diagram: DiagramDefinition = {
|
||||
cnf.class = {};
|
||||
}
|
||||
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
db.clear();
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/unbound-method -- Broken for Vitest mocks, see https://github.com/vitest-dev/eslint-plugin-vitest/pull/286 */
|
||||
// @ts-expect-error Jison doesn't export types
|
||||
import { parser } from './parser/classDiagram.jison';
|
||||
import classDb from './classDb.js';
|
||||
import { ClassDB } from './classDb.js';
|
||||
import { vi, describe, it, expect } from 'vitest';
|
||||
import type { ClassMap, NamespaceNode } from './classTypes.js';
|
||||
const spyOn = vi.spyOn;
|
||||
@@ -10,8 +11,9 @@ const abstractCssStyle = 'font-style:italic;';
|
||||
|
||||
describe('given a basic class diagram, ', function () {
|
||||
describe('when parsing class definition', function () {
|
||||
let classDb: ClassDB;
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
classDb = new ClassDB();
|
||||
parser.yy = classDb;
|
||||
});
|
||||
it('should handle classes within namespaces', () => {
|
||||
@@ -564,8 +566,9 @@ class C13["With Città foreign language"]
|
||||
});
|
||||
|
||||
describe('when parsing class defined in brackets', function () {
|
||||
let classDb: ClassDB;
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
classDb = new ClassDB();
|
||||
parser.yy = classDb;
|
||||
});
|
||||
|
||||
@@ -656,8 +659,9 @@ class C13["With Città foreign language"]
|
||||
});
|
||||
|
||||
describe('when parsing comments', function () {
|
||||
let classDb: ClassDB;
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
classDb = new ClassDB();
|
||||
parser.yy = classDb;
|
||||
});
|
||||
|
||||
@@ -746,8 +750,9 @@ foo()
|
||||
});
|
||||
|
||||
describe('when parsing click statements', function () {
|
||||
let classDb: ClassDB;
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
classDb = new ClassDB();
|
||||
parser.yy = classDb;
|
||||
});
|
||||
it('should handle href link', function () {
|
||||
@@ -857,8 +862,9 @@ foo()
|
||||
});
|
||||
|
||||
describe('when parsing annotations', function () {
|
||||
let classDb: ClassDB;
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
classDb = new ClassDB();
|
||||
parser.yy = classDb;
|
||||
});
|
||||
|
||||
@@ -921,8 +927,9 @@ foo()
|
||||
|
||||
describe('given a class diagram with members and methods ', function () {
|
||||
describe('when parsing members', function () {
|
||||
let classDb: ClassDB;
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
classDb = new ClassDB();
|
||||
parser.yy = classDb;
|
||||
});
|
||||
|
||||
@@ -980,8 +987,9 @@ describe('given a class diagram with members and methods ', function () {
|
||||
});
|
||||
|
||||
describe('when parsing method definition', function () {
|
||||
let classDb: ClassDB;
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
classDb = new ClassDB();
|
||||
parser.yy = classDb;
|
||||
});
|
||||
|
||||
@@ -1067,8 +1075,9 @@ describe('given a class diagram with members and methods ', function () {
|
||||
|
||||
describe('given a class diagram with generics, ', function () {
|
||||
describe('when parsing valid generic classes', function () {
|
||||
let classDb: ClassDB;
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
classDb = new ClassDB();
|
||||
parser.yy = classDb;
|
||||
});
|
||||
|
||||
@@ -1180,8 +1189,9 @@ namespace space {
|
||||
|
||||
describe('given a class diagram with relationships, ', function () {
|
||||
describe('when parsing basic relationships', function () {
|
||||
let classDb: ClassDB;
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
classDb = new ClassDB();
|
||||
parser.yy = classDb;
|
||||
});
|
||||
|
||||
@@ -1714,7 +1724,9 @@ class Class2
|
||||
});
|
||||
|
||||
describe('when parsing classDiagram with text labels', () => {
|
||||
let classDb: ClassDB;
|
||||
beforeEach(function () {
|
||||
classDb = new ClassDB();
|
||||
parser.yy = classDb;
|
||||
parser.yy.clear();
|
||||
});
|
||||
@@ -1897,3 +1909,40 @@ class C13["With Città foreign language"]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('class db class', () => {
|
||||
let classDb: ClassDB;
|
||||
beforeEach(() => {
|
||||
classDb = new ClassDB();
|
||||
});
|
||||
// This is to ensure that functions used in class JISON are exposed as function from ClassDB
|
||||
it('should have functions used in class JISON as own property', () => {
|
||||
const functionsUsedInParser = [
|
||||
'addRelation',
|
||||
'cleanupLabel',
|
||||
'setAccTitle',
|
||||
'setAccDescription',
|
||||
'addClassesToNamespace',
|
||||
'addNamespace',
|
||||
'setCssClass',
|
||||
'addMembers',
|
||||
'addClass',
|
||||
'setClassLabel',
|
||||
'addAnnotation',
|
||||
'addMember',
|
||||
'addNote',
|
||||
'defineClass',
|
||||
'setDirection',
|
||||
'relationType',
|
||||
'lineType',
|
||||
'setClickEvent',
|
||||
'setTooltip',
|
||||
'setLink',
|
||||
'setCssStyle',
|
||||
] as const satisfies (keyof ClassDB)[];
|
||||
|
||||
for (const fun of functionsUsedInParser) {
|
||||
expect(Object.hasOwn(classDb, fun)).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import type { DiagramDefinition } from '../../diagram-api/types.js';
|
||||
// @ts-ignore: JISON doesn't support types
|
||||
import parser from './parser/classDiagram.jison';
|
||||
import db from './classDb.js';
|
||||
import { ClassDB } from './classDb.js';
|
||||
import styles from './styles.js';
|
||||
import renderer from './classRenderer-v3-unified.js';
|
||||
|
||||
export const diagram: DiagramDefinition = {
|
||||
parser,
|
||||
db,
|
||||
get db() {
|
||||
return new ClassDB();
|
||||
},
|
||||
renderer,
|
||||
styles,
|
||||
init: (cnf) => {
|
||||
@@ -15,6 +17,5 @@ export const diagram: DiagramDefinition = {
|
||||
cnf.class = {};
|
||||
}
|
||||
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
db.clear();
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { parser } from './classDiagram.jison';
|
||||
import classDb from '../classDb.js';
|
||||
import { ClassDB } from '../classDb.js';
|
||||
|
||||
describe('class diagram', function () {
|
||||
let classDb;
|
||||
beforeEach(function () {
|
||||
classDb = new ClassDB();
|
||||
parser.yy = classDb;
|
||||
parser.yy.clear();
|
||||
});
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import flowDb from './flowDb.js';
|
||||
import { FlowDB } from './flowDb.js';
|
||||
import type { FlowSubGraph } from './types.js';
|
||||
|
||||
describe('flow db subgraphs', () => {
|
||||
let flowDb: FlowDB;
|
||||
let subgraphs: FlowSubGraph[];
|
||||
beforeEach(() => {
|
||||
flowDb = new FlowDB();
|
||||
subgraphs = [
|
||||
{ nodes: ['a', 'b', 'c', 'e'] },
|
||||
{ nodes: ['f', 'g', 'h'] },
|
||||
@@ -44,8 +46,9 @@ describe('flow db subgraphs', () => {
|
||||
});
|
||||
|
||||
describe('flow db addClass', () => {
|
||||
let flowDb: FlowDB;
|
||||
beforeEach(() => {
|
||||
flowDb.clear();
|
||||
flowDb = new FlowDB();
|
||||
});
|
||||
it('should detect many classes', () => {
|
||||
flowDb.addClass('a,b', ['stroke-width: 8px']);
|
||||
@@ -65,3 +68,33 @@ describe('flow db addClass', () => {
|
||||
expect(classes.get('a')?.styles).toEqual(['stroke-width: 8px']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('flow db class', () => {
|
||||
let flowDb: FlowDB;
|
||||
beforeEach(() => {
|
||||
flowDb = new FlowDB();
|
||||
});
|
||||
// This is to ensure that functions used in flow JISON are exposed as function from FlowDB
|
||||
it('should have functions used in flow JISON as own property', () => {
|
||||
const functionsUsedInParser = [
|
||||
'setDirection',
|
||||
'addSubGraph',
|
||||
'setAccTitle',
|
||||
'setAccDescription',
|
||||
'addVertex',
|
||||
'addLink',
|
||||
'setClass',
|
||||
'destructLink',
|
||||
'addClass',
|
||||
'setClickEvent',
|
||||
'setTooltip',
|
||||
'setLink',
|
||||
'updateLink',
|
||||
'updateLinkInterpolate',
|
||||
] as const satisfies (keyof FlowDB)[];
|
||||
|
||||
for (const fun of functionsUsedInParser) {
|
||||
expect(Object.hasOwn(flowDb, fun)).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,17 @@
|
||||
import type { MermaidConfig } from '../../config.type.js';
|
||||
import { setConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import flowDb from './flowDb.js';
|
||||
import { FlowDB } from './flowDb.js';
|
||||
import renderer from './flowRenderer-v3-unified.js';
|
||||
// @ts-ignore: JISON doesn't support types
|
||||
import flowParser from './parser/flow.jison';
|
||||
//import flowParser from './parser/flow.jison';
|
||||
import flowParser from './parser/flowParser.ts';
|
||||
import flowStyles from './styles.js';
|
||||
|
||||
export const diagram = {
|
||||
parser: flowParser,
|
||||
db: flowDb,
|
||||
get db() {
|
||||
return new FlowDB();
|
||||
},
|
||||
renderer,
|
||||
styles: flowStyles,
|
||||
init: (cnf: MermaidConfig) => {
|
||||
@@ -20,7 +23,5 @@ export const diagram = {
|
||||
}
|
||||
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
setConfig({ flowchart: { arrowMarkerAbsolute: cnf.arrowMarkerAbsolute } });
|
||||
flowDb.clear();
|
||||
flowDb.setGen('gen-2');
|
||||
},
|
||||
};
|
||||
|
||||
@@ -7,7 +7,6 @@ import { getRegisteredLayoutAlgorithm, render } from '../../rendering-util/rende
|
||||
import { setupViewPortForSVG } from '../../rendering-util/setupViewPortForSVG.js';
|
||||
import type { LayoutData } from '../../rendering-util/types.js';
|
||||
import utils from '../../utils.js';
|
||||
import { getDirection } from './flowDb.js';
|
||||
|
||||
export const getClasses = function (
|
||||
text: string,
|
||||
@@ -37,7 +36,7 @@ export const draw = async function (text: string, id: string, _version: string,
|
||||
log.debug('Data: ', data4Layout);
|
||||
// Create the root SVG
|
||||
const svg = getDiagramElement(id, securityLevel);
|
||||
const direction = getDirection();
|
||||
const direction = diag.db.getDirection();
|
||||
|
||||
data4Layout.type = diag.type;
|
||||
data4Layout.layoutAlgorithm = getRegisteredLayoutAlgorithm(layout);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
setConfig({
|
||||
@@ -8,7 +8,7 @@ setConfig({
|
||||
|
||||
describe('[Arrows] when parsing', () => {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
import { cleanupComments } from '../../../diagram-api/comments.js';
|
||||
|
||||
@@ -9,7 +9,7 @@ setConfig({
|
||||
|
||||
describe('[Comments] when parsing', () => {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
setConfig({
|
||||
@@ -8,7 +8,7 @@ setConfig({
|
||||
|
||||
describe('when parsing directions', function () {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
flow.parser.yy.setGen('gen-2');
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
setConfig({
|
||||
@@ -39,10 +39,31 @@ const doubleEndedEdges = [
|
||||
{ edgeStart: '<==', edgeEnd: '==>', stroke: 'thick', type: 'double_arrow_point' },
|
||||
{ edgeStart: '<-.', edgeEnd: '.->', stroke: 'dotted', type: 'double_arrow_point' },
|
||||
];
|
||||
const regularEdges = [
|
||||
{ edgeStart: '--', edgeEnd: '--x', stroke: 'normal', type: 'arrow_cross' },
|
||||
{ edgeStart: '==', edgeEnd: '==x', stroke: 'thick', type: 'arrow_cross' },
|
||||
{ edgeStart: '-.', edgeEnd: '.-x', stroke: 'dotted', type: 'arrow_cross' },
|
||||
{ edgeStart: '--', edgeEnd: '--o', stroke: 'normal', type: 'arrow_circle' },
|
||||
{ edgeStart: '==', edgeEnd: '==o', stroke: 'thick', type: 'arrow_circle' },
|
||||
{ edgeStart: '-.', edgeEnd: '.-o', stroke: 'dotted', type: 'arrow_circle' },
|
||||
{ edgeStart: '--', edgeEnd: '-->', stroke: 'normal', type: 'arrow_point' },
|
||||
{ edgeStart: '==', edgeEnd: '==>', stroke: 'thick', type: 'arrow_point' },
|
||||
{ edgeStart: '-.', edgeEnd: '.->', stroke: 'dotted', type: 'arrow_point' },
|
||||
|
||||
{ edgeStart: '--', edgeEnd: '----x', stroke: 'normal', type: 'arrow_cross' },
|
||||
{ edgeStart: '==', edgeEnd: '====x', stroke: 'thick', type: 'arrow_cross' },
|
||||
{ edgeStart: '-.', edgeEnd: '...-x', stroke: 'dotted', type: 'arrow_cross' },
|
||||
{ edgeStart: '--', edgeEnd: '----o', stroke: 'normal', type: 'arrow_circle' },
|
||||
{ edgeStart: '==', edgeEnd: '====o', stroke: 'thick', type: 'arrow_circle' },
|
||||
{ edgeStart: '-.', edgeEnd: '...-o', stroke: 'dotted', type: 'arrow_circle' },
|
||||
{ edgeStart: '--', edgeEnd: '---->', stroke: 'normal', type: 'arrow_point' },
|
||||
{ edgeStart: '==', edgeEnd: '====>', stroke: 'thick', type: 'arrow_point' },
|
||||
{ edgeStart: '-.', edgeEnd: '...->', stroke: 'dotted', type: 'arrow_point' },
|
||||
];
|
||||
|
||||
describe('[Edges] when parsing', () => {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
@@ -67,6 +88,74 @@ describe('[Edges] when parsing', () => {
|
||||
expect(edges[0].type).toBe('arrow_circle');
|
||||
});
|
||||
|
||||
describe('edges with ids', function () {
|
||||
describe('open ended edges with ids and labels', function () {
|
||||
regularEdges.forEach((edgeType) => {
|
||||
it(`should handle ${edgeType.stroke} ${edgeType.type} with no text`, function () {
|
||||
const res = flow.parser.parse(
|
||||
`flowchart TD;\nA e1@${edgeType.edgeStart}${edgeType.edgeEnd} B;`
|
||||
);
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].id).toBe('e1');
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
expect(edges[0].type).toBe(`${edgeType.type}`);
|
||||
expect(edges[0].text).toBe('');
|
||||
expect(edges[0].stroke).toBe(`${edgeType.stroke}`);
|
||||
});
|
||||
it(`should handle ${edgeType.stroke} ${edgeType.type} with text`, function () {
|
||||
const res = flow.parser.parse(
|
||||
`flowchart TD;\nA e1@${edgeType.edgeStart}${edgeType.edgeEnd} B;`
|
||||
);
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].id).toBe('e1');
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
expect(edges[0].type).toBe(`${edgeType.type}`);
|
||||
expect(edges[0].text).toBe('');
|
||||
expect(edges[0].stroke).toBe(`${edgeType.stroke}`);
|
||||
});
|
||||
});
|
||||
it('should handle normal edges where you also have a node with metadata', function () {
|
||||
const res = flow.parser.parse(`flowchart LR
|
||||
A id1@-->B
|
||||
A@{ shape: 'rect' }
|
||||
`);
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges[0].id).toBe('id1');
|
||||
});
|
||||
});
|
||||
describe('double ended edges with ids and labels', function () {
|
||||
doubleEndedEdges.forEach((edgeType) => {
|
||||
it(`should handle ${edgeType.stroke} ${edgeType.type} with text`, function () {
|
||||
const res = flow.parser.parse(
|
||||
`flowchart TD;\nA e1@${edgeType.edgeStart} label ${edgeType.edgeEnd} B;`
|
||||
);
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].id).toBe('e1');
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
expect(edges[0].type).toBe(`${edgeType.type}`);
|
||||
expect(edges[0].text).toBe('label');
|
||||
expect(edges[0].stroke).toBe(`${edgeType.stroke}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('edges', function () {
|
||||
doubleEndedEdges.forEach((edgeType) => {
|
||||
it(`should handle ${edgeType.stroke} ${edgeType.type} with no text`, function () {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
setConfig({
|
||||
@@ -8,7 +8,7 @@ setConfig({
|
||||
|
||||
describe('[Text] when parsing', () => {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
import { vi } from 'vitest';
|
||||
const spyOn = vi.spyOn;
|
||||
@@ -9,7 +9,9 @@ setConfig({
|
||||
});
|
||||
|
||||
describe('[Interactions] when parsing', () => {
|
||||
let flowDb;
|
||||
beforeEach(function () {
|
||||
flowDb = new FlowDB();
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
setConfig({
|
||||
@@ -8,7 +8,7 @@ setConfig({
|
||||
|
||||
describe('[Lines] when parsing', () => {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
setConfig({
|
||||
@@ -8,7 +8,7 @@ setConfig({
|
||||
|
||||
describe('parsing a flow chart with markdown strings', function () {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
setConfig({
|
||||
@@ -8,7 +8,7 @@ setConfig({
|
||||
|
||||
describe('when parsing directions', function () {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
flow.parser.yy.setGen('gen-2');
|
||||
});
|
||||
@@ -251,7 +251,7 @@ describe('when parsing directions', function () {
|
||||
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
|
||||
expect(data4Layout.nodes[0].label).toEqual('This is a<br/>multiline string');
|
||||
});
|
||||
it(' should be possible to use } in strings', function () {
|
||||
it('should be possible to use } in strings', function () {
|
||||
const res = flow.parser.parse(`flowchart TB
|
||||
A@{
|
||||
label: "This is a string with }"
|
||||
@@ -264,7 +264,7 @@ describe('when parsing directions', function () {
|
||||
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
|
||||
expect(data4Layout.nodes[0].label).toEqual('This is a string with }');
|
||||
});
|
||||
it(' should be possible to use @ in strings', function () {
|
||||
it('should be possible to use @ in strings', function () {
|
||||
const res = flow.parser.parse(`flowchart TB
|
||||
A@{
|
||||
label: "This is a string with @"
|
||||
@@ -277,7 +277,7 @@ describe('when parsing directions', function () {
|
||||
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
|
||||
expect(data4Layout.nodes[0].label).toEqual('This is a string with @');
|
||||
});
|
||||
it(' should be possible to use @ in strings', function () {
|
||||
it('should be possible to use @ in strings', function () {
|
||||
const res = flow.parser.parse(`flowchart TB
|
||||
A@{
|
||||
label: "This is a string with}"
|
||||
@@ -290,4 +290,126 @@ describe('when parsing directions', function () {
|
||||
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
|
||||
expect(data4Layout.nodes[0].label).toEqual('This is a string with}');
|
||||
});
|
||||
|
||||
it('should be possible to use @ syntax to add labels on multi nodes', function () {
|
||||
const res = flow.parser.parse(`flowchart TB
|
||||
n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"}
|
||||
`);
|
||||
|
||||
const data4Layout = flow.parser.yy.getData();
|
||||
expect(data4Layout.nodes.length).toBe(3);
|
||||
expect(data4Layout.nodes[0].label).toEqual('label for n2');
|
||||
expect(data4Layout.nodes[1].label).toEqual('labe for n4');
|
||||
expect(data4Layout.nodes[2].label).toEqual('labe for n5');
|
||||
});
|
||||
|
||||
it('should be possible to use @ syntax to add labels on multi nodes with edge/link', function () {
|
||||
const res = flow.parser.parse(`flowchart TD
|
||||
A["A"] --> B["for B"] & C@{ label: "for c"} & E@{label : "for E"}
|
||||
D@{label: "for D"}
|
||||
`);
|
||||
|
||||
const data4Layout = flow.parser.yy.getData();
|
||||
expect(data4Layout.nodes.length).toBe(5);
|
||||
expect(data4Layout.nodes[0].label).toEqual('A');
|
||||
expect(data4Layout.nodes[1].label).toEqual('for B');
|
||||
expect(data4Layout.nodes[2].label).toEqual('for c');
|
||||
expect(data4Layout.nodes[3].label).toEqual('for E');
|
||||
expect(data4Layout.nodes[4].label).toEqual('for D');
|
||||
});
|
||||
|
||||
it('should be possible to use @ syntax in labels', function () {
|
||||
const res = flow.parser.parse(`flowchart TD
|
||||
A["@A@"] --> B["@for@ B@"] & C@{ label: "@for@ c@"} & E{"\`@for@ E@\`"} & D(("@for@ D@"))
|
||||
H1{{"@for@ H@"}}
|
||||
H2{{"\`@for@ H@\`"}}
|
||||
Q1{"@for@ Q@"}
|
||||
Q2{"\`@for@ Q@\`"}
|
||||
AS1>"@for@ AS@"]
|
||||
AS2>"\`@for@ AS@\`"]
|
||||
`);
|
||||
|
||||
const data4Layout = flow.parser.yy.getData();
|
||||
expect(data4Layout.nodes.length).toBe(11);
|
||||
expect(data4Layout.nodes[0].label).toEqual('@A@');
|
||||
expect(data4Layout.nodes[1].label).toEqual('@for@ B@');
|
||||
expect(data4Layout.nodes[2].label).toEqual('@for@ c@');
|
||||
expect(data4Layout.nodes[3].label).toEqual('@for@ E@');
|
||||
expect(data4Layout.nodes[4].label).toEqual('@for@ D@');
|
||||
expect(data4Layout.nodes[5].label).toEqual('@for@ H@');
|
||||
expect(data4Layout.nodes[6].label).toEqual('@for@ H@');
|
||||
expect(data4Layout.nodes[7].label).toEqual('@for@ Q@');
|
||||
expect(data4Layout.nodes[8].label).toEqual('@for@ Q@');
|
||||
expect(data4Layout.nodes[9].label).toEqual('@for@ AS@');
|
||||
expect(data4Layout.nodes[10].label).toEqual('@for@ AS@');
|
||||
});
|
||||
|
||||
it('should handle unique edge creation with using @ and &', function () {
|
||||
const res = flow.parser.parse(`flowchart TD
|
||||
A & B e1@--> C & D
|
||||
A1 e2@--> C1 & D1
|
||||
`);
|
||||
|
||||
const data4Layout = flow.parser.yy.getData();
|
||||
expect(data4Layout.nodes.length).toBe(7);
|
||||
expect(data4Layout.edges.length).toBe(6);
|
||||
expect(data4Layout.edges[0].id).toEqual('L_A_C_0');
|
||||
expect(data4Layout.edges[1].id).toEqual('L_A_D_0');
|
||||
expect(data4Layout.edges[2].id).toEqual('e1');
|
||||
expect(data4Layout.edges[3].id).toEqual('L_B_D_0');
|
||||
expect(data4Layout.edges[4].id).toEqual('e2');
|
||||
expect(data4Layout.edges[5].id).toEqual('L_A1_D1_0');
|
||||
});
|
||||
|
||||
it('should handle redefine same edge ids again', function () {
|
||||
const res = flow.parser.parse(`flowchart TD
|
||||
A & B e1@--> C & D
|
||||
A1 e1@--> C1 & D1
|
||||
`);
|
||||
|
||||
const data4Layout = flow.parser.yy.getData();
|
||||
expect(data4Layout.nodes.length).toBe(7);
|
||||
expect(data4Layout.edges.length).toBe(6);
|
||||
expect(data4Layout.edges[0].id).toEqual('L_A_C_0');
|
||||
expect(data4Layout.edges[1].id).toEqual('L_A_D_0');
|
||||
expect(data4Layout.edges[2].id).toEqual('e1');
|
||||
expect(data4Layout.edges[3].id).toEqual('L_B_D_0');
|
||||
expect(data4Layout.edges[4].id).toEqual('L_A1_C1_0');
|
||||
expect(data4Layout.edges[5].id).toEqual('L_A1_D1_0');
|
||||
});
|
||||
|
||||
it('should handle overriding edge animate again', function () {
|
||||
const res = flow.parser.parse(`flowchart TD
|
||||
A e1@--> B
|
||||
C e2@--> D
|
||||
E e3@--> F
|
||||
e1@{ animate: true }
|
||||
e2@{ animate: false }
|
||||
e3@{ animate: true }
|
||||
e3@{ animate: false }
|
||||
`);
|
||||
|
||||
const data4Layout = flow.parser.yy.getData();
|
||||
expect(data4Layout.nodes.length).toBe(6);
|
||||
expect(data4Layout.edges.length).toBe(3);
|
||||
expect(data4Layout.edges[0].id).toEqual('e1');
|
||||
expect(data4Layout.edges[0].animate).toEqual(true);
|
||||
expect(data4Layout.edges[1].id).toEqual('e2');
|
||||
expect(data4Layout.edges[1].animate).toEqual(false);
|
||||
expect(data4Layout.edges[2].id).toEqual('e3');
|
||||
expect(data4Layout.edges[2].animate).toEqual(false);
|
||||
});
|
||||
|
||||
it.skip('should be possible to use @ syntax to add labels with trail spaces', function () {
|
||||
const res = flow.parser.parse(
|
||||
`flowchart TB
|
||||
n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"} `
|
||||
);
|
||||
|
||||
const data4Layout = flow.parser.yy.getData();
|
||||
expect(data4Layout.nodes.length).toBe(3);
|
||||
expect(data4Layout.nodes[0].label).toEqual('label for n2');
|
||||
expect(data4Layout.nodes[1].label).toEqual('labe for n4');
|
||||
expect(data4Layout.nodes[2].label).toEqual('labe for n5');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
setConfig({
|
||||
@@ -31,7 +31,7 @@ const specialChars = ['#', ':', '0', '&', ',', '*', '.', '\\', 'v', '-', '/', '_
|
||||
|
||||
describe('[Singlenodes] when parsing', () => {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
setConfig({
|
||||
@@ -8,7 +8,7 @@ setConfig({
|
||||
|
||||
describe('[Style] when parsing', () => {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
flow.parser.yy.setGen('gen-2');
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
setConfig({
|
||||
@@ -8,7 +8,7 @@ setConfig({
|
||||
|
||||
describe('[Text] when parsing', () => {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
setConfig({
|
||||
@@ -8,7 +8,7 @@ setConfig({
|
||||
|
||||
describe('when parsing flowcharts', function () {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
flow.parser.yy.setGen('gen-2');
|
||||
});
|
||||
|
||||
@@ -141,6 +141,7 @@ that id.
|
||||
.*direction\s+RL[^\n]* return 'direction_rl';
|
||||
.*direction\s+LR[^\n]* return 'direction_lr';
|
||||
|
||||
[^\s\"]+\@(?=[^\{\"]) { return 'LINK_ID'; }
|
||||
[0-9]+ return 'NUM';
|
||||
\# return 'BRKT';
|
||||
":::" return 'STYLE_SEPARATOR';
|
||||
@@ -201,7 +202,9 @@ that id.
|
||||
"*" return 'MULT';
|
||||
"#" return 'BRKT';
|
||||
"&" return 'AMP';
|
||||
([A-Za-z0-9!"\#$%&'*+\.`?\\_\/]|\-(?=[^\>\-\.])|=(?!=))+ return 'NODE_STRING';
|
||||
([A-Za-z0-9!"\#$%&'*+\.`?\\_\/]|\-(?=[^\>\-\.])|=(?!=))+ {
|
||||
return 'NODE_STRING';
|
||||
}
|
||||
"-" return 'MINUS'
|
||||
[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|
|
||||
[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|
|
||||
@@ -361,7 +364,7 @@ spaceList
|
||||
|
||||
statement
|
||||
: vertexStatement separator
|
||||
{ /* console.warn('finat vs', $vertexStatement.nodes); */ $$=$vertexStatement.nodes}
|
||||
{ $$=$vertexStatement.nodes}
|
||||
| styleStatement separator
|
||||
{$$=[];}
|
||||
| linkStyleStatement separator
|
||||
@@ -396,7 +399,7 @@ shapeData:
|
||||
;
|
||||
|
||||
vertexStatement: vertexStatement link node shapeData
|
||||
{ /* console.warn('vs shapeData',$vertexStatement.stmt,$node, $shapeData);*/ yy.addVertex($node[0],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData); yy.addLink($vertexStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($vertexStatement.nodes) } }
|
||||
{ /* console.warn('vs shapeData',$vertexStatement.stmt,$node, $shapeData);*/ yy.addVertex($node[$node.length-1],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData); yy.addLink($vertexStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($vertexStatement.nodes) } }
|
||||
| vertexStatement link node
|
||||
{ /*console.warn('vs',$vertexStatement.stmt,$node);*/ yy.addLink($vertexStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($vertexStatement.nodes) } }
|
||||
| vertexStatement link node spaceList
|
||||
@@ -404,7 +407,7 @@ vertexStatement: vertexStatement link node shapeData
|
||||
|node spaceList { /*console.warn('vertexStatement: node spaceList', $node);*/ $$ = {stmt: $node, nodes:$node }}
|
||||
|node shapeData {
|
||||
/*console.warn('vertexStatement: node shapeData', $node[0], $shapeData);*/
|
||||
yy.addVertex($node[0],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData);
|
||||
yy.addVertex($node[$node.length-1],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData);
|
||||
$$ = {stmt: $node, nodes:$node, shapeData: $shapeData}
|
||||
}
|
||||
|node { /* console.warn('vertexStatement: single node', $node); */ $$ = {stmt: $node, nodes:$node }}
|
||||
@@ -413,7 +416,7 @@ vertexStatement: vertexStatement link node shapeData
|
||||
node: styledVertex
|
||||
{ /*console.warn('nod', $styledVertex);*/ $$ = [$styledVertex];}
|
||||
| node shapeData spaceList AMP spaceList styledVertex
|
||||
{ yy.addVertex($node[0],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData); $$ = $node.concat($styledVertex); /*console.warn('pip2', $node[0], $styledVertex, $$);*/ }
|
||||
{ yy.addVertex($node[$node.length-1],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData); $$ = $node.concat($styledVertex); /*console.warn('pip2', $node[0], $styledVertex, $$);*/ }
|
||||
| node spaceList AMP spaceList styledVertex
|
||||
{ $$ = $node.concat($styledVertex); /*console.warn('pip', $node[0], $styledVertex, $$);*/ }
|
||||
;
|
||||
@@ -472,6 +475,8 @@ link: linkStatement arrowText
|
||||
{$$ = $linkStatement;}
|
||||
| START_LINK edgeText LINK
|
||||
{var inf = yy.destructLink($LINK, $START_LINK); $$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length,"text":$edgeText};}
|
||||
| LINK_ID START_LINK edgeText LINK
|
||||
{var inf = yy.destructLink($LINK, $START_LINK); $$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length,"text":$edgeText, "id": $LINK_ID};}
|
||||
;
|
||||
|
||||
edgeText: edgeTextToken
|
||||
@@ -487,6 +492,8 @@ edgeText: edgeTextToken
|
||||
|
||||
linkStatement: LINK
|
||||
{var inf = yy.destructLink($LINK);$$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length};}
|
||||
| LINK_ID LINK
|
||||
{var inf = yy.destructLink($LINK);$$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length, "id": $LINK_ID};}
|
||||
;
|
||||
|
||||
arrowText:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { cleanupComments } from '../../../diagram-api/comments.js';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
@@ -9,7 +9,7 @@ setConfig({
|
||||
|
||||
describe('parsing a flow chart', function () {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
|
||||
12
packages/mermaid/src/diagrams/flowchart/parser/flowParser.ts
Normal file
12
packages/mermaid/src/diagrams/flowchart/parser/flowParser.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// @ts-ignore: JISON doesn't support types
|
||||
import flowJisonParser from './flow.jison';
|
||||
|
||||
const newParser = Object.assign({}, flowJisonParser);
|
||||
|
||||
newParser.parse = (src: string): unknown => {
|
||||
// remove the trailing whitespace after closing curly braces when ending a line break
|
||||
const newSrc = src.replace(/}\s*\n/g, '}\n');
|
||||
return flowJisonParser.parse(newSrc);
|
||||
};
|
||||
|
||||
export default newParser;
|
||||
@@ -1,5 +1,5 @@
|
||||
import flowDb from '../flowDb.js';
|
||||
import flow from './flow.jison';
|
||||
import { FlowDB } from '../flowDb.js';
|
||||
import flow from './flowParser.ts';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
setConfig({
|
||||
@@ -8,7 +8,7 @@ setConfig({
|
||||
|
||||
describe('when parsing subgraphs', function () {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy = new FlowDB();
|
||||
flow.parser.yy.clear();
|
||||
flow.parser.yy.setGen('gen-2');
|
||||
});
|
||||
|
||||
@@ -53,6 +53,7 @@ export interface FlowText {
|
||||
}
|
||||
|
||||
export interface FlowEdge {
|
||||
isUserDefinedId: boolean;
|
||||
start: string;
|
||||
end: string;
|
||||
interpolate?: string;
|
||||
@@ -62,6 +63,10 @@ export interface FlowEdge {
|
||||
length?: number;
|
||||
text: string;
|
||||
labelType: 'text';
|
||||
classes: string[];
|
||||
id?: string;
|
||||
animation?: 'fast' | 'slow';
|
||||
animate?: boolean;
|
||||
}
|
||||
|
||||
export interface FlowClass {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const getStyles = (options) =>
|
||||
`
|
||||
.mermaid-main-font {
|
||||
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
||||
font-family: ${options.fontFamily};
|
||||
}
|
||||
|
||||
.exclude-range {
|
||||
@@ -45,7 +45,7 @@ const getStyles = (options) =>
|
||||
|
||||
.sectionTitle {
|
||||
text-anchor: start;
|
||||
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
||||
font-family: ${options.fontFamily};
|
||||
}
|
||||
|
||||
|
||||
@@ -86,13 +86,13 @@ const getStyles = (options) =>
|
||||
|
||||
.taskText {
|
||||
text-anchor: middle;
|
||||
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
||||
font-family: ${options.fontFamily};
|
||||
}
|
||||
|
||||
.taskTextOutsideRight {
|
||||
fill: ${options.taskTextDarkColor};
|
||||
text-anchor: start;
|
||||
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
||||
font-family: ${options.fontFamily};
|
||||
}
|
||||
|
||||
.taskTextOutsideLeft {
|
||||
@@ -248,7 +248,7 @@ const getStyles = (options) =>
|
||||
text-anchor: middle;
|
||||
font-size: 18px;
|
||||
fill: ${options.titleColor || options.textColor};
|
||||
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
||||
font-family: ${options.fontFamily};
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@@ -4,11 +4,13 @@ import parser from './parser/sankey.jison';
|
||||
import db from './sankeyDB.js';
|
||||
import renderer from './sankeyRenderer.js';
|
||||
import { prepareTextForParsing } from './sankeyUtils.js';
|
||||
import sankeyStyles from './styles.js';
|
||||
|
||||
const originalParse = parser.parse.bind(parser);
|
||||
parser.parse = (text: string) => originalParse(prepareTextForParsing(text));
|
||||
|
||||
export const diagram: DiagramDefinition = {
|
||||
styles: sankeyStyles,
|
||||
parser,
|
||||
db,
|
||||
renderer,
|
||||
|
||||
@@ -136,7 +136,6 @@ export const draw = function (text: string, id: string, _version: string, diagOb
|
||||
svg
|
||||
.append('g')
|
||||
.attr('class', 'node-labels')
|
||||
.attr('font-family', 'sans-serif')
|
||||
.attr('font-size', 14)
|
||||
.selectAll('text')
|
||||
.data(graph.nodes)
|
||||
|
||||
6
packages/mermaid/src/diagrams/sankey/styles.js
Normal file
6
packages/mermaid/src/diagrams/sankey/styles.js
Normal file
@@ -0,0 +1,6 @@
|
||||
const getStyles = (options) =>
|
||||
`.label {
|
||||
font-family: ${options.fontFamily};
|
||||
}`;
|
||||
|
||||
export default getStyles;
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,26 @@
|
||||
import type { DiagramDefinition } from '../../diagram-api/types.js';
|
||||
// @ts-ignore: JISON doesn't support types
|
||||
import parser from './parser/sequenceDiagram.jison';
|
||||
import db from './sequenceDb.js';
|
||||
import { SequenceDB } from './sequenceDb.js';
|
||||
import styles from './styles.js';
|
||||
import { setConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import renderer from './sequenceRenderer.js';
|
||||
import type { MermaidConfig } from '../../config.type.js';
|
||||
|
||||
export const diagram: DiagramDefinition = {
|
||||
parser,
|
||||
db,
|
||||
get db() {
|
||||
return new SequenceDB();
|
||||
},
|
||||
renderer,
|
||||
styles,
|
||||
init: ({ wrap }) => {
|
||||
db.setWrap(wrap);
|
||||
init: (cnf: MermaidConfig) => {
|
||||
if (!cnf.sequence) {
|
||||
cnf.sequence = {};
|
||||
}
|
||||
if (cnf.wrap) {
|
||||
cnf.sequence.wrap = cnf.wrap;
|
||||
setConfig({ sequence: { wrap: cnf.wrap } });
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1538,7 +1538,6 @@ const calculateLoopBounds = async function (messages, actors, _maxWidthPerActor,
|
||||
let current, noteModel, msgModel;
|
||||
|
||||
for (const msg of messages) {
|
||||
msg.id = utils.random({ length: 10 });
|
||||
switch (msg.type) {
|
||||
case diagObj.db.LINETYPE.LOOP_START:
|
||||
case diagObj.db.LINETYPE.ALT_START:
|
||||
|
||||
@@ -20,6 +20,7 @@ export interface Actor {
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
id: string;
|
||||
from?: string;
|
||||
to?: string;
|
||||
message:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import stateDb from '../stateDb.js';
|
||||
import { StateDB } from '../stateDb.js';
|
||||
import stateDiagram from './stateDiagram.jison';
|
||||
import { setConfig } from '../../../config.js';
|
||||
|
||||
@@ -7,7 +7,9 @@ setConfig({
|
||||
});
|
||||
|
||||
describe('state parser can parse...', () => {
|
||||
let stateDb;
|
||||
beforeEach(function () {
|
||||
stateDb = new StateDB(2);
|
||||
stateDiagram.parser.yy = stateDb;
|
||||
stateDiagram.parser.yy.clear();
|
||||
});
|
||||
@@ -18,7 +20,6 @@ describe('state parser can parse...', () => {
|
||||
const diagramText = `stateDiagram-v2
|
||||
state "Small State 1" as namedState1`;
|
||||
stateDiagram.parser.parse(diagramText);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const states = stateDiagram.parser.yy.getStates();
|
||||
expect(states.get('namedState1')).not.toBeUndefined();
|
||||
@@ -31,7 +32,6 @@ describe('state parser can parse...', () => {
|
||||
const diagramText = `stateDiagram-v2
|
||||
namedState1 : Small State 1`;
|
||||
stateDiagram.parser.parse(diagramText);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const states = stateDiagram.parser.yy.getStates();
|
||||
expect(states.get('namedState1')).not.toBeUndefined();
|
||||
@@ -42,7 +42,6 @@ describe('state parser can parse...', () => {
|
||||
const diagramText = `stateDiagram-v2
|
||||
namedState1:Small State 1`;
|
||||
stateDiagram.parser.parse(diagramText);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const states = stateDiagram.parser.yy.getStates();
|
||||
expect(states.get('namedState1')).not.toBeUndefined();
|
||||
@@ -60,7 +59,6 @@ describe('state parser can parse...', () => {
|
||||
state assemblies
|
||||
`;
|
||||
stateDiagram.parser.parse(diagramText);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
const states = stateDiagram.parser.yy.getStates();
|
||||
expect(states.get('assemble')).not.toBeUndefined();
|
||||
expect(states.get('assemblies')).not.toBeUndefined();
|
||||
@@ -71,7 +69,6 @@ describe('state parser can parse...', () => {
|
||||
state "as" as as
|
||||
`;
|
||||
stateDiagram.parser.parse(diagramText);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
const states = stateDiagram.parser.yy.getStates();
|
||||
expect(states.get('as')).not.toBeUndefined();
|
||||
expect(states.get('as').descriptions.join(' ')).toEqual('as');
|
||||
@@ -96,7 +93,6 @@ describe('state parser can parse...', () => {
|
||||
namedState2 --> bigState2: should point to \\nbigState2 container`;
|
||||
|
||||
stateDiagram.parser.parse(diagramText);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const states = stateDiagram.parser.yy.getStates();
|
||||
expect(states.get('namedState1')).not.toBeUndefined();
|
||||
@@ -120,7 +116,6 @@ describe('state parser can parse...', () => {
|
||||
inner1 --> inner2
|
||||
}`;
|
||||
stateDiagram.parser.parse(diagramText);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const states = stateDiagram.parser.yy.getStates();
|
||||
expect(states.get('bigState1')).not.toBeUndefined();
|
||||
@@ -137,7 +132,6 @@ describe('state parser can parse...', () => {
|
||||
stateDiagram-v2
|
||||
[*] --> ${prop}
|
||||
${prop} --> [*]`);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
const states = stateDiagram.parser.yy.getStates();
|
||||
expect(states.get(prop)).not.toBeUndefined();
|
||||
});
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import stateDb from '../stateDb.js';
|
||||
import stateDiagram from './stateDiagram.jison';
|
||||
import { setConfig } from '../../../config.js';
|
||||
import { StateDB } from '../stateDb.js';
|
||||
import stateDiagram from './stateDiagram.jison';
|
||||
|
||||
setConfig({
|
||||
securityLevel: 'strict',
|
||||
});
|
||||
|
||||
describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
let stateDb;
|
||||
beforeEach(function () {
|
||||
stateDb = new StateDB(2);
|
||||
stateDiagram.parser.yy = stateDb;
|
||||
stateDiagram.parser.yy.clear();
|
||||
});
|
||||
@@ -16,7 +18,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
describe('defining (classDef)', () => {
|
||||
it('has "classDef" as a keyword, an id, and can set a css style attribute', function () {
|
||||
stateDiagram.parser.parse('stateDiagram-v2\n classDef exampleClass background:#bbb;');
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const styleClasses = stateDb.getClasses();
|
||||
expect(styleClasses.get('exampleClass').styles.length).toEqual(1);
|
||||
@@ -27,7 +28,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
stateDiagram.parser.parse(
|
||||
'stateDiagram-v2\n classDef exampleClass background:#bbb, font-weight:bold, font-style:italic;'
|
||||
);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const styleClasses = stateDb.getClasses();
|
||||
expect(styleClasses.get('exampleClass').styles.length).toEqual(3);
|
||||
@@ -41,7 +41,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
stateDiagram.parser.parse(
|
||||
'stateDiagram-v2\n classDef exampleStyleClass background:#bbb,border:1.5px solid red;'
|
||||
);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const classes = stateDiagram.parser.yy.getClasses();
|
||||
expect(classes.get('exampleStyleClass').styles.length).toBe(2);
|
||||
@@ -53,7 +52,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
stateDiagram.parser.parse(
|
||||
'stateDiagram-v2\n classDef exampleStyleClass background: #bbb,border:1.5px solid red;'
|
||||
);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const classes = stateDiagram.parser.yy.getClasses();
|
||||
expect(classes.get('exampleStyleClass').styles.length).toBe(2);
|
||||
@@ -65,7 +63,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
stateDiagram.parser.parse(
|
||||
'stateDiagram-v2\n classDef __proto__ background:#bbb,border:1.5px solid red;\n classDef constructor background:#bbb,border:1.5px solid red;'
|
||||
);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
const classes = stateDiagram.parser.yy.getClasses();
|
||||
expect(classes.get('__proto__').styles.length).toBe(2);
|
||||
expect(classes.get('constructor').styles.length).toBe(2);
|
||||
@@ -81,7 +78,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
diagram += 'class a exampleStyleClass';
|
||||
|
||||
stateDiagram.parser.parse(diagram);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const classes = stateDb.getClasses();
|
||||
expect(classes.get('exampleStyleClass').styles.length).toEqual(2);
|
||||
@@ -102,7 +98,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
diagram += 'class a_a exampleStyleClass';
|
||||
|
||||
stateDiagram.parser.parse(diagram);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const classes = stateDiagram.parser.yy.getClasses();
|
||||
expect(classes.get('exampleStyleClass').styles.length).toBe(2);
|
||||
@@ -122,7 +117,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
diagram += 'a --> b:::exampleStyleClass' + '\n';
|
||||
|
||||
stateDiagram.parser.parse(diagram);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const states = stateDiagram.parser.yy.getStates();
|
||||
const classes = stateDiagram.parser.yy.getClasses();
|
||||
@@ -141,7 +135,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
diagram += '[*]:::exampleStyleClass --> b\n';
|
||||
|
||||
stateDiagram.parser.parse(diagram);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const states = stateDiagram.parser.yy.getStates();
|
||||
const classes = stateDiagram.parser.yy.getClasses();
|
||||
@@ -161,7 +154,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
diagram += 'class a,b exampleStyleClass';
|
||||
|
||||
stateDiagram.parser.parse(diagram);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
let classes = stateDiagram.parser.yy.getClasses();
|
||||
let states = stateDiagram.parser.yy.getStates();
|
||||
|
||||
@@ -180,7 +172,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
diagram += 'class a,b,c, d, e exampleStyleClass';
|
||||
|
||||
stateDiagram.parser.parse(diagram);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
const classes = stateDiagram.parser.yy.getClasses();
|
||||
const states = stateDiagram.parser.yy.getStates();
|
||||
|
||||
@@ -208,7 +199,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
diagram += '}\n';
|
||||
|
||||
stateDiagram.parser.parse(diagram);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const states = stateDiagram.parser.yy.getStates();
|
||||
|
||||
@@ -224,7 +214,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
stateDiagram.parser.parse(`stateDiagram-v2
|
||||
id1
|
||||
style id1 background:#bbb`);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
const data4Layout = stateDiagram.parser.yy.getData();
|
||||
|
||||
expect(data4Layout.nodes[0].cssStyles).toEqual(['background:#bbb']);
|
||||
@@ -234,7 +223,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
id1
|
||||
id2
|
||||
style id1,id2 background:#bbb`);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
const data4Layout = stateDiagram.parser.yy.getData();
|
||||
|
||||
expect(data4Layout.nodes[0].cssStyles).toEqual(['background:#bbb']);
|
||||
@@ -247,7 +235,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
id2
|
||||
style id1,id2 background:#bbb, font-weight:bold, font-style:italic;`);
|
||||
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
const data4Layout = stateDiagram.parser.yy.getData();
|
||||
|
||||
expect(data4Layout.nodes[0].cssStyles).toEqual([
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { line, curveBasis } from 'd3';
|
||||
import idCache from './id-cache.js';
|
||||
import stateDb from './stateDb.js';
|
||||
import { StateDB } from './stateDb.js';
|
||||
import utils from '../../utils.js';
|
||||
import common from '../common/common.js';
|
||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||
@@ -414,13 +414,13 @@ let edgeCount = 0;
|
||||
export const drawEdge = function (elem, path, relation) {
|
||||
const getRelationType = function (type) {
|
||||
switch (type) {
|
||||
case stateDb.relationType.AGGREGATION:
|
||||
case StateDB.relationType.AGGREGATION:
|
||||
return 'aggregation';
|
||||
case stateDb.relationType.EXTENSION:
|
||||
case StateDB.relationType.EXTENSION:
|
||||
return 'extension';
|
||||
case stateDb.relationType.COMPOSITION:
|
||||
case StateDB.relationType.COMPOSITION:
|
||||
return 'composition';
|
||||
case stateDb.relationType.DEPENDENCY:
|
||||
case StateDB.relationType.DEPENDENCY:
|
||||
return 'dependency';
|
||||
}
|
||||
};
|
||||
@@ -459,7 +459,7 @@ export const drawEdge = function (elem, path, relation) {
|
||||
|
||||
svgPath.attr(
|
||||
'marker-end',
|
||||
'url(' + url + '#' + getRelationType(stateDb.relationType.DEPENDENCY) + 'End' + ')'
|
||||
'url(' + url + '#' + getRelationType(StateDB.relationType.DEPENDENCY) + 'End' + ')'
|
||||
);
|
||||
|
||||
if (relation.title !== undefined) {
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
*/
|
||||
|
||||
// default diagram direction
|
||||
export const DEFAULT_DIAGRAM_DIRECTION = 'LR';
|
||||
export const DEFAULT_DIAGRAM_DIRECTION = 'TB';
|
||||
|
||||
// default direction for any nested documents (composites)
|
||||
export const DEFAULT_NESTED_DOC_DIR = 'TB';
|
||||
|
||||
// parsed statement type for a direction
|
||||
export const STMT_DIRECTION = 'dir';
|
||||
|
||||
// parsed statement type for a state
|
||||
export const STMT_STATE = 'state';
|
||||
// parsed statement type for a relation
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,9 @@
|
||||
import stateDb from './stateDb.js';
|
||||
import { StateDB } from './stateDb.js';
|
||||
|
||||
describe('State Diagram stateDb', () => {
|
||||
let stateDb;
|
||||
beforeEach(() => {
|
||||
stateDb.clear();
|
||||
stateDb = new StateDB(1);
|
||||
});
|
||||
|
||||
describe('addStyleClass', () => {
|
||||
@@ -20,8 +21,9 @@ describe('State Diagram stateDb', () => {
|
||||
});
|
||||
|
||||
describe('addDescription to a state', () => {
|
||||
let stateDb;
|
||||
beforeEach(() => {
|
||||
stateDb.clear();
|
||||
stateDb = new StateDB(1);
|
||||
stateDb.addState('state1');
|
||||
});
|
||||
|
||||
@@ -73,3 +75,25 @@ describe('State Diagram stateDb', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('state db class', () => {
|
||||
let stateDb;
|
||||
beforeEach(() => {
|
||||
stateDb = new StateDB(1);
|
||||
});
|
||||
// This is to ensure that functions used in state JISON are exposed as function from StateDb
|
||||
it('should have functions used in flow JISON as own property', () => {
|
||||
const functionsUsedInParser = [
|
||||
'setRootDoc',
|
||||
'trimColon',
|
||||
'getDividerId',
|
||||
'setAccTitle',
|
||||
'setAccDescription',
|
||||
'setDirection',
|
||||
];
|
||||
|
||||
for (const fun of functionsUsedInParser) {
|
||||
expect(Object.hasOwn(stateDb, fun)).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { parser } from './parser/stateDiagram.jison';
|
||||
import stateDb from './stateDb.js';
|
||||
import stateDiagram from './parser/stateDiagram.jison';
|
||||
import stateDiagram, { parser } from './parser/stateDiagram.jison';
|
||||
import { DEFAULT_DIAGRAM_DIRECTION } from './stateCommon.js';
|
||||
import { StateDB } from './stateDb.js';
|
||||
|
||||
describe('state diagram V2, ', function () {
|
||||
// TODO - these examples should be put into ./parser/stateDiagram.spec.js
|
||||
describe('when parsing an info graph it', function () {
|
||||
let stateDb;
|
||||
beforeEach(function () {
|
||||
stateDb = new StateDB(2);
|
||||
parser.yy = stateDb;
|
||||
stateDiagram.parser.yy = stateDb;
|
||||
stateDiagram.parser.yy.clear();
|
||||
@@ -127,7 +129,6 @@ describe('state diagram V2, ', function () {
|
||||
`;
|
||||
|
||||
stateDiagram.parser.parse(diagram);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const rels = stateDb.getRelations();
|
||||
const rel_1_2 = rels.find((rel) => rel.id1 === 'State1' && rel.id2 === 'State2');
|
||||
@@ -402,7 +403,6 @@ describe('state diagram V2, ', function () {
|
||||
`;
|
||||
|
||||
stateDiagram.parser.parse(diagram);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const states = stateDb.getStates();
|
||||
expect(states.get('Active').doc[0].id).toEqual('Idle');
|
||||
@@ -413,5 +413,34 @@ describe('state diagram V2, ', function () {
|
||||
const rel_Active_Active = rels.find((rel) => rel.id1 === 'Active' && rel.id2 === 'Active');
|
||||
expect(rel_Active_Active.relationTitle).toEqual('LOG');
|
||||
});
|
||||
|
||||
it('should check default diagram direction', () => {
|
||||
const diagram = `
|
||||
stateDiagram
|
||||
[*] --> Still
|
||||
Still --> [*]
|
||||
`;
|
||||
|
||||
parser.parse(diagram);
|
||||
|
||||
// checking default direction if no direction is specified
|
||||
const defaultDir = stateDb.getDirection();
|
||||
expect(defaultDir).toEqual(DEFAULT_DIAGRAM_DIRECTION);
|
||||
});
|
||||
|
||||
it('retrieve the diagram direction correctly', () => {
|
||||
const diagram = `
|
||||
stateDiagram
|
||||
direction LR
|
||||
[*] --> Still
|
||||
Still --> [*]
|
||||
`;
|
||||
|
||||
parser.parse(diagram);
|
||||
|
||||
//retrieve the diagram direction
|
||||
const currentDirection = stateDb.getDirection();
|
||||
expect(currentDirection).toEqual('LR');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user