mirror of
				https://github.com/mermaid-js/mermaid.git
				synced 2025-10-31 02:44:17 +01:00 
			
		
		
		
	Compare commits
	
		
			261 Commits
		
	
	
		
			4743-timel
			...
			architectu
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 0a23304d1a | ||
|   | 7effdc147b | ||
|   | 6e67515f41 | ||
|   | d5c4eff251 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 5324fd8dfd | ||
|   | 37e3a6951b | ||
|   | 0de0b063e4 | ||
|   | 619515e5a9 | ||
|   | 59c8b07509 | ||
|   | 9e72bbf62d | ||
|   | 2a2c46f1e2 | ||
|   | f25df353d4 | ||
|   | 398345a8bc | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | 7fd2d94ef7 | ||
|   | bcc1472b9d | ||
|   | ddc1cfe6c8 | ||
|   | 18e9c1174d | ||
|   | 789018abf6 | ||
|   | 16569b295b | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 11a35c11ee | ||
|   | 216be22801 | ||
|   | e87f77a865 | ||
|   | a9579083bf | ||
|   | 6fd78d0856 | ||
|   | 994f7df29a | ||
|   | 531f5e9380 | ||
|   | dc11b8645c | ||
|   | ad4c227477 | ||
|   | 181af8167b | ||
|   | 799d2ed547 | ||
|   | a44e3e992c | ||
|   | ca5b370ffb | ||
|   | 08160a74b4 | ||
|   | 6d221fb3ca | ||
|   | 8b20907141 | ||
|   | d318f1a13c | ||
|   | 525a7de8ae | ||
|   | a459c436c9 | ||
|   | 1c2a0020bd | ||
|   | 141c6b3808 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 8d4ffdf808 | ||
|   | 32106e259c | ||
|   | 450754221e | ||
|   | 7a4f5b62c9 | ||
|   | b36edd557e | ||
|   | 5e3b5e8f36 | ||
|   | 764b315dc1 | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | 47c0d2d040 | ||
|   | ac3b777bf6 | ||
|   | cf08ba0ef8 | ||
|   | 166782cd38 | ||
|   | b37eb6d0d1 | ||
|   | f759f5dcf7 | ||
|   | 80bcefe321 | ||
|   | 70cbbe69d8 | ||
|   | baf4093e8d | ||
|   | fd185f7694 | ||
|   | 027d7b6368 | ||
|   | 7986b66a88 | ||
|   | edb0edc451 | ||
|   | b511a2e9be | ||
|   | 4829dfa8c5 | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | b80ea26a2b | ||
|   | f88986a87d | ||
|   | e16f0848ab | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | e7811886c3 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 32eda8565c | ||
|   | 2812a0d12a | ||
|   | 25fa26d915 | ||
|   | 62915183b1 | ||
|   | 6874ab3fb6 | ||
|   | 040af4f545 | ||
|   | 65ca3eabfd | ||
|   | 8b9bbad842 | ||
|   | d2773db7dc | ||
|   | 3840451fda | ||
|   | cfe9238882 | ||
|   | 9c85521e16 | ||
| ![github-actions[bot]](/assets/img/avatar_default.png)  | 8a565bce92 | ||
|   | baf510b935 | ||
|   | c1f2d052be | ||
|   | bce40e180a | ||
|   | 0dd46a3543 | ||
|   | f81e63663c | ||
|   | 7109e3a17f | ||
|   | e0bd51941e | ||
|   | 38f4e67ca7 | ||
|   | 681d829227 | ||
|   | 164e44c3d9 | ||
|   | f47dec3680 | ||
| ![github-actions[bot]](/assets/img/avatar_default.png)  | 88dc4beade | ||
|   | e9232088c0 | ||
|   | e96614ab86 | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | 73115cb416 | ||
|   | 480438bd52 | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | 34fc8bddc4 | ||
|   | 4dd89e439f | ||
|   | 150177c449 | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | bf58ed2b53 | ||
|   | 827ced0014 | ||
|   | 133d46bde2 | ||
|   | e1017266ac | ||
|   | 404fdaf2ff | ||
|   | 2e1d156d66 | ||
|   | e863ad1547 | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | e231b692fd | ||
|   | 68c365f906 | ||
|   | 494c7294cb | ||
|   | fb20ee99eb | ||
|   | 1a22154a3a | ||
|   | 2972bf25bf | ||
|   | 6b1a7a9e1a | ||
|   | 33bc4a0b4e | ||
|   | c6f25167a2 | ||
|   | a150f92fb0 | ||
|   | 5d31ded7a0 | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | 0ed31bfa2c | ||
|   | 51b9185a6b | ||
|   | b219497847 | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | 7e96c89be5 | ||
|   | 16a8d0e794 | ||
|   | 7bb9981d8a | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | ea3d38bf64 | ||
|   | 8f628b85e5 | ||
|   | defc922acd | ||
|   | 88ae8d1f2b | ||
|   | 8c7c9ac38a | ||
|   | 0e146d50f7 | ||
|   | 454e1e3927 | ||
|   | 4f9875fd4e | ||
|   | 82800a2c84 | ||
|   | 27e700debd | ||
|   | 01e47333d5 | ||
|   | d47ba7c2d1 | ||
|   | b1c4eb3f5c | ||
|   | 869709a75f | ||
|   | 310fcd2292 | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | 85e9ca2a0f | ||
|   | 65d225cb2c | ||
|   | 04b6fc1280 | ||
|   | 21eddc3f23 | ||
|   | f46a151075 | ||
|   | b7e9d02b7c | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | 0ef3130510 | ||
|   | 862d40cc3a | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | 4b63214a72 | ||
|   | 4937ebc058 | ||
|   | 00f5700320 | ||
|   | e32dc8513f | ||
|   | 50127f3ffe | ||
|   | 29bb0e3dca | ||
|   | 1221de4c2d | ||
| ![github-actions[bot]](/assets/img/avatar_default.png)  | c41e08cb7a | ||
|   | 4760ed8893 | ||
|   | 31ecf31c2e | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | b52766653c | ||
|   | 8322a63598 | ||
|   | 202172135d | ||
|   | b94ab243a8 | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | 11c8848e1f | ||
|   | 231fcc700f | ||
|   | 8ba7520acc | ||
|   | e0a5a2489d | ||
|   | bd400a5130 | ||
|   | d35f84f337 | ||
|   | af3bbdc591 | ||
| ![github-actions[bot]](/assets/img/avatar_default.png)  | 8813cf2c94 | ||
|   | d145c0e910 | ||
|   | 8dadb853a0 | ||
|   | a700e8bf97 | ||
|   | 7091792694 | ||
|   | efd94b705d | ||
|   | 9ec989e633 | ||
|   | 61d9143acb | ||
|   | c88f74a6ee | ||
|   | 6377d6f64d | ||
|   | 1b0bc05fc2 | ||
|   | 45edeb9307 | ||
|   | 211974b2b7 | ||
|   | 1f5ad3e315 | ||
|   | d7848e8a3d | ||
|   | c0e2d4a23b | ||
|   | 89b9f0df70 | ||
|   | e9011567bd | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | 0429970d58 | ||
|   | ecad9cee6c | ||
|   | 1e8a9f76a9 | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | e42fdf1c54 | ||
|   | c75566ddc3 | ||
|   | 7e9577dffd | ||
|   | f7a0844a31 | ||
|   | 2817383714 | ||
|   | 180dc7bdff | ||
|   | cc9581842d | ||
|   | a716a525c3 | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | d782e4bb17 | ||
|   | ba9ad9385b | ||
|   | 91edfa40f7 | ||
|   | c8b00bb929 | ||
|   | 57eadbf6af | ||
|   | a906adce26 | ||
|   | 11abfc9ae5 | ||
|   | 227cef05b3 | ||
|   | a6d26ef6c3 | ||
|   | 80c6faf4d5 | ||
|   | 2b3f94eb7d | ||
|   | 81b0ffb92a | ||
|   | dd36046e23 | ||
|   | 1507435e15 | ||
|   | 68c01b76bf | ||
|   | 28717e108d | ||
|   | 688d9b383d | ||
|   | e68424d748 | ||
|   | 204a9a338f | ||
|   | 6a6a39ff33 | ||
| ![autofix-ci[bot]](/assets/img/avatar_default.png)  | b296db9a33 | ||
|   | 01ce84d8ee | ||
|   | f48e663d4c | ||
|   | a4aa2bd355 | ||
|   | b51b9d50c2 | ||
|   | b61780f735 | ||
|   | 1d3681053b | ||
|   | 93df13898f | ||
|   | 074f18dfb8 | ||
|   | d7308b0f43 | ||
|   | 2f1860386a | ||
|   | f0bca7da55 | ||
|   | 6fcdf5bfcc | ||
|   | e2ce0450c1 | ||
|   | c95c64139d | ||
|   | a7f12f1baa | ||
|   | 2a8653de2b | ||
|   | a92c3bb251 | ||
|   | 3677abe9e5 | ||
|   | 95847ad236 | ||
|   | e0152fb873 | ||
|   | 2298b96d8e | ||
|   | 5db83365b6 | ||
|   | 341a81a113 | ||
|   | 8a62b4cace | ||
|   | ccafc20917 | ||
|   | d5cb4eaa59 | ||
|   | 425fb7ee33 | ||
|   | cd6f8e5a24 | ||
|   | 8314554eb5 | ||
|   | b7c03dc27e | ||
|   | c7f2f609a9 | ||
|   | 4c3de3a1ec | ||
|   | f0445b74d1 | ||
|   | ba52eef257 | ||
|   | c13ce2a5c0 | ||
|   | d2463f41b5 | ||
|   | eadb343292 | ||
|   | e7208622f7 | ||
|   | fbae611406 | ||
|   | 34027bc589 | ||
|   | f2eef37599 | ||
|   | 1e3ea13323 | ||
|   | 4c8c48cde9 | ||
|   | c8e50276e8 | ||
|   | 1e6419a63f | 
| @@ -33,6 +33,11 @@ export const packageOptions = { | |||||||
|     packageName: 'mermaid-layout-elk', |     packageName: 'mermaid-layout-elk', | ||||||
|     file: 'layouts.ts', |     file: 'layouts.ts', | ||||||
|   }, |   }, | ||||||
|  |   'mermaid-layout-tidy-tree': { | ||||||
|  |     name: 'mermaid-layout-tidy-tree', | ||||||
|  |     packageName: 'mermaid-layout-tidy-tree', | ||||||
|  |     file: 'index.ts', | ||||||
|  |   }, | ||||||
|   examples: { |   examples: { | ||||||
|     name: 'mermaid-examples', |     name: 'mermaid-examples', | ||||||
|     packageName: 'examples', |     packageName: 'examples', | ||||||
|   | |||||||
| @@ -1,5 +0,0 @@ | |||||||
| --- |  | ||||||
| 'mermaid': patch |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| fix: Handle arrows correctly when auto number is enabled |  | ||||||
							
								
								
									
										5
									
								
								.changeset/deep-pumas-run.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.changeset/deep-pumas-run.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | --- | ||||||
|  | 'mermaid': patch | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | chore: Fix mindmap rendering in docs and apply tidytree layout | ||||||
							
								
								
									
										5
									
								
								.changeset/four-eyes-wish.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.changeset/four-eyes-wish.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | --- | ||||||
|  | 'mermaid': patch | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | fix: Ensure edge label color is applied when using classDef with edge IDs | ||||||
| @@ -1,5 +0,0 @@ | |||||||
| --- |  | ||||||
| 'mermaid': minor |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| feat: Added support for new participant types (`actor`, `boundary`, `control`, `entity`, `database`, `collections`, `queue`) in `sequenceDiagram`. |  | ||||||
							
								
								
									
										5
									
								
								.changeset/moody-fans-try.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.changeset/moody-fans-try.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | --- | ||||||
|  | 'mermaid': patch | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | fix: Resolve gantt chart crash due to invalid array length | ||||||
| @@ -1,5 +0,0 @@ | |||||||
| --- |  | ||||||
| 'mermaid': major |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| Currently, HTML tags such as <em>, <strong>, <sup>, <a>, <ul>, and <li> are supported in Flowchart and Class diagram labels but not in Timeline diagrams. This change introduces support for basic HTML formatting in Timeline labels, enabling richer text formatting and better usability for multi-line content like descriptions, footnotes, and styled annotations |  | ||||||
							
								
								
									
										5
									
								
								.changeset/proud-colts-smell.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.changeset/proud-colts-smell.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | --- | ||||||
|  | 'mermaid': minor | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | feat: Add IDs in architecture diagrams | ||||||
							
								
								
									
										9
									
								
								.changeset/revert-marked-dependency.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								.changeset/revert-marked-dependency.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | --- | ||||||
|  | 'mermaid': patch | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | chore: revert marked dependency from ^15.0.7 to ^16.0.0 | ||||||
|  |  | ||||||
|  | - Reverted marked package version to ^16.0.0 for better compatibility | ||||||
|  | - This is a dependency update that maintains API compatibility | ||||||
|  | - All tests pass with the updated version | ||||||
| @@ -5,8 +5,10 @@ bmatrix | |||||||
| braintree | braintree | ||||||
| catmull | catmull | ||||||
| compositTitleSize | compositTitleSize | ||||||
|  | cose | ||||||
| curv | curv | ||||||
| doublecircle | doublecircle | ||||||
|  | elem | ||||||
| elems | elems | ||||||
| gantt | gantt | ||||||
| gitgraph | gitgraph | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| BRANDES | BRANDES | ||||||
|  | Buzan | ||||||
| circo | circo | ||||||
| handDrawn | handDrawn | ||||||
| KOEPF | KOEPF | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
								
							| @@ -26,8 +26,8 @@ jobs: | |||||||
|     strategy: |     strategy: | ||||||
|       fail-fast: false |       fail-fast: false | ||||||
|       matrix: |       matrix: | ||||||
|         language: ['javascript'] |         language: ['javascript', 'actions'] | ||||||
|         # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] |         # CodeQL supports [ 'actions', 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] | ||||||
|         # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support |         # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support | ||||||
|  |  | ||||||
|     steps: |     steps: | ||||||
| @@ -36,7 +36,7 @@ jobs: | |||||||
|  |  | ||||||
|       # Initializes the CodeQL tools for scanning. |       # Initializes the CodeQL tools for scanning. | ||||||
|       - name: Initialize CodeQL |       - name: Initialize CodeQL | ||||||
|         uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 |         uses: github/codeql-action/init@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21 | ||||||
|         with: |         with: | ||||||
|           config-file: ./.github/codeql/codeql-config.yml |           config-file: ./.github/codeql/codeql-config.yml | ||||||
|           languages: ${{ matrix.language }} |           languages: ${{ matrix.language }} | ||||||
| @@ -48,7 +48,7 @@ jobs: | |||||||
|       # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java). |       # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java). | ||||||
|       # If this step fails, then you should remove it and run the build manually (see below) |       # If this step fails, then you should remove it and run the build manually (see below) | ||||||
|       - name: Autobuild |       - name: Autobuild | ||||||
|         uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 |         uses: github/codeql-action/autobuild@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21 | ||||||
|  |  | ||||||
|       # ℹ️ Command-line programs to run using the OS shell. |       # ℹ️ Command-line programs to run using the OS shell. | ||||||
|       # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun |       # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun | ||||||
| @@ -62,4 +62,4 @@ jobs: | |||||||
|       #   make release |       #   make release | ||||||
|  |  | ||||||
|       - name: Perform CodeQL Analysis |       - name: Perform CodeQL Analysis | ||||||
|         uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 |         uses: github/codeql-action/analyze@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21 | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								.github/workflows/e2e-applitools.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.github/workflows/e2e-applitools.yml
									
									
									
									
										vendored
									
									
								
							| @@ -23,9 +23,6 @@ env: | |||||||
| jobs: | jobs: | ||||||
|   e2e-applitools: |   e2e-applitools: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     container: |  | ||||||
|       image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1 |  | ||||||
|       options: --user 1001 |  | ||||||
|     steps: |     steps: | ||||||
|       - if: ${{ ! env.USE_APPLI }} |       - if: ${{ ! env.USE_APPLI }} | ||||||
|         name: Warn if not using Applitools |         name: Warn if not using Applitools | ||||||
| @@ -56,7 +53,7 @@ jobs: | |||||||
|           args: -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH" |           args: -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH" | ||||||
|  |  | ||||||
|       - name: Cypress run |       - name: Cypress run | ||||||
|         uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 |         uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16 | ||||||
|         id: cypress |         id: cypress | ||||||
|         with: |         with: | ||||||
|           start: pnpm run dev |           start: pnpm run dev | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								.github/workflows/e2e-timings.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/e2e-timings.yml
									
									
									
									
										vendored
									
									
								
							| @@ -27,12 +27,12 @@ jobs: | |||||||
|         with: |         with: | ||||||
|           node-version-file: '.node-version' |           node-version-file: '.node-version' | ||||||
|       - name: Install dependencies |       - name: Install dependencies | ||||||
|         uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 |         uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16 | ||||||
|         with: |         with: | ||||||
|           runTests: false |           runTests: false | ||||||
|  |  | ||||||
|       - name: Cypress run |       - name: Cypress run | ||||||
|         uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 |         uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16 | ||||||
|         id: cypress |         id: cypress | ||||||
|         with: |         with: | ||||||
|           install: false |           install: false | ||||||
| @@ -58,7 +58,7 @@ jobs: | |||||||
|           echo "EOF" >> $GITHUB_OUTPUT |           echo "EOF" >> $GITHUB_OUTPUT | ||||||
|  |  | ||||||
|       - name: Commit and create pull request |       - name: Commit and create pull request | ||||||
|         uses: peter-evans/create-pull-request@cb4d3bfce175d44325c6b7697f81e0afe8a79bdf |         uses: peter-evans/create-pull-request@915d841dae6a4f191bb78faf61a257411d7be4d2 | ||||||
|         with: |         with: | ||||||
|           add-paths: | |           add-paths: | | ||||||
|             cypress/timings.json |             cypress/timings.json | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								.github/workflows/e2e.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.github/workflows/e2e.yml
									
									
									
									
										vendored
									
									
								
							| @@ -45,7 +45,7 @@ jobs: | |||||||
|           node-version-file: '.node-version' |           node-version-file: '.node-version' | ||||||
|       - name: Cache snapshots |       - name: Cache snapshots | ||||||
|         id: cache-snapshot |         id: cache-snapshot | ||||||
|         uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 |         uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 | ||||||
|         with: |         with: | ||||||
|           path: ./cypress/snapshots |           path: ./cypress/snapshots | ||||||
|           key: ${{ runner.os }}-snapshots-${{ env.targetHash }} |           key: ${{ runner.os }}-snapshots-${{ env.targetHash }} | ||||||
| @@ -59,7 +59,7 @@ jobs: | |||||||
|  |  | ||||||
|       - name: Install dependencies |       - name: Install dependencies | ||||||
|         if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} |         if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} | ||||||
|         uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 |         uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16 | ||||||
|         with: |         with: | ||||||
|           # just perform install |           # just perform install | ||||||
|           runTests: false |           runTests: false | ||||||
| @@ -95,13 +95,13 @@ jobs: | |||||||
|       # These cached snapshots are downloaded, providing the reference snapshots. |       # These cached snapshots are downloaded, providing the reference snapshots. | ||||||
|       - name: Cache snapshots |       - name: Cache snapshots | ||||||
|         id: cache-snapshot |         id: cache-snapshot | ||||||
|         uses: actions/cache/restore@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 |         uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 | ||||||
|         with: |         with: | ||||||
|           path: ./cypress/snapshots |           path: ./cypress/snapshots | ||||||
|           key: ${{ runner.os }}-snapshots-${{ env.targetHash }} |           key: ${{ runner.os }}-snapshots-${{ env.targetHash }} | ||||||
|  |  | ||||||
|       - name: Install dependencies |       - name: Install dependencies | ||||||
|         uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 |         uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16 | ||||||
|         with: |         with: | ||||||
|           runTests: false |           runTests: false | ||||||
|  |  | ||||||
| @@ -117,7 +117,7 @@ jobs: | |||||||
|       # Install NPM dependencies, cache them correctly |       # Install NPM dependencies, cache them correctly | ||||||
|       # and run all Cypress tests |       # and run all Cypress tests | ||||||
|       - name: Cypress run |       - name: Cypress run | ||||||
|         uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 |         uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16 | ||||||
|         id: cypress |         id: cypress | ||||||
|         with: |         with: | ||||||
|           install: false |           install: false | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/workflows/link-checker.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/link-checker.yml
									
									
									
									
										vendored
									
									
								
							| @@ -32,7 +32,7 @@ jobs: | |||||||
|       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||||||
|  |  | ||||||
|       - name: Restore lychee cache |       - name: Restore lychee cache | ||||||
|         uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 |         uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 | ||||||
|         with: |         with: | ||||||
|           path: .lycheecache |           path: .lycheecache | ||||||
|           key: cache-lychee-${{ github.sha }} |           key: cache-lychee-${{ github.sha }} | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -36,7 +36,7 @@ jobs: | |||||||
|  |  | ||||||
|       - name: Create Release Pull Request or Publish to npm |       - name: Create Release Pull Request or Publish to npm | ||||||
|         id: changesets |         id: changesets | ||||||
|         uses: changesets/action@c8bada60c408975afd1a20b3db81d6eee6789308 # v1.4.9 |         uses: changesets/action@06245a4e0a36c064a573d4150030f5ec548e4fcc # v1.4.10 | ||||||
|         with: |         with: | ||||||
|           version: pnpm changeset:version |           version: pnpm changeset:version | ||||||
|           publish: pnpm changeset:publish |           publish: pnpm changeset:publish | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								.github/workflows/scorecard.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/scorecard.yml
									
									
									
									
										vendored
									
									
								
							| @@ -20,18 +20,18 @@ jobs: | |||||||
|         with: |         with: | ||||||
|           persist-credentials: false |           persist-credentials: false | ||||||
|       - name: Run analysis |       - name: Run analysis | ||||||
|         uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 |         uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 | ||||||
|         with: |         with: | ||||||
|           results_file: results.sarif |           results_file: results.sarif | ||||||
|           results_format: sarif |           results_format: sarif | ||||||
|           publish_results: true |           publish_results: true | ||||||
|       - name: Upload artifact |       - name: Upload artifact | ||||||
|         uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 |         uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | ||||||
|         with: |         with: | ||||||
|           name: SARIF file |           name: SARIF file | ||||||
|           path: results.sarif |           path: results.sarif | ||||||
|           retention-days: 5 |           retention-days: 5 | ||||||
|       - name: Upload to code-scanning |       - name: Upload to code-scanning | ||||||
|         uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 |         uses: github/codeql-action/upload-sarif@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21 | ||||||
|         with: |         with: | ||||||
|           sarif_file: results.sarif |           sarif_file: results.sarif | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/workflows/update-browserlist.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/update-browserlist.yml
									
									
									
									
										vendored
									
									
								
							| @@ -19,7 +19,7 @@ jobs: | |||||||
|           message: 'chore: update browsers list' |           message: 'chore: update browsers list' | ||||||
|           push: false |           push: false | ||||||
|       - name: Create Pull Request |       - name: Create Pull Request | ||||||
|         uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 |         uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 | ||||||
|         with: |         with: | ||||||
|           branch: update-browserslist |           branch: update-browserslist | ||||||
|           title: Update Browserslist |           title: Update Browserslist | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/workflows/validate-lockfile.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/validate-lockfile.yml
									
									
									
									
										vendored
									
									
								
							| @@ -35,7 +35,7 @@ jobs: | |||||||
|  |  | ||||||
|           # 2) No unwanted vitepress paths |           # 2) No unwanted vitepress paths | ||||||
|           if grep -qF 'packages/mermaid/src/vitepress' pnpm-lock.yaml; then |           if grep -qF 'packages/mermaid/src/vitepress' pnpm-lock.yaml; then | ||||||
|             issues+=("• Disallowed path 'packages/mermaid/src/vitepress' present. Run `rm -rf packages/mermaid/src/vitepress && pnpm install` to regenerate.") |             issues+=("• Disallowed path 'packages/mermaid/src/vitepress' present. Run \`rm -rf packages/mermaid/src/vitepress && pnpm install\` to regenerate.") | ||||||
|           fi |           fi | ||||||
|  |  | ||||||
|           # 3) Lockfile only changes when package.json changes |           # 3) Lockfile only changes when package.json changes | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -4,6 +4,7 @@ node_modules/ | |||||||
| coverage/ | coverage/ | ||||||
| .idea/ | .idea/ | ||||||
| .pnpm-store/ | .pnpm-store/ | ||||||
|  | .instructions/ | ||||||
|  |  | ||||||
| dist | dist | ||||||
| v8-compile-cache-0 | v8-compile-cache-0 | ||||||
|   | |||||||
| @@ -98,12 +98,12 @@ describe('Configuration', () => { | |||||||
|     it('should handle arrowMarkerAbsolute set to true', () => { |     it('should handle arrowMarkerAbsolute set to true', () => { | ||||||
|       renderGraph( |       renderGraph( | ||||||
|         `flowchart TD |         `flowchart TD | ||||||
|         A[Christmas] -->|Get money| B(Go shopping) |     A[Christmas] -->|Get money| B(Go shopping) | ||||||
|         B --> C{Let me think} |     B --> C{Let me think} | ||||||
|         C -->|One| D[Laptop] |     C -->|One| D[Laptop] | ||||||
|         C -->|Two| E[iPhone] |     C -->|Two| E[iPhone] | ||||||
|         C -->|Three| F[fa:fa-car Car] |     C -->|Three| F[fa:fa-car Car] | ||||||
|         `, |     `, | ||||||
|         { |         { | ||||||
|           arrowMarkerAbsolute: true, |           arrowMarkerAbsolute: true, | ||||||
|         } |         } | ||||||
| @@ -113,8 +113,7 @@ describe('Configuration', () => { | |||||||
|         cy.get('path') |         cy.get('path') | ||||||
|           .first() |           .first() | ||||||
|           .should('have.attr', 'marker-end') |           .should('have.attr', 'marker-end') | ||||||
|           .should('exist') |           .and('include', 'url(http://localhost'); | ||||||
|           .and('include', 'url(http\\:\\/\\/localhost'); |  | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|     it('should not taint the initial configuration when using multiple directives', () => { |     it('should not taint the initial configuration when using multiple directives', () => { | ||||||
|   | |||||||
| @@ -524,5 +524,18 @@ describe('Class diagram', () => { | |||||||
|       `, |       `, | ||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|  |     it('should handle an empty class body with empty braces', () => { | ||||||
|  |       imgSnapshotTest( | ||||||
|  |         ` classDiagram | ||||||
|  |         class FooBase~T~ {} | ||||||
|  |     class Bar { | ||||||
|  |         +Zip | ||||||
|  |         +Zap() | ||||||
|  |     } | ||||||
|  |     FooBase <|-- Ba | ||||||
|  |         `, | ||||||
|  |         { flowchart: { defaultRenderer: 'elk' } } | ||||||
|  |       ); | ||||||
|  |     }); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -109,7 +109,7 @@ describe('Flowchart ELK', () => { | |||||||
|       const style = svg.attr('style'); |       const style = svg.attr('style'); | ||||||
|       expect(style).to.match(/^max-width: [\d.]+px;$/); |       expect(style).to.match(/^max-width: [\d.]+px;$/); | ||||||
|       const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); |       const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); | ||||||
|       verifyNumber(maxWidthValue, 380); |       verifyNumber(maxWidthValue, 380, 15); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|   it('8-elk: should render a flowchart when useMaxWidth is false', () => { |   it('8-elk: should render a flowchart when useMaxWidth is false', () => { | ||||||
| @@ -128,7 +128,7 @@ describe('Flowchart ELK', () => { | |||||||
|       const width = parseFloat(svg.attr('width')); |       const width = parseFloat(svg.attr('width')); | ||||||
|       // use within because the absolute value can be slightly different depending on the environment ±5% |       // 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(height).to.be.within(446 * 0.95, 446 * 1.05); | ||||||
|       verifyNumber(width, 380); |       verifyNumber(width, 380, 15); | ||||||
|       expect(svg).to.not.have.attr('style'); |       expect(svg).to.not.have.attr('style'); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|   | |||||||
| @@ -1186,4 +1186,17 @@ end | |||||||
|       imgSnapshotTest(graph, { htmlLabels: false }); |       imgSnapshotTest(graph, { htmlLabels: false }); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|  |   it('V2 - 17: should apply class def colour to edge label', () => { | ||||||
|  |     imgSnapshotTest( | ||||||
|  |       ` graph LR | ||||||
|  |     id1(Start) link@-- "Label" -->id2(Stop) | ||||||
|  |     style id1 fill:#f9f,stroke:#333,stroke-width:4px | ||||||
|  |  | ||||||
|  | class id2 myClass | ||||||
|  | classDef myClass fill:#bbf,stroke:#f66,stroke-width:2px,color:white,stroke-dasharray: 5 5 | ||||||
|  | class link myClass | ||||||
|  | ` | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -803,4 +803,34 @@ describe('Gantt diagram', () => { | |||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |   it('should handle numeric timestamps with dateFormat x', () => { | ||||||
|  |     imgSnapshotTest( | ||||||
|  |       ` | ||||||
|  |      gantt | ||||||
|  |      title Process time profile (ms) | ||||||
|  |      dateFormat x | ||||||
|  |      axisFormat %L | ||||||
|  |      tickInterval 250millisecond | ||||||
|  |  | ||||||
|  |      section Pipeline | ||||||
|  |      Parse JSON p1: 000, 120 | ||||||
|  |     `, | ||||||
|  |       {} | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  |   it('should handle numeric timestamps with dateFormat X', () => { | ||||||
|  |     imgSnapshotTest( | ||||||
|  |       ` | ||||||
|  |      gantt | ||||||
|  |      title Process time profile (ms) | ||||||
|  |      dateFormat X | ||||||
|  |      axisFormat %L | ||||||
|  |      tickInterval 250millisecond | ||||||
|  |  | ||||||
|  |      section Pipeline | ||||||
|  |      Parse JSON p1: 000, 120 | ||||||
|  |     `, | ||||||
|  |       {} | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
| }); | }); | ||||||
|   | |||||||
							
								
								
									
										79
									
								
								cypress/integration/rendering/mindmap-tidy-tree.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								cypress/integration/rendering/mindmap-tidy-tree.spec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | |||||||
|  | import { imgSnapshotTest } from '../../helpers/util.ts'; | ||||||
|  |  | ||||||
|  | describe('Mindmap Tidy Tree', () => { | ||||||
|  |   it('1-tidy-tree: should render a simple mindmap without children', () => { | ||||||
|  |     imgSnapshotTest( | ||||||
|  |       ` --- | ||||||
|  |       config: | ||||||
|  |         layout: tidy-tree | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         A | ||||||
|  |         B | ||||||
|  |       ` | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  |   it('2-tidy-tree: should render a simple mindmap', () => { | ||||||
|  |     imgSnapshotTest( | ||||||
|  |       ` --- | ||||||
|  |       config: | ||||||
|  |         layout: tidy-tree | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap is a long thing)) | ||||||
|  |         A | ||||||
|  |         B | ||||||
|  |         C | ||||||
|  |         D | ||||||
|  |       ` | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  |   it('3-tidy-tree: should render a  mindmap with different shapes', () => { | ||||||
|  |     imgSnapshotTest( | ||||||
|  |       ` --- | ||||||
|  |       config: | ||||||
|  |         layout: tidy-tree | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         Origins | ||||||
|  |           Long history | ||||||
|  |           ::icon(fa fa-book) | ||||||
|  |           Popularisation | ||||||
|  |             British popular psychology author Tony Buzan | ||||||
|  |         Research | ||||||
|  |           On effectiveness<br/>and features | ||||||
|  |           On Automatic creation | ||||||
|  |             Uses | ||||||
|  |                 Creative techniques | ||||||
|  |                 Strategic planning | ||||||
|  |                 Argument mapping | ||||||
|  |         Tools | ||||||
|  |               id)I am a cloud( | ||||||
|  |                   id))I am a bang(( | ||||||
|  |                     Tools | ||||||
|  |       ` | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  |   it('4-tidy-tree: should render a mindmap with children', () => { | ||||||
|  |     imgSnapshotTest( | ||||||
|  |       ` --- | ||||||
|  |       config: | ||||||
|  |         layout: tidy-tree | ||||||
|  |       --- | ||||||
|  |        mindmap | ||||||
|  |       ((This is a mindmap)) | ||||||
|  |         child1 | ||||||
|  |          grandchild 1 | ||||||
|  |          grandchild 2 | ||||||
|  |         child2 | ||||||
|  |          grandchild 3 | ||||||
|  |          grandchild 4 | ||||||
|  |         child3 | ||||||
|  |          grandchild 5 | ||||||
|  |          grandchild 6 | ||||||
|  |       ` | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @@ -159,12 +159,10 @@ root | |||||||
|   }); |   }); | ||||||
|   it('square shape', () => { |   it('square shape', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       `mindmap | ||||||
| mindmap |  | ||||||
|     root[ |     root[ | ||||||
|       The root |       The root | ||||||
|     ] |     ]`, | ||||||
|       `, |  | ||||||
|       {}, |       {}, | ||||||
|       undefined, |       undefined, | ||||||
|       shouldHaveRoot |       shouldHaveRoot | ||||||
| @@ -172,12 +170,10 @@ mindmap | |||||||
|   }); |   }); | ||||||
|   it('rounded rect shape', () => { |   it('rounded rect shape', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       `mindmap | ||||||
| mindmap |  | ||||||
|     root(( |     root(( | ||||||
|       The root |       The root | ||||||
|     )) |     ))`, | ||||||
|       `, |  | ||||||
|       {}, |       {}, | ||||||
|       undefined, |       undefined, | ||||||
|       shouldHaveRoot |       shouldHaveRoot | ||||||
| @@ -185,12 +181,10 @@ mindmap | |||||||
|   }); |   }); | ||||||
|   it('circle shape', () => { |   it('circle shape', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       `mindmap | ||||||
| mindmap |  | ||||||
|     root( |     root( | ||||||
|       The root |       The root | ||||||
|     ) |     )`, | ||||||
|       `, |  | ||||||
|       {}, |       {}, | ||||||
|       undefined, |       undefined, | ||||||
|       shouldHaveRoot |       shouldHaveRoot | ||||||
| @@ -198,10 +192,8 @@ mindmap | |||||||
|   }); |   }); | ||||||
|   it('default shape', () => { |   it('default shape', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       `mindmap | ||||||
| mindmap |   The root`, | ||||||
|   The root |  | ||||||
|       `, |  | ||||||
|       {}, |       {}, | ||||||
|       undefined, |       undefined, | ||||||
|       shouldHaveRoot |       shouldHaveRoot | ||||||
| @@ -209,12 +201,10 @@ mindmap | |||||||
|   }); |   }); | ||||||
|   it('adding children', () => { |   it('adding children', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       `mindmap | ||||||
| mindmap |  | ||||||
|   The root |   The root | ||||||
|     child1 |     child1 | ||||||
|     child2 |     child2`, | ||||||
|       `, |  | ||||||
|       {}, |       {}, | ||||||
|       undefined, |       undefined, | ||||||
|       shouldHaveRoot |       shouldHaveRoot | ||||||
| @@ -222,13 +212,11 @@ mindmap | |||||||
|   }); |   }); | ||||||
|   it('adding grand children', () => { |   it('adding grand children', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       `mindmap | ||||||
| mindmap |  | ||||||
|   The root |   The root | ||||||
|     child1 |     child1 | ||||||
|       child2 |       child2 | ||||||
|       child3 |       child3`, | ||||||
|       `, |  | ||||||
|       {}, |       {}, | ||||||
|       undefined, |       undefined, | ||||||
|       shouldHaveRoot |       shouldHaveRoot | ||||||
| @@ -240,25 +228,21 @@ mindmap | |||||||
|         `mindmap |         `mindmap | ||||||
|     id1[\`**Start** with |     id1[\`**Start** with | ||||||
|     a second line 😎\`] |     a second line 😎\`] | ||||||
|       id2[\`The dog in **the** hog... a *very long text* about it |       id2[\`The dog in **the** hog... a *very long text* about it Word!\`]` | ||||||
| Word!\`] |  | ||||||
| ` |  | ||||||
|       ); |       ); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|   describe('Include char sequence "graph" in text (#6795)', () => { |   describe('Include char sequence "graph" in text (#6795)', () => { | ||||||
|     it('has a label with char sequence "graph"', () => { |     it('has a label with char sequence "graph"', () => { | ||||||
|       imgSnapshotTest( |       imgSnapshotTest( | ||||||
|         ` |         ` mindmap | ||||||
|         mindmap |  | ||||||
|           root |           root | ||||||
|             Photograph |             Photograph | ||||||
|               Waterfall |               Waterfall | ||||||
|               Landscape |               Landscape | ||||||
|             Geography |             Geography | ||||||
|               Mountains |               Mountains | ||||||
|               Rocks |               Rocks`, | ||||||
|         `, |  | ||||||
|         { flowchart: { defaultRenderer: 'elk' } } |         { flowchart: { defaultRenderer: 'elk' } } | ||||||
|       ); |       ); | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -225,24 +225,4 @@ timeline | |||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('13: should render markdown htmlLabels', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|     theme: forest |  | ||||||
| --- |  | ||||||
|  |  | ||||||
|  timeline |  | ||||||
|     title Timeline of Industrial Revolution |  | ||||||
|     section 17th-20th century |  | ||||||
|         Industry 1.0 : Machinery, Water power, Steam <br>power |  | ||||||
|         Industry 2.0 : Electricity, <strong>Internal combustion engine </strong>, Mass production |  | ||||||
|         Industry 3.0 : Electronics, Computers, Automation |  | ||||||
|     section 21st century |  | ||||||
|         Industry 4.0 : Internet, Robotics, Internet of Things |  | ||||||
|         Industry 5.0 : Artificial intelligence, Big data, 3D printing |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -32,26 +32,8 @@ | |||||||
|       href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap" |       href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap" | ||||||
|       rel="stylesheet" |       rel="stylesheet" | ||||||
|     /> |     /> | ||||||
|     <link rel="preconnect" href="https://fonts.googleapis.com" /> |  | ||||||
|     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> |  | ||||||
|     <link |  | ||||||
|       href="https://fonts.googleapis.com/css2?family=Recursive:wght@300..1000&display=swap" |  | ||||||
|       rel="stylesheet" |  | ||||||
|     /> |  | ||||||
|  |  | ||||||
|     <style> |     <style> | ||||||
|       .recursive-mermaid { |  | ||||||
|         font-family: 'Recursive', sans-serif; |  | ||||||
|         font-optical-sizing: auto; |  | ||||||
|         font-weight: 500; |  | ||||||
|         font-style: normal; |  | ||||||
|         font-variation-settings: |  | ||||||
|           'slnt' 0, |  | ||||||
|           'CASL' 0, |  | ||||||
|           'CRSV' 0.5, |  | ||||||
|           'MONO' 0; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       body { |       body { | ||||||
|         /* background: rgb(221, 208, 208); */ |         /* background: rgb(221, 208, 208); */ | ||||||
|         /* background: #333; */ |         /* background: #333; */ | ||||||
| @@ -63,9 +45,7 @@ | |||||||
|       h1 { |       h1 { | ||||||
|         color: grey; |         color: grey; | ||||||
|       } |       } | ||||||
|       .mermaid { |  | ||||||
|         border: 1px solid red; |  | ||||||
|       } |  | ||||||
|       .mermaid2 { |       .mermaid2 { | ||||||
|         display: none; |         display: none; | ||||||
|       } |       } | ||||||
| @@ -103,11 +83,6 @@ | |||||||
|         width: 100%; |         width: 100%; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       .class2 { |  | ||||||
|         fill: red; |  | ||||||
|         fill-opacity: 1; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       /* tspan { |       /* tspan { | ||||||
|               font-size: 6px !important; |               font-size: 6px !important; | ||||||
|             } */ |             } */ | ||||||
| @@ -131,6 +106,194 @@ | |||||||
|  |  | ||||||
|   <body> |   <body> | ||||||
|     <pre id="diagram4" class="mermaid"> |     <pre id="diagram4" class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |       --- | ||||||
|  |       flowchart-elk TB | ||||||
|  |       c1-->a2 | ||||||
|  |       subgraph one | ||||||
|  |       a1-->a2 | ||||||
|  |       end | ||||||
|  |       subgraph two | ||||||
|  |       b1-->b2 | ||||||
|  |       end | ||||||
|  |       subgraph three | ||||||
|  |       c1-->c2 | ||||||
|  |       end | ||||||
|  |       one --> two | ||||||
|  |       three --> two | ||||||
|  |       two --> c2 | ||||||
|  |  | ||||||
|  | </pre | ||||||
|  |     > | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |       --- | ||||||
|  |       flowchart TB | ||||||
|  |  | ||||||
|  |         process_C | ||||||
|  |       subgraph container_Alpha | ||||||
|  |         subgraph process_B | ||||||
|  |           pppB | ||||||
|  |         end | ||||||
|  |         subgraph process_A | ||||||
|  |           pppA | ||||||
|  |         end | ||||||
|  |         process_B-->|via_AWSBatch|container_Beta | ||||||
|  |         process_A-->|messages|container_Beta | ||||||
|  |       end | ||||||
|  |  | ||||||
|  | </pre | ||||||
|  |     > | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |       --- | ||||||
|  |       flowchart TB | ||||||
|  |       subgraph container_Beta | ||||||
|  |         process_C | ||||||
|  |       end | ||||||
|  |       subgraph container_Alpha | ||||||
|  |         subgraph process_B | ||||||
|  |           pppB | ||||||
|  |         end | ||||||
|  |         subgraph process_A | ||||||
|  |           pppA | ||||||
|  |         end | ||||||
|  |         process_B-->|via_AWSBatch|container_Beta | ||||||
|  |         process_A-->|messages|container_Beta | ||||||
|  |       end | ||||||
|  |  | ||||||
|  | </pre | ||||||
|  |     > | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |       --- | ||||||
|  |       flowchart TB | ||||||
|  |       subgraph container_Beta | ||||||
|  |         process_C | ||||||
|  |       end | ||||||
|  |  | ||||||
|  |         process_B-->|via_AWSBatch|container_Beta | ||||||
|  |  | ||||||
|  |  | ||||||
|  | </pre | ||||||
|  |     > | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |       --- | ||||||
|  |       classDiagram | ||||||
|  |       note "I love this diagram!\nDo you love it?" | ||||||
|  |       Class01 <|-- AveryLongClass : Cool | ||||||
|  |       <<interface>> Class01 | ||||||
|  |       Class03 "1" *-- "*" Class04 | ||||||
|  |       Class05 "1" o-- "many" Class06 | ||||||
|  |       Class07 "1" .. "*" Class08 | ||||||
|  |       Class09 "1" --> "*" C2 : Where am i? | ||||||
|  |       Class09 "*" --* "*" C3 | ||||||
|  |       Class09 "1" --|> "1" Class07 | ||||||
|  |       Class12 <|.. Class08 | ||||||
|  |       Class11 ..>Class12 | ||||||
|  |       Class07 : equals() | ||||||
|  |       Class07 : Object[] elementData | ||||||
|  |       Class01 : size() | ||||||
|  |       Class01 : int chimp | ||||||
|  |       Class01 : int gorilla | ||||||
|  |       Class01 : -int privateChimp | ||||||
|  |       Class01 : +int publicGorilla | ||||||
|  |       Class01 : #int protectedMarmoset | ||||||
|  |       Class08 <--> C2: Cool label | ||||||
|  |       class Class10 { | ||||||
|  |         <<service>> | ||||||
|  |         int id | ||||||
|  |         test() | ||||||
|  |       } | ||||||
|  |       note for Class10 "Cool class\nI said it's very cool class!" | ||||||
|  | </pre | ||||||
|  |     > | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |       --- | ||||||
|  |       requirementDiagram | ||||||
|  |         requirement test_req { | ||||||
|  |         id: 1 | ||||||
|  |         text: the test text. | ||||||
|  |         risk: high | ||||||
|  |         verifymethod: test | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         element test_entity { | ||||||
|  |         type: simulation | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         test_entity - satisfies -> test_req | ||||||
|  | </pre | ||||||
|  |     > | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |       --- | ||||||
|  |       flowchart-elk TB | ||||||
|  |       internet | ||||||
|  |       nat | ||||||
|  |       router | ||||||
|  |       compute1 | ||||||
|  |  | ||||||
|  |       subgraph project | ||||||
|  |       router | ||||||
|  |       nat | ||||||
|  |         subgraph subnet1 | ||||||
|  |           compute1 | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  |  | ||||||
|  |       %% router --> subnet1 | ||||||
|  |       subnet1  --> nat | ||||||
|  |       %% nat --> internet | ||||||
|  | </pre | ||||||
|  |     > | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |       --- | ||||||
|  |       flowchart-elk TB | ||||||
|  |       internet | ||||||
|  |       nat | ||||||
|  |       router | ||||||
|  |       lb1 | ||||||
|  |       lb2 | ||||||
|  |       compute1 | ||||||
|  |       compute2 | ||||||
|  |       subgraph project | ||||||
|  |       router | ||||||
|  |       nat | ||||||
|  |         subgraph subnet1 | ||||||
|  |           compute1 | ||||||
|  |           lb1 | ||||||
|  |         end | ||||||
|  |         subgraph subnet2 | ||||||
|  |           compute2 | ||||||
|  |           lb2 | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  |       internet --> router | ||||||
|  |       router --> subnet1 & subnet2 | ||||||
|  |       subnet1 & subnet2 --> nat --> internet | ||||||
|  | </pre | ||||||
|  |     > | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
| --- | --- | ||||||
| config: | config: | ||||||
|   layout: elk |   layout: elk | ||||||
| @@ -157,84 +320,149 @@ treemap | |||||||
|     "Leaf 2.2": 25 |     "Leaf 2.2": 25 | ||||||
|     "Leaf 2.3": 12 |     "Leaf 2.3": 12 | ||||||
|  |  | ||||||
| classDef class1   fill:red,color:blue,stroke:#FFD600; |     </pre> | ||||||
|  |     <pre id="diagram5" class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |         flowchart: | ||||||
|  |           curve: rounded | ||||||
|  |       --- | ||||||
|  |       flowchart LR | ||||||
|  |           I["fa:fa-code Text"] -- Mermaid js --> D["Use<br/>the<br/>editor!"] | ||||||
|  |           I --> D & D | ||||||
|  |           D@{ shape: question} | ||||||
|  |           I@{ shape: question} | ||||||
|  |  | ||||||
|  |     </pre> | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: tidy-tree | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         Origins | ||||||
|  |           Long history | ||||||
|  |           ::icon(fa fa-book) | ||||||
|  |           Popularisation | ||||||
|  |             British popular psychology author Tony Buzan | ||||||
|  |         Research | ||||||
|  |           On effectiveness<br/>and features | ||||||
|  |           On Automatic creation | ||||||
|  |             Uses | ||||||
|  |                 Creative techniques | ||||||
|  |                 Strategic planning | ||||||
|  |                 Argument mapping | ||||||
|  |         Tools | ||||||
|  |           Pen and paper | ||||||
|  |           Mermaid | ||||||
|  |  | ||||||
| </pre |     </pre> | ||||||
|     > |     <pre id="diagram4" class="mermaid"> | ||||||
|     <pre id="diagram4" class="mermaid2"> |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |         flowchart: | ||||||
|  |           curve: linear | ||||||
|  |       --- | ||||||
|  |       flowchart LR | ||||||
|  |           A[A] --> B[B] | ||||||
|  |           A[A] --- B([C]) | ||||||
|  |           A@{ shape: diamond} | ||||||
|  |           %%B@{ shape: diamond} | ||||||
|  |  | ||||||
|  |     </pre> | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |         flowchart: | ||||||
|  |           curve: linear | ||||||
|  |       --- | ||||||
|  |       flowchart LR | ||||||
|  |           A[A] -- Mermaid js --> B[B] | ||||||
|  |           A[A] -- Mermaid js --- B[B] | ||||||
|  |           A@{ shape: diamond} | ||||||
|  |           B@{ shape: diamond} | ||||||
|  |  | ||||||
|  |     </pre> | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |         flowchart: | ||||||
|  |           curve: rounded | ||||||
|  |       --- | ||||||
|  |       flowchart LR | ||||||
|  |           D["Use the editor"] -- Mermaid js --> I["fa:fa-code Text"] | ||||||
|  |           I --> D & D | ||||||
|  |           D@{ shape: question} | ||||||
|  |           I@{ shape: question} | ||||||
|  |     </pre> | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |         flowchart: | ||||||
|  |           curve: rounded | ||||||
|  |         elk: | ||||||
|  |           nodePlacementStrategy: NETWORK_SIMPLEX | ||||||
|  |       --- | ||||||
|  |       flowchart LR | ||||||
|  |           D["Use the editor"] -- Mermaid js --> I["fa:fa-code Text"] | ||||||
|  |           D --> I & I | ||||||
|  |           a["a"] | ||||||
|  |           D@{ shape: trap-b} | ||||||
|  |           I@{ shape: lean-l} | ||||||
|  |     </pre> | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
| --- | --- | ||||||
| config: | config: | ||||||
|   treemap: |   layout: elk | ||||||
|     valueFormat: '$0,0' |  | ||||||
| --- | --- | ||||||
| treemap | flowchart LR | ||||||
| "Budget" |  %% subgraph s1["Untitled subgraph"] | ||||||
|     "Operations" |         C["Evaluate"] | ||||||
|         "Salaries": 7000 |  %% end | ||||||
|         "Equipment": 2000 |  | ||||||
|         "Supplies": 1000 |  | ||||||
|     "Marketing" |  | ||||||
|         "Advertising": 4000 |  | ||||||
|         "Events": 1000 |  | ||||||
|  |  | ||||||
| </pre |     B --> C | ||||||
|     > |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid"> |     <pre id="diagram4" class="mermaid"> | ||||||
|     treemap | --- | ||||||
|       title Accessible Treemap Title | config: | ||||||
|       "Category A" |   layout: elk | ||||||
|           "Item A1": 10 |   flowchart: | ||||||
|           "Item A2": 20 |     //curve: linear | ||||||
|       "Category B" | --- | ||||||
|           "Item B1": 15 |  | ||||||
|           "Item B2": 25 |  | ||||||
|     </pre> |  | ||||||
|     <pre id="diagram4" class="mermaid2"> |  | ||||||
|       flowchart LR |  | ||||||
|         AB["apa@apa@"] --> B(("`apa@apa`")) |  | ||||||
|     </pre> |  | ||||||
|     <pre id="diagram4" class="mermaid2"> |  | ||||||
|       flowchart |  | ||||||
|         D(("for D")) |  | ||||||
|     </pre> |  | ||||||
|     <pre id="diagram4" class="mermaid2"> |  | ||||||
|       flowchart LR |  | ||||||
|         A e1@==> B |  | ||||||
|         e1@{ animate: true} |  | ||||||
|     </pre> |  | ||||||
|     <pre id="diagram4" class="mermaid2"> |  | ||||||
| flowchart LR | flowchart LR | ||||||
|   A e1@--> B | %% A ==> B | ||||||
|   classDef animate stroke-width:2,stroke-dasharray:10\,8,stroke-dashoffset:-180,animation: edge-animation-frame 6s linear infinite, stroke-linecap: round | %% A2 --> B2 | ||||||
|   class e1 animate | A{A} --> B((Bo boo)) & B & B & B | ||||||
|     </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"> |     </pre> | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
| info    </pre |       --- | ||||||
|     > |       config: | ||||||
|     <pre id="diagram4" class="mermaid2"> |         layout: elk | ||||||
|  |         theme: default | ||||||
|  |         look: classic | ||||||
|  |       --- | ||||||
|  |       flowchart LR | ||||||
|  |        subgraph s1["APA"] | ||||||
|  |               D{"Use the editor"} | ||||||
|  |         end | ||||||
|  |        subgraph S2["S2"] | ||||||
|  |               s1 | ||||||
|  |               I>"fa:fa-code Text"] | ||||||
|  |               E["E"] | ||||||
|  |         end | ||||||
|  |           D -- Mermaid js --> I | ||||||
|  |           D --> I & E | ||||||
|  |           E --> I | ||||||
|  |     </pre> | ||||||
|  |     <pre id="diagram4" class="mermaid"> | ||||||
| --- | --- | ||||||
| config: | config: | ||||||
|   layout: elk |   layout: elk | ||||||
| @@ -259,7 +487,7 @@ config: | |||||||
|       end |       end | ||||||
|       end |       end | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| --- | --- | ||||||
| config: | config: | ||||||
|   layout: elk |   layout: elk | ||||||
| @@ -272,7 +500,7 @@ config: | |||||||
|       D-->I |       D-->I | ||||||
|       D-->I |       D-->I | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| --- | --- | ||||||
| config: | config: | ||||||
|   layout: elk |   layout: elk | ||||||
| @@ -311,7 +539,7 @@ flowchart LR | |||||||
|     n8@{ shape: rect} |     n8@{ shape: rect} | ||||||
|  |  | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| --- | --- | ||||||
| config: | config: | ||||||
|   layout: elk |   layout: elk | ||||||
| @@ -327,7 +555,7 @@ flowchart LR | |||||||
|  |  | ||||||
|  |  | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| --- | --- | ||||||
| config: | config: | ||||||
|   layout: elk |   layout: elk | ||||||
| @@ -336,7 +564,7 @@ flowchart LR | |||||||
|     A{A} --> B & C |     A{A} --> B & C | ||||||
| </pre | </pre | ||||||
|     > |     > | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| --- | --- | ||||||
| config: | config: | ||||||
|   layout: elk |   layout: elk | ||||||
| @@ -348,7 +576,7 @@ flowchart LR | |||||||
|     end |     end | ||||||
| </pre | </pre | ||||||
|     > |     > | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| --- | --- | ||||||
| config: | config: | ||||||
|   layout: elk |   layout: elk | ||||||
| @@ -366,7 +594,7 @@ flowchart LR | |||||||
|  |  | ||||||
|  |  | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| --- | --- | ||||||
| config: | config: | ||||||
|   kanban: |   kanban: | ||||||
| @@ -385,81 +613,81 @@ kanban | |||||||
|     task3[💻 Develop login feature]@{ ticket: 103 } |     task3[💻 Develop login feature]@{ ticket: 103 } | ||||||
|  |  | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| flowchart LR | flowchart LR | ||||||
| nA[Default] --> A@{ icon: 'fa:bell', form: 'rounded' } | nA[Default] --> A@{ icon: 'fa:bell', form: 'rounded' } | ||||||
|  |  | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| flowchart LR | flowchart LR | ||||||
| nA[Style] --> A@{ icon: 'fa:bell', form: 'rounded' } | nA[Style] --> A@{ icon: 'fa:bell', form: 'rounded' } | ||||||
| style A fill:#f9f,stroke:#333,stroke-width:4px | style A fill:#f9f,stroke:#333,stroke-width:4px | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| flowchart LR | flowchart LR | ||||||
| nA[Class] --> A@{ icon: 'fa:bell', form: 'rounded' } | nA[Class] --> A@{ icon: 'fa:bell', form: 'rounded' } | ||||||
| A:::AClass | A:::AClass | ||||||
| classDef AClass fill:#f9f,stroke:#333,stroke-width:4px | classDef AClass fill:#f9f,stroke:#333,stroke-width:4px | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| flowchart LR | flowchart LR | ||||||
|   nA[Class] --> A@{ icon: 'logos:aws', form: 'rounded' } |   nA[Class] --> A@{ icon: 'logos:aws', form: 'rounded' } | ||||||
|  |  | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| flowchart LR | flowchart LR | ||||||
| nA[Default] --> A@{ icon: 'fa:bell', form: 'square' } | nA[Default] --> A@{ icon: 'fa:bell', form: 'square' } | ||||||
|  |  | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| flowchart LR | flowchart LR | ||||||
| nA[Style] --> A@{ icon: 'fa:bell', form: 'square' } | nA[Style] --> A@{ icon: 'fa:bell', form: 'square' } | ||||||
| style A fill:#f9f,stroke:#333,stroke-width:4px | style A fill:#f9f,stroke:#333,stroke-width:4px | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| flowchart LR | flowchart LR | ||||||
| nA[Class] --> A@{ icon: 'fa:bell', form: 'square' } | nA[Class] --> A@{ icon: 'fa:bell', form: 'square' } | ||||||
| A:::AClass | A:::AClass | ||||||
| classDef AClass fill:#f9f,stroke:#333,stroke-width:4px | classDef AClass fill:#f9f,stroke:#333,stroke-width:4px | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| flowchart LR | flowchart LR | ||||||
|   nA[Class] --> A@{ icon: 'logos:aws', form: 'square' } |   nA[Class] --> A@{ icon: 'logos:aws', form: 'square' } | ||||||
|  |  | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| flowchart LR | flowchart LR | ||||||
| nA[Default] --> A@{ icon: 'fa:bell', form: 'circle' } | nA[Default] --> A@{ icon: 'fa:bell', form: 'circle' } | ||||||
|  |  | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| flowchart LR | flowchart LR | ||||||
| nA[Style] --> A@{ icon: 'fa:bell', form: 'circle' } | nA[Style] --> A@{ icon: 'fa:bell', form: 'circle' } | ||||||
| style A fill:#f9f,stroke:#333,stroke-width:4px | style A fill:#f9f,stroke:#333,stroke-width:4px | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| flowchart LR | flowchart LR | ||||||
| nA[Class] --> A@{ icon: 'fa:bell', form: 'circle' } | nA[Class] --> A@{ icon: 'fa:bell', form: 'circle' } | ||||||
| A:::AClass | A:::AClass | ||||||
| classDef AClass fill:#f9f,stroke:#333,stroke-width:4px | classDef AClass fill:#f9f,stroke:#333,stroke-width:4px | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| flowchart LR | flowchart LR | ||||||
|   nA[Class] --> A@{ icon: 'logos:aws', form: 'circle' } |   nA[Class] --> A@{ icon: 'logos:aws', form: 'circle' } | ||||||
|   A:::AClass |   A:::AClass | ||||||
|   classDef AClass fill:#f9f,stroke:#333,stroke-width:4px |   classDef AClass fill:#f9f,stroke:#333,stroke-width:4px | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| flowchart LR | flowchart LR | ||||||
|   nA[Style] --> A@{ icon: 'logos:aws', form: 'circle' } |   nA[Style] --> A@{ icon: 'logos:aws', form: 'circle' } | ||||||
|   style A fill:#f9f,stroke:#333,stroke-width:4px |   style A fill:#f9f,stroke:#333,stroke-width:4px | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| kanban | kanban | ||||||
|   id2[In progress] |   id2[In progress] | ||||||
|     docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' } |     docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' } | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram4" class="mermaid2"> |     <pre id="diagram4" class="mermaid"> | ||||||
| --- | --- | ||||||
| config: | config: | ||||||
|   kanban: |   kanban: | ||||||
| @@ -523,18 +751,22 @@ kanban | |||||||
|         alert('It worked'); |         alert('It worked'); | ||||||
|       } |       } | ||||||
|       await mermaid.initialize({ |       await mermaid.initialize({ | ||||||
|         // theme: 'forest', |         // theme: 'base', | ||||||
|         // theme: 'default', |         // theme: 'default', | ||||||
|         // theme: 'forest', |         // theme: 'forest', | ||||||
|         // handDrawnSeed: 12, |         // handDrawnSeed: 12, | ||||||
|         // look: 'handDrawn', |         // look: 'handDrawn', | ||||||
|         // 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX', |         // 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX', | ||||||
|         // layout: 'dagre', |         // layout: 'dagre', | ||||||
|         // layout: 'elk', |         layout: 'elk', | ||||||
|         // layout: 'fixed', |         // layout: 'fixed', | ||||||
|         // htmlLabels: false, |         // htmlLabels: false, | ||||||
|         flowchart: { titleTopMargin: 10 }, |         flowchart: { titleTopMargin: 10 }, | ||||||
|         fontFamily: "'Recursive', sans-serif", |  | ||||||
|  |         // fontFamily: 'Caveat', | ||||||
|  |         // fontFamily: 'Kalam', | ||||||
|  |         // fontFamily: 'courier', | ||||||
|  |         fontFamily: 'arial', | ||||||
|         sequence: { |         sequence: { | ||||||
|           actorFontFamily: 'courier', |           actorFontFamily: 'courier', | ||||||
|           noteFontFamily: 'courier', |           noteFontFamily: 'courier', | ||||||
|   | |||||||
							
								
								
									
										376
									
								
								cypress/platform/mindmap-layouts.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										376
									
								
								cypress/platform/mindmap-layouts.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,376 @@ | |||||||
|  | <!doctype html> | ||||||
|  | <html lang="en"> | ||||||
|  |   <head> | ||||||
|  |     <meta charset="utf-8" /> | ||||||
|  |     <meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||||||
|  |     <title>Mermaid Quick Test Page</title> | ||||||
|  |     <link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" /> | ||||||
|  |     <style> | ||||||
|  |       div.mermaid { | ||||||
|  |         font-family: 'Courier New', Courier, monospace !important; | ||||||
|  |       } | ||||||
|  |     </style> | ||||||
|  |   </head> | ||||||
|  |  | ||||||
|  |   <body> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |  --- | ||||||
|  |       config: | ||||||
|  |         layout: tidy-tree | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         A | ||||||
|  |         B | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |  --- | ||||||
|  |       config: | ||||||
|  |         layout: dagre | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         A | ||||||
|  |         B | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |  --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         A | ||||||
|  |         B | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |  --- | ||||||
|  |       config: | ||||||
|  |         layout: cose-bilkent | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         A | ||||||
|  |         B | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |     --- | ||||||
|  |       config: | ||||||
|  |         layout: tidy-tree | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap is a long thing)) | ||||||
|  |         A | ||||||
|  |         B | ||||||
|  |         C | ||||||
|  |         D | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |     --- | ||||||
|  |       config: | ||||||
|  |         layout: dagre | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap is a long thing)) | ||||||
|  |         A | ||||||
|  |         B | ||||||
|  |         C | ||||||
|  |         D | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |     --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap is a long thing)) | ||||||
|  |         A | ||||||
|  |         B | ||||||
|  |         C | ||||||
|  |         D | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |     --- | ||||||
|  |       config: | ||||||
|  |         layout: cose-bilkent | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap is a long thing)) | ||||||
|  |         A | ||||||
|  |         B | ||||||
|  |         C | ||||||
|  |         D | ||||||
|  |     </pre> | ||||||
|  |  | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |     --- | ||||||
|  |       config: | ||||||
|  |         layout: tidy-tree | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         Origins | ||||||
|  |           Long history | ||||||
|  |           ::icon(fa fa-book) | ||||||
|  |           Popularisation | ||||||
|  |             British popular psychology author Tony Buzan | ||||||
|  |         Research | ||||||
|  |           On effectiveness<br/>and features | ||||||
|  |           On Automatic creation | ||||||
|  |             Uses | ||||||
|  |                 Creative techniques | ||||||
|  |                 Strategic planning | ||||||
|  |                 Argument mapping | ||||||
|  |         Tools | ||||||
|  |               id)I am a cloud( | ||||||
|  |                   id))I am a bang(( | ||||||
|  |                     Tools | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |     --- | ||||||
|  |       config: | ||||||
|  |         layout: dagre | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         Origins | ||||||
|  |           Long history | ||||||
|  |           ::icon(fa fa-book) | ||||||
|  |           Popularisation | ||||||
|  |             British popular psychology author Tony Buzan | ||||||
|  |         Research | ||||||
|  |           On effectiveness<br/>and features | ||||||
|  |           On Automatic creation | ||||||
|  |             Uses | ||||||
|  |                 Creative techniques | ||||||
|  |                 Strategic planning | ||||||
|  |                 Argument mapping | ||||||
|  |         Tools | ||||||
|  |               id)I am a cloud( | ||||||
|  |                   id))I am a bang(( | ||||||
|  |                     Tools | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |     --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         Origins | ||||||
|  |           Long history | ||||||
|  |           ::icon(fa fa-book) | ||||||
|  |           Popularisation | ||||||
|  |             British popular psychology author Tony Buzan | ||||||
|  |         Research | ||||||
|  |           On effectiveness<br/>and features | ||||||
|  |           On Automatic creation | ||||||
|  |             Uses | ||||||
|  |                 Creative techniques | ||||||
|  |                 Strategic planning | ||||||
|  |                 Argument mapping | ||||||
|  |         Tools | ||||||
|  |               id)I am a cloud( | ||||||
|  |                   id))I am a bang(( | ||||||
|  |                     Tools | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |     --- | ||||||
|  |       config: | ||||||
|  |         layout: cose-bilkent | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         Origins | ||||||
|  |           Long history | ||||||
|  |           ::icon(fa fa-book) | ||||||
|  |           Popularisation | ||||||
|  |             British popular psychology author Tony Buzan | ||||||
|  |         Research | ||||||
|  |           On effectiveness<br/>and features | ||||||
|  |           On Automatic creation | ||||||
|  |             Uses | ||||||
|  |                 Creative techniques | ||||||
|  |                 Strategic planning | ||||||
|  |                 Argument mapping | ||||||
|  |         Tools | ||||||
|  |               id)I am a cloud( | ||||||
|  |                   id))I am a bang(( | ||||||
|  |                     Tools | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: tidy-tree | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         A | ||||||
|  |           a | ||||||
|  |             apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |             apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |           b | ||||||
|  |           c | ||||||
|  |           d | ||||||
|  |         B | ||||||
|  |             apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |         D | ||||||
|  |           apa5[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |           apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |  | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: dagre | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         A | ||||||
|  |           a | ||||||
|  |             apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |             apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |           b | ||||||
|  |           c | ||||||
|  |           d | ||||||
|  |         B | ||||||
|  |             apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |         D | ||||||
|  |           apa5[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |           apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |  | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         A | ||||||
|  |           a | ||||||
|  |             apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |             apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |           b | ||||||
|  |           c | ||||||
|  |           d | ||||||
|  |         B | ||||||
|  |             apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |         D | ||||||
|  |           apa5[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |           apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |  | ||||||
|  |     </pre> | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |       --- | ||||||
|  |       config: | ||||||
|  |         layout: cose-bilkent | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       root((mindmap)) | ||||||
|  |         A | ||||||
|  |           a | ||||||
|  |             apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |             apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |           b | ||||||
|  |           c | ||||||
|  |           d | ||||||
|  |         B | ||||||
|  |             apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |         D | ||||||
|  |           apa5[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |           apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on] | ||||||
|  |  | ||||||
|  |     </pre> | ||||||
|  |  | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |  --- | ||||||
|  |       config: | ||||||
|  |         layout: tidy-tree | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       ((This is a mindmap)) | ||||||
|  |         child1 | ||||||
|  |          grandchild 1 | ||||||
|  |          grandchild 2 | ||||||
|  |         child2 | ||||||
|  |          grandchild 3 | ||||||
|  |          grandchild 4 | ||||||
|  |         child3 | ||||||
|  |          grandchild 5 | ||||||
|  |          grandchild 6 | ||||||
|  |        | ||||||
|  |     </pre> | ||||||
|  |  | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |  --- | ||||||
|  |       config: | ||||||
|  |         layout: dagre | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       ((This is a mindmap)) | ||||||
|  |         child1 | ||||||
|  |          grandchild 1 | ||||||
|  |          grandchild 2 | ||||||
|  |         child2 | ||||||
|  |          grandchild 3 | ||||||
|  |          grandchild 4 | ||||||
|  |         child3 | ||||||
|  |          grandchild 5 | ||||||
|  |          grandchild 6 | ||||||
|  |        | ||||||
|  |     </pre> | ||||||
|  |  | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |  --- | ||||||
|  |       config: | ||||||
|  |         layout: elk | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       ((This is a mindmap)) | ||||||
|  |         child1 | ||||||
|  |          grandchild 1 | ||||||
|  |          grandchild 2 | ||||||
|  |         child2 | ||||||
|  |          grandchild 3 | ||||||
|  |          grandchild 4 | ||||||
|  |         child3 | ||||||
|  |          grandchild 5 | ||||||
|  |          grandchild 6 | ||||||
|  |        | ||||||
|  |     </pre> | ||||||
|  |  | ||||||
|  |     <pre class="mermaid"> | ||||||
|  |  --- | ||||||
|  |       config: | ||||||
|  |         layout: cose-bilkent | ||||||
|  |       --- | ||||||
|  |       mindmap | ||||||
|  |       ((This is a mindmap)) | ||||||
|  |         child1 | ||||||
|  |          grandchild 1 | ||||||
|  |          grandchild 2 | ||||||
|  |         child2 | ||||||
|  |          grandchild 3 | ||||||
|  |          grandchild 4 | ||||||
|  |         child3 | ||||||
|  |          grandchild 5 | ||||||
|  |          grandchild 6 | ||||||
|  |        | ||||||
|  |     </pre> | ||||||
|  |  | ||||||
|  |     <hr /> | ||||||
|  |     <script type="module"> | ||||||
|  |       import mermaid from '/mermaid.esm.mjs'; | ||||||
|  |       import tidytree from '/mermaid-layout-tidy-tree.esm.mjs'; | ||||||
|  |       import layouts from './mermaid-layout-elk.esm.mjs'; | ||||||
|  |       mermaid.registerLayoutLoaders(layouts); | ||||||
|  |       mermaid.registerLayoutLoaders(tidytree); | ||||||
|  |       mermaid.initialize({ | ||||||
|  |         theme: 'default', | ||||||
|  |         logLevel: 3, | ||||||
|  |         securityLevel: 'loose', | ||||||
|  |       }); | ||||||
|  |     </script> | ||||||
|  |   </body> | ||||||
|  | </html> | ||||||
| @@ -1,5 +1,6 @@ | |||||||
| import externalExample from './mermaid-example-diagram.esm.mjs'; | import externalExample from './mermaid-example-diagram.esm.mjs'; | ||||||
| import layouts from './mermaid-layout-elk.esm.mjs'; | import layouts from './mermaid-layout-elk.esm.mjs'; | ||||||
|  | import tidyTree from './mermaid-layout-tidy-tree.esm.mjs'; | ||||||
| import zenUml from './mermaid-zenuml.esm.mjs'; | import zenUml from './mermaid-zenuml.esm.mjs'; | ||||||
| import mermaid from './mermaid.esm.mjs'; | import mermaid from './mermaid.esm.mjs'; | ||||||
|  |  | ||||||
| @@ -65,6 +66,7 @@ const contentLoaded = async function () { | |||||||
|     await mermaid.registerExternalDiagrams([externalExample, zenUml]); |     await mermaid.registerExternalDiagrams([externalExample, zenUml]); | ||||||
|  |  | ||||||
|     mermaid.registerLayoutLoaders(layouts); |     mermaid.registerLayoutLoaders(layouts); | ||||||
|  |     mermaid.registerLayoutLoaders(tidyTree); | ||||||
|     mermaid.initialize(graphObj.mermaid); |     mermaid.initialize(graphObj.mermaid); | ||||||
|     /** |     /** | ||||||
|      *  CC-BY-4.0 |      *  CC-BY-4.0 | ||||||
|   | |||||||
| @@ -2,219 +2,227 @@ | |||||||
|   "durations": [ |   "durations": [ | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/other/configuration.spec.js", |       "spec": "cypress/integration/other/configuration.spec.js", | ||||||
|       "duration": 6297 |       "duration": 5841 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/other/external-diagrams.spec.js", |       "spec": "cypress/integration/other/external-diagrams.spec.js", | ||||||
|       "duration": 2187 |       "duration": 2138 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/other/ghsa.spec.js", |       "spec": "cypress/integration/other/ghsa.spec.js", | ||||||
|       "duration": 3509 |       "duration": 3370 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/other/iife.spec.js", |       "spec": "cypress/integration/other/iife.spec.js", | ||||||
|       "duration": 2218 |       "duration": 2052 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/other/interaction.spec.js", |       "spec": "cypress/integration/other/interaction.spec.js", | ||||||
|       "duration": 12104 |       "duration": 12243 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/other/rerender.spec.js", |       "spec": "cypress/integration/other/rerender.spec.js", | ||||||
|       "duration": 2151 |       "duration": 2065 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/other/xss.spec.js", |       "spec": "cypress/integration/other/xss.spec.js", | ||||||
|       "duration": 33064 |       "duration": 31288 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/appli.spec.js", |       "spec": "cypress/integration/rendering/appli.spec.js", | ||||||
|       "duration": 3488 |       "duration": 3421 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/architecture.spec.ts", |       "spec": "cypress/integration/rendering/architecture.spec.ts", | ||||||
|       "duration": 106 |       "duration": 97 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/block.spec.js", |       "spec": "cypress/integration/rendering/block.spec.js", | ||||||
|       "duration": 18317 |       "duration": 18500 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/c4.spec.js", |       "spec": "cypress/integration/rendering/c4.spec.js", | ||||||
|       "duration": 5592 |       "duration": 5793 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/classDiagram-elk-v3.spec.js", |       "spec": "cypress/integration/rendering/classDiagram-elk-v3.spec.js", | ||||||
|       "duration": 39358 |       "duration": 40966 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/classDiagram-handDrawn-v3.spec.js", |       "spec": "cypress/integration/rendering/classDiagram-handDrawn-v3.spec.js", | ||||||
|       "duration": 37160 |       "duration": 39176 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/classDiagram-v2.spec.js", |       "spec": "cypress/integration/rendering/classDiagram-v2.spec.js", | ||||||
|       "duration": 23660 |       "duration": 23468 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/classDiagram-v3.spec.js", |       "spec": "cypress/integration/rendering/classDiagram-v3.spec.js", | ||||||
|       "duration": 36866 |       "duration": 38291 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/classDiagram.spec.js", |       "spec": "cypress/integration/rendering/classDiagram.spec.js", | ||||||
|       "duration": 17334 |       "duration": 16949 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/conf-and-directives.spec.js", |       "spec": "cypress/integration/rendering/conf-and-directives.spec.js", | ||||||
|       "duration": 9871 |       "duration": 9480 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/current.spec.js", |       "spec": "cypress/integration/rendering/current.spec.js", | ||||||
|       "duration": 2833 |       "duration": 2753 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/erDiagram-unified.spec.js", |       "spec": "cypress/integration/rendering/erDiagram-unified.spec.js", | ||||||
|       "duration": 85321 |       "duration": 88028 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/erDiagram.spec.js", |       "spec": "cypress/integration/rendering/erDiagram.spec.js", | ||||||
|       "duration": 15673 |       "duration": 15615 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/errorDiagram.spec.js", |       "spec": "cypress/integration/rendering/errorDiagram.spec.js", | ||||||
|       "duration": 3724 |       "duration": 3706 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/flowchart-elk.spec.js", |       "spec": "cypress/integration/rendering/flowchart-elk.spec.js", | ||||||
|       "duration": 41178 |       "duration": 43905 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/flowchart-handDrawn.spec.js", |       "spec": "cypress/integration/rendering/flowchart-handDrawn.spec.js", | ||||||
|       "duration": 29966 |       "duration": 31217 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/flowchart-icon.spec.js", |       "spec": "cypress/integration/rendering/flowchart-icon.spec.js", | ||||||
|       "duration": 7689 |       "duration": 7531 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/flowchart-shape-alias.spec.ts", |       "spec": "cypress/integration/rendering/flowchart-shape-alias.spec.ts", | ||||||
|       "duration": 24709 |       "duration": 25423 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/flowchart-v2.spec.js", |       "spec": "cypress/integration/rendering/flowchart-v2.spec.js", | ||||||
|       "duration": 45565 |       "duration": 49664 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/flowchart.spec.js", |       "spec": "cypress/integration/rendering/flowchart.spec.js", | ||||||
|       "duration": 31144 |       "duration": 32525 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/gantt.spec.js", |       "spec": "cypress/integration/rendering/gantt.spec.js", | ||||||
|       "duration": 20808 |       "duration": 20915 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/gitGraph.spec.js", |       "spec": "cypress/integration/rendering/gitGraph.spec.js", | ||||||
|       "duration": 49985 |       "duration": 53556 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/iconShape.spec.ts", |       "spec": "cypress/integration/rendering/iconShape.spec.ts", | ||||||
|       "duration": 273272 |       "duration": 283038 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/imageShape.spec.ts", |       "spec": "cypress/integration/rendering/imageShape.spec.ts", | ||||||
|       "duration": 55880 |       "duration": 59434 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/info.spec.ts", |       "spec": "cypress/integration/rendering/info.spec.ts", | ||||||
|       "duration": 3271 |       "duration": 3101 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/journey.spec.js", |       "spec": "cypress/integration/rendering/journey.spec.js", | ||||||
|       "duration": 7293 |       "duration": 7099 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/kanban.spec.ts", |       "spec": "cypress/integration/rendering/kanban.spec.ts", | ||||||
|       "duration": 7861 |       "duration": 7567 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/katex.spec.js", |       "spec": "cypress/integration/rendering/katex.spec.js", | ||||||
|       "duration": 3922 |       "duration": 3817 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/marker_unique_id.spec.js", |       "spec": "cypress/integration/rendering/marker_unique_id.spec.js", | ||||||
|       "duration": 2726 |       "duration": 2624 | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "spec": "cypress/integration/rendering/mindmap-tidy-tree.spec.js", | ||||||
|  |       "duration": 4246 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/mindmap.spec.ts", |       "spec": "cypress/integration/rendering/mindmap.spec.ts", | ||||||
|       "duration": 11670 |       "duration": 11967 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/newShapes.spec.ts", |       "spec": "cypress/integration/rendering/newShapes.spec.ts", | ||||||
|       "duration": 146020 |       "duration": 151914 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/oldShapes.spec.ts", |       "spec": "cypress/integration/rendering/oldShapes.spec.ts", | ||||||
|       "duration": 114244 |       "duration": 116698 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/packet.spec.ts", |       "spec": "cypress/integration/rendering/packet.spec.ts", | ||||||
|       "duration": 5036 |       "duration": 4967 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/pie.spec.ts", |       "spec": "cypress/integration/rendering/pie.spec.ts", | ||||||
|       "duration": 6545 |       "duration": 6700 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/quadrantChart.spec.js", |       "spec": "cypress/integration/rendering/quadrantChart.spec.js", | ||||||
|       "duration": 9097 |       "duration": 8963 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/radar.spec.js", |       "spec": "cypress/integration/rendering/radar.spec.js", | ||||||
|       "duration": 5676 |       "duration": 5540 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/requirement.spec.js", |       "spec": "cypress/integration/rendering/requirement.spec.js", | ||||||
|       "duration": 2795 |       "duration": 2782 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/requirementDiagram-unified.spec.js", |       "spec": "cypress/integration/rendering/requirementDiagram-unified.spec.js", | ||||||
|       "duration": 51660 |       "duration": 54797 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/sankey.spec.ts", |       "spec": "cypress/integration/rendering/sankey.spec.ts", | ||||||
|       "duration": 6957 |       "duration": 6914 | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "spec": "cypress/integration/rendering/sequencediagram-v2.spec.js", | ||||||
|  |       "duration": 20481 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/sequencediagram.spec.js", |       "spec": "cypress/integration/rendering/sequencediagram.spec.js", | ||||||
|       "duration": 36026 |       "duration": 38490 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/stateDiagram-v2.spec.js", |       "spec": "cypress/integration/rendering/stateDiagram-v2.spec.js", | ||||||
|       "duration": 29551 |       "duration": 30766 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/stateDiagram.spec.js", |       "spec": "cypress/integration/rendering/stateDiagram.spec.js", | ||||||
|       "duration": 17364 |       "duration": 16705 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/theme.spec.js", |       "spec": "cypress/integration/rendering/theme.spec.js", | ||||||
|       "duration": 30209 |       "duration": 30928 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/timeline.spec.ts", |       "spec": "cypress/integration/rendering/timeline.spec.ts", | ||||||
|       "duration": 8699 |       "duration": 8424 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/treemap.spec.ts", |       "spec": "cypress/integration/rendering/treemap.spec.ts", | ||||||
|       "duration": 12168 |       "duration": 12533 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/xyChart.spec.js", |       "spec": "cypress/integration/rendering/xyChart.spec.js", | ||||||
|       "duration": 21453 |       "duration": 21197 | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "spec": "cypress/integration/rendering/zenuml.spec.js", |       "spec": "cypress/integration/rendering/zenuml.spec.js", | ||||||
|       "duration": 3577 |       "duration": 3455 | ||||||
|     } |     } | ||||||
|   ] |   ] | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
|   "compilerOptions": { |   "compilerOptions": { | ||||||
|     "target": "es2020", |     "target": "es2020", | ||||||
|     "lib": ["es2020", "dom"], |     "lib": ["es2020", "dom"], | ||||||
|     "types": ["cypress", "node", "@argos-ci/cypress/dist/support.d.ts"], |     "types": ["cypress", "node", "@argos-ci/cypress/support"], | ||||||
|     "allowImportingTsExtensions": true, |     "allowImportingTsExtensions": true, | ||||||
|     "noEmit": true |     "noEmit": true | ||||||
|   }, |   }, | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|       rel="stylesheet" |       rel="stylesheet" | ||||||
|     /> |     /> | ||||||
|     <link |     <link | ||||||
|       href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" |       href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" | ||||||
|       rel="stylesheet" |       rel="stylesheet" | ||||||
|     /> |     /> | ||||||
|     <link |     <link | ||||||
|   | |||||||
| @@ -29,7 +29,8 @@ In GitHub, you first [**fork a mermaid repository**](https://github.com/mermaid- | |||||||
|  |  | ||||||
| Then you **clone** a copy to your local development machine (e.g. where you code) to make a copy with all the files to work with. | Then you **clone** a copy to your local development machine (e.g. where you code) to make a copy with all the files to work with. | ||||||
|  |  | ||||||
| > **💡 Tip** > [Here is a GitHub document that gives an overview of the process](https://docs.github.com/en/get-started/quickstart/fork-a-repo). | > **💡 Tip** | ||||||
|  | > [Here is a GitHub document that gives an overview of the process](https://docs.github.com/en/get-started/quickstart/fork-a-repo). | ||||||
|  |  | ||||||
| ```bash | ```bash | ||||||
| git clone git@github.com/your-fork/mermaid | git clone git@github.com/your-fork/mermaid | ||||||
|   | |||||||
| @@ -33,7 +33,8 @@ mindmap | |||||||
|  |  | ||||||
| ## Join the Development | ## Join the Development | ||||||
|  |  | ||||||
| > **💡 Tip** > **Check out our** [**detailed contribution guide**](./contributing.md). | > **💡 Tip** | ||||||
|  | > **Check out our** [**detailed contribution guide**](./contributing.md). | ||||||
|  |  | ||||||
| Where to start: | Where to start: | ||||||
|  |  | ||||||
| @@ -47,7 +48,8 @@ Where to start: | |||||||
|  |  | ||||||
| ## A Question Or a Suggestion? | ## A Question Or a Suggestion? | ||||||
|  |  | ||||||
| > **💡 Tip** > **Have a look at** [**how to open an issue**](./questions-and-suggestions.md). | > **💡 Tip** | ||||||
|  | > **Have a look at** [**how to open an issue**](./questions-and-suggestions.md). | ||||||
|  |  | ||||||
| If you have faced a vulnerability [report it to us](./security.md). | If you have faced a vulnerability [report it to us](./security.md). | ||||||
|  |  | ||||||
|   | |||||||
| @@ -22,7 +22,6 @@ While directives allow you to change most of the default configuration settings, | |||||||
| Mermaid basically supports two types of configuration options to be overridden by directives. | Mermaid basically supports two types of configuration options to be overridden by directives. | ||||||
|  |  | ||||||
| 1. _General/Top Level configurations_ : These are the configurations that are available and applied to all the diagram. **Some of the most important top-level** configurations are: | 1. _General/Top Level configurations_ : These are the configurations that are available and applied to all the diagram. **Some of the most important top-level** configurations are: | ||||||
|  |  | ||||||
|    - theme |    - theme | ||||||
|    - fontFamily |    - fontFamily | ||||||
|    - logLevel |    - logLevel | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
|  |  | ||||||
| # Frequently Asked Questions | # Frequently Asked Questions | ||||||
|  |  | ||||||
| 1. [How to add title to flowchart?](https://github.com/mermaid-js/mermaid/issues/556#issuecomment-363182217) | 1. [How to add title to flowchart?](https://github.com/mermaid-js/mermaid/issues/1433#issuecomment-1991554712) | ||||||
| 2. [How to specify custom CSS file?](https://github.com/mermaidjs/mermaid.cli/pull/24#issuecomment-373402785) | 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/mermaid-js/mermaid/issues/542#issuecomment-3343564621) | 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) | 4. [How to specify gantt diagram xAxis format?](https://github.com/mermaid-js/mermaid/issues/269#issuecomment-373229136) | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								docs/config/layouts.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								docs/config/layouts.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | > **Warning** | ||||||
|  | > | ||||||
|  | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. | ||||||
|  | > | ||||||
|  | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/layouts.md](../../packages/mermaid/src/docs/config/layouts.md). | ||||||
|  |  | ||||||
|  | # Layouts | ||||||
|  |  | ||||||
|  | This page lists the available layout algorithms supported in Mermaid diagrams. | ||||||
|  |  | ||||||
|  | ## Supported Layouts | ||||||
|  |  | ||||||
|  | - **elk**: [ELK (Eclipse Layout Kernel)](https://www.eclipse.org/elk/) | ||||||
|  | - **tidy-tree**: Tidy tree layout for hierarchical diagrams [Tidy Tree Configuration](/config/tidy-tree) | ||||||
|  | - **cose-bilkent**: Cose Bilkent layout for force-directed graphs | ||||||
|  | - **dagre**: Dagre layout for layered graphs | ||||||
|  |  | ||||||
|  | ## How to Use | ||||||
|  |  | ||||||
|  | You can specify the layout in your diagram's YAML config or initialization options. For example: | ||||||
|  |  | ||||||
|  | ```mermaid-example | ||||||
|  | --- | ||||||
|  | config: | ||||||
|  |   layout: elk | ||||||
|  | --- | ||||||
|  | graph TD; | ||||||
|  |   A-->B; | ||||||
|  |   B-->C; | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```mermaid | ||||||
|  | --- | ||||||
|  | config: | ||||||
|  |   layout: elk | ||||||
|  | --- | ||||||
|  | graph TD; | ||||||
|  |   A-->B; | ||||||
|  |   B-->C; | ||||||
|  | ``` | ||||||
| @@ -19,6 +19,7 @@ | |||||||
| - [addDirective](functions/addDirective.md) | - [addDirective](functions/addDirective.md) | ||||||
| - [getConfig](functions/getConfig.md) | - [getConfig](functions/getConfig.md) | ||||||
| - [getSiteConfig](functions/getSiteConfig.md) | - [getSiteConfig](functions/getSiteConfig.md) | ||||||
|  | - [getUserDefinedConfig](functions/getUserDefinedConfig.md) | ||||||
| - [reset](functions/reset.md) | - [reset](functions/reset.md) | ||||||
| - [sanitize](functions/sanitize.md) | - [sanitize](functions/sanitize.md) | ||||||
| - [saveConfigFromInitialize](functions/saveConfigFromInitialize.md) | - [saveConfigFromInitialize](functions/saveConfigFromInitialize.md) | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								docs/config/setup/config/functions/getUserDefinedConfig.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								docs/config/setup/config/functions/getUserDefinedConfig.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | > **Warning** | ||||||
|  | > | ||||||
|  | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. | ||||||
|  | > | ||||||
|  | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/config/functions/getUserDefinedConfig.md](../../../../../packages/mermaid/src/docs/config/setup/config/functions/getUserDefinedConfig.md). | ||||||
|  |  | ||||||
|  | [**mermaid**](../../README.md) | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | # Function: getUserDefinedConfig() | ||||||
|  |  | ||||||
|  | > **getUserDefinedConfig**(): [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) | ||||||
|  |  | ||||||
|  | Defined in: [packages/mermaid/src/config.ts:252](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L252) | ||||||
|  |  | ||||||
|  | ## Returns | ||||||
|  |  | ||||||
|  | [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) | ||||||
| @@ -10,10 +10,6 @@ | |||||||
|  |  | ||||||
| # mermaid | # mermaid | ||||||
|  |  | ||||||
| ## Classes |  | ||||||
|  |  | ||||||
| - [UnknownDiagramError](classes/UnknownDiagramError.md) |  | ||||||
|  |  | ||||||
| ## Interfaces | ## Interfaces | ||||||
|  |  | ||||||
| - [DetailedError](interfaces/DetailedError.md) | - [DetailedError](interfaces/DetailedError.md) | ||||||
| @@ -27,6 +23,7 @@ | |||||||
| - [RenderOptions](interfaces/RenderOptions.md) | - [RenderOptions](interfaces/RenderOptions.md) | ||||||
| - [RenderResult](interfaces/RenderResult.md) | - [RenderResult](interfaces/RenderResult.md) | ||||||
| - [RunOptions](interfaces/RunOptions.md) | - [RunOptions](interfaces/RunOptions.md) | ||||||
|  | - [UnknownDiagramError](interfaces/UnknownDiagramError.md) | ||||||
|  |  | ||||||
| ## Type Aliases | ## Type Aliases | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,159 +0,0 @@ | |||||||
| > **Warning** |  | ||||||
| > |  | ||||||
| > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. |  | ||||||
| > |  | ||||||
| > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/mermaid/classes/UnknownDiagramError.md](../../../../../packages/mermaid/src/docs/config/setup/mermaid/classes/UnknownDiagramError.md). |  | ||||||
|  |  | ||||||
| [**mermaid**](../../README.md) |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| # Class: UnknownDiagramError |  | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/errors.ts:1](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/errors.ts#L1) |  | ||||||
|  |  | ||||||
| ## Extends |  | ||||||
|  |  | ||||||
| - `Error` |  | ||||||
|  |  | ||||||
| ## Constructors |  | ||||||
|  |  | ||||||
| ### new UnknownDiagramError() |  | ||||||
|  |  | ||||||
| > **new UnknownDiagramError**(`message`): [`UnknownDiagramError`](UnknownDiagramError.md) |  | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/errors.ts:2](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/errors.ts#L2) |  | ||||||
|  |  | ||||||
| #### Parameters |  | ||||||
|  |  | ||||||
| ##### message |  | ||||||
|  |  | ||||||
| `string` |  | ||||||
|  |  | ||||||
| #### Returns |  | ||||||
|  |  | ||||||
| [`UnknownDiagramError`](UnknownDiagramError.md) |  | ||||||
|  |  | ||||||
| #### Overrides |  | ||||||
|  |  | ||||||
| `Error.constructor` |  | ||||||
|  |  | ||||||
| ## Properties |  | ||||||
|  |  | ||||||
| ### cause? |  | ||||||
|  |  | ||||||
| > `optional` **cause**: `unknown` |  | ||||||
|  |  | ||||||
| Defined in: node_modules/.pnpm/typescript\@5.7.3/node_modules/typescript/lib/lib.es2022.error.d.ts:26 |  | ||||||
|  |  | ||||||
| #### Inherited from |  | ||||||
|  |  | ||||||
| `Error.cause` |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| ### message |  | ||||||
|  |  | ||||||
| > **message**: `string` |  | ||||||
|  |  | ||||||
| Defined in: node_modules/.pnpm/typescript\@5.7.3/node_modules/typescript/lib/lib.es5.d.ts:1077 |  | ||||||
|  |  | ||||||
| #### Inherited from |  | ||||||
|  |  | ||||||
| `Error.message` |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| ### name |  | ||||||
|  |  | ||||||
| > **name**: `string` |  | ||||||
|  |  | ||||||
| Defined in: node_modules/.pnpm/typescript\@5.7.3/node_modules/typescript/lib/lib.es5.d.ts:1076 |  | ||||||
|  |  | ||||||
| #### Inherited from |  | ||||||
|  |  | ||||||
| `Error.name` |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| ### stack? |  | ||||||
|  |  | ||||||
| > `optional` **stack**: `string` |  | ||||||
|  |  | ||||||
| Defined in: node_modules/.pnpm/typescript\@5.7.3/node_modules/typescript/lib/lib.es5.d.ts:1078 |  | ||||||
|  |  | ||||||
| #### Inherited from |  | ||||||
|  |  | ||||||
| `Error.stack` |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| ### prepareStackTrace()? |  | ||||||
|  |  | ||||||
| > `static` `optional` **prepareStackTrace**: (`err`, `stackTraces`) => `any` |  | ||||||
|  |  | ||||||
| Defined in: node_modules/.pnpm/@types+node\@22.13.5/node_modules/@types/node/globals.d.ts:143 |  | ||||||
|  |  | ||||||
| Optional override for formatting stack traces |  | ||||||
|  |  | ||||||
| #### Parameters |  | ||||||
|  |  | ||||||
| ##### err |  | ||||||
|  |  | ||||||
| `Error` |  | ||||||
|  |  | ||||||
| ##### stackTraces |  | ||||||
|  |  | ||||||
| `CallSite`\[] |  | ||||||
|  |  | ||||||
| #### Returns |  | ||||||
|  |  | ||||||
| `any` |  | ||||||
|  |  | ||||||
| #### See |  | ||||||
|  |  | ||||||
| <https://v8.dev/docs/stack-trace-api#customizing-stack-traces> |  | ||||||
|  |  | ||||||
| #### Inherited from |  | ||||||
|  |  | ||||||
| `Error.prepareStackTrace` |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| ### stackTraceLimit |  | ||||||
|  |  | ||||||
| > `static` **stackTraceLimit**: `number` |  | ||||||
|  |  | ||||||
| Defined in: node_modules/.pnpm/@types+node\@22.13.5/node_modules/@types/node/globals.d.ts:145 |  | ||||||
|  |  | ||||||
| #### Inherited from |  | ||||||
|  |  | ||||||
| `Error.stackTraceLimit` |  | ||||||
|  |  | ||||||
| ## Methods |  | ||||||
|  |  | ||||||
| ### captureStackTrace() |  | ||||||
|  |  | ||||||
| > `static` **captureStackTrace**(`targetObject`, `constructorOpt`?): `void` |  | ||||||
|  |  | ||||||
| Defined in: node_modules/.pnpm/@types+node\@22.13.5/node_modules/@types/node/globals.d.ts:136 |  | ||||||
|  |  | ||||||
| Create .stack property on a target object |  | ||||||
|  |  | ||||||
| #### Parameters |  | ||||||
|  |  | ||||||
| ##### targetObject |  | ||||||
|  |  | ||||||
| `object` |  | ||||||
|  |  | ||||||
| ##### constructorOpt? |  | ||||||
|  |  | ||||||
| `Function` |  | ||||||
|  |  | ||||||
| #### Returns |  | ||||||
|  |  | ||||||
| `void` |  | ||||||
|  |  | ||||||
| #### Inherited from |  | ||||||
|  |  | ||||||
| `Error.captureStackTrace` |  | ||||||
| @@ -10,7 +10,7 @@ | |||||||
|  |  | ||||||
| # Interface: ExternalDiagramDefinition | # Interface: ExternalDiagramDefinition | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/diagram-api/types.ts:94](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L94) | Defined in: [packages/mermaid/src/diagram-api/types.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L96) | ||||||
|  |  | ||||||
| ## Properties | ## Properties | ||||||
|  |  | ||||||
| @@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/diagram-api/types.ts:94](https://github.com/me | |||||||
|  |  | ||||||
| > **detector**: `DiagramDetector` | > **detector**: `DiagramDetector` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/diagram-api/types.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L96) | Defined in: [packages/mermaid/src/diagram-api/types.ts:98](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L98) | ||||||
|  |  | ||||||
| --- | --- | ||||||
|  |  | ||||||
| @@ -26,7 +26,7 @@ Defined in: [packages/mermaid/src/diagram-api/types.ts:96](https://github.com/me | |||||||
|  |  | ||||||
| > **id**: `string` | > **id**: `string` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/diagram-api/types.ts:95](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L95) | Defined in: [packages/mermaid/src/diagram-api/types.ts:97](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L97) | ||||||
|  |  | ||||||
| --- | --- | ||||||
|  |  | ||||||
| @@ -34,4 +34,4 @@ Defined in: [packages/mermaid/src/diagram-api/types.ts:95](https://github.com/me | |||||||
|  |  | ||||||
| > **loader**: `DiagramLoader` | > **loader**: `DiagramLoader` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/diagram-api/types.ts:97](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L97) | Defined in: [packages/mermaid/src/diagram-api/types.ts:99](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L99) | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
|  |  | ||||||
| # Interface: LayoutData | # Interface: LayoutData | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/rendering-util/types.ts:145](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L145) | Defined in: [packages/mermaid/src/rendering-util/types.ts:168](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L168) | ||||||
|  |  | ||||||
| ## Indexable | ## Indexable | ||||||
|  |  | ||||||
| @@ -22,7 +22,7 @@ Defined in: [packages/mermaid/src/rendering-util/types.ts:145](https://github.co | |||||||
|  |  | ||||||
| > **config**: [`MermaidConfig`](MermaidConfig.md) | > **config**: [`MermaidConfig`](MermaidConfig.md) | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/rendering-util/types.ts:148](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L148) | Defined in: [packages/mermaid/src/rendering-util/types.ts:171](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L171) | ||||||
|  |  | ||||||
| --- | --- | ||||||
|  |  | ||||||
| @@ -30,7 +30,7 @@ Defined in: [packages/mermaid/src/rendering-util/types.ts:148](https://github.co | |||||||
|  |  | ||||||
| > **edges**: `Edge`\[] | > **edges**: `Edge`\[] | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/rendering-util/types.ts:147](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L147) | Defined in: [packages/mermaid/src/rendering-util/types.ts:170](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L170) | ||||||
|  |  | ||||||
| --- | --- | ||||||
|  |  | ||||||
| @@ -38,4 +38,4 @@ Defined in: [packages/mermaid/src/rendering-util/types.ts:147](https://github.co | |||||||
|  |  | ||||||
| > **nodes**: `Node`\[] | > **nodes**: `Node`\[] | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/rendering-util/types.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L146) | Defined in: [packages/mermaid/src/rendering-util/types.ts:169](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L169) | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
|  |  | ||||||
| # Interface: LayoutLoaderDefinition | # Interface: LayoutLoaderDefinition | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/rendering-util/render.ts:21](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L21) | Defined in: [packages/mermaid/src/rendering-util/render.ts:24](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L24) | ||||||
|  |  | ||||||
| ## Properties | ## Properties | ||||||
|  |  | ||||||
| @@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/rendering-util/render.ts:21](https://github.co | |||||||
|  |  | ||||||
| > `optional` **algorithm**: `string` | > `optional` **algorithm**: `string` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/rendering-util/render.ts:24](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L24) | Defined in: [packages/mermaid/src/rendering-util/render.ts:27](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L27) | ||||||
|  |  | ||||||
| --- | --- | ||||||
|  |  | ||||||
| @@ -26,7 +26,7 @@ Defined in: [packages/mermaid/src/rendering-util/render.ts:24](https://github.co | |||||||
|  |  | ||||||
| > **loader**: `LayoutLoader` | > **loader**: `LayoutLoader` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/rendering-util/render.ts:23](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L23) | Defined in: [packages/mermaid/src/rendering-util/render.ts:26](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L26) | ||||||
|  |  | ||||||
| --- | --- | ||||||
|  |  | ||||||
| @@ -34,4 +34,4 @@ Defined in: [packages/mermaid/src/rendering-util/render.ts:23](https://github.co | |||||||
|  |  | ||||||
| > **name**: `string` | > **name**: `string` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/rendering-util/render.ts:22](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L22) | Defined in: [packages/mermaid/src/rendering-util/render.ts:25](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L25) | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ page. | |||||||
|  |  | ||||||
| ### detectType() | ### detectType() | ||||||
|  |  | ||||||
| > **detectType**: (`text`, `config`?) => `string` | > **detectType**: (`text`, `config?`) => `string` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/mermaid.ts:449](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L449) | Defined in: [packages/mermaid/src/mermaid.ts:449](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L449) | ||||||
|  |  | ||||||
| @@ -105,7 +105,7 @@ An array of objects with the id of the diagram. | |||||||
|  |  | ||||||
| ### ~~init()~~ | ### ~~init()~~ | ||||||
|  |  | ||||||
| > **init**: (`config`?, `nodes`?, `callback`?) => `Promise`<`void`> | > **init**: (`config?`, `nodes?`, `callback?`) => `Promise`<`void`> | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/mermaid.ts:442](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L442) | Defined in: [packages/mermaid/src/mermaid.ts:442](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L442) | ||||||
|  |  | ||||||
| @@ -117,7 +117,7 @@ Defined in: [packages/mermaid/src/mermaid.ts:442](https://github.com/mermaid-js/ | |||||||
|  |  | ||||||
| [`MermaidConfig`](MermaidConfig.md) | [`MermaidConfig`](MermaidConfig.md) | ||||||
|  |  | ||||||
| **Deprecated**, please set configuration in [initialize](Mermaid.md#initialize). | **Deprecated**, please set configuration in [initialize](#initialize). | ||||||
|  |  | ||||||
| ##### nodes? | ##### nodes? | ||||||
|  |  | ||||||
| @@ -141,13 +141,13 @@ Called once for each rendered diagram's id. | |||||||
|  |  | ||||||
| #### Deprecated | #### Deprecated | ||||||
|  |  | ||||||
| Use [initialize](Mermaid.md#initialize) and [run](Mermaid.md#run) instead. | Use [initialize](#initialize) and [run](#run) instead. | ||||||
|  |  | ||||||
| Renders the mermaid diagrams | Renders the mermaid diagrams | ||||||
|  |  | ||||||
| #### Deprecated | #### Deprecated | ||||||
|  |  | ||||||
| Use [initialize](Mermaid.md#initialize) and [run](Mermaid.md#run) instead. | Use [initialize](#initialize) and [run](#run) instead. | ||||||
|  |  | ||||||
| --- | --- | ||||||
|  |  | ||||||
| @@ -176,7 +176,7 @@ Configuration object for mermaid. | |||||||
|  |  | ||||||
| ### ~~mermaidAPI~~ | ### ~~mermaidAPI~~ | ||||||
|  |  | ||||||
| > **mermaidAPI**: `Readonly`<{ `defaultConfig`: [`MermaidConfig`](MermaidConfig.md); `getConfig`: () => [`MermaidConfig`](MermaidConfig.md); `getDiagramFromText`: (`text`, `metadata`) => `Promise`<`Diagram`>; `getSiteConfig`: () => [`MermaidConfig`](MermaidConfig.md); `globalReset`: () => `void`; `initialize`: (`userOptions`) => `void`; `parse`: (`text`, `parseOptions`) => `Promise`<`false` | [`ParseResult`](ParseResult.md)>(`text`, `parseOptions`?) => `Promise`<[`ParseResult`](ParseResult.md)>; `render`: (`id`, `text`, `svgContainingElement`?) => `Promise`<[`RenderResult`](RenderResult.md)>; `reset`: () => `void`; `setConfig`: (`conf`) => [`MermaidConfig`](MermaidConfig.md); `updateSiteConfig`: (`conf`) => [`MermaidConfig`](MermaidConfig.md); }> | > **mermaidAPI**: `Readonly`<{ `defaultConfig`: [`MermaidConfig`](MermaidConfig.md); `getConfig`: () => [`MermaidConfig`](MermaidConfig.md); `getDiagramFromText`: (`text`, `metadata`) => `Promise`<`Diagram`>; `getSiteConfig`: () => [`MermaidConfig`](MermaidConfig.md); `globalReset`: () => `void`; `initialize`: (`userOptions`) => `void`; `parse`: {(`text`, `parseOptions`): `Promise`<`false` | [`ParseResult`](ParseResult.md)>; (`text`, `parseOptions?`): `Promise`<[`ParseResult`](ParseResult.md)>; }; `render`: (`id`, `text`, `svgContainingElement?`) => `Promise`<[`RenderResult`](RenderResult.md)>; `reset`: () => `void`; `setConfig`: (`conf`) => [`MermaidConfig`](MermaidConfig.md); `updateSiteConfig`: (`conf`) => [`MermaidConfig`](MermaidConfig.md); }> | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/mermaid.ts:436](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L436) | Defined in: [packages/mermaid/src/mermaid.ts:436](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L436) | ||||||
|  |  | ||||||
| @@ -184,73 +184,81 @@ Defined in: [packages/mermaid/src/mermaid.ts:436](https://github.com/mermaid-js/ | |||||||
|  |  | ||||||
| #### Deprecated | #### Deprecated | ||||||
|  |  | ||||||
| Use [parse](Mermaid.md#parse) and [render](Mermaid.md#render) instead. Please [open a discussion](https://github.com/mermaid-js/mermaid/discussions) if your use case does not fit the new API. | Use [parse](#parse) and [render](#render) instead. Please [open a discussion](https://github.com/mermaid-js/mermaid/discussions) if your use case does not fit the new API. | ||||||
|  |  | ||||||
| --- | --- | ||||||
|  |  | ||||||
| ### parse() | ### parse() | ||||||
|  |  | ||||||
| > **parse**: (`text`, `parseOptions`) => `Promise`<`false` | [`ParseResult`](ParseResult.md)>(`text`, `parseOptions`?) => `Promise`<[`ParseResult`](ParseResult.md)> | > **parse**: {(`text`, `parseOptions`): `Promise`<`false` | [`ParseResult`](ParseResult.md)>; (`text`, `parseOptions?`): `Promise`<[`ParseResult`](ParseResult.md)>; } | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/mermaid.ts:437](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L437) | Defined in: [packages/mermaid/src/mermaid.ts:437](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L437) | ||||||
|  |  | ||||||
|  | #### Call Signature | ||||||
|  |  | ||||||
|  | > (`text`, `parseOptions`): `Promise`<`false` | [`ParseResult`](ParseResult.md)> | ||||||
|  |  | ||||||
| Parse the text and validate the syntax. | Parse the text and validate the syntax. | ||||||
|  |  | ||||||
| #### Parameters | ##### Parameters | ||||||
|  |  | ||||||
| ##### text | ###### text | ||||||
|  |  | ||||||
| `string` | `string` | ||||||
|  |  | ||||||
| The mermaid diagram definition. | The mermaid diagram definition. | ||||||
|  |  | ||||||
| ##### parseOptions | ###### parseOptions | ||||||
|  |  | ||||||
| [`ParseOptions`](ParseOptions.md) & `object` | [`ParseOptions`](ParseOptions.md) & `object` | ||||||
|  |  | ||||||
| Options for parsing. | Options for parsing. | ||||||
|  |  | ||||||
| #### Returns | ##### Returns | ||||||
|  |  | ||||||
| `Promise`<`false` | [`ParseResult`](ParseResult.md)> | `Promise`<`false` | [`ParseResult`](ParseResult.md)> | ||||||
|  |  | ||||||
| An object with the `diagramType` set to type of the diagram if valid. Otherwise `false` if parseOptions.suppressErrors is `true`. | An object with the `diagramType` set to type of the diagram if valid. Otherwise `false` if parseOptions.suppressErrors is `true`. | ||||||
|  |  | ||||||
| #### See | ##### See | ||||||
|  |  | ||||||
| [ParseOptions](ParseOptions.md) | [ParseOptions](ParseOptions.md) | ||||||
|  |  | ||||||
| #### Throws | ##### Throws | ||||||
|  |  | ||||||
| Error if the diagram is invalid and parseOptions.suppressErrors is false or not set. | Error if the diagram is invalid and parseOptions.suppressErrors is false or not set. | ||||||
|  |  | ||||||
|  | #### Call Signature | ||||||
|  |  | ||||||
|  | > (`text`, `parseOptions?`): `Promise`<[`ParseResult`](ParseResult.md)> | ||||||
|  |  | ||||||
| Parse the text and validate the syntax. | Parse the text and validate the syntax. | ||||||
|  |  | ||||||
| #### Parameters | ##### Parameters | ||||||
|  |  | ||||||
| ##### text | ###### text | ||||||
|  |  | ||||||
| `string` | `string` | ||||||
|  |  | ||||||
| The mermaid diagram definition. | The mermaid diagram definition. | ||||||
|  |  | ||||||
| ##### parseOptions? | ###### parseOptions? | ||||||
|  |  | ||||||
| [`ParseOptions`](ParseOptions.md) | [`ParseOptions`](ParseOptions.md) | ||||||
|  |  | ||||||
| Options for parsing. | Options for parsing. | ||||||
|  |  | ||||||
| #### Returns | ##### Returns | ||||||
|  |  | ||||||
| `Promise`<[`ParseResult`](ParseResult.md)> | `Promise`<[`ParseResult`](ParseResult.md)> | ||||||
|  |  | ||||||
| An object with the `diagramType` set to type of the diagram if valid. Otherwise `false` if parseOptions.suppressErrors is `true`. | An object with the `diagramType` set to type of the diagram if valid. Otherwise `false` if parseOptions.suppressErrors is `true`. | ||||||
|  |  | ||||||
| #### See | ##### See | ||||||
|  |  | ||||||
| [ParseOptions](ParseOptions.md) | [ParseOptions](ParseOptions.md) | ||||||
|  |  | ||||||
| #### Throws | ##### Throws | ||||||
|  |  | ||||||
| Error if the diagram is invalid and parseOptions.suppressErrors is false or not set. | Error if the diagram is invalid and parseOptions.suppressErrors is false or not set. | ||||||
|  |  | ||||||
| @@ -332,7 +340,7 @@ Defined in: [packages/mermaid/src/mermaid.ts:444](https://github.com/mermaid-js/ | |||||||
|  |  | ||||||
| ### render() | ### render() | ||||||
|  |  | ||||||
| > **render**: (`id`, `text`, `svgContainingElement`?) => `Promise`<[`RenderResult`](RenderResult.md)> | > **render**: (`id`, `text`, `svgContainingElement?`) => `Promise`<[`RenderResult`](RenderResult.md)> | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/mermaid.ts:438](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L438) | Defined in: [packages/mermaid/src/mermaid.ts:438](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L438) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
|  |  | ||||||
| # Interface: ParseOptions | # Interface: ParseOptions | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/types.ts:84](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L84) | Defined in: [packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L88) | ||||||
|  |  | ||||||
| ## Properties | ## Properties | ||||||
|  |  | ||||||
| @@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:84](https://github.com/mermaid-js/mer | |||||||
|  |  | ||||||
| > `optional` **suppressErrors**: `boolean` | > `optional` **suppressErrors**: `boolean` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/types.ts:89](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L89) | Defined in: [packages/mermaid/src/types.ts:93](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L93) | ||||||
|  |  | ||||||
| If `true`, parse will return `false` instead of throwing error when the diagram is invalid. | If `true`, parse will return `false` instead of throwing error when the diagram is invalid. | ||||||
| The `parseError` function will not be called. | The `parseError` function will not be called. | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
|  |  | ||||||
| # Interface: ParseResult | # Interface: ParseResult | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/types.ts:92](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L92) | Defined in: [packages/mermaid/src/types.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L96) | ||||||
|  |  | ||||||
| ## Properties | ## Properties | ||||||
|  |  | ||||||
| @@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:92](https://github.com/mermaid-js/mer | |||||||
|  |  | ||||||
| > **config**: [`MermaidConfig`](MermaidConfig.md) | > **config**: [`MermaidConfig`](MermaidConfig.md) | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/types.ts:100](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L100) | Defined in: [packages/mermaid/src/types.ts:104](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L104) | ||||||
|  |  | ||||||
| The config passed as YAML frontmatter or directives | The config passed as YAML frontmatter or directives | ||||||
|  |  | ||||||
| @@ -28,6 +28,6 @@ The config passed as YAML frontmatter or directives | |||||||
|  |  | ||||||
| > **diagramType**: `string` | > **diagramType**: `string` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/types.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L96) | Defined in: [packages/mermaid/src/types.ts:100](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L100) | ||||||
|  |  | ||||||
| The diagram type, e.g. 'flowchart', 'sequence', etc. | The diagram type, e.g. 'flowchart', 'sequence', etc. | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
|  |  | ||||||
| # Interface: RenderOptions | # Interface: RenderOptions | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/rendering-util/render.ts:7](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L7) | Defined in: [packages/mermaid/src/rendering-util/render.ts:10](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L10) | ||||||
|  |  | ||||||
| ## Properties | ## Properties | ||||||
|  |  | ||||||
| @@ -18,4 +18,4 @@ Defined in: [packages/mermaid/src/rendering-util/render.ts:7](https://github.com | |||||||
|  |  | ||||||
| > `optional` **algorithm**: `string` | > `optional` **algorithm**: `string` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/rendering-util/render.ts:8](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L8) | Defined in: [packages/mermaid/src/rendering-util/render.ts:11](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L11) | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
|  |  | ||||||
| # Interface: RenderResult | # Interface: RenderResult | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/types.ts:110](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L110) | Defined in: [packages/mermaid/src/types.ts:114](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L114) | ||||||
|  |  | ||||||
| ## Properties | ## Properties | ||||||
|  |  | ||||||
| @@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:110](https://github.com/mermaid-js/me | |||||||
|  |  | ||||||
| > `optional` **bindFunctions**: (`element`) => `void` | > `optional` **bindFunctions**: (`element`) => `void` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/types.ts:128](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L128) | Defined in: [packages/mermaid/src/types.ts:132](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L132) | ||||||
|  |  | ||||||
| Bind function to be called after the svg has been inserted into the DOM. | Bind function to be called after the svg has been inserted into the DOM. | ||||||
| This is necessary for adding event listeners to the elements in the svg. | This is necessary for adding event listeners to the elements in the svg. | ||||||
| @@ -45,7 +45,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present. | |||||||
|  |  | ||||||
| > **diagramType**: `string` | > **diagramType**: `string` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/types.ts:118](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L118) | Defined in: [packages/mermaid/src/types.ts:122](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L122) | ||||||
|  |  | ||||||
| The diagram type, e.g. 'flowchart', 'sequence', etc. | The diagram type, e.g. 'flowchart', 'sequence', etc. | ||||||
|  |  | ||||||
| @@ -55,6 +55,6 @@ The diagram type, e.g. 'flowchart', 'sequence', etc. | |||||||
|  |  | ||||||
| > **svg**: `string` | > **svg**: `string` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/types.ts:114](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L114) | Defined in: [packages/mermaid/src/types.ts:118](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L118) | ||||||
|  |  | ||||||
| The svg code for the rendered graph. | The svg code for the rendered graph. | ||||||
|   | |||||||
							
								
								
									
										65
									
								
								docs/config/setup/mermaid/interfaces/UnknownDiagramError.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								docs/config/setup/mermaid/interfaces/UnknownDiagramError.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | |||||||
|  | > **Warning** | ||||||
|  | > | ||||||
|  | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. | ||||||
|  | > | ||||||
|  | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/mermaid/interfaces/UnknownDiagramError.md](../../../../../packages/mermaid/src/docs/config/setup/mermaid/interfaces/UnknownDiagramError.md). | ||||||
|  |  | ||||||
|  | [**mermaid**](../../README.md) | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | # Interface: UnknownDiagramError | ||||||
|  |  | ||||||
|  | Defined in: [packages/mermaid/src/errors.ts:1](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/errors.ts#L1) | ||||||
|  |  | ||||||
|  | ## Extends | ||||||
|  |  | ||||||
|  | - `Error` | ||||||
|  |  | ||||||
|  | ## Properties | ||||||
|  |  | ||||||
|  | ### cause? | ||||||
|  |  | ||||||
|  | > `optional` **cause**: `unknown` | ||||||
|  |  | ||||||
|  | Defined in: node_modules/.pnpm/typescript\@5.7.3/node_modules/typescript/lib/lib.es2022.error.d.ts:26 | ||||||
|  |  | ||||||
|  | #### Inherited from | ||||||
|  |  | ||||||
|  | `Error.cause` | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ### message | ||||||
|  |  | ||||||
|  | > **message**: `string` | ||||||
|  |  | ||||||
|  | Defined in: node_modules/.pnpm/typescript\@5.7.3/node_modules/typescript/lib/lib.es5.d.ts:1077 | ||||||
|  |  | ||||||
|  | #### Inherited from | ||||||
|  |  | ||||||
|  | `Error.message` | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ### name | ||||||
|  |  | ||||||
|  | > **name**: `string` | ||||||
|  |  | ||||||
|  | Defined in: node_modules/.pnpm/typescript\@5.7.3/node_modules/typescript/lib/lib.es5.d.ts:1076 | ||||||
|  |  | ||||||
|  | #### Inherited from | ||||||
|  |  | ||||||
|  | `Error.name` | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ### stack? | ||||||
|  |  | ||||||
|  | > `optional` **stack**: `string` | ||||||
|  |  | ||||||
|  | Defined in: node_modules/.pnpm/typescript\@5.7.3/node_modules/typescript/lib/lib.es5.d.ts:1078 | ||||||
|  |  | ||||||
|  | #### Inherited from | ||||||
|  |  | ||||||
|  | `Error.stack` | ||||||
| @@ -10,6 +10,6 @@ | |||||||
|  |  | ||||||
| # Type Alias: InternalHelpers | # Type Alias: InternalHelpers | ||||||
|  |  | ||||||
| > **InternalHelpers**: _typeof_ `internalHelpers` | > **InternalHelpers** = _typeof_ `internalHelpers` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/internals.ts:33](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/internals.ts#L33) | Defined in: [packages/mermaid/src/internals.ts:33](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/internals.ts#L33) | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
|  |  | ||||||
| # Type Alias: ParseErrorFunction() | # Type Alias: ParseErrorFunction() | ||||||
|  |  | ||||||
| > **ParseErrorFunction**: (`err`, `hash`?) => `void` | > **ParseErrorFunction** = (`err`, `hash?`) => `void` | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/Diagram.ts:10](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/Diagram.ts#L10) | Defined in: [packages/mermaid/src/Diagram.ts:10](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/Diagram.ts#L10) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,6 +10,6 @@ | |||||||
|  |  | ||||||
| # Type Alias: SVG | # Type Alias: SVG | ||||||
|  |  | ||||||
| > **SVG**: `d3.Selection`<`SVGSVGElement`, `unknown`, `Element` | `null`, `unknown`> | > **SVG** = `d3.Selection`<`SVGSVGElement`, `unknown`, `Element` | `null`, `unknown`> | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/diagram-api/types.ts:126](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L126) | Defined in: [packages/mermaid/src/diagram-api/types.ts:128](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L128) | ||||||
|   | |||||||
| @@ -10,6 +10,6 @@ | |||||||
|  |  | ||||||
| # Type Alias: SVGGroup | # Type Alias: SVGGroup | ||||||
|  |  | ||||||
| > **SVGGroup**: `d3.Selection`<`SVGGElement`, `unknown`, `Element` | `null`, `unknown`> | > **SVGGroup** = `d3.Selection`<`SVGGElement`, `unknown`, `Element` | `null`, `unknown`> | ||||||
|  |  | ||||||
| Defined in: [packages/mermaid/src/diagram-api/types.ts:128](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L128) | Defined in: [packages/mermaid/src/diagram-api/types.ts:130](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L130) | ||||||
|   | |||||||
							
								
								
									
										89
									
								
								docs/config/tidy-tree.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								docs/config/tidy-tree.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | |||||||
|  | > **Warning** | ||||||
|  | > | ||||||
|  | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. | ||||||
|  | > | ||||||
|  | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/tidy-tree.md](../../packages/mermaid/src/docs/config/tidy-tree.md). | ||||||
|  |  | ||||||
|  | # Tidy-tree Layout | ||||||
|  |  | ||||||
|  | The **tidy-tree** layout arranges nodes in a hierarchical, tree-like structure. It is especially useful for diagrams where parent-child relationships are important, such as mindmaps. | ||||||
|  |  | ||||||
|  | ## Features | ||||||
|  |  | ||||||
|  | - Organizes nodes in a tidy, non-overlapping tree | ||||||
|  | - Ideal for mindmaps and hierarchical data | ||||||
|  | - Automatically adjusts spacing for readability | ||||||
|  |  | ||||||
|  | ## Example Usage | ||||||
|  |  | ||||||
|  | ```mermaid-example | ||||||
|  | --- | ||||||
|  | config: | ||||||
|  |   layout: tidy-tree | ||||||
|  | --- | ||||||
|  | mindmap | ||||||
|  | root((mindmap is a long thing)) | ||||||
|  |   A | ||||||
|  |   B | ||||||
|  |   C | ||||||
|  |   D | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```mermaid | ||||||
|  | --- | ||||||
|  | config: | ||||||
|  |   layout: tidy-tree | ||||||
|  | --- | ||||||
|  | mindmap | ||||||
|  | root((mindmap is a long thing)) | ||||||
|  |   A | ||||||
|  |   B | ||||||
|  |   C | ||||||
|  |   D | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```mermaid-example | ||||||
|  | --- | ||||||
|  | config: | ||||||
|  |   layout: tidy-tree | ||||||
|  | --- | ||||||
|  | mindmap | ||||||
|  | root((mindmap)) | ||||||
|  |     Origins | ||||||
|  |       Long history | ||||||
|  |       ::icon(fa fa-book) | ||||||
|  |       Popularisation | ||||||
|  |         British popular psychology author Tony Buzan | ||||||
|  |     Research | ||||||
|  |       On effectiveness<br/>and features | ||||||
|  |       On Automatic creation | ||||||
|  |         Uses | ||||||
|  |             Creative techniques | ||||||
|  |             Strategic planning | ||||||
|  |             Argument mapping | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```mermaid | ||||||
|  | --- | ||||||
|  | config: | ||||||
|  |   layout: tidy-tree | ||||||
|  | --- | ||||||
|  | mindmap | ||||||
|  | root((mindmap)) | ||||||
|  |     Origins | ||||||
|  |       Long history | ||||||
|  |       ::icon(fa fa-book) | ||||||
|  |       Popularisation | ||||||
|  |         British popular psychology author Tony Buzan | ||||||
|  |     Research | ||||||
|  |       On effectiveness<br/>and features | ||||||
|  |       On Automatic creation | ||||||
|  |         Uses | ||||||
|  |             Creative techniques | ||||||
|  |             Strategic planning | ||||||
|  |             Argument mapping | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Note | ||||||
|  |  | ||||||
|  | - Currently, tidy-tree is primarily supported for mindmap diagrams. | ||||||
| @@ -29,7 +29,6 @@ Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an accoun | |||||||
| - **Plugins** - A plugin system for extending the functionality of Mermaid. | - **Plugins** - A plugin system for extending the functionality of Mermaid. | ||||||
|  |  | ||||||
|   Official Mermaid Chart plugins: |   Official Mermaid Chart plugins: | ||||||
|  |  | ||||||
|   - [Mermaid Chart GPT](https://chatgpt.com/g/g-684cc36f30208191b21383b88650a45d-mermaid-chart-diagrams-and-charts) |   - [Mermaid Chart GPT](https://chatgpt.com/g/g-684cc36f30208191b21383b88650a45d-mermaid-chart-diagrams-and-charts) | ||||||
|   - [Confluence](https://marketplace.atlassian.com/apps/1234056/mermaid-chart-for-confluence?hosting=cloud&tab=overview) |   - [Confluence](https://marketplace.atlassian.com/apps/1234056/mermaid-chart-for-confluence?hosting=cloud&tab=overview) | ||||||
|   - [Jira](https://marketplace.atlassian.com/apps/1234810/mermaid-chart-for-jira?tab=overview&hosting=cloud) |   - [Jira](https://marketplace.atlassian.com/apps/1234810/mermaid-chart-for-jira?tab=overview&hosting=cloud) | ||||||
|   | |||||||
| @@ -35,13 +35,11 @@ The Mermaid Chart team is excited to introduce a new Visual Editor for Flowchart | |||||||
| Learn more: | Learn more: | ||||||
|  |  | ||||||
| - Visual Editor For Flowcharts | - Visual Editor For Flowcharts | ||||||
|  |  | ||||||
|   - [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-releases-new-visual-editor-for-flowcharts) |   - [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-releases-new-visual-editor-for-flowcharts) | ||||||
|  |  | ||||||
|   - [Demo video](https://www.youtube.com/watch?v=5aja0gijoO0) |   - [Demo video](https://www.youtube.com/watch?v=5aja0gijoO0) | ||||||
|  |  | ||||||
| - Visual Editor For Sequence diagrams | - Visual Editor For Sequence diagrams | ||||||
|  |  | ||||||
|   - [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-unveils-visual-editor-for-sequence-diagrams) |   - [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-unveils-visual-editor-for-sequence-diagrams) | ||||||
|  |  | ||||||
|   - [Demo video](https://youtu.be/imc2u5_N6Dc) |   - [Demo video](https://youtu.be/imc2u5_N6Dc) | ||||||
|   | |||||||
| @@ -6,6 +6,18 @@ | |||||||
|  |  | ||||||
| # Blog | # Blog | ||||||
|  |  | ||||||
|  | ## [The Essential Guide to Mermaid Chart Plugin for VS Code \[08/2025\]](https://docs.mermaidchart.com/blog/posts/the-essential-guide-to-mermaid-chart-plugin-for-vs-code-08-2025) | ||||||
|  |  | ||||||
|  | 9/9/2025 • 5 mins | ||||||
|  |  | ||||||
|  | Creating diagrams in VS Code has never been easier—the Mermaid VS Code plugin transforms text-based syntax into clear, professional visuals right inside your editor. With live previews, smart editing, and AI-powered diagram generation, it removes the friction from visualization so you can focus on coding. | ||||||
|  |  | ||||||
|  | ## [How to Create Perfect Flowcharts Using AI in 2025 Step-by-Step Guide](https://docs.mermaidchart.com/blog/posts/how-to-create-perfect-flowcharts-using-ai-in-2025-step-by-step-guide) | ||||||
|  |  | ||||||
|  | 7/22/2025 • 8 mins | ||||||
|  |  | ||||||
|  | In 2025, AI tools make creating flowcharts faster and easier than ever. With Mermaid’s AI flowchart generator, you can turn plain text into clear, accurate diagrams in seconds. This guide walks through how it works and how to get the most out of it for technical and business workflows alike. | ||||||
|  |  | ||||||
| ## [Mermaid introduces the Visual Editor for Entity Relationship diagrams](https://docs.mermaidchart.com/blog/posts/mermaid-introduces-the-visual-editor-for-entity-relationship-diagrams) | ## [Mermaid introduces the Visual Editor for Entity Relationship diagrams](https://docs.mermaidchart.com/blog/posts/mermaid-introduces-the-visual-editor-for-entity-relationship-diagrams) | ||||||
|  |  | ||||||
| 7/15/2025 • 7 mins | 7/15/2025 • 7 mins | ||||||
|   | |||||||
| @@ -194,7 +194,7 @@ architecture-beta | |||||||
| ## Icons | ## Icons | ||||||
|  |  | ||||||
| By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`. | By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`. | ||||||
| Users can use any of the 200,000+ icons available in iconify.design, or [add custom icons](../config/icons.md). | Users can use any of the 200,000+ icons available in iconify.design, or add other custom icons, by [registering an icon pack](../config/icons.md). | ||||||
|  |  | ||||||
| After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack. | After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -139,7 +139,6 @@ The following unfinished features are not supported in the short term. | |||||||
| - [ ] Legend | - [ ] Legend | ||||||
|  |  | ||||||
| - [x] System Context | - [x] System Context | ||||||
|  |  | ||||||
|   - [x] Person(alias, label, ?descr, ?sprite, ?tags, $link) |   - [x] Person(alias, label, ?descr, ?sprite, ?tags, $link) | ||||||
|   - [x] Person_Ext |   - [x] Person_Ext | ||||||
|   - [x] System(alias, label, ?descr, ?sprite, ?tags, $link) |   - [x] System(alias, label, ?descr, ?sprite, ?tags, $link) | ||||||
| @@ -153,7 +152,6 @@ The following unfinished features are not supported in the short term. | |||||||
|   - [x] System_Boundary |   - [x] System_Boundary | ||||||
|  |  | ||||||
| - [x] Container diagram | - [x] Container diagram | ||||||
|  |  | ||||||
|   - [x] Container(alias, label, ?techn, ?descr, ?sprite, ?tags, $link) |   - [x] Container(alias, label, ?techn, ?descr, ?sprite, ?tags, $link) | ||||||
|   - [x] ContainerDb |   - [x] ContainerDb | ||||||
|   - [x] ContainerQueue |   - [x] ContainerQueue | ||||||
| @@ -163,7 +161,6 @@ The following unfinished features are not supported in the short term. | |||||||
|   - [x] Container_Boundary(alias, label, ?tags, $link) |   - [x] Container_Boundary(alias, label, ?tags, $link) | ||||||
|  |  | ||||||
| - [x] Component diagram | - [x] Component diagram | ||||||
|  |  | ||||||
|   - [x] Component(alias, label, ?techn, ?descr, ?sprite, ?tags, $link) |   - [x] Component(alias, label, ?techn, ?descr, ?sprite, ?tags, $link) | ||||||
|   - [x] ComponentDb |   - [x] ComponentDb | ||||||
|   - [x] ComponentQueue |   - [x] ComponentQueue | ||||||
| @@ -172,18 +169,15 @@ The following unfinished features are not supported in the short term. | |||||||
|   - [x] ComponentQueue_Ext |   - [x] ComponentQueue_Ext | ||||||
|  |  | ||||||
| - [x] Dynamic diagram | - [x] Dynamic diagram | ||||||
|  |  | ||||||
|   - [x] RelIndex(index, from, to, label, ?tags, $link) |   - [x] RelIndex(index, from, to, label, ?tags, $link) | ||||||
|  |  | ||||||
| - [x] Deployment diagram | - [x] Deployment diagram | ||||||
|  |  | ||||||
|   - [x] Deployment_Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link) |   - [x] Deployment_Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link) | ||||||
|   - [x] Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link): short name of Deployment_Node() |   - [x] Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link): short name of Deployment_Node() | ||||||
|   - [x] Node_L(alias, label, ?type, ?descr, ?sprite, ?tags, $link): left aligned Node() |   - [x] Node_L(alias, label, ?type, ?descr, ?sprite, ?tags, $link): left aligned Node() | ||||||
|   - [x] Node_R(alias, label, ?type, ?descr, ?sprite, ?tags, $link): right aligned Node() |   - [x] Node_R(alias, label, ?type, ?descr, ?sprite, ?tags, $link): right aligned Node() | ||||||
|  |  | ||||||
| - [x] Relationship Types | - [x] Relationship Types | ||||||
|  |  | ||||||
|   - [x] Rel(from, to, label, ?techn, ?descr, ?sprite, ?tags, $link) |   - [x] Rel(from, to, label, ?techn, ?descr, ?sprite, ?tags, $link) | ||||||
|   - [x] BiRel (bidirectional relationship) |   - [x] BiRel (bidirectional relationship) | ||||||
|   - [x] Rel_U, Rel_Up |   - [x] Rel_U, Rel_Up | ||||||
|   | |||||||
| @@ -326,7 +326,9 @@ Below is a comprehensive list of the newly introduced shapes and their correspon | |||||||
|  |  | ||||||
| | **Semantic Name**                 | **Shape Name**         | **Short Name** | **Description**                | **Alias Supported**                                              | | | **Semantic Name**                 | **Shape Name**         | **Short Name** | **Description**                | **Alias Supported**                                              | | ||||||
| | --------------------------------- | ---------------------- | -------------- | ------------------------------ | ---------------------------------------------------------------- | | | --------------------------------- | ---------------------- | -------------- | ------------------------------ | ---------------------------------------------------------------- | | ||||||
|  | | Bang                              | Bang                   | `bang`         | Bang                           | `bang`                                                           | | ||||||
| | Card                              | Notched Rectangle      | `notch-rect`   | Represents a card              | `card`, `notched-rectangle`                                      | | | Card                              | Notched Rectangle      | `notch-rect`   | Represents a card              | `card`, `notched-rectangle`                                      | | ||||||
|  | | Cloud                             | Cloud                  | `cloud`        | cloud                          | `cloud`                                                          | | ||||||
| | Collate                           | Hourglass              | `hourglass`    | Represents a collate operation | `collate`, `hourglass`                                           | | | Collate                           | Hourglass              | `hourglass`    | Represents a collate operation | `collate`, `hourglass`                                           | | ||||||
| | Com Link                          | Lightning Bolt         | `bolt`         | Communication link             | `com-link`, `lightning-bolt`                                     | | | Com Link                          | Lightning Bolt         | `bolt`         | Communication link             | `com-link`, `lightning-bolt`                                     | | ||||||
| | Comment                           | Curly Brace            | `brace`        | Adds a comment                 | `brace-l`, `comment`                                             | | | Comment                           | Curly Brace            | `brace`        | Adds a comment                 | `brace-l`, `comment`                                             | | ||||||
|   | |||||||
| @@ -360,7 +360,8 @@ gantt | |||||||
|   weekday monday |   weekday monday | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| > **Warning** > `millisecond` and `second` support was added in v10.3.0 | > **Warning** | ||||||
|  | > `millisecond` and `second` support was added in v10.3.0 | ||||||
|  |  | ||||||
| ## Output in compact mode | ## Output in compact mode | ||||||
|  |  | ||||||
|   | |||||||
| @@ -314,3 +314,22 @@ You can also refer the [implementation in the live editor](https://github.com/me | |||||||
| cspell:locale en,en-gb | cspell:locale en,en-gb | ||||||
| cspell:ignore Buzan | cspell:ignore Buzan | ||||||
| ---> | ---> | ||||||
|  |  | ||||||
|  | ## Layouts | ||||||
|  |  | ||||||
|  | Mermaid also supports a Tidy Tree layout for mindmaps. | ||||||
|  |  | ||||||
|  | ``` | ||||||
|  | --- | ||||||
|  | config: | ||||||
|  |   layout: tidy-tree | ||||||
|  | --- | ||||||
|  | mindmap | ||||||
|  | root((mindmap is a long thing)) | ||||||
|  |   A | ||||||
|  |   B | ||||||
|  |   C | ||||||
|  |   D | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Instructions to add and register tidy-tree layout are present in [Tidy Tree Configuration](/config/tidy-tree) | ||||||
|   | |||||||
| @@ -38,3 +38,5 @@ Each user journey is split into sections, these describe the part of the task | |||||||
| the user is trying to complete. | the user is trying to complete. | ||||||
|  |  | ||||||
| Tasks syntax is `Task name: <score>: <comma separated list of actors>` | Tasks syntax is `Task name: <score>: <comma separated list of actors>` | ||||||
|  |  | ||||||
|  | Score is a number between 1 and 5, inclusive. | ||||||
|   | |||||||
| @@ -138,7 +138,7 @@ xychart | |||||||
|  |  | ||||||
| ## Chart Theme Variables | ## Chart Theme Variables | ||||||
|  |  | ||||||
| Themes for xychart resides inside xychart attribute so to set the variables use this syntax: | Themes for xychart reside inside the `xychart` attribute, allowing customization through the following syntax: | ||||||
|  |  | ||||||
| ```yaml | ```yaml | ||||||
| --- | --- | ||||||
| @@ -163,6 +163,52 @@ config: | |||||||
| | yAxisLineColor   | Color of the y-axis line                                  | | | yAxisLineColor   | Color of the y-axis line                                  | | ||||||
| | plotColorPalette | String of colors separated by comma e.g. "#f3456, #43445" | | | plotColorPalette | String of colors separated by comma e.g. "#f3456, #43445" | | ||||||
|  |  | ||||||
|  | ### Setting Colors for Lines and Bars | ||||||
|  |  | ||||||
|  | To set the color for lines and bars, use the `plotColorPalette` parameter. Colors in the palette will correspond sequentially to the elements in your chart (e.g., first bar/line will use the first color specified in the palette). | ||||||
|  |  | ||||||
|  | ```mermaid-example | ||||||
|  | --- | ||||||
|  | config: | ||||||
|  |   themeVariables: | ||||||
|  |     xyChart: | ||||||
|  |       plotColorPalette: '#000000, #0000FF, #00FF00, #FF0000' | ||||||
|  | --- | ||||||
|  | xychart | ||||||
|  | title "Different Colors in xyChart" | ||||||
|  | x-axis "categoriesX" ["Category 1", "Category 2", "Category 3", "Category 4"] | ||||||
|  | y-axis "valuesY" 0 --> 50 | ||||||
|  | %% Black line | ||||||
|  | line [10,20,30,40] | ||||||
|  | %% Blue bar | ||||||
|  | bar [20,30,25,35] | ||||||
|  | %% Green bar | ||||||
|  | bar [15,25,20,30] | ||||||
|  | %% Red line | ||||||
|  | line [5,15,25,35] | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```mermaid | ||||||
|  | --- | ||||||
|  | config: | ||||||
|  |   themeVariables: | ||||||
|  |     xyChart: | ||||||
|  |       plotColorPalette: '#000000, #0000FF, #00FF00, #FF0000' | ||||||
|  | --- | ||||||
|  | xychart | ||||||
|  | title "Different Colors in xyChart" | ||||||
|  | x-axis "categoriesX" ["Category 1", "Category 2", "Category 3", "Category 4"] | ||||||
|  | y-axis "valuesY" 0 --> 50 | ||||||
|  | %% Black line | ||||||
|  | line [10,20,30,40] | ||||||
|  | %% Blue bar | ||||||
|  | bar [20,30,25,35] | ||||||
|  | %% Green bar | ||||||
|  | bar [15,25,20,30] | ||||||
|  | %% Red line | ||||||
|  | line [5,15,25,35] | ||||||
|  | ``` | ||||||
|  |  | ||||||
| ## Example on config and theme | ## Example on config and theme | ||||||
|  |  | ||||||
| ```mermaid-example | ```mermaid-example | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ export default tseslint.config( | |||||||
|   ...tseslint.configs.stylisticTypeChecked, |   ...tseslint.configs.stylisticTypeChecked, | ||||||
|   { |   { | ||||||
|     ignores: [ |     ignores: [ | ||||||
|  |       '**/*.d.ts', | ||||||
|       '**/dist/', |       '**/dist/', | ||||||
|       '**/node_modules/', |       '**/node_modules/', | ||||||
|       '.git/', |       '.git/', | ||||||
|   | |||||||
							
								
								
									
										54
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								package.json
									
									
									
									
									
								
							| @@ -63,36 +63,36 @@ | |||||||
|     ] |     ] | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@applitools/eyes-cypress": "^3.44.9", |     "@applitools/eyes-cypress": "^3.55.2", | ||||||
|     "@argos-ci/cypress": "^5.0.2", |     "@argos-ci/cypress": "^6.1.1", | ||||||
|     "@changesets/changelog-github": "^0.5.1", |     "@changesets/changelog-github": "^0.5.1", | ||||||
|     "@changesets/cli": "^2.27.12", |     "@changesets/cli": "^2.29.7", | ||||||
|     "@cspell/eslint-plugin": "^8.19.4", |     "@cspell/eslint-plugin": "^8.19.4", | ||||||
|     "@cypress/code-coverage": "^3.12.49", |     "@cypress/code-coverage": "^3.14.6", | ||||||
|     "@eslint/js": "^9.26.0", |     "@eslint/js": "^9.26.0", | ||||||
|     "@rollup/plugin-typescript": "^12.1.2", |     "@rollup/plugin-typescript": "^12.1.4", | ||||||
|     "@types/cors": "^2.8.17", |     "@types/cors": "^2.8.19", | ||||||
|     "@types/express": "^5.0.0", |     "@types/express": "^5.0.3", | ||||||
|     "@types/js-yaml": "^4.0.9", |     "@types/js-yaml": "^4.0.9", | ||||||
|     "@types/jsdom": "^21.1.7", |     "@types/jsdom": "^21.1.7", | ||||||
|     "@types/lodash": "^4.17.15", |     "@types/lodash": "^4.17.20", | ||||||
|     "@types/mdast": "^4.0.4", |     "@types/mdast": "^4.0.4", | ||||||
|     "@types/node": "^22.13.5", |     "@types/node": "^22.18.6", | ||||||
|     "@types/rollup-plugin-visualizer": "^5.0.3", |     "@types/rollup-plugin-visualizer": "^5.0.3", | ||||||
|     "@vitest/coverage-v8": "^3.0.6", |     "@vitest/coverage-v8": "^3.2.4", | ||||||
|     "@vitest/spy": "^3.0.6", |     "@vitest/spy": "^3.2.4", | ||||||
|     "@vitest/ui": "^3.0.6", |     "@vitest/ui": "^3.2.4", | ||||||
|     "ajv": "^8.17.1", |     "ajv": "^8.17.1", | ||||||
|     "chokidar": "3.6.0", |     "chokidar": "3.6.0", | ||||||
|     "concurrently": "^9.1.2", |     "concurrently": "^9.2.1", | ||||||
|     "cors": "^2.8.5", |     "cors": "^2.8.5", | ||||||
|     "cpy-cli": "^5.0.0", |     "cpy-cli": "^5.0.0", | ||||||
|     "cross-env": "^7.0.3", |     "cross-env": "^7.0.3", | ||||||
|     "cspell": "^9.1.3", |     "cspell": "^9.2.1", | ||||||
|     "cypress": "^14.5.1", |     "cypress": "^14.5.4", | ||||||
|     "cypress-image-snapshot": "^4.0.1", |     "cypress-image-snapshot": "^4.0.1", | ||||||
|     "cypress-split": "^1.24.14", |     "cypress-split": "^1.24.23", | ||||||
|     "esbuild": "^0.25.0", |     "esbuild": "^0.25.10", | ||||||
|     "eslint": "^9.26.0", |     "eslint": "^9.26.0", | ||||||
|     "eslint-config-prettier": "^10.1.8", |     "eslint-config-prettier": "^10.1.8", | ||||||
|     "eslint-plugin-cypress": "^4.3.0", |     "eslint-plugin-cypress": "^4.3.0", | ||||||
| @@ -106,30 +106,30 @@ | |||||||
|     "eslint-plugin-tsdoc": "^0.4.0", |     "eslint-plugin-tsdoc": "^0.4.0", | ||||||
|     "eslint-plugin-unicorn": "^59.0.1", |     "eslint-plugin-unicorn": "^59.0.1", | ||||||
|     "express": "^5.1.0", |     "express": "^5.1.0", | ||||||
|     "globals": "^16.0.0", |     "globals": "^16.4.0", | ||||||
|     "globby": "^14.0.2", |     "globby": "^14.1.0", | ||||||
|     "husky": "^9.1.7", |     "husky": "^9.1.7", | ||||||
|     "jest": "^30.0.4", |     "jest": "^30.1.3", | ||||||
|     "jison": "^0.4.18", |     "jison": "^0.4.18", | ||||||
|     "js-yaml": "^4.1.0", |     "js-yaml": "^4.1.0", | ||||||
|     "jsdom": "^26.1.0", |     "jsdom": "^26.1.0", | ||||||
|     "langium-cli": "3.3.0", |     "langium-cli": "3.3.0", | ||||||
|     "lint-staged": "^16.1.2", |     "lint-staged": "^16.1.6", | ||||||
|     "markdown-table": "^3.0.4", |     "markdown-table": "^3.0.4", | ||||||
|     "nyc": "^17.1.0", |     "nyc": "^17.1.0", | ||||||
|     "path-browserify": "^1.0.1", |     "path-browserify": "^1.0.1", | ||||||
|     "prettier": "^3.5.2", |     "prettier": "^3.6.2", | ||||||
|     "prettier-plugin-jsdoc": "^1.3.2", |     "prettier-plugin-jsdoc": "^1.3.3", | ||||||
|     "rimraf": "^6.0.1", |     "rimraf": "^6.0.1", | ||||||
|     "rollup-plugin-visualizer": "^6.0.3", |     "rollup-plugin-visualizer": "^6.0.3", | ||||||
|     "start-server-and-test": "^2.0.10", |     "start-server-and-test": "^2.1.2", | ||||||
|     "tslib": "^2.8.1", |     "tslib": "^2.8.1", | ||||||
|     "tsx": "^4.7.3", |     "tsx": "^4.20.5", | ||||||
|     "typescript": "~5.7.3", |     "typescript": "~5.7.3", | ||||||
|     "typescript-eslint": "^8.38.0", |     "typescript-eslint": "^8.38.0", | ||||||
|     "vite": "^7.0.3", |     "vite": "^7.0.7", | ||||||
|     "vite-plugin-istanbul": "^7.0.0", |     "vite-plugin-istanbul": "^7.0.0", | ||||||
|     "vitest": "^3.0.6" |     "vitest": "^3.2.4" | ||||||
|   }, |   }, | ||||||
|   "nyc": { |   "nyc": { | ||||||
|     "report-dir": "coverage/cypress" |     "report-dir": "coverage/cypress" | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ | |||||||
|   "version": "1.0.0", |   "version": "1.0.0", | ||||||
|   "description": "Mermaid examples package", |   "description": "Mermaid examples package", | ||||||
|   "author": "Sidharth Vinod", |   "author": "Sidharth Vinod", | ||||||
|  |   "license": "MIT", | ||||||
|   "type": "module", |   "type": "module", | ||||||
|   "module": "./dist/mermaid-examples.core.mjs", |   "module": "./dist/mermaid-examples.core.mjs", | ||||||
|   "types": "./dist/mermaid.d.ts", |   "types": "./dist/mermaid.d.ts", | ||||||
|   | |||||||
| @@ -37,12 +37,12 @@ | |||||||
|     ] |     ] | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@braintree/sanitize-url": "^7.0.4", |     "@braintree/sanitize-url": "^7.1.1", | ||||||
|     "d3": "^7.9.0", |     "d3": "^7.9.0", | ||||||
|     "khroma": "^2.1.0" |     "khroma": "^2.1.0" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "concurrently": "^9.1.2", |     "concurrently": "^9.2.1", | ||||||
|     "mermaid": "workspace:*", |     "mermaid": "workspace:*", | ||||||
|     "rimraf": "^6.0.1" |     "rimraf": "^6.0.1" | ||||||
|   }, |   }, | ||||||
|   | |||||||
| @@ -1,5 +1,16 @@ | |||||||
| # @mermaid-js/layout-elk | # @mermaid-js/layout-elk | ||||||
|  |  | ||||||
|  | ## 0.2.0 | ||||||
|  |  | ||||||
|  | ### Minor Changes | ||||||
|  |  | ||||||
|  | - [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes | ||||||
|  |  | ||||||
|  | ### Patch Changes | ||||||
|  |  | ||||||
|  | - Updated dependencies [[`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800), [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20), [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05), [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8)]: | ||||||
|  |   - mermaid@11.11.0 | ||||||
|  |  | ||||||
| ## 0.1.9 | ## 0.1.9 | ||||||
|  |  | ||||||
| ### Patch Changes | ### Patch Changes | ||||||
|   | |||||||
| @@ -69,4 +69,4 @@ mermaid.registerLayoutLoaders(elkLayouts); | |||||||
| - `elk.mrtree`: Multi-root tree layout | - `elk.mrtree`: Multi-root tree layout | ||||||
| - `elk.sporeOverlap`: Spore overlap layout | - `elk.sporeOverlap`: Spore overlap layout | ||||||
|  |  | ||||||
| <!-- TODO: Add images for these layouts, as GitHub doesn't support natively --> | <!-- TODO: Add images for these layouts, as GitHub doesn't support natively. --> | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "@mermaid-js/layout-elk", |   "name": "@mermaid-js/layout-elk", | ||||||
|   "version": "0.1.9", |   "version": "0.2.0", | ||||||
|   "description": "ELK layout engine for mermaid", |   "description": "ELK layout engine for mermaid", | ||||||
|   "module": "dist/mermaid-layout-elk.core.mjs", |   "module": "dist/mermaid-layout-elk.core.mjs", | ||||||
|   "types": "dist/layouts.d.ts", |   "types": "dist/layouts.d.ts", | ||||||
|   | |||||||
							
								
								
									
										67
									
								
								packages/mermaid-layout-elk/src/__tests__/geometry.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								packages/mermaid-layout-elk/src/__tests__/geometry.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | |||||||
|  | import { describe, it, expect } from 'vitest'; | ||||||
|  | import { | ||||||
|  |   intersection, | ||||||
|  |   ensureTrulyOutside, | ||||||
|  |   makeInsidePoint, | ||||||
|  |   tryNodeIntersect, | ||||||
|  |   replaceEndpoint, | ||||||
|  |   type RectLike, | ||||||
|  |   type P, | ||||||
|  | } from '../geometry.js'; | ||||||
|  |  | ||||||
|  | const approx = (a: number, b: number, eps = 1e-6) => Math.abs(a - b) < eps; | ||||||
|  |  | ||||||
|  | describe('geometry helpers', () => { | ||||||
|  |   it('intersection: vertical approach hits bottom border', () => { | ||||||
|  |     const rect: RectLike = { x: 0, y: 0, width: 100, height: 50 }; | ||||||
|  |     const h = rect.height / 2; // 25 | ||||||
|  |     const outside: P = { x: 0, y: 100 }; | ||||||
|  |     const inside: P = { x: 0, y: 0 }; | ||||||
|  |     const res = intersection(rect, outside, inside); | ||||||
|  |     expect(approx(res.x, 0)).toBe(true); | ||||||
|  |     expect(approx(res.y, h)).toBe(true); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('ensureTrulyOutside nudges near-boundary point outward', () => { | ||||||
|  |     const rect: RectLike = { x: 0, y: 0, width: 100, height: 50 }; | ||||||
|  |     // near bottom boundary (y ~ h) | ||||||
|  |     const near: P = { x: 0, y: rect.height / 2 - 0.2 }; | ||||||
|  |     const out = ensureTrulyOutside(rect, near, 10); | ||||||
|  |     expect(out.y).toBeGreaterThan(rect.height / 2); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('makeInsidePoint keeps x for vertical and y from center', () => { | ||||||
|  |     const rect: RectLike = { x: 10, y: 5, width: 100, height: 50 }; | ||||||
|  |     const outside: P = { x: 10, y: 40 }; | ||||||
|  |     const center: P = { x: 99, y: -123 }; // center y should be used | ||||||
|  |     const inside = makeInsidePoint(rect, outside, center); | ||||||
|  |     expect(inside.x).toBe(outside.x); | ||||||
|  |     expect(inside.y).toBe(center.y); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('tryNodeIntersect returns null for wrong-side intersections', () => { | ||||||
|  |     const rect: RectLike = { x: 0, y: 0, width: 100, height: 50 }; | ||||||
|  |     const outside: P = { x: -50, y: 0 }; | ||||||
|  |     const node = { intersect: () => ({ x: 10, y: 0 }) } as any; // right side of center | ||||||
|  |     const res = tryNodeIntersect(node, rect, outside); | ||||||
|  |     expect(res).toBeNull(); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('replaceEndpoint dedup removes end/start appropriately', () => { | ||||||
|  |     const pts: P[] = [ | ||||||
|  |       { x: 0, y: 0 }, | ||||||
|  |       { x: 1, y: 1 }, | ||||||
|  |     ]; | ||||||
|  |     // remove duplicate end | ||||||
|  |     replaceEndpoint(pts, 'end', { x: 1, y: 1 }); | ||||||
|  |     expect(pts.length).toBe(1); | ||||||
|  |  | ||||||
|  |     const pts2: P[] = [ | ||||||
|  |       { x: 0, y: 0 }, | ||||||
|  |       { x: 1, y: 1 }, | ||||||
|  |     ]; | ||||||
|  |     // remove duplicate start | ||||||
|  |     replaceEndpoint(pts2, 'start', { x: 0, y: 0 }); | ||||||
|  |     expect(pts2.length).toBe(1); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
							
								
								
									
										9
									
								
								packages/mermaid-layout-elk/src/find-common-ancestor.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								packages/mermaid-layout-elk/src/find-common-ancestor.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | export interface TreeData { | ||||||
|  |   parentById: Record<string, string>; | ||||||
|  |   childrenById: Record<string, string[]>; | ||||||
|  | } | ||||||
|  | export declare const findCommonAncestor: ( | ||||||
|  |   id1: string, | ||||||
|  |   id2: string, | ||||||
|  |   { parentById }: TreeData | ||||||
|  | ) => string; | ||||||
							
								
								
									
										209
									
								
								packages/mermaid-layout-elk/src/geometry.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								packages/mermaid-layout-elk/src/geometry.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,209 @@ | |||||||
|  | /* Geometry utilities extracted from render.ts for reuse and testing */ | ||||||
|  |  | ||||||
|  | export interface P { | ||||||
|  |   x: number; | ||||||
|  |   y: number; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export interface RectLike { | ||||||
|  |   x: number; // center x | ||||||
|  |   y: number; // center y | ||||||
|  |   width: number; | ||||||
|  |   height: number; | ||||||
|  |   padding?: number; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export interface NodeLike { | ||||||
|  |   intersect?: (p: P) => P | null; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export const EPS = 1; | ||||||
|  | export const PUSH_OUT = 10; | ||||||
|  |  | ||||||
|  | export const onBorder = (bounds: RectLike, p: P, tol = 0.5): boolean => { | ||||||
|  |   const halfW = bounds.width / 2; | ||||||
|  |   const halfH = bounds.height / 2; | ||||||
|  |   const left = bounds.x - halfW; | ||||||
|  |   const right = bounds.x + halfW; | ||||||
|  |   const top = bounds.y - halfH; | ||||||
|  |   const bottom = bounds.y + halfH; | ||||||
|  |  | ||||||
|  |   const onLeft = Math.abs(p.x - left) <= tol && p.y >= top - tol && p.y <= bottom + tol; | ||||||
|  |   const onRight = Math.abs(p.x - right) <= tol && p.y >= top - tol && p.y <= bottom + tol; | ||||||
|  |   const onTop = Math.abs(p.y - top) <= tol && p.x >= left - tol && p.x <= right + tol; | ||||||
|  |   const onBottom = Math.abs(p.y - bottom) <= tol && p.x >= left - tol && p.x <= right + tol; | ||||||
|  |   return onLeft || onRight || onTop || onBottom; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Compute intersection between a rectangle (center x/y, width/height) and the line | ||||||
|  |  * segment from insidePoint -\> outsidePoint. Returns the point on the rectangle border. | ||||||
|  |  * | ||||||
|  |  * This version avoids snapping to outsidePoint when certain variables evaluate to 0 | ||||||
|  |  * (previously caused vertical top/bottom cases to miss the border). It only enforces | ||||||
|  |  * axis-constant behavior for purely vertical/horizontal approaches. | ||||||
|  |  */ | ||||||
|  | export const intersection = (node: RectLike, outsidePoint: P, insidePoint: P): P => { | ||||||
|  |   const x = node.x; | ||||||
|  |   const y = node.y; | ||||||
|  |  | ||||||
|  |   const dx = Math.abs(x - insidePoint.x); | ||||||
|  |   const w = node.width / 2; | ||||||
|  |   let r = insidePoint.x < outsidePoint.x ? w - dx : w + dx; | ||||||
|  |   const h = node.height / 2; | ||||||
|  |  | ||||||
|  |   const Q = Math.abs(outsidePoint.y - insidePoint.y); | ||||||
|  |   const R = Math.abs(outsidePoint.x - insidePoint.x); | ||||||
|  |  | ||||||
|  |   if (Math.abs(y - outsidePoint.y) * w > Math.abs(x - outsidePoint.x) * h) { | ||||||
|  |     // Intersection is top or bottom of rect. | ||||||
|  |     const q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y; | ||||||
|  |     r = (R * q) / Q; | ||||||
|  |     const res = { | ||||||
|  |       x: insidePoint.x < outsidePoint.x ? insidePoint.x + r : insidePoint.x - R + r, | ||||||
|  |       y: insidePoint.y < outsidePoint.y ? insidePoint.y + Q - q : insidePoint.y - Q + q, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     // Keep axis-constant special-cases only | ||||||
|  |     if (R === 0) { | ||||||
|  |       res.x = outsidePoint.x; | ||||||
|  |     } | ||||||
|  |     if (Q === 0) { | ||||||
|  |       res.y = outsidePoint.y; | ||||||
|  |     } | ||||||
|  |     return res; | ||||||
|  |   } else { | ||||||
|  |     // Intersection on sides of rect | ||||||
|  |     if (insidePoint.x < outsidePoint.x) { | ||||||
|  |       r = outsidePoint.x - w - x; | ||||||
|  |     } else { | ||||||
|  |       r = x - w - outsidePoint.x; | ||||||
|  |     } | ||||||
|  |     const q = (Q * r) / R; | ||||||
|  |     let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x - R + r; | ||||||
|  |     let _y = insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q; | ||||||
|  |  | ||||||
|  |     // Only handle axis-constant cases | ||||||
|  |     if (R === 0) { | ||||||
|  |       _x = outsidePoint.x; | ||||||
|  |     } | ||||||
|  |     if (Q === 0) { | ||||||
|  |       _y = outsidePoint.y; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return { x: _x, y: _y }; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const outsideNode = (node: RectLike, point: P): boolean => { | ||||||
|  |   const x = node.x; | ||||||
|  |   const y = node.y; | ||||||
|  |   const dx = Math.abs(point.x - x); | ||||||
|  |   const dy = Math.abs(point.y - y); | ||||||
|  |   const w = node.width / 2; | ||||||
|  |   const h = node.height / 2; | ||||||
|  |   return dx >= w || dy >= h; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const ensureTrulyOutside = (bounds: RectLike, p: P, push = PUSH_OUT): P => { | ||||||
|  |   const dx = Math.abs(p.x - bounds.x); | ||||||
|  |   const dy = Math.abs(p.y - bounds.y); | ||||||
|  |   const w = bounds.width / 2; | ||||||
|  |   const h = bounds.height / 2; | ||||||
|  |   if (Math.abs(dx - w) < EPS || Math.abs(dy - h) < EPS) { | ||||||
|  |     const dirX = p.x - bounds.x; | ||||||
|  |     const dirY = p.y - bounds.y; | ||||||
|  |     const len = Math.sqrt(dirX * dirX + dirY * dirY); | ||||||
|  |     if (len > 0) { | ||||||
|  |       return { | ||||||
|  |         x: bounds.x + (dirX / len) * (len + push), | ||||||
|  |         y: bounds.y + (dirY / len) * (len + push), | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return p; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const makeInsidePoint = (bounds: RectLike, outside: P, center: P): P => { | ||||||
|  |   const isVertical = Math.abs(outside.x - bounds.x) < EPS; | ||||||
|  |   const isHorizontal = Math.abs(outside.y - bounds.y) < EPS; | ||||||
|  |   return { | ||||||
|  |     x: isVertical | ||||||
|  |       ? outside.x | ||||||
|  |       : outside.x < bounds.x | ||||||
|  |         ? bounds.x - bounds.width / 4 | ||||||
|  |         : bounds.x + bounds.width / 4, | ||||||
|  |     y: isHorizontal ? outside.y : center.y, | ||||||
|  |   }; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const tryNodeIntersect = (node: NodeLike, bounds: RectLike, outside: P): P | null => { | ||||||
|  |   if (!node?.intersect) { | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  |   const res = node.intersect(outside); | ||||||
|  |   if (!res) { | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  |   const wrongSide = | ||||||
|  |     (outside.x < bounds.x && res.x > bounds.x) || (outside.x > bounds.x && res.x < bounds.x); | ||||||
|  |   if (wrongSide) { | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  |   const dist = Math.hypot(outside.x - res.x, outside.y - res.y); | ||||||
|  |   if (dist <= EPS) { | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  |   return res; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const fallbackIntersection = (bounds: RectLike, outside: P, center: P): P => { | ||||||
|  |   const inside = makeInsidePoint(bounds, outside, center); | ||||||
|  |   return intersection(bounds, outside, inside); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const computeNodeIntersection = ( | ||||||
|  |   node: NodeLike, | ||||||
|  |   bounds: RectLike, | ||||||
|  |   outside: P, | ||||||
|  |   center: P | ||||||
|  | ): P => { | ||||||
|  |   const outside2 = ensureTrulyOutside(bounds, outside); | ||||||
|  |   return tryNodeIntersect(node, bounds, outside2) ?? fallbackIntersection(bounds, outside2, center); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const replaceEndpoint = ( | ||||||
|  |   points: P[], | ||||||
|  |   which: 'start' | 'end', | ||||||
|  |   value: P | null | undefined, | ||||||
|  |   tol = 0.1 | ||||||
|  | ) => { | ||||||
|  |   if (!value || points.length === 0) { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (which === 'start') { | ||||||
|  |     if ( | ||||||
|  |       points.length > 0 && | ||||||
|  |       Math.abs(points[0].x - value.x) < tol && | ||||||
|  |       Math.abs(points[0].y - value.y) < tol | ||||||
|  |     ) { | ||||||
|  |       // duplicate start remove it | ||||||
|  |       points.shift(); | ||||||
|  |     } else { | ||||||
|  |       points[0] = value; | ||||||
|  |     } | ||||||
|  |   } else { | ||||||
|  |     const last = points.length - 1; | ||||||
|  |     if ( | ||||||
|  |       points.length > 0 && | ||||||
|  |       Math.abs(points[last].x - value.x) < tol && | ||||||
|  |       Math.abs(points[last].y - value.y) < tol | ||||||
|  |     ) { | ||||||
|  |       // duplicate end remove it | ||||||
|  |       points.pop(); | ||||||
|  |     } else { | ||||||
|  |       points[last] = value; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }; | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -5,6 +5,6 @@ | |||||||
|     "outDir": "./dist", |     "outDir": "./dist", | ||||||
|     "types": ["vitest/importMeta", "vitest/globals"] |     "types": ["vitest/importMeta", "vitest/globals"] | ||||||
|   }, |   }, | ||||||
|   "include": ["./src/**/*.ts"], |   "include": ["./src/**/*.ts", "./src/**/*.d.ts"], | ||||||
|   "typeRoots": ["./src/types"] |   "typeRoots": ["./src/types"] | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								packages/mermaid-layout-tidy-tree/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								packages/mermaid-layout-tidy-tree/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | # @mermaid-js/layout-tidy-tree | ||||||
|  |  | ||||||
|  | ## 0.2.0 | ||||||
|  |  | ||||||
|  | ### Minor Changes | ||||||
|  |  | ||||||
|  | - [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes | ||||||
|  |  | ||||||
|  | ### Patch Changes | ||||||
|  |  | ||||||
|  | - Updated dependencies [[`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800), [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20), [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05), [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8)]: | ||||||
|  |   - mermaid@11.11.0 | ||||||
							
								
								
									
										59
									
								
								packages/mermaid-layout-tidy-tree/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								packages/mermaid-layout-tidy-tree/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | |||||||
|  | # @mermaid-js/layout-tidy-tree | ||||||
|  |  | ||||||
|  | This package provides a bidirectional tidy tree layout engine for Mermaid based on the non-layered-tidy-tree-layout algorithm. | ||||||
|  |  | ||||||
|  | > [!NOTE] | ||||||
|  | > The Tidy Tree Layout engine will not be available in all providers that support mermaid by default. | ||||||
|  | > The websites will have to install the @mermaid-js/layout-tidy-tree package to use the Tidy Tree layout engine. | ||||||
|  |  | ||||||
|  | ## Usage | ||||||
|  |  | ||||||
|  | ``` | ||||||
|  | --- | ||||||
|  | config: | ||||||
|  |   layout: tidy-tree | ||||||
|  | --- | ||||||
|  | mindmap | ||||||
|  | root((mindmap)) | ||||||
|  |   A | ||||||
|  |   B | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### With bundlers | ||||||
|  |  | ||||||
|  | ```sh | ||||||
|  | npm install @mermaid-js/layout-tidy-tree | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ```ts | ||||||
|  | import mermaid from 'mermaid'; | ||||||
|  | import tidyTreeLayouts from '@mermaid-js/layout-tidy-tree'; | ||||||
|  |  | ||||||
|  | mermaid.registerLayoutLoaders(tidyTreeLayouts); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### With CDN | ||||||
|  |  | ||||||
|  | ```html | ||||||
|  | <script type="module"> | ||||||
|  |   import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs'; | ||||||
|  |   import tidyTreeLayouts from 'https://cdn.jsdelivr.net/npm/@mermaid-js/layout-tidy-tree@0/dist/mermaid-layout-tidy-tree.esm.min.mjs'; | ||||||
|  |  | ||||||
|  |   mermaid.registerLayoutLoaders(tidyTreeLayouts); | ||||||
|  | </script> | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Tidy Tree Layout Overview | ||||||
|  |  | ||||||
|  | tidy-tree: The bidirectional tidy tree layout | ||||||
|  |  | ||||||
|  | The bidirectional tidy tree layout algorithm creates two separate trees that grow horizontally in opposite directions from a central root node: | ||||||
|  | Left tree: grows horizontally to the left (children alternate: 1st, 3rd, 5th...) | ||||||
|  | Right tree: grows horizontally to the right (children alternate: 2nd, 4th, 6th...) | ||||||
|  |  | ||||||
|  | This creates a balanced, symmetric layout that is ideal for mindmaps, organizational charts, and other tree-based diagrams. | ||||||
|  |  | ||||||
|  | Layout Structure: | ||||||
|  | [Child 3] ← [Child 1] ← [Root] → [Child 2] → [Child 4] | ||||||
|  | ↓ ↓ ↓ ↓ | ||||||
|  | [GrandChild] [GrandChild] [GrandChild] [GrandChild] | ||||||
							
								
								
									
										46
									
								
								packages/mermaid-layout-tidy-tree/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								packages/mermaid-layout-tidy-tree/package.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | { | ||||||
|  |   "name": "@mermaid-js/layout-tidy-tree", | ||||||
|  |   "version": "0.2.0", | ||||||
|  |   "description": "Tidy-tree layout engine for mermaid", | ||||||
|  |   "module": "dist/mermaid-layout-tidy-tree.core.mjs", | ||||||
|  |   "types": "dist/layouts.d.ts", | ||||||
|  |   "type": "module", | ||||||
|  |   "exports": { | ||||||
|  |     ".": { | ||||||
|  |       "import": "./dist/mermaid-layout-tidy-tree.core.mjs", | ||||||
|  |       "types": "./dist/layouts.d.ts" | ||||||
|  |     }, | ||||||
|  |     "./": "./" | ||||||
|  |   }, | ||||||
|  |   "keywords": [ | ||||||
|  |     "diagram", | ||||||
|  |     "markdown", | ||||||
|  |     "tidy-tree", | ||||||
|  |     "mermaid", | ||||||
|  |     "layout" | ||||||
|  |   ], | ||||||
|  |   "scripts": {}, | ||||||
|  |   "repository": { | ||||||
|  |     "type": "git", | ||||||
|  |     "url": "https://github.com/mermaid-js/mermaid" | ||||||
|  |   }, | ||||||
|  |   "contributors": [ | ||||||
|  |     "Knut Sveidqvist", | ||||||
|  |     "Sidharth Vinod" | ||||||
|  |   ], | ||||||
|  |   "license": "MIT", | ||||||
|  |   "dependencies": { | ||||||
|  |     "d3": "^7.9.0", | ||||||
|  |     "non-layered-tidy-tree-layout": "^2.0.2" | ||||||
|  |   }, | ||||||
|  |   "devDependencies": { | ||||||
|  |     "@types/d3": "^7.4.3", | ||||||
|  |     "mermaid": "workspace:^" | ||||||
|  |   }, | ||||||
|  |   "peerDependencies": { | ||||||
|  |     "mermaid": "^11.0.2" | ||||||
|  |   }, | ||||||
|  |   "files": [ | ||||||
|  |     "dist" | ||||||
|  |   ] | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								packages/mermaid-layout-tidy-tree/src/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								packages/mermaid-layout-tidy-tree/src/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | /** | ||||||
|  |  * Bidirectional Tidy-Tree Layout Algorithm for Generic Diagrams | ||||||
|  |  * | ||||||
|  |  * This module provides a layout algorithm implementation using the | ||||||
|  |  * non-layered-tidy-tree-layout algorithm for positioning nodes and edges | ||||||
|  |  * in tree structures with a bidirectional approach. | ||||||
|  |  * | ||||||
|  |  * The algorithm creates two separate trees that grow horizontally in opposite | ||||||
|  |  * directions from a central root node: | ||||||
|  |  * - Left tree: grows horizontally to the left (children alternate: 1st, 3rd, 5th...) | ||||||
|  |  * - Right tree: grows horizontally to the right (children alternate: 2nd, 4th, 6th...) | ||||||
|  |  * | ||||||
|  |  * This creates a balanced, symmetric layout that is ideal for mindmaps, | ||||||
|  |  * organizational charts, and other tree-based diagrams. | ||||||
|  |  * | ||||||
|  |  * The algorithm follows the unified rendering pattern and can be used | ||||||
|  |  * by any diagram type that provides compatible LayoutData. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Render function for the bidirectional tidy-tree layout algorithm | ||||||
|  |  * | ||||||
|  |  * This function follows the unified rendering pattern used by all layout algorithms. | ||||||
|  |  * It takes LayoutData, inserts nodes into DOM, runs the bidirectional tidy-tree layout algorithm, | ||||||
|  |  * and renders the positioned elements to the SVG. | ||||||
|  |  * | ||||||
|  |  * Features: | ||||||
|  |  * - Alternates root children between left and right trees | ||||||
|  |  * - Left tree grows horizontally to the left (rotated 90° counterclockwise) | ||||||
|  |  * - Right tree grows horizontally to the right (rotated 90° clockwise) | ||||||
|  |  * - Uses tidy-tree algorithm for optimal spacing within each tree | ||||||
|  |  * - Creates symmetric, balanced layouts | ||||||
|  |  * - Maintains proper edge connections between all nodes | ||||||
|  |  * | ||||||
|  |  * Layout Structure: | ||||||
|  |  * ``` | ||||||
|  |  * [Child 3] ← [Child 1] ← [Root] → [Child 2] → [Child 4] | ||||||
|  |  *     ↓           ↓                     ↓           ↓ | ||||||
|  |  * [GrandChild]  [GrandChild]      [GrandChild]  [GrandChild] | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * @param layoutData - Layout data containing nodes, edges, and configuration | ||||||
|  |  * @param svg - SVG element to render to | ||||||
|  |  * @param helpers - Internal helper functions for rendering | ||||||
|  |  * @param options - Rendering options | ||||||
|  |  */ | ||||||
|  | export { default } from './layouts.js'; | ||||||
|  | export * from './types.js'; | ||||||
|  | export * from './layout.js'; | ||||||
|  | export { render } from './render.js'; | ||||||
							
								
								
									
										409
									
								
								packages/mermaid-layout-tidy-tree/src/layout.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										409
									
								
								packages/mermaid-layout-tidy-tree/src/layout.test.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,409 @@ | |||||||
|  | import { describe, it, expect, beforeEach, vi } from 'vitest'; | ||||||
|  | import { executeTidyTreeLayout, validateLayoutData } from './layout.js'; | ||||||
|  | import type { LayoutResult } from './types.js'; | ||||||
|  | import type { LayoutData, MermaidConfig } from 'mermaid'; | ||||||
|  |  | ||||||
|  | // Mock non-layered-tidy-tree-layout | ||||||
|  | vi.mock('non-layered-tidy-tree-layout', () => ({ | ||||||
|  |   BoundingBox: vi.fn().mockImplementation(() => ({})), | ||||||
|  |   Layout: vi.fn().mockImplementation(() => ({ | ||||||
|  |     layout: vi.fn().mockImplementation((treeData) => { | ||||||
|  |       const result = { ...treeData }; | ||||||
|  |  | ||||||
|  |       if (result.id?.toString().startsWith('virtual-root')) { | ||||||
|  |         result.x = 0; | ||||||
|  |         result.y = 0; | ||||||
|  |       } else { | ||||||
|  |         result.x = 100; | ||||||
|  |         result.y = 50; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (result.children) { | ||||||
|  |         result.children.forEach((child: any, index: number) => { | ||||||
|  |           child.x = 50 + index * 100; | ||||||
|  |           child.y = 100; | ||||||
|  |  | ||||||
|  |           if (child.children) { | ||||||
|  |             child.children.forEach((grandchild: any, gIndex: number) => { | ||||||
|  |               grandchild.x = 25 + gIndex * 50; | ||||||
|  |               grandchild.y = 200; | ||||||
|  |             }); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       return { | ||||||
|  |         result, | ||||||
|  |         boundingBox: { | ||||||
|  |           left: 0, | ||||||
|  |           right: 200, | ||||||
|  |           top: 0, | ||||||
|  |           bottom: 250, | ||||||
|  |         }, | ||||||
|  |       }; | ||||||
|  |     }), | ||||||
|  |   })), | ||||||
|  | })); | ||||||
|  |  | ||||||
|  | describe('Tidy-Tree Layout Algorithm', () => { | ||||||
|  |   let mockConfig: MermaidConfig; | ||||||
|  |   let mockLayoutData: LayoutData; | ||||||
|  |  | ||||||
|  |   beforeEach(() => { | ||||||
|  |     mockConfig = { | ||||||
|  |       theme: 'default', | ||||||
|  |     } as MermaidConfig; | ||||||
|  |  | ||||||
|  |     mockLayoutData = { | ||||||
|  |       nodes: [ | ||||||
|  |         { | ||||||
|  |           id: 'root', | ||||||
|  |           label: 'Root', | ||||||
|  |           isGroup: false, | ||||||
|  |           shape: 'rect', | ||||||
|  |           width: 100, | ||||||
|  |           height: 50, | ||||||
|  |           padding: 10, | ||||||
|  |           x: 0, | ||||||
|  |           y: 0, | ||||||
|  |           cssClasses: '', | ||||||
|  |           cssStyles: [], | ||||||
|  |           look: 'default', | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           id: 'child1', | ||||||
|  |           label: 'Child 1', | ||||||
|  |           isGroup: false, | ||||||
|  |           shape: 'rect', | ||||||
|  |           width: 80, | ||||||
|  |           height: 40, | ||||||
|  |           padding: 10, | ||||||
|  |           x: 0, | ||||||
|  |           y: 0, | ||||||
|  |           cssClasses: '', | ||||||
|  |           cssStyles: [], | ||||||
|  |           look: 'default', | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           id: 'child2', | ||||||
|  |           label: 'Child 2', | ||||||
|  |           isGroup: false, | ||||||
|  |           shape: 'rect', | ||||||
|  |           width: 80, | ||||||
|  |           height: 40, | ||||||
|  |           padding: 10, | ||||||
|  |           x: 0, | ||||||
|  |           y: 0, | ||||||
|  |           cssClasses: '', | ||||||
|  |           cssStyles: [], | ||||||
|  |           look: 'default', | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           id: 'child3', | ||||||
|  |           label: 'Child 3', | ||||||
|  |           isGroup: false, | ||||||
|  |           shape: 'rect', | ||||||
|  |           width: 80, | ||||||
|  |           height: 40, | ||||||
|  |           padding: 10, | ||||||
|  |           x: 0, | ||||||
|  |           y: 0, | ||||||
|  |           cssClasses: '', | ||||||
|  |           cssStyles: [], | ||||||
|  |           look: 'default', | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           id: 'child4', | ||||||
|  |           label: 'Child 4', | ||||||
|  |           isGroup: false, | ||||||
|  |           shape: 'rect', | ||||||
|  |           width: 80, | ||||||
|  |           height: 40, | ||||||
|  |           padding: 10, | ||||||
|  |           x: 0, | ||||||
|  |           y: 0, | ||||||
|  |           cssClasses: '', | ||||||
|  |           cssStyles: [], | ||||||
|  |           look: 'default', | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |       edges: [ | ||||||
|  |         { | ||||||
|  |           id: 'root_child1', | ||||||
|  |           start: 'root', | ||||||
|  |           end: 'child1', | ||||||
|  |           type: 'edge', | ||||||
|  |           classes: '', | ||||||
|  |           style: [], | ||||||
|  |           animate: false, | ||||||
|  |           arrowTypeEnd: 'arrow_point', | ||||||
|  |           arrowTypeStart: 'none', | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           id: 'root_child2', | ||||||
|  |           start: 'root', | ||||||
|  |           end: 'child2', | ||||||
|  |           type: 'edge', | ||||||
|  |           classes: '', | ||||||
|  |           style: [], | ||||||
|  |           animate: false, | ||||||
|  |           arrowTypeEnd: 'arrow_point', | ||||||
|  |           arrowTypeStart: 'none', | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           id: 'root_child3', | ||||||
|  |           start: 'root', | ||||||
|  |           end: 'child3', | ||||||
|  |           type: 'edge', | ||||||
|  |           classes: '', | ||||||
|  |           style: [], | ||||||
|  |           animate: false, | ||||||
|  |           arrowTypeEnd: 'arrow_point', | ||||||
|  |           arrowTypeStart: 'none', | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           id: 'root_child4', | ||||||
|  |           start: 'root', | ||||||
|  |           end: 'child4', | ||||||
|  |           type: 'edge', | ||||||
|  |           classes: '', | ||||||
|  |           style: [], | ||||||
|  |           animate: false, | ||||||
|  |           arrowTypeEnd: 'arrow_point', | ||||||
|  |           arrowTypeStart: 'none', | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |       config: mockConfig, | ||||||
|  |       direction: 'TB', | ||||||
|  |       type: 'test', | ||||||
|  |       diagramId: 'test-diagram', | ||||||
|  |       markers: [], | ||||||
|  |     }; | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   describe('validateLayoutData', () => { | ||||||
|  |     it('should validate correct layout data', () => { | ||||||
|  |       expect(() => validateLayoutData(mockLayoutData)).not.toThrow(); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should throw error for missing data', () => { | ||||||
|  |       expect(() => validateLayoutData(null as any)).toThrow('Layout data is required'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should throw error for missing config', () => { | ||||||
|  |       const invalidData = { ...mockLayoutData, config: null as any }; | ||||||
|  |       expect(() => validateLayoutData(invalidData)).toThrow('Configuration is required'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should throw error for invalid nodes array', () => { | ||||||
|  |       const invalidData = { ...mockLayoutData, nodes: null as any }; | ||||||
|  |       expect(() => validateLayoutData(invalidData)).toThrow('Nodes array is required'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should throw error for invalid edges array', () => { | ||||||
|  |       const invalidData = { ...mockLayoutData, edges: null as any }; | ||||||
|  |       expect(() => validateLayoutData(invalidData)).toThrow('Edges array is required'); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   describe('executeTidyTreeLayout function', () => { | ||||||
|  |     it('should execute layout algorithm successfully', async () => { | ||||||
|  |       const result: LayoutResult = await executeTidyTreeLayout(mockLayoutData); | ||||||
|  |  | ||||||
|  |       expect(result).toBeDefined(); | ||||||
|  |       expect(result.nodes).toBeDefined(); | ||||||
|  |       expect(result.edges).toBeDefined(); | ||||||
|  |       expect(Array.isArray(result.nodes)).toBe(true); | ||||||
|  |       expect(Array.isArray(result.edges)).toBe(true); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should return positioned nodes with coordinates', async () => { | ||||||
|  |       const result: LayoutResult = await executeTidyTreeLayout(mockLayoutData); | ||||||
|  |  | ||||||
|  |       expect(result.nodes.length).toBeGreaterThan(0); | ||||||
|  |       result.nodes.forEach((node) => { | ||||||
|  |         expect(node.x).toBeDefined(); | ||||||
|  |         expect(node.y).toBeDefined(); | ||||||
|  |         expect(typeof node.x).toBe('number'); | ||||||
|  |         expect(typeof node.y).toBe('number'); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should return positioned edges with coordinates', async () => { | ||||||
|  |       const result: LayoutResult = await executeTidyTreeLayout(mockLayoutData); | ||||||
|  |  | ||||||
|  |       expect(result.edges.length).toBeGreaterThan(0); | ||||||
|  |       result.edges.forEach((edge) => { | ||||||
|  |         expect(edge.startX).toBeDefined(); | ||||||
|  |         expect(edge.startY).toBeDefined(); | ||||||
|  |         expect(edge.midX).toBeDefined(); | ||||||
|  |         expect(edge.midY).toBeDefined(); | ||||||
|  |         expect(edge.endX).toBeDefined(); | ||||||
|  |         expect(edge.endY).toBeDefined(); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should handle empty layout data gracefully', async () => { | ||||||
|  |       const emptyData: LayoutData = { | ||||||
|  |         ...mockLayoutData, | ||||||
|  |         nodes: [], | ||||||
|  |         edges: [], | ||||||
|  |       }; | ||||||
|  |  | ||||||
|  |       await expect(executeTidyTreeLayout(emptyData)).rejects.toThrow( | ||||||
|  |         'No nodes found in layout data' | ||||||
|  |       ); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should throw error for missing nodes', async () => { | ||||||
|  |       const invalidData = { ...mockLayoutData, nodes: [] }; | ||||||
|  |  | ||||||
|  |       await expect(executeTidyTreeLayout(invalidData)).rejects.toThrow( | ||||||
|  |         'No nodes found in layout data' | ||||||
|  |       ); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should handle empty edges (single node tree)', async () => { | ||||||
|  |       const singleNodeData = { | ||||||
|  |         ...mockLayoutData, | ||||||
|  |         edges: [], | ||||||
|  |         nodes: [mockLayoutData.nodes[0]], | ||||||
|  |       }; | ||||||
|  |  | ||||||
|  |       const result = await executeTidyTreeLayout(singleNodeData); | ||||||
|  |       expect(result).toBeDefined(); | ||||||
|  |       expect(result.nodes).toHaveLength(1); | ||||||
|  |       expect(result.edges).toHaveLength(0); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should create bidirectional dual-tree layout with alternating left/right children', async () => { | ||||||
|  |       const result = await executeTidyTreeLayout(mockLayoutData); | ||||||
|  |  | ||||||
|  |       expect(result).toBeDefined(); | ||||||
|  |       expect(result.nodes).toHaveLength(5); | ||||||
|  |  | ||||||
|  |       const rootNode = result.nodes.find((node) => node.id === 'root'); | ||||||
|  |       expect(rootNode).toBeDefined(); | ||||||
|  |       expect(rootNode!.x).toBe(0); | ||||||
|  |       expect(rootNode!.y).toBe(20); | ||||||
|  |  | ||||||
|  |       const child1 = result.nodes.find((node) => node.id === 'child1'); | ||||||
|  |       const child2 = result.nodes.find((node) => node.id === 'child2'); | ||||||
|  |       const child3 = result.nodes.find((node) => node.id === 'child3'); | ||||||
|  |       const child4 = result.nodes.find((node) => node.id === 'child4'); | ||||||
|  |  | ||||||
|  |       expect(child1).toBeDefined(); | ||||||
|  |       expect(child2).toBeDefined(); | ||||||
|  |       expect(child3).toBeDefined(); | ||||||
|  |       expect(child4).toBeDefined(); | ||||||
|  |  | ||||||
|  |       expect(child1!.x).toBeLessThan(rootNode!.x); | ||||||
|  |       expect(child2!.x).toBeGreaterThan(rootNode!.x); | ||||||
|  |       expect(child3!.x).toBeLessThan(rootNode!.x); | ||||||
|  |       expect(child4!.x).toBeGreaterThan(rootNode!.x); | ||||||
|  |  | ||||||
|  |       expect(child1!.x).toBeLessThan(-100); | ||||||
|  |       expect(child3!.x).toBeLessThan(-100); | ||||||
|  |  | ||||||
|  |       expect(child2!.x).toBeGreaterThan(100); | ||||||
|  |       expect(child4!.x).toBeGreaterThan(100); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should correctly transpose coordinates to prevent high nodes from covering nodes above them', async () => { | ||||||
|  |       const testData = { | ||||||
|  |         ...mockLayoutData, | ||||||
|  |         nodes: [ | ||||||
|  |           { | ||||||
|  |             id: 'root', | ||||||
|  |             label: 'Root', | ||||||
|  |             isGroup: false, | ||||||
|  |             shape: 'rect' as const, | ||||||
|  |             width: 100, | ||||||
|  |             height: 50, | ||||||
|  |             padding: 10, | ||||||
|  |             x: 0, | ||||||
|  |             y: 0, | ||||||
|  |             cssClasses: '', | ||||||
|  |             cssStyles: [], | ||||||
|  |             look: 'default', | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             id: 'tall-child', | ||||||
|  |             label: 'Tall Child', | ||||||
|  |             isGroup: false, | ||||||
|  |             shape: 'rect' as const, | ||||||
|  |             width: 80, | ||||||
|  |             height: 120, | ||||||
|  |             padding: 10, | ||||||
|  |             x: 0, | ||||||
|  |             y: 0, | ||||||
|  |             cssClasses: '', | ||||||
|  |             cssStyles: [], | ||||||
|  |             look: 'default', | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             id: 'short-child', | ||||||
|  |             label: 'Short Child', | ||||||
|  |             isGroup: false, | ||||||
|  |             shape: 'rect' as const, | ||||||
|  |             width: 80, | ||||||
|  |             height: 30, | ||||||
|  |             padding: 10, | ||||||
|  |             x: 0, | ||||||
|  |             y: 0, | ||||||
|  |             cssClasses: '', | ||||||
|  |             cssStyles: [], | ||||||
|  |             look: 'default', | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|  |         edges: [ | ||||||
|  |           { | ||||||
|  |             id: 'root_tall', | ||||||
|  |             start: 'root', | ||||||
|  |             end: 'tall-child', | ||||||
|  |             type: 'edge', | ||||||
|  |             classes: '', | ||||||
|  |             style: [], | ||||||
|  |             animate: false, | ||||||
|  |             arrowTypeEnd: 'arrow_point', | ||||||
|  |             arrowTypeStart: 'none', | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             id: 'root_short', | ||||||
|  |             start: 'root', | ||||||
|  |             end: 'short-child', | ||||||
|  |             type: 'edge', | ||||||
|  |             classes: '', | ||||||
|  |             style: [], | ||||||
|  |             animate: false, | ||||||
|  |             arrowTypeEnd: 'arrow_point', | ||||||
|  |             arrowTypeStart: 'none', | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|  |       }; | ||||||
|  |  | ||||||
|  |       const result = await executeTidyTreeLayout(testData); | ||||||
|  |  | ||||||
|  |       expect(result).toBeDefined(); | ||||||
|  |       expect(result.nodes).toHaveLength(3); | ||||||
|  |  | ||||||
|  |       const rootNode = result.nodes.find((node) => node.id === 'root'); | ||||||
|  |       const tallChild = result.nodes.find((node) => node.id === 'tall-child'); | ||||||
|  |       const shortChild = result.nodes.find((node) => node.id === 'short-child'); | ||||||
|  |  | ||||||
|  |       expect(rootNode).toBeDefined(); | ||||||
|  |       expect(tallChild).toBeDefined(); | ||||||
|  |       expect(shortChild).toBeDefined(); | ||||||
|  |  | ||||||
|  |       expect(tallChild!.x).not.toBe(shortChild!.x); | ||||||
|  |  | ||||||
|  |       expect(tallChild!.width).toBe(80); | ||||||
|  |       expect(tallChild!.height).toBe(120); | ||||||
|  |       expect(shortChild!.width).toBe(80); | ||||||
|  |       expect(shortChild!.height).toBe(30); | ||||||
|  |  | ||||||
|  |       const yDifference = Math.abs(tallChild!.y - shortChild!.y); | ||||||
|  |       expect(yDifference).toBeGreaterThanOrEqual(0); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
							
								
								
									
										629
									
								
								packages/mermaid-layout-tidy-tree/src/layout.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										629
									
								
								packages/mermaid-layout-tidy-tree/src/layout.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,629 @@ | |||||||
|  | import type { LayoutData } from 'mermaid'; | ||||||
|  | import type { Bounds, Point } from 'mermaid/src/types.js'; | ||||||
|  | import { BoundingBox, Layout } from 'non-layered-tidy-tree-layout'; | ||||||
|  | import type { | ||||||
|  |   Edge, | ||||||
|  |   LayoutResult, | ||||||
|  |   Node, | ||||||
|  |   PositionedEdge, | ||||||
|  |   PositionedNode, | ||||||
|  |   TidyTreeNode, | ||||||
|  | } from './types.js'; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Execute the tidy-tree layout algorithm on generic layout data | ||||||
|  |  * | ||||||
|  |  * This function takes layout data and uses the non-layered-tidy-tree-layout | ||||||
|  |  * algorithm to calculate optimal node positions for tree structures. | ||||||
|  |  * | ||||||
|  |  * @param data - The layout data containing nodes, edges, and configuration | ||||||
|  |  * @param config - Mermaid configuration object | ||||||
|  |  * @returns Promise resolving to layout result with positioned nodes and edges | ||||||
|  |  */ | ||||||
|  | export function executeTidyTreeLayout(data: LayoutData): Promise<LayoutResult> { | ||||||
|  |   let intersectionShift = 50; | ||||||
|  |  | ||||||
|  |   return new Promise((resolve, reject) => { | ||||||
|  |     try { | ||||||
|  |       if (!data.nodes || !Array.isArray(data.nodes) || data.nodes.length === 0) { | ||||||
|  |         throw new Error('No nodes found in layout data'); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (!data.edges || !Array.isArray(data.edges)) { | ||||||
|  |         data.edges = []; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       const { leftTree, rightTree, rootNode } = convertToDualTreeFormat(data); | ||||||
|  |  | ||||||
|  |       const gap = 20; | ||||||
|  |       const bottomPadding = 40; | ||||||
|  |       intersectionShift = 30; | ||||||
|  |  | ||||||
|  |       const bb = new BoundingBox(gap, bottomPadding); | ||||||
|  |       const layout = new Layout(bb); | ||||||
|  |  | ||||||
|  |       let leftResult = null; | ||||||
|  |       let rightResult = null; | ||||||
|  |  | ||||||
|  |       if (leftTree) { | ||||||
|  |         const leftLayoutResult = layout.layout(leftTree); | ||||||
|  |         leftResult = leftLayoutResult.result; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (rightTree) { | ||||||
|  |         const rightLayoutResult = layout.layout(rightTree); | ||||||
|  |         rightResult = rightLayoutResult.result; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       const positionedNodes = combineAndPositionTrees(rootNode, leftResult, rightResult); | ||||||
|  |       const positionedEdges = calculateEdgePositions( | ||||||
|  |         data.edges, | ||||||
|  |         positionedNodes, | ||||||
|  |         intersectionShift | ||||||
|  |       ); | ||||||
|  |       resolve({ | ||||||
|  |         nodes: positionedNodes, | ||||||
|  |         edges: positionedEdges, | ||||||
|  |       }); | ||||||
|  |     } catch (error) { | ||||||
|  |       reject(error); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Convert LayoutData to dual-tree format (left and right trees) | ||||||
|  |  * | ||||||
|  |  * This function builds two separate tree structures from the nodes and edges, | ||||||
|  |  * alternating children between left and right trees. | ||||||
|  |  */ | ||||||
|  | function convertToDualTreeFormat(data: LayoutData): { | ||||||
|  |   leftTree: TidyTreeNode | null; | ||||||
|  |   rightTree: TidyTreeNode | null; | ||||||
|  |   rootNode: TidyTreeNode; | ||||||
|  | } { | ||||||
|  |   const { nodes, edges } = data; | ||||||
|  |  | ||||||
|  |   const nodeMap = new Map<string, Node>(); | ||||||
|  |   nodes.forEach((node) => nodeMap.set(node.id, node)); | ||||||
|  |  | ||||||
|  |   const children = new Map<string, string[]>(); | ||||||
|  |   const parents = new Map<string, string>(); | ||||||
|  |  | ||||||
|  |   edges.forEach((edge) => { | ||||||
|  |     const parentId = edge.start; | ||||||
|  |     const childId = edge.end; | ||||||
|  |  | ||||||
|  |     if (parentId && childId) { | ||||||
|  |       if (!children.has(parentId)) { | ||||||
|  |         children.set(parentId, []); | ||||||
|  |       } | ||||||
|  |       children.get(parentId)!.push(childId); | ||||||
|  |       parents.set(childId, parentId); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   const rootNodeData = nodes.find((node) => !parents.has(node.id)); | ||||||
|  |   if (!rootNodeData && nodes.length === 0) { | ||||||
|  |     throw new Error('No nodes available to create tree'); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const actualRoot = rootNodeData ?? nodes[0]; | ||||||
|  |  | ||||||
|  |   const rootNode: TidyTreeNode = { | ||||||
|  |     id: actualRoot.id, | ||||||
|  |     width: actualRoot.width ?? 100, | ||||||
|  |     height: actualRoot.height ?? 50, | ||||||
|  |     _originalNode: actualRoot, | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   const rootChildren = children.get(actualRoot.id) ?? []; | ||||||
|  |   const leftChildren: string[] = []; | ||||||
|  |   const rightChildren: string[] = []; | ||||||
|  |  | ||||||
|  |   rootChildren.forEach((childId, index) => { | ||||||
|  |     if (index % 2 === 0) { | ||||||
|  |       leftChildren.push(childId); | ||||||
|  |     } else { | ||||||
|  |       rightChildren.push(childId); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   const leftTree = leftChildren.length > 0 ? buildSubTree(leftChildren, children, nodeMap) : null; | ||||||
|  |  | ||||||
|  |   const rightTree = | ||||||
|  |     rightChildren.length > 0 ? buildSubTree(rightChildren, children, nodeMap) : null; | ||||||
|  |  | ||||||
|  |   return { leftTree, rightTree, rootNode }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Build a subtree from a list of root children | ||||||
|  |  * For horizontal trees, we need to transpose width/height since the tree will be rotated 90° | ||||||
|  |  */ | ||||||
|  | function buildSubTree( | ||||||
|  |   rootChildren: string[], | ||||||
|  |   children: Map<string, string[]>, | ||||||
|  |   nodeMap: Map<string, Node> | ||||||
|  | ): TidyTreeNode { | ||||||
|  |   const virtualRoot: TidyTreeNode = { | ||||||
|  |     id: `virtual-root-${Math.random()}`, | ||||||
|  |     width: 1, | ||||||
|  |     height: 1, | ||||||
|  |     children: rootChildren | ||||||
|  |       .map((childId) => nodeMap.get(childId)) | ||||||
|  |       .filter((child): child is Node => child !== undefined) | ||||||
|  |       .map((child) => convertNodeToTidyTreeTransposed(child, children, nodeMap)), | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   return virtualRoot; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Recursively convert a node and its children to tidy-tree format | ||||||
|  |  * This version transposes width/height for horizontal tree layout | ||||||
|  |  */ | ||||||
|  | function convertNodeToTidyTreeTransposed( | ||||||
|  |   node: Node, | ||||||
|  |   children: Map<string, string[]>, | ||||||
|  |   nodeMap: Map<string, Node> | ||||||
|  | ): TidyTreeNode { | ||||||
|  |   const childIds = children.get(node.id) ?? []; | ||||||
|  |   const childNodes = childIds | ||||||
|  |     .map((childId) => nodeMap.get(childId)) | ||||||
|  |     .filter((child): child is Node => child !== undefined) | ||||||
|  |     .map((child) => convertNodeToTidyTreeTransposed(child, children, nodeMap)); | ||||||
|  |  | ||||||
|  |   return { | ||||||
|  |     id: node.id, | ||||||
|  |     width: node.height ?? 50, | ||||||
|  |     height: node.width ?? 100, | ||||||
|  |     children: childNodes.length > 0 ? childNodes : undefined, | ||||||
|  |     _originalNode: node, | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | /** | ||||||
|  |  * Combine and position the left and right trees around the root node | ||||||
|  |  * Creates a bidirectional layout where left tree grows left and right tree grows right | ||||||
|  |  */ | ||||||
|  | function combineAndPositionTrees( | ||||||
|  |   rootNode: TidyTreeNode, | ||||||
|  |   leftResult: TidyTreeNode | null, | ||||||
|  |   rightResult: TidyTreeNode | null | ||||||
|  | ): PositionedNode[] { | ||||||
|  |   const positionedNodes: PositionedNode[] = []; | ||||||
|  |  | ||||||
|  |   const rootX = 0; | ||||||
|  |   const rootY = 0; | ||||||
|  |  | ||||||
|  |   const treeSpacing = rootNode.width / 2 + 30; | ||||||
|  |   const leftTreeNodes: PositionedNode[] = []; | ||||||
|  |   const rightTreeNodes: PositionedNode[] = []; | ||||||
|  |  | ||||||
|  |   if (leftResult?.children) { | ||||||
|  |     positionLeftTreeBidirectional(leftResult.children, leftTreeNodes, rootX - treeSpacing, rootY); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (rightResult?.children) { | ||||||
|  |     positionRightTreeBidirectional( | ||||||
|  |       rightResult.children, | ||||||
|  |       rightTreeNodes, | ||||||
|  |       rootX + treeSpacing, | ||||||
|  |       rootY | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   let leftTreeCenterY = 0; | ||||||
|  |   let rightTreeCenterY = 0; | ||||||
|  |  | ||||||
|  |   if (leftTreeNodes.length > 0) { | ||||||
|  |     const leftTreeXPositions = [...new Set(leftTreeNodes.map((node) => node.x))].sort( | ||||||
|  |       (a, b) => b - a | ||||||
|  |     ); | ||||||
|  |     const firstLevelLeftX = leftTreeXPositions[0]; | ||||||
|  |     const firstLevelLeftNodes = leftTreeNodes.filter((node) => node.x === firstLevelLeftX); | ||||||
|  |  | ||||||
|  |     if (firstLevelLeftNodes.length > 0) { | ||||||
|  |       const leftMinY = Math.min( | ||||||
|  |         ...firstLevelLeftNodes.map((node) => node.y - (node.height ?? 50) / 2) | ||||||
|  |       ); | ||||||
|  |       const leftMaxY = Math.max( | ||||||
|  |         ...firstLevelLeftNodes.map((node) => node.y + (node.height ?? 50) / 2) | ||||||
|  |       ); | ||||||
|  |       leftTreeCenterY = (leftMinY + leftMaxY) / 2; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (rightTreeNodes.length > 0) { | ||||||
|  |     const rightTreeXPositions = [...new Set(rightTreeNodes.map((node) => node.x))].sort( | ||||||
|  |       (a, b) => a - b | ||||||
|  |     ); | ||||||
|  |     const firstLevelRightX = rightTreeXPositions[0]; | ||||||
|  |     const firstLevelRightNodes = rightTreeNodes.filter((node) => node.x === firstLevelRightX); | ||||||
|  |  | ||||||
|  |     if (firstLevelRightNodes.length > 0) { | ||||||
|  |       const rightMinY = Math.min( | ||||||
|  |         ...firstLevelRightNodes.map((node) => node.y - (node.height ?? 50) / 2) | ||||||
|  |       ); | ||||||
|  |       const rightMaxY = Math.max( | ||||||
|  |         ...firstLevelRightNodes.map((node) => node.y + (node.height ?? 50) / 2) | ||||||
|  |       ); | ||||||
|  |       rightTreeCenterY = (rightMinY + rightMaxY) / 2; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const leftTreeOffset = -leftTreeCenterY; | ||||||
|  |   const rightTreeOffset = -rightTreeCenterY; | ||||||
|  |  | ||||||
|  |   positionedNodes.push({ | ||||||
|  |     id: String(rootNode.id), | ||||||
|  |     x: rootX, | ||||||
|  |     y: rootY + 20, | ||||||
|  |     section: 'root', | ||||||
|  |     width: rootNode._originalNode?.width ?? rootNode.width, | ||||||
|  |     height: rootNode._originalNode?.height ?? rootNode.height, | ||||||
|  |     originalNode: rootNode._originalNode, | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   const leftTreeNodesWithOffset = leftTreeNodes.map((node) => ({ | ||||||
|  |     id: node.id, | ||||||
|  |     x: node.x - (node.width ?? 0) / 2, | ||||||
|  |     y: node.y + leftTreeOffset + (node.height ?? 0) / 2, | ||||||
|  |     section: 'left' as const, | ||||||
|  |     width: node.width, | ||||||
|  |     height: node.height, | ||||||
|  |     originalNode: node.originalNode, | ||||||
|  |   })); | ||||||
|  |  | ||||||
|  |   const rightTreeNodesWithOffset = rightTreeNodes.map((node) => ({ | ||||||
|  |     id: node.id, | ||||||
|  |     x: node.x + (node.width ?? 0) / 2, | ||||||
|  |     y: node.y + rightTreeOffset + (node.height ?? 0) / 2, | ||||||
|  |     section: 'right' as const, | ||||||
|  |     width: node.width, | ||||||
|  |     height: node.height, | ||||||
|  |     originalNode: node.originalNode, | ||||||
|  |   })); | ||||||
|  |  | ||||||
|  |   positionedNodes.push(...leftTreeNodesWithOffset); | ||||||
|  |   positionedNodes.push(...rightTreeNodesWithOffset); | ||||||
|  |  | ||||||
|  |   return positionedNodes; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Position nodes from the left tree in a bidirectional layout (grows to the left) | ||||||
|  |  * Rotates the tree 90 degrees counterclockwise so it grows horizontally to the left | ||||||
|  |  */ | ||||||
|  | function positionLeftTreeBidirectional( | ||||||
|  |   nodes: TidyTreeNode[], | ||||||
|  |   positionedNodes: PositionedNode[], | ||||||
|  |   offsetX: number, | ||||||
|  |   offsetY: number | ||||||
|  | ): void { | ||||||
|  |   nodes.forEach((node) => { | ||||||
|  |     const distanceFromRoot = node.y ?? 0; | ||||||
|  |     const verticalPosition = node.x ?? 0; | ||||||
|  |  | ||||||
|  |     const originalWidth = node._originalNode?.width ?? 100; | ||||||
|  |     const originalHeight = node._originalNode?.height ?? 50; | ||||||
|  |  | ||||||
|  |     const adjustedY = offsetY + verticalPosition; | ||||||
|  |  | ||||||
|  |     positionedNodes.push({ | ||||||
|  |       id: String(node.id), | ||||||
|  |       x: offsetX - distanceFromRoot, | ||||||
|  |       y: adjustedY, | ||||||
|  |       width: originalWidth, | ||||||
|  |       height: originalHeight, | ||||||
|  |       originalNode: node._originalNode, | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     if (node.children) { | ||||||
|  |       positionLeftTreeBidirectional(node.children, positionedNodes, offsetX, offsetY); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Position nodes from the right tree in a bidirectional layout (grows to the right) | ||||||
|  |  * Rotates the tree 90 degrees clockwise so it grows horizontally to the right | ||||||
|  |  */ | ||||||
|  | function positionRightTreeBidirectional( | ||||||
|  |   nodes: TidyTreeNode[], | ||||||
|  |   positionedNodes: PositionedNode[], | ||||||
|  |   offsetX: number, | ||||||
|  |   offsetY: number | ||||||
|  | ): void { | ||||||
|  |   nodes.forEach((node) => { | ||||||
|  |     const distanceFromRoot = node.y ?? 0; | ||||||
|  |     const verticalPosition = node.x ?? 0; | ||||||
|  |  | ||||||
|  |     const originalWidth = node._originalNode?.width ?? 100; | ||||||
|  |     const originalHeight = node._originalNode?.height ?? 50; | ||||||
|  |  | ||||||
|  |     const adjustedY = offsetY + verticalPosition; | ||||||
|  |  | ||||||
|  |     positionedNodes.push({ | ||||||
|  |       id: String(node.id), | ||||||
|  |       x: offsetX + distanceFromRoot, | ||||||
|  |       y: adjustedY, | ||||||
|  |       width: originalWidth, | ||||||
|  |       height: originalHeight, | ||||||
|  |       originalNode: node._originalNode, | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     if (node.children) { | ||||||
|  |       positionRightTreeBidirectional(node.children, positionedNodes, offsetX, offsetY); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Calculate the intersection point of a line with a circle | ||||||
|  |  * @param circle - Circle coordinates and radius | ||||||
|  |  * @param lineStart - Starting point of the line | ||||||
|  |  * @param lineEnd - Ending point of the line | ||||||
|  |  * @returns The intersection point | ||||||
|  |  */ | ||||||
|  | function computeCircleEdgeIntersection(circle: Bounds, lineStart: Point, lineEnd: Point): Point { | ||||||
|  |   const radius = Math.min(circle.width, circle.height) / 2; | ||||||
|  |  | ||||||
|  |   const dx = lineEnd.x - lineStart.x; | ||||||
|  |   const dy = lineEnd.y - lineStart.y; | ||||||
|  |   const length = Math.sqrt(dx * dx + dy * dy); | ||||||
|  |  | ||||||
|  |   if (length === 0) { | ||||||
|  |     return lineStart; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const nx = dx / length; | ||||||
|  |   const ny = dy / length; | ||||||
|  |  | ||||||
|  |   return { | ||||||
|  |     x: circle.x - nx * radius, | ||||||
|  |     y: circle.y - ny * radius, | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function intersection(node: PositionedNode, outsidePoint: Point, insidePoint: Point): Point { | ||||||
|  |   const x = node.x; | ||||||
|  |   const y = node.y; | ||||||
|  |  | ||||||
|  |   if (!node.width || !node.height) { | ||||||
|  |     return { x: outsidePoint.x, y: outsidePoint.y }; | ||||||
|  |   } | ||||||
|  |   const dx = Math.abs(x - insidePoint.x); | ||||||
|  |   const w = node?.width / 2; | ||||||
|  |   let r = insidePoint.x < outsidePoint.x ? w - dx : w + dx; | ||||||
|  |   const h = node.height / 2; | ||||||
|  |  | ||||||
|  |   const Q = Math.abs(outsidePoint.y - insidePoint.y); | ||||||
|  |   const R = Math.abs(outsidePoint.x - insidePoint.x); | ||||||
|  |  | ||||||
|  |   if (Math.abs(y - outsidePoint.y) * w > Math.abs(x - outsidePoint.x) * h) { | ||||||
|  |     // Intersection is top or bottom of rect. | ||||||
|  |     const q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y; | ||||||
|  |     r = (R * q) / Q; | ||||||
|  |     const res = { | ||||||
|  |       x: insidePoint.x < outsidePoint.x ? insidePoint.x + r : insidePoint.x - R + r, | ||||||
|  |       y: insidePoint.y < outsidePoint.y ? insidePoint.y + Q - q : insidePoint.y - Q + q, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     if (r === 0) { | ||||||
|  |       res.x = outsidePoint.x; | ||||||
|  |       res.y = outsidePoint.y; | ||||||
|  |     } | ||||||
|  |     if (R === 0) { | ||||||
|  |       res.x = outsidePoint.x; | ||||||
|  |     } | ||||||
|  |     if (Q === 0) { | ||||||
|  |       res.y = outsidePoint.y; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return res; | ||||||
|  |   } else { | ||||||
|  |     if (insidePoint.x < outsidePoint.x) { | ||||||
|  |       r = outsidePoint.x - w - x; | ||||||
|  |     } else { | ||||||
|  |       r = x - w - outsidePoint.x; | ||||||
|  |     } | ||||||
|  |     const q = (Q * r) / R; | ||||||
|  |     let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x - R + r; | ||||||
|  |     let _y = insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q; | ||||||
|  |  | ||||||
|  |     if (r === 0) { | ||||||
|  |       _x = outsidePoint.x; | ||||||
|  |       _y = outsidePoint.y; | ||||||
|  |     } | ||||||
|  |     if (R === 0) { | ||||||
|  |       _x = outsidePoint.x; | ||||||
|  |     } | ||||||
|  |     if (Q === 0) { | ||||||
|  |       _y = outsidePoint.y; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return { x: _x, y: _y }; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Calculate edge positions based on positioned nodes | ||||||
|  |  * Now includes tree membership and node dimensions for precise edge calculations | ||||||
|  |  * Edges now stop at shape boundaries instead of extending to centers | ||||||
|  |  */ | ||||||
|  | function calculateEdgePositions( | ||||||
|  |   edges: Edge[], | ||||||
|  |   positionedNodes: PositionedNode[], | ||||||
|  |   intersectionShift: number | ||||||
|  | ): PositionedEdge[] { | ||||||
|  |   const nodeInfo = new Map<string, PositionedNode>(); | ||||||
|  |   positionedNodes.forEach((node) => { | ||||||
|  |     nodeInfo.set(node.id, node); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   return edges.map((edge) => { | ||||||
|  |     const sourceNode = nodeInfo.get(edge.start ?? ''); | ||||||
|  |     const targetNode = nodeInfo.get(edge.end ?? ''); | ||||||
|  |  | ||||||
|  |     if (!sourceNode || !targetNode) { | ||||||
|  |       return { | ||||||
|  |         id: edge.id, | ||||||
|  |         source: edge.start ?? '', | ||||||
|  |         target: edge.end ?? '', | ||||||
|  |         startX: 0, | ||||||
|  |         startY: 0, | ||||||
|  |         midX: 0, | ||||||
|  |         midY: 0, | ||||||
|  |         endX: 0, | ||||||
|  |         endY: 0, | ||||||
|  |         points: [{ x: 0, y: 0 }], | ||||||
|  |         sourceSection: undefined, | ||||||
|  |         targetSection: undefined, | ||||||
|  |         sourceWidth: undefined, | ||||||
|  |         sourceHeight: undefined, | ||||||
|  |         targetWidth: undefined, | ||||||
|  |         targetHeight: undefined, | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const sourceCenter = { x: sourceNode.x, y: sourceNode.y }; | ||||||
|  |     const targetCenter = { x: targetNode.x, y: targetNode.y }; | ||||||
|  |  | ||||||
|  |     const isSourceRound = ['circle', 'cloud', 'bang'].includes( | ||||||
|  |       sourceNode.originalNode?.shape ?? '' | ||||||
|  |     ); | ||||||
|  |     const isTargetRound = ['circle', 'cloud', 'bang'].includes( | ||||||
|  |       targetNode.originalNode?.shape ?? '' | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     let startPos = isSourceRound | ||||||
|  |       ? computeCircleEdgeIntersection( | ||||||
|  |           { | ||||||
|  |             x: sourceNode.x, | ||||||
|  |             y: sourceNode.y, | ||||||
|  |             width: sourceNode.width ?? 100, | ||||||
|  |             height: sourceNode.height ?? 100, | ||||||
|  |           }, | ||||||
|  |           targetCenter, | ||||||
|  |           sourceCenter | ||||||
|  |         ) | ||||||
|  |       : intersection(sourceNode, sourceCenter, targetCenter); | ||||||
|  |  | ||||||
|  |     let endPos = isTargetRound | ||||||
|  |       ? computeCircleEdgeIntersection( | ||||||
|  |           { | ||||||
|  |             x: targetNode.x, | ||||||
|  |             y: targetNode.y, | ||||||
|  |             width: targetNode.width ?? 100, | ||||||
|  |             height: targetNode.height ?? 100, | ||||||
|  |           }, | ||||||
|  |           sourceCenter, | ||||||
|  |           targetCenter | ||||||
|  |         ) | ||||||
|  |       : intersection(targetNode, targetCenter, sourceCenter); | ||||||
|  |  | ||||||
|  |     const midX = (startPos.x + endPos.x) / 2; | ||||||
|  |     const midY = (startPos.y + endPos.y) / 2; | ||||||
|  |  | ||||||
|  |     const points = [startPos]; | ||||||
|  |     if (sourceNode.section === 'left') { | ||||||
|  |       points.push({ | ||||||
|  |         x: sourceNode.x - (sourceNode.width ?? 0) / 2 - intersectionShift, | ||||||
|  |         y: sourceNode.y, | ||||||
|  |       }); | ||||||
|  |     } else if (sourceNode.section === 'right') { | ||||||
|  |       points.push({ | ||||||
|  |         x: sourceNode.x + (sourceNode.width ?? 0) / 2 + intersectionShift, | ||||||
|  |         y: sourceNode.y, | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     if (targetNode.section === 'left') { | ||||||
|  |       points.push({ | ||||||
|  |         x: targetNode.x + (targetNode.width ?? 0) / 2 + intersectionShift, | ||||||
|  |         y: targetNode.y, | ||||||
|  |       }); | ||||||
|  |     } else if (targetNode.section === 'right') { | ||||||
|  |       points.push({ | ||||||
|  |         x: targetNode.x - (targetNode.width ?? 0) / 2 - intersectionShift, | ||||||
|  |         y: targetNode.y, | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     points.push(endPos); | ||||||
|  |  | ||||||
|  |     const secondPoint = points.length > 1 ? points[1] : targetCenter; | ||||||
|  |     startPos = isSourceRound | ||||||
|  |       ? computeCircleEdgeIntersection( | ||||||
|  |           { | ||||||
|  |             x: sourceNode.x, | ||||||
|  |             y: sourceNode.y, | ||||||
|  |             width: sourceNode.width ?? 100, | ||||||
|  |             height: sourceNode.height ?? 100, | ||||||
|  |           }, | ||||||
|  |           secondPoint, | ||||||
|  |           sourceCenter | ||||||
|  |         ) | ||||||
|  |       : intersection(sourceNode, secondPoint, sourceCenter); | ||||||
|  |     points[0] = startPos; | ||||||
|  |  | ||||||
|  |     const secondLastPoint = points.length > 1 ? points[points.length - 2] : sourceCenter; | ||||||
|  |     endPos = isTargetRound | ||||||
|  |       ? computeCircleEdgeIntersection( | ||||||
|  |           { | ||||||
|  |             x: targetNode.x, | ||||||
|  |             y: targetNode.y, | ||||||
|  |             width: targetNode.width ?? 100, | ||||||
|  |             height: targetNode.height ?? 100, | ||||||
|  |           }, | ||||||
|  |           secondLastPoint, | ||||||
|  |           targetCenter | ||||||
|  |         ) | ||||||
|  |       : intersection(targetNode, secondLastPoint, targetCenter); | ||||||
|  |     points[points.length - 1] = endPos; | ||||||
|  |  | ||||||
|  |     return { | ||||||
|  |       id: edge.id, | ||||||
|  |       source: edge.start ?? '', | ||||||
|  |       target: edge.end ?? '', | ||||||
|  |       startX: startPos.x, | ||||||
|  |       startY: startPos.y, | ||||||
|  |       midX, | ||||||
|  |       midY, | ||||||
|  |       endX: endPos.x, | ||||||
|  |       endY: endPos.y, | ||||||
|  |       points, | ||||||
|  |       sourceSection: sourceNode?.section, | ||||||
|  |       targetSection: targetNode?.section, | ||||||
|  |       sourceWidth: sourceNode?.width, | ||||||
|  |       sourceHeight: sourceNode?.height, | ||||||
|  |       targetWidth: targetNode?.width, | ||||||
|  |       targetHeight: targetNode?.height, | ||||||
|  |     }; | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Validate layout data structure | ||||||
|  |  * @param data - The data to validate | ||||||
|  |  * @returns True if data is valid, throws error otherwise | ||||||
|  |  */ | ||||||
|  | export function validateLayoutData(data: LayoutData): boolean { | ||||||
|  |   if (!data) { | ||||||
|  |     throw new Error('Layout data is required'); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (!data.config) { | ||||||
|  |     throw new Error('Configuration is required in layout data'); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (!Array.isArray(data.nodes)) { | ||||||
|  |     throw new Error('Nodes array is required in layout data'); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (!Array.isArray(data.edges)) { | ||||||
|  |     throw new Error('Edges array is required in layout data'); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return true; | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								packages/mermaid-layout-tidy-tree/src/layouts.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								packages/mermaid-layout-tidy-tree/src/layouts.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | import type { LayoutLoaderDefinition } from 'mermaid'; | ||||||
|  |  | ||||||
|  | const loader = async () => await import(`./render.js`); | ||||||
|  |  | ||||||
|  | const tidyTreeLayout: LayoutLoaderDefinition[] = [ | ||||||
|  |   { | ||||||
|  |     name: 'tidy-tree', | ||||||
|  |     loader, | ||||||
|  |     algorithm: 'tidy-tree', | ||||||
|  |   }, | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | export default tidyTreeLayout; | ||||||
							
								
								
									
										18
									
								
								packages/mermaid-layout-tidy-tree/src/non-layered-tidy-tree-layout.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								packages/mermaid-layout-tidy-tree/src/non-layered-tidy-tree-layout.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | declare module 'non-layered-tidy-tree-layout' { | ||||||
|  |   export class BoundingBox { | ||||||
|  |     constructor(gap: number, bottomPadding: number); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   export class Layout { | ||||||
|  |     constructor(boundingBox: BoundingBox); | ||||||
|  |     layout(data: any): { | ||||||
|  |       result: any; | ||||||
|  |       boundingBox: { | ||||||
|  |         left: number; | ||||||
|  |         right: number; | ||||||
|  |         top: number; | ||||||
|  |         bottom: number; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										180
									
								
								packages/mermaid-layout-tidy-tree/src/render.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								packages/mermaid-layout-tidy-tree/src/render.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,180 @@ | |||||||
|  | import type { InternalHelpers, LayoutData, RenderOptions, SVG } from 'mermaid'; | ||||||
|  | import { executeTidyTreeLayout } from './layout.js'; | ||||||
|  |  | ||||||
|  | interface NodeWithPosition { | ||||||
|  |   id: string; | ||||||
|  |   x?: number; | ||||||
|  |   y?: number; | ||||||
|  |   width?: number; | ||||||
|  |   height?: number; | ||||||
|  |   domId?: any; | ||||||
|  |   [key: string]: any; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Render function for bidirectional tidy-tree layout algorithm | ||||||
|  |  * | ||||||
|  |  * This follows the same pattern as ELK and dagre renderers: | ||||||
|  |  * 1. Insert nodes into DOM to get their actual dimensions | ||||||
|  |  * 2. Run the bidirectional tidy-tree layout algorithm to calculate positions | ||||||
|  |  * 3. Position the nodes and edges based on layout results | ||||||
|  |  * | ||||||
|  |  * The bidirectional layout creates two trees that grow horizontally in opposite | ||||||
|  |  * directions from a central root node: | ||||||
|  |  * - Left tree: grows horizontally to the left (children: 1st, 3rd, 5th...) | ||||||
|  |  * - Right tree: grows horizontally to the right (children: 2nd, 4th, 6th...) | ||||||
|  |  */ | ||||||
|  | export const render = async ( | ||||||
|  |   data4Layout: LayoutData, | ||||||
|  |   svg: SVG, | ||||||
|  |   { | ||||||
|  |     insertCluster, | ||||||
|  |     insertEdge, | ||||||
|  |     insertEdgeLabel, | ||||||
|  |     insertMarkers, | ||||||
|  |     insertNode, | ||||||
|  |     log, | ||||||
|  |     positionEdgeLabel, | ||||||
|  |   }: InternalHelpers, | ||||||
|  |   { algorithm: _algorithm }: RenderOptions | ||||||
|  | ) => { | ||||||
|  |   const nodeDb: Record<string, NodeWithPosition> = {}; | ||||||
|  |   const clusterDb: Record<string, any> = {}; | ||||||
|  |  | ||||||
|  |   const element = svg.select('g'); | ||||||
|  |   insertMarkers(element, data4Layout.markers, data4Layout.type, data4Layout.diagramId); | ||||||
|  |  | ||||||
|  |   const subGraphsEl = element.insert('g').attr('class', 'subgraphs'); | ||||||
|  |   const edgePaths = element.insert('g').attr('class', 'edgePaths'); | ||||||
|  |   const edgeLabels = element.insert('g').attr('class', 'edgeLabels'); | ||||||
|  |   const nodes = element.insert('g').attr('class', 'nodes'); | ||||||
|  |   // Step 1: Insert nodes into DOM to get their actual dimensions | ||||||
|  |   log.debug('Inserting nodes into DOM for dimension calculation'); | ||||||
|  |  | ||||||
|  |   await Promise.all( | ||||||
|  |     data4Layout.nodes.map(async (node) => { | ||||||
|  |       if (node.isGroup) { | ||||||
|  |         const clusterNode: NodeWithPosition = { | ||||||
|  |           ...node, | ||||||
|  |           id: node.id, | ||||||
|  |           width: node.width, | ||||||
|  |           height: node.height, | ||||||
|  |         }; | ||||||
|  |         clusterDb[node.id] = clusterNode; | ||||||
|  |         nodeDb[node.id] = clusterNode; | ||||||
|  |  | ||||||
|  |         await insertCluster(subGraphsEl, node); | ||||||
|  |       } else { | ||||||
|  |         const nodeWithPosition: NodeWithPosition = { | ||||||
|  |           ...node, | ||||||
|  |           id: node.id, | ||||||
|  |           width: node.width, | ||||||
|  |           height: node.height, | ||||||
|  |         }; | ||||||
|  |         nodeDb[node.id] = nodeWithPosition; | ||||||
|  |  | ||||||
|  |         const nodeEl = await insertNode(nodes, node, { | ||||||
|  |           config: data4Layout.config, | ||||||
|  |           dir: data4Layout.direction || 'TB', | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         const boundingBox = nodeEl.node()!.getBBox(); | ||||||
|  |         nodeWithPosition.width = boundingBox.width; | ||||||
|  |         nodeWithPosition.height = boundingBox.height; | ||||||
|  |         nodeWithPosition.domId = nodeEl; | ||||||
|  |  | ||||||
|  |         log.debug(`Node ${node.id} dimensions: ${boundingBox.width}x${boundingBox.height}`); | ||||||
|  |       } | ||||||
|  |     }) | ||||||
|  |   ); | ||||||
|  |   // Step 2: Run the bidirectional tidy-tree layout algorithm | ||||||
|  |   log.debug('Running bidirectional tidy-tree layout algorithm'); | ||||||
|  |  | ||||||
|  |   const updatedLayoutData = { | ||||||
|  |     ...data4Layout, | ||||||
|  |     nodes: data4Layout.nodes.map((node) => { | ||||||
|  |       const nodeWithDimensions = nodeDb[node.id]; | ||||||
|  |       return { | ||||||
|  |         ...node, | ||||||
|  |         width: nodeWithDimensions.width ?? node.width ?? 100, | ||||||
|  |         height: nodeWithDimensions.height ?? node.height ?? 50, | ||||||
|  |       }; | ||||||
|  |     }), | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   const layoutResult = await executeTidyTreeLayout(updatedLayoutData); | ||||||
|  |   // Step 3: Position the nodes based on bidirectional layout results | ||||||
|  |   log.debug('Positioning nodes based on bidirectional layout results'); | ||||||
|  |  | ||||||
|  |   layoutResult.nodes.forEach((positionedNode) => { | ||||||
|  |     const node = nodeDb[positionedNode.id]; | ||||||
|  |     if (node?.domId) { | ||||||
|  |       // Position the node at the calculated coordinates from bidirectional layout | ||||||
|  |       // The layout algorithm has already calculated positions for: | ||||||
|  |       // - Root node at center (0, 0) | ||||||
|  |       // - Left tree nodes with negative x coordinates (growing left) | ||||||
|  |       // - Right tree nodes with positive x coordinates (growing right) | ||||||
|  |       node.domId.attr('transform', `translate(${positionedNode.x}, ${positionedNode.y})`); | ||||||
|  |       // Store the final position | ||||||
|  |       node.x = positionedNode.x; | ||||||
|  |       node.y = positionedNode.y; | ||||||
|  |       // Step 3: Position the nodes based on bidirectional layout results | ||||||
|  |       log.debug(`Positioned node ${node.id} at (${positionedNode.x}, ${positionedNode.y})`); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   log.debug('Inserting and positioning edges'); | ||||||
|  |  | ||||||
|  |   await Promise.all( | ||||||
|  |     data4Layout.edges.map(async (edge) => { | ||||||
|  |       await insertEdgeLabel(edgeLabels, edge); | ||||||
|  |  | ||||||
|  |       const startNode = nodeDb[edge.start ?? '']; | ||||||
|  |       const endNode = nodeDb[edge.end ?? '']; | ||||||
|  |  | ||||||
|  |       if (startNode && endNode) { | ||||||
|  |         const positionedEdge = layoutResult.edges.find((e) => e.id === edge.id); | ||||||
|  |  | ||||||
|  |         if (positionedEdge) { | ||||||
|  |           log.debug('APA01 positionedEdge', positionedEdge); | ||||||
|  |           const edgeWithPath = { | ||||||
|  |             ...edge, | ||||||
|  |             points: positionedEdge.points, | ||||||
|  |           }; | ||||||
|  |           const paths = insertEdge( | ||||||
|  |             edgePaths, | ||||||
|  |             edgeWithPath, | ||||||
|  |             clusterDb, | ||||||
|  |             data4Layout.type, | ||||||
|  |             startNode, | ||||||
|  |             endNode, | ||||||
|  |             data4Layout.diagramId | ||||||
|  |           ); | ||||||
|  |  | ||||||
|  |           positionEdgeLabel(edgeWithPath, paths); | ||||||
|  |         } else { | ||||||
|  |           const edgeWithPath = { | ||||||
|  |             ...edge, | ||||||
|  |             points: [ | ||||||
|  |               { x: startNode.x ?? 0, y: startNode.y ?? 0 }, | ||||||
|  |               { x: endNode.x ?? 0, y: endNode.y ?? 0 }, | ||||||
|  |             ], | ||||||
|  |           }; | ||||||
|  |  | ||||||
|  |           const paths = insertEdge( | ||||||
|  |             edgePaths, | ||||||
|  |             edgeWithPath, | ||||||
|  |             clusterDb, | ||||||
|  |             data4Layout.type, | ||||||
|  |             startNode, | ||||||
|  |             endNode, | ||||||
|  |             data4Layout.diagramId | ||||||
|  |           ); | ||||||
|  |           positionEdgeLabel(edgeWithPath, paths); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }) | ||||||
|  |   ); | ||||||
|  |  | ||||||
|  |   log.debug('Bidirectional tidy-tree rendering completed'); | ||||||
|  | }; | ||||||
							
								
								
									
										69
									
								
								packages/mermaid-layout-tidy-tree/src/types.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								packages/mermaid-layout-tidy-tree/src/types.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | |||||||
|  | import type { LayoutData } from 'mermaid'; | ||||||
|  |  | ||||||
|  | export type Node = LayoutData['nodes'][number]; | ||||||
|  | export type Edge = LayoutData['edges'][number]; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Positioned node after layout calculation | ||||||
|  |  */ | ||||||
|  | export interface PositionedNode { | ||||||
|  |   id: string; | ||||||
|  |   x: number; | ||||||
|  |   y: number; | ||||||
|  |   section?: 'root' | 'left' | 'right'; | ||||||
|  |   width?: number; | ||||||
|  |   height?: number; | ||||||
|  |   originalNode?: Node; | ||||||
|  |   [key: string]: unknown; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Positioned edge after layout calculation | ||||||
|  |  */ | ||||||
|  | export interface PositionedEdge { | ||||||
|  |   id: string; | ||||||
|  |   source: string; | ||||||
|  |   target: string; | ||||||
|  |   startX: number; | ||||||
|  |   startY: number; | ||||||
|  |   midX: number; | ||||||
|  |   midY: number; | ||||||
|  |   endX: number; | ||||||
|  |   endY: number; | ||||||
|  |   sourceSection?: 'root' | 'left' | 'right'; | ||||||
|  |   targetSection?: 'root' | 'left' | 'right'; | ||||||
|  |   sourceWidth?: number; | ||||||
|  |   sourceHeight?: number; | ||||||
|  |   targetWidth?: number; | ||||||
|  |   targetHeight?: number; | ||||||
|  |   [key: string]: unknown; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Result of layout algorithm execution | ||||||
|  |  */ | ||||||
|  | export interface LayoutResult { | ||||||
|  |   nodes: PositionedNode[]; | ||||||
|  |   edges: PositionedEdge[]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Tidy-tree node structure compatible with non-layered-tidy-tree-layout | ||||||
|  |  */ | ||||||
|  | export interface TidyTreeNode { | ||||||
|  |   id: string | number; | ||||||
|  |   width: number; | ||||||
|  |   height: number; | ||||||
|  |   x?: number; | ||||||
|  |   y?: number; | ||||||
|  |   children?: TidyTreeNode[]; | ||||||
|  |   _originalNode?: Node; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Tidy-tree layout configuration | ||||||
|  |  */ | ||||||
|  | export interface TidyTreeLayoutConfig { | ||||||
|  |   gap: number; | ||||||
|  |   bottomPadding: number; | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								packages/mermaid-layout-tidy-tree/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								packages/mermaid-layout-tidy-tree/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | { | ||||||
|  |   "extends": "../../tsconfig.json", | ||||||
|  |   "compilerOptions": { | ||||||
|  |     "rootDir": "./src", | ||||||
|  |     "outDir": "./dist", | ||||||
|  |     "types": ["vitest/importMeta", "vitest/globals"] | ||||||
|  |   }, | ||||||
|  |   "include": ["./src/**/*.ts", "./src/**/*.d.ts"], | ||||||
|  |   "typeRoots": ["./src/types"] | ||||||
|  | } | ||||||
| @@ -33,7 +33,7 @@ | |||||||
|   ], |   ], | ||||||
|   "license": "MIT", |   "license": "MIT", | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@zenuml/core": "^3.35.2" |     "@zenuml/core": "^3.41.4" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "mermaid": "workspace:^" |     "mermaid": "workspace:^" | ||||||
|   | |||||||
| @@ -1,5 +1,19 @@ | |||||||
| # mermaid | # mermaid | ||||||
|  |  | ||||||
|  | ## 11.11.0 | ||||||
|  |  | ||||||
|  | ### Minor Changes | ||||||
|  |  | ||||||
|  | - [#6704](https://github.com/mermaid-js/mermaid/pull/6704) [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05) Thanks [@omkarht](https://github.com/omkarht)! - feat: Added support for new participant types (`actor`, `boundary`, `control`, `entity`, `database`, `collections`, `queue`) in `sequenceDiagram`. | ||||||
|  |  | ||||||
|  | - [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes | ||||||
|  |  | ||||||
|  | ### Patch Changes | ||||||
|  |  | ||||||
|  | - [#6905](https://github.com/mermaid-js/mermaid/pull/6905) [`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Render newlines as spaces in class diagrams | ||||||
|  |  | ||||||
|  | - [#6886](https://github.com/mermaid-js/mermaid/pull/6886) [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Handle arrows correctly when auto number is enabled | ||||||
|  |  | ||||||
| ## 11.10.0 | ## 11.10.0 | ||||||
|  |  | ||||||
| ### Minor Changes | ### Minor Changes | ||||||
| @@ -154,7 +168,6 @@ | |||||||
| ### Minor Changes | ### Minor Changes | ||||||
|  |  | ||||||
| - [#6408](https://github.com/mermaid-js/mermaid/pull/6408) [`ad65313`](https://github.com/mermaid-js/mermaid/commit/ad653138e16765d095613a6e5de86dc5e52ac8f0) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - fix: restore curve type configuration functionality for flowcharts. This fixes the issue where curve type settings were not being applied when configured through any of the following methods: | - [#6408](https://github.com/mermaid-js/mermaid/pull/6408) [`ad65313`](https://github.com/mermaid-js/mermaid/commit/ad653138e16765d095613a6e5de86dc5e52ac8f0) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - fix: restore curve type configuration functionality for flowcharts. This fixes the issue where curve type settings were not being applied when configured through any of the following methods: | ||||||
|  |  | ||||||
|   - Config |   - Config | ||||||
|   - Init directive (%%{ init: { 'flowchart': { 'curve': '...' } } }%%) |   - Init directive (%%{ init: { 'flowchart': { 'curve': '...' } } }%%) | ||||||
|   - LinkStyle command (linkStyle default interpolate ...) |   - LinkStyle command (linkStyle default interpolate ...) | ||||||
| @@ -173,14 +186,12 @@ | |||||||
| ### Minor Changes | ### Minor Changes | ||||||
|  |  | ||||||
| - [#6187](https://github.com/mermaid-js/mermaid/pull/6187) [`7809b5a`](https://github.com/mermaid-js/mermaid/commit/7809b5a93fae127f45727071f5ff14325222c518) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Flowchart new syntax for node metadata bugs | - [#6187](https://github.com/mermaid-js/mermaid/pull/6187) [`7809b5a`](https://github.com/mermaid-js/mermaid/commit/7809b5a93fae127f45727071f5ff14325222c518) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Flowchart new syntax for node metadata bugs | ||||||
|  |  | ||||||
|   - Incorrect label mapping for nodes when using `&` |   - Incorrect label mapping for nodes when using `&` | ||||||
|   - Syntax error when `}` with trailing spaces before new line |   - Syntax error when `}` with trailing spaces before new line | ||||||
|  |  | ||||||
| - [#6136](https://github.com/mermaid-js/mermaid/pull/6136) [`ec0d9c3`](https://github.com/mermaid-js/mermaid/commit/ec0d9c389aa6018043187654044c1e0b5aa4f600) Thanks [@knsv](https://github.com/knsv)! - Adding support for animation of flowchart edges | - [#6136](https://github.com/mermaid-js/mermaid/pull/6136) [`ec0d9c3`](https://github.com/mermaid-js/mermaid/commit/ec0d9c389aa6018043187654044c1e0b5aa4f600) Thanks [@knsv](https://github.com/knsv)! - Adding support for animation of flowchart edges | ||||||
|  |  | ||||||
| - [#6373](https://github.com/mermaid-js/mermaid/pull/6373) [`05bdf0e`](https://github.com/mermaid-js/mermaid/commit/05bdf0e20e2629fe77513218fbd4e28e65f75882) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Upgrade Requirement and ER diagram to use the common renderer flow | - [#6373](https://github.com/mermaid-js/mermaid/pull/6373) [`05bdf0e`](https://github.com/mermaid-js/mermaid/commit/05bdf0e20e2629fe77513218fbd4e28e65f75882) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Upgrade Requirement and ER diagram to use the common renderer flow | ||||||
|  |  | ||||||
|   - Added support for directions |   - Added support for directions | ||||||
|   - Added support for hand drawn look |   - Added support for hand drawn look | ||||||
|  |  | ||||||
| @@ -229,7 +240,6 @@ | |||||||
| - [#5999](https://github.com/mermaid-js/mermaid/pull/5999) [`742ad7c`](https://github.com/mermaid-js/mermaid/commit/742ad7c130964df1fb5544e909d9556081285f68) Thanks [@knsv](https://github.com/knsv)! - Adding Kanban board, a new diagram type | - [#5999](https://github.com/mermaid-js/mermaid/pull/5999) [`742ad7c`](https://github.com/mermaid-js/mermaid/commit/742ad7c130964df1fb5544e909d9556081285f68) Thanks [@knsv](https://github.com/knsv)! - Adding Kanban board, a new diagram type | ||||||
|  |  | ||||||
| - [#5880](https://github.com/mermaid-js/mermaid/pull/5880) [`bdf145f`](https://github.com/mermaid-js/mermaid/commit/bdf145ffe362462176d9c1e68d5f3ff5c9d962b0) Thanks [@yari-dewalt](https://github.com/yari-dewalt)! - Class diagram changes: | - [#5880](https://github.com/mermaid-js/mermaid/pull/5880) [`bdf145f`](https://github.com/mermaid-js/mermaid/commit/bdf145ffe362462176d9c1e68d5f3ff5c9d962b0) Thanks [@yari-dewalt](https://github.com/yari-dewalt)! - Class diagram changes: | ||||||
|  |  | ||||||
|   - Updates the class diagram to the new unified way of rendering. |   - Updates the class diagram to the new unified way of rendering. | ||||||
|   - Includes a new "classBox" shape to be used in diagrams |   - Includes a new "classBox" shape to be used in diagrams | ||||||
|   - Other updates such as: |   - Other updates such as: | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "mermaid", |   "name": "mermaid", | ||||||
|   "version": "11.10.0", |   "version": "11.11.0", | ||||||
|   "description": "Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.", |   "description": "Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.", | ||||||
|   "type": "module", |   "type": "module", | ||||||
|   "module": "./dist/mermaid.core.mjs", |   "module": "./dist/mermaid.core.mjs", | ||||||
| @@ -67,29 +67,29 @@ | |||||||
|     ] |     ] | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@braintree/sanitize-url": "^7.0.4", |     "@braintree/sanitize-url": "^7.1.1", | ||||||
|     "@iconify/utils": "^2.1.33", |     "@iconify/utils": "^3.0.2", | ||||||
|     "@mermaid-js/parser": "workspace:^", |     "@mermaid-js/parser": "workspace:^", | ||||||
|     "@types/d3": "^7.4.3", |     "@types/d3": "^7.4.3", | ||||||
|     "cytoscape": "^3.29.3", |     "cytoscape": "^3.33.1", | ||||||
|     "cytoscape-cose-bilkent": "^4.1.0", |     "cytoscape-cose-bilkent": "^4.1.0", | ||||||
|     "cytoscape-fcose": "^2.2.0", |     "cytoscape-fcose": "^2.2.0", | ||||||
|     "d3": "^7.9.0", |     "d3": "^7.9.0", | ||||||
|     "d3-sankey": "^0.12.3", |     "d3-sankey": "^0.12.3", | ||||||
|     "dagre-d3-es": "7.0.11", |     "dagre-d3-es": "7.0.11", | ||||||
|     "dayjs": "^1.11.13", |     "dayjs": "^1.11.18", | ||||||
|     "dompurify": "^3.2.5", |     "dompurify": "^3.2.5", | ||||||
|     "katex": "^0.16.22", |     "katex": "^0.16.22", | ||||||
|     "khroma": "^2.1.0", |     "khroma": "^2.1.0", | ||||||
|     "lodash-es": "^4.17.21", |     "lodash-es": "^4.17.21", | ||||||
|     "marked": "^16.0.0", |     "marked": "^16.3.0", | ||||||
|     "roughjs": "^4.6.6", |     "roughjs": "^4.6.6", | ||||||
|     "stylis": "^4.3.6", |     "stylis": "^4.3.6", | ||||||
|     "ts-dedent": "^2.2.0", |     "ts-dedent": "^2.2.0", | ||||||
|     "uuid": "^11.1.0" |     "uuid": "^11.1.0" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@adobe/jsonschema2md": "^8.0.2", |     "@adobe/jsonschema2md": "^8.0.5", | ||||||
|     "@iconify/types": "^2.0.0", |     "@iconify/types": "^2.0.0", | ||||||
|     "@types/cytoscape": "^3.21.9", |     "@types/cytoscape": "^3.21.9", | ||||||
|     "@types/cytoscape-fcose": "^2.2.4", |     "@types/cytoscape-fcose": "^2.2.4", | ||||||
| @@ -105,30 +105,30 @@ | |||||||
|     "@types/stylis": "^4.2.7", |     "@types/stylis": "^4.2.7", | ||||||
|     "@types/uuid": "^10.0.0", |     "@types/uuid": "^10.0.0", | ||||||
|     "ajv": "^8.17.1", |     "ajv": "^8.17.1", | ||||||
|     "canvas": "^3.1.0", |     "canvas": "^3.2.0", | ||||||
|     "chokidar": "3.6.0", |     "chokidar": "3.6.0", | ||||||
|     "concurrently": "^9.1.2", |     "concurrently": "^9.2.1", | ||||||
|     "csstree-validator": "^4.0.1", |     "csstree-validator": "^4.0.1", | ||||||
|     "globby": "^14.0.2", |     "globby": "^14.1.0", | ||||||
|     "jison": "^0.4.18", |     "jison": "^0.4.18", | ||||||
|     "js-base64": "^3.7.7", |     "js-base64": "^3.7.8", | ||||||
|     "jsdom": "^26.1.0", |     "jsdom": "^26.1.0", | ||||||
|     "json-schema-to-typescript": "^15.0.4", |     "json-schema-to-typescript": "^15.0.4", | ||||||
|     "micromatch": "^4.0.8", |     "micromatch": "^4.0.8", | ||||||
|     "path-browserify": "^1.0.1", |     "path-browserify": "^1.0.1", | ||||||
|     "prettier": "^3.5.2", |     "prettier": "^3.6.2", | ||||||
|     "remark": "^15.0.1", |     "remark": "^15.0.1", | ||||||
|     "remark-frontmatter": "^5.0.0", |     "remark-frontmatter": "^5.0.0", | ||||||
|     "remark-gfm": "^4.0.1", |     "remark-gfm": "^4.0.1", | ||||||
|     "rimraf": "^6.0.1", |     "rimraf": "^6.0.1", | ||||||
|     "start-server-and-test": "^2.0.10", |     "start-server-and-test": "^2.1.2", | ||||||
|     "type-fest": "^4.35.0", |     "type-fest": "^4.41.0", | ||||||
|     "typedoc": "^0.27.8", |     "typedoc": "^0.28.13", | ||||||
|     "typedoc-plugin-markdown": "^4.4.2", |     "typedoc-plugin-markdown": "^4.8.1", | ||||||
|     "typescript": "~5.7.3", |     "typescript": "~5.7.3", | ||||||
|     "unist-util-flatmap": "^1.0.0", |     "unist-util-flatmap": "^1.0.0", | ||||||
|     "unist-util-visit": "^5.0.0", |     "unist-util-visit": "^5.0.0", | ||||||
|     "vitepress": "^1.0.2", |     "vitepress": "^1.6.4", | ||||||
|     "vitepress-plugin-search": "1.0.4-alpha.22" |     "vitepress-plugin-search": "1.0.4-alpha.22" | ||||||
|   }, |   }, | ||||||
|   "files": [ |   "files": [ | ||||||
|   | |||||||
| @@ -171,7 +171,9 @@ This Markdown should be kept. | |||||||
|       expect(buildShapeDoc()).toMatchInlineSnapshot(` |       expect(buildShapeDoc()).toMatchInlineSnapshot(` | ||||||
|         "| **Semantic Name**                 | **Shape Name**         | **Short Name** | **Description**                | **Alias Supported**                                              | |         "| **Semantic Name**                 | **Shape Name**         | **Short Name** | **Description**                | **Alias Supported**                                              | | ||||||
|         | --------------------------------- | ---------------------- | -------------- | ------------------------------ | ---------------------------------------------------------------- | |         | --------------------------------- | ---------------------- | -------------- | ------------------------------ | ---------------------------------------------------------------- | | ||||||
|  |         | Bang                              | Bang                   | \`bang\`         | Bang                           | \`bang\`                                                           | | ||||||
|         | Card                              | Notched Rectangle      | \`notch-rect\`   | Represents a card              | \`card\`, \`notched-rectangle\`                                      | |         | Card                              | Notched Rectangle      | \`notch-rect\`   | Represents a card              | \`card\`, \`notched-rectangle\`                                      | | ||||||
|  |         | Cloud                             | Cloud                  | \`cloud\`        | cloud                          | \`cloud\`                                                          | | ||||||
|         | Collate                           | Hourglass              | \`hourglass\`    | Represents a collate operation | \`collate\`, \`hourglass\`                                           | |         | Collate                           | Hourglass              | \`hourglass\`    | Represents a collate operation | \`collate\`, \`hourglass\`                                           | | ||||||
|         | Com Link                          | Lightning Bolt         | \`bolt\`         | Communication link             | \`com-link\`, \`lightning-bolt\`                                     | |         | Com Link                          | Lightning Bolt         | \`bolt\`         | Communication link             | \`com-link\`, \`lightning-bolt\`                                     | | ||||||
|         | Comment                           | Curly Brace            | \`brace\`        | Adds a comment                 | \`brace-l\`, \`comment\`                                             | |         | Comment                           | Curly Brace            | \`brace\`        | Adds a comment                 | \`brace-l\`, \`comment\`                                             | | ||||||
|   | |||||||
| @@ -78,3 +78,187 @@ describe('when working with site config', () => { | |||||||
|     expect(config_4.altFontFamily).toBeUndefined(); |     expect(config_4.altFontFamily).toBeUndefined(); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | describe('getUserDefinedConfig', () => { | ||||||
|  |   beforeEach(() => { | ||||||
|  |     configApi.reset(); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('should return empty object when no user config is defined', () => { | ||||||
|  |     const userConfig = configApi.getUserDefinedConfig(); | ||||||
|  |     expect(userConfig).toEqual({}); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('should return config from initialize only', () => { | ||||||
|  |     const initConfig: MermaidConfig = { theme: 'dark', fontFamily: 'Arial' }; | ||||||
|  |     configApi.saveConfigFromInitialize(initConfig); | ||||||
|  |  | ||||||
|  |     const userConfig = configApi.getUserDefinedConfig(); | ||||||
|  |     expect(userConfig).toEqual(initConfig); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('should return config from directives only', () => { | ||||||
|  |     const directive1: MermaidConfig = { layout: 'elk', fontSize: 14 }; | ||||||
|  |     const directive2: MermaidConfig = { theme: 'forest' }; | ||||||
|  |  | ||||||
|  |     configApi.addDirective(directive1); | ||||||
|  |     configApi.addDirective(directive2); | ||||||
|  |  | ||||||
|  |     expect(configApi.getUserDefinedConfig()).toMatchInlineSnapshot(` | ||||||
|  |       { | ||||||
|  |         "fontFamily": "Arial", | ||||||
|  |         "fontSize": 14, | ||||||
|  |         "layout": "elk", | ||||||
|  |         "theme": "forest", | ||||||
|  |       } | ||||||
|  |     `); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('should combine initialize config and directives', () => { | ||||||
|  |     const initConfig: MermaidConfig = { theme: 'dark', fontFamily: 'Arial', layout: 'dagre' }; | ||||||
|  |     const directive1: MermaidConfig = { layout: 'elk', fontSize: 14 }; | ||||||
|  |     const directive2: MermaidConfig = { theme: 'forest' }; | ||||||
|  |  | ||||||
|  |     configApi.saveConfigFromInitialize(initConfig); | ||||||
|  |     configApi.addDirective(directive1); | ||||||
|  |     configApi.addDirective(directive2); | ||||||
|  |  | ||||||
|  |     const userConfig = configApi.getUserDefinedConfig(); | ||||||
|  |     expect(userConfig).toMatchInlineSnapshot(` | ||||||
|  |       { | ||||||
|  |         "fontFamily": "Arial", | ||||||
|  |         "fontSize": 14, | ||||||
|  |         "layout": "elk", | ||||||
|  |         "theme": "forest", | ||||||
|  |       } | ||||||
|  |     `); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('should handle nested config objects properly', () => { | ||||||
|  |     const initConfig: MermaidConfig = { | ||||||
|  |       flowchart: { nodeSpacing: 50, rankSpacing: 100 }, | ||||||
|  |       theme: 'default', | ||||||
|  |     }; | ||||||
|  |     const directive: MermaidConfig = { | ||||||
|  |       flowchart: { nodeSpacing: 75, curve: 'basis' }, | ||||||
|  |       mindmap: { padding: 20 }, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     configApi.saveConfigFromInitialize(initConfig); | ||||||
|  |     configApi.addDirective(directive); | ||||||
|  |  | ||||||
|  |     const userConfig = configApi.getUserDefinedConfig(); | ||||||
|  |     expect(userConfig).toMatchInlineSnapshot(` | ||||||
|  |       { | ||||||
|  |         "flowchart": { | ||||||
|  |           "curve": "basis", | ||||||
|  |           "nodeSpacing": 75, | ||||||
|  |           "rankSpacing": 100, | ||||||
|  |         }, | ||||||
|  |         "mindmap": { | ||||||
|  |           "padding": 20, | ||||||
|  |         }, | ||||||
|  |         "theme": "default", | ||||||
|  |       } | ||||||
|  |     `); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('should handle complex nested overrides', () => { | ||||||
|  |     const initConfig: MermaidConfig = { | ||||||
|  |       flowchart: { | ||||||
|  |         nodeSpacing: 50, | ||||||
|  |         rankSpacing: 100, | ||||||
|  |         curve: 'linear', | ||||||
|  |       }, | ||||||
|  |       theme: 'default', | ||||||
|  |     }; | ||||||
|  |     const directive1: MermaidConfig = { | ||||||
|  |       flowchart: { | ||||||
|  |         nodeSpacing: 75, | ||||||
|  |       }, | ||||||
|  |       fontSize: 12, | ||||||
|  |     }; | ||||||
|  |     const directive2: MermaidConfig = { | ||||||
|  |       flowchart: { | ||||||
|  |         curve: 'basis', | ||||||
|  |         nodeSpacing: 100, | ||||||
|  |       }, | ||||||
|  |       mindmap: { | ||||||
|  |         padding: 15, | ||||||
|  |       }, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     configApi.saveConfigFromInitialize(initConfig); | ||||||
|  |     configApi.addDirective(directive1); | ||||||
|  |     configApi.addDirective(directive2); | ||||||
|  |  | ||||||
|  |     const userConfig = configApi.getUserDefinedConfig(); | ||||||
|  |     expect(userConfig).toMatchInlineSnapshot(` | ||||||
|  |       { | ||||||
|  |         "flowchart": { | ||||||
|  |           "curve": "basis", | ||||||
|  |           "nodeSpacing": 100, | ||||||
|  |           "rankSpacing": 100, | ||||||
|  |         }, | ||||||
|  |         "fontSize": 12, | ||||||
|  |         "mindmap": { | ||||||
|  |           "padding": 15, | ||||||
|  |         }, | ||||||
|  |         "theme": "default", | ||||||
|  |       } | ||||||
|  |     `); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('should return independent copies (not references)', () => { | ||||||
|  |     const initConfig: MermaidConfig = { theme: 'dark', flowchart: { nodeSpacing: 50 } }; | ||||||
|  |     configApi.saveConfigFromInitialize(initConfig); | ||||||
|  |  | ||||||
|  |     const userConfig1 = configApi.getUserDefinedConfig(); | ||||||
|  |     const userConfig2 = configApi.getUserDefinedConfig(); | ||||||
|  |  | ||||||
|  |     userConfig1.theme = 'neutral'; | ||||||
|  |     userConfig1.flowchart!.nodeSpacing = 999; | ||||||
|  |  | ||||||
|  |     expect(userConfig2).toMatchInlineSnapshot(` | ||||||
|  |       { | ||||||
|  |         "flowchart": { | ||||||
|  |           "nodeSpacing": 50, | ||||||
|  |         }, | ||||||
|  |         "theme": "dark", | ||||||
|  |       } | ||||||
|  |     `); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('should handle edge cases with undefined values', () => { | ||||||
|  |     const initConfig: MermaidConfig = { theme: 'dark', layout: undefined }; | ||||||
|  |     const directive: MermaidConfig = { fontSize: 14, fontFamily: undefined }; | ||||||
|  |  | ||||||
|  |     configApi.saveConfigFromInitialize(initConfig); | ||||||
|  |     configApi.addDirective(directive); | ||||||
|  |  | ||||||
|  |     expect(configApi.getUserDefinedConfig()).toMatchInlineSnapshot(` | ||||||
|  |       { | ||||||
|  |         "fontSize": 14, | ||||||
|  |         "layout": undefined, | ||||||
|  |         "theme": "dark", | ||||||
|  |       } | ||||||
|  |     `); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('should retain config from initialize after reset', () => { | ||||||
|  |     const initConfig: MermaidConfig = { theme: 'dark' }; | ||||||
|  |     const directive: MermaidConfig = { layout: 'elk' }; | ||||||
|  |  | ||||||
|  |     configApi.saveConfigFromInitialize(initConfig); | ||||||
|  |     configApi.addDirective(directive); | ||||||
|  |  | ||||||
|  |     expect(configApi.getUserDefinedConfig()).toMatchInlineSnapshot(` | ||||||
|  |       { | ||||||
|  |         "layout": "elk", | ||||||
|  |         "theme": "dark", | ||||||
|  |       } | ||||||
|  |     `); | ||||||
|  |  | ||||||
|  |     configApi.reset(); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|   | |||||||
| @@ -248,3 +248,17 @@ const checkConfig = (config: MermaidConfig) => { | |||||||
|     issueWarning('LAZY_LOAD_DEPRECATED'); |     issueWarning('LAZY_LOAD_DEPRECATED'); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | export const getUserDefinedConfig = (): MermaidConfig => { | ||||||
|  |   let userConfig: MermaidConfig = {}; | ||||||
|  |  | ||||||
|  |   if (configFromInitialize) { | ||||||
|  |     userConfig = assignWithDepth(userConfig, configFromInitialize); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   for (const d of directives) { | ||||||
|  |     userConfig = assignWithDepth(userConfig, d); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return userConfig; | ||||||
|  | }; | ||||||
|   | |||||||
| @@ -1075,6 +1075,10 @@ export interface ArchitectureDiagramConfig extends BaseDiagramConfig { | |||||||
| export interface MindmapDiagramConfig extends BaseDiagramConfig { | export interface MindmapDiagramConfig extends BaseDiagramConfig { | ||||||
|   padding?: number; |   padding?: number; | ||||||
|   maxNodeWidth?: number; |   maxNodeWidth?: number; | ||||||
|  |   /** | ||||||
|  |    * Layout algorithm to use for positioning mindmap nodes | ||||||
|  |    */ | ||||||
|  |   layoutAlgorithm?: string; | ||||||
| } | } | ||||||
| /** | /** | ||||||
|  * The object containing configurations specific for kanban diagrams |  * The object containing configurations specific for kanban diagrams | ||||||
|   | |||||||
| @@ -1,5 +1,3 @@ | |||||||
| // tests to check that comments are removed |  | ||||||
|  |  | ||||||
| import { cleanupComments } from './comments.js'; | import { cleanupComments } from './comments.js'; | ||||||
| import { describe, it, expect } from 'vitest'; | import { describe, it, expect } from 'vitest'; | ||||||
|  |  | ||||||
| @@ -10,12 +8,12 @@ describe('comments', () => { | |||||||
| %% This is a comment | %% This is a comment | ||||||
| %% This is another comment | %% This is another comment | ||||||
| graph TD | graph TD | ||||||
| 	A-->B |     A-->B | ||||||
| %% This is a comment | %% This is a comment | ||||||
| `; | `; | ||||||
|     expect(cleanupComments(text)).toMatchInlineSnapshot(` |     expect(cleanupComments(text)).toMatchInlineSnapshot(` | ||||||
|       "graph TD |       "graph TD | ||||||
|       	A-->B |           A-->B | ||||||
|       " |       " | ||||||
|     `); |     `); | ||||||
|   }); |   }); | ||||||
| @@ -29,9 +27,9 @@ graph TD | |||||||
| %%{ init: {'theme': 'space before init'}}%% | %%{ init: {'theme': 'space before init'}}%% | ||||||
| %%{init: {'theme': 'space after ending'}}%% | %%{init: {'theme': 'space after ending'}}%% | ||||||
| graph TD | graph TD | ||||||
| 	A-->B |     A-->B | ||||||
|  |  | ||||||
| 	B-->C |     B-->C | ||||||
| %% This is a comment | %% This is a comment | ||||||
| `; | `; | ||||||
|     expect(cleanupComments(text)).toMatchInlineSnapshot(` |     expect(cleanupComments(text)).toMatchInlineSnapshot(` | ||||||
| @@ -39,9 +37,9 @@ graph TD | |||||||
|       %%{ init: {'theme': 'space before init'}}%% |       %%{ init: {'theme': 'space before init'}}%% | ||||||
|       %%{init: {'theme': 'space after ending'}}%% |       %%{init: {'theme': 'space after ending'}}%% | ||||||
|       graph TD |       graph TD | ||||||
|       	A-->B |           A-->B | ||||||
|  |  | ||||||
|       	B-->C |           B-->C | ||||||
|       " |       " | ||||||
|     `); |     `); | ||||||
|   }); |   }); | ||||||
| @@ -50,14 +48,14 @@ graph TD | |||||||
|     const text = ` |     const text = ` | ||||||
| %% This is a comment | %% This is a comment | ||||||
| graph TD | graph TD | ||||||
| 	A-->B |     A-->B | ||||||
| 	%% This is a comment |     %% This is a comment | ||||||
| 	C-->D |     C-->D | ||||||
| `; | `; | ||||||
|     expect(cleanupComments(text)).toMatchInlineSnapshot(` |     expect(cleanupComments(text)).toMatchInlineSnapshot(` | ||||||
|       "graph TD |       "graph TD | ||||||
| 	A-->B |           A-->B | ||||||
| 	C-->D |           C-->D | ||||||
|       " |       " | ||||||
|     `); |     `); | ||||||
|   }); |   }); | ||||||
| @@ -70,11 +68,11 @@ graph TD | |||||||
|  |  | ||||||
| %% This is a comment | %% This is a comment | ||||||
| graph TD | graph TD | ||||||
| 	A-->B |     A-->B | ||||||
| `; | `; | ||||||
|     expect(cleanupComments(text)).toMatchInlineSnapshot(` |     expect(cleanupComments(text)).toMatchInlineSnapshot(` | ||||||
|       "graph TD |       "graph TD | ||||||
|       	A-->B |           A-->B | ||||||
|       " |       " | ||||||
|     `); |     `); | ||||||
|   }); |   }); | ||||||
| @@ -82,12 +80,12 @@ graph TD | |||||||
|   it('should remove comments at end of text with no newline', () => { |   it('should remove comments at end of text with no newline', () => { | ||||||
|     const text = ` |     const text = ` | ||||||
| graph TD | graph TD | ||||||
| 	A-->B |     A-->B | ||||||
| %% This is a comment`; | %% This is a comment`; | ||||||
|  |  | ||||||
|     expect(cleanupComments(text)).toMatchInlineSnapshot(` |     expect(cleanupComments(text)).toMatchInlineSnapshot(` | ||||||
|       "graph TD |       "graph TD | ||||||
| 	A-->B |           A-->B | ||||||
|       " |       " | ||||||
|     `); |     `); | ||||||
|   }); |   }); | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ import type * as d3 from 'd3'; | |||||||
| import type { SetOptional, SetRequired } from 'type-fest'; | import type { SetOptional, SetRequired } from 'type-fest'; | ||||||
| import type { Diagram } from '../Diagram.js'; | import type { Diagram } from '../Diagram.js'; | ||||||
| import type { BaseDiagramConfig, MermaidConfig } from '../config.type.js'; | import type { BaseDiagramConfig, MermaidConfig } from '../config.type.js'; | ||||||
|  | import type { DiagramOrientation } from '../diagrams/git/gitGraphTypes.js'; | ||||||
|  |  | ||||||
| export interface DiagramMetadata { | export interface DiagramMetadata { | ||||||
|   title?: string; |   title?: string; | ||||||
| @@ -35,7 +36,8 @@ export interface DiagramDB { | |||||||
|   getAccTitle?: () => string; |   getAccTitle?: () => string; | ||||||
|   setAccDescription?: (description: string) => void; |   setAccDescription?: (description: string) => void; | ||||||
|   getAccDescription?: () => string; |   getAccDescription?: () => string; | ||||||
|  |   getDirection?: () => string | undefined; | ||||||
|  |   setDirection?: (dir: DiagramOrientation) => void; | ||||||
|   setDisplayMode?: (title: string) => void; |   setDisplayMode?: (title: string) => void; | ||||||
|   bindFunctions?: (element: Element) => void; |   bindFunctions?: (element: Element) => void; | ||||||
| } | } | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user