mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-12-24 13:16:39 +01:00
Compare commits
209 Commits
release/9.
...
3056_Chrom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f107026a9 | ||
|
|
c846b48882 | ||
|
|
5b63260240 | ||
|
|
d7e0888801 | ||
|
|
49d1a8e248 | ||
|
|
0135ab2ab1 | ||
|
|
a5d4fdb142 | ||
|
|
d4a28cc0ec | ||
|
|
97c998c64b | ||
|
|
e7df5d52ba | ||
|
|
32b697f674 | ||
|
|
7e28fc087d | ||
|
|
17ccd1fd0b | ||
|
|
4e3d3a7288 | ||
|
|
018844e8ea | ||
|
|
850135a936 | ||
|
|
080bde0bc2 | ||
|
|
e6e7bdcb55 | ||
|
|
9e4ae66346 | ||
|
|
b7f9495a14 | ||
|
|
3b93c39249 | ||
|
|
2968b400c4 | ||
|
|
0779c39654 | ||
|
|
b2f5ba3ee8 | ||
|
|
86b3a4f09e | ||
|
|
cde3a7cf70 | ||
|
|
49eebc1c20 | ||
|
|
0583c4fa25 | ||
|
|
a3ace00ed4 | ||
|
|
fd70b862ed | ||
|
|
1c8035e029 | ||
|
|
11809e799b | ||
|
|
c50745323a | ||
|
|
2af91f5bbb | ||
|
|
08793e0b50 | ||
|
|
db961ecefe | ||
|
|
d3ae5e3e10 | ||
|
|
576445847c | ||
|
|
248a7aff7a | ||
|
|
9ef3164991 | ||
|
|
b0b54f48f9 | ||
|
|
35ba62bae2 | ||
|
|
ea0e9aa7f4 | ||
|
|
8c56f68a06 | ||
|
|
2cf9348f53 | ||
|
|
d97ce7eab8 | ||
|
|
0c8f7163db | ||
|
|
6e16369d85 | ||
|
|
8caeeccea3 | ||
|
|
102542b4e7 | ||
|
|
05d664d8d1 | ||
|
|
8fa57b0b14 | ||
|
|
858f2eadd4 | ||
|
|
bc2b4c57c9 | ||
|
|
280c7e8da1 | ||
|
|
19a9f90186 | ||
|
|
e19581b540 | ||
|
|
ecf62e3b7a | ||
|
|
ea3573c989 | ||
|
|
8d3617f0c7 | ||
|
|
34ea67c8c4 | ||
|
|
2e392232eb | ||
|
|
2f4af87bf7 | ||
|
|
33f06273a9 | ||
|
|
e1977dd889 | ||
|
|
6635d4bc97 | ||
|
|
a89b6fd054 | ||
|
|
02fc68a3f6 | ||
|
|
a9e798c399 | ||
|
|
b65c67ec2c | ||
|
|
1befbe08ff | ||
|
|
b21cb43639 | ||
|
|
db4ff451bf | ||
|
|
f30d19c539 | ||
|
|
52fcb92f51 | ||
|
|
18d44c643f | ||
|
|
d01929255c | ||
|
|
20e4e81765 | ||
|
|
2df0c52bc7 | ||
|
|
4acda0d98c | ||
|
|
efadeca7dd | ||
|
|
e5c2de1134 | ||
|
|
e745290ba9 | ||
|
|
808bcb8022 | ||
|
|
af8a5cbbfa | ||
|
|
cb4b60e8e4 | ||
|
|
2cc88df08a | ||
|
|
dce89571ef | ||
|
|
1512d8120d | ||
|
|
ac41a98610 | ||
|
|
bf4272102d | ||
|
|
7257bba3f3 | ||
|
|
6e5eeb7215 | ||
|
|
a5aef9e330 | ||
|
|
48fe013c83 | ||
|
|
02bf5befc4 | ||
|
|
0cac8abe75 | ||
|
|
822b741612 | ||
|
|
b0a459c8a1 | ||
|
|
60f6bbd42a | ||
|
|
93fa3f018f | ||
|
|
680a06a60e | ||
|
|
b7925936f8 | ||
|
|
4dcf7feec0 | ||
|
|
f5bcd54b89 | ||
|
|
66585ccd3b | ||
|
|
0ab152d644 | ||
|
|
e6b410af04 | ||
|
|
585795fb0a | ||
|
|
09eddb59f5 | ||
|
|
56c4637d1e | ||
|
|
ee1ec3d6d0 | ||
|
|
a8aef0ca64 | ||
|
|
3f683f0dfd | ||
|
|
ca12b9f253 | ||
|
|
c3aad38628 | ||
|
|
6f7670e5ff | ||
|
|
c2a34b5d71 | ||
|
|
3caa5e0f39 | ||
|
|
fd4a136e2b | ||
|
|
4babbc133a | ||
|
|
3c5fa95c7a | ||
|
|
ad3f2d0023 | ||
|
|
8f5823fac1 | ||
|
|
617592a959 | ||
|
|
12f682b7bc | ||
|
|
6a86e846c3 | ||
|
|
ce86354a57 | ||
|
|
72cfa3b8fc | ||
|
|
1166df3471 | ||
|
|
09b8f5b540 | ||
|
|
dcbb134525 | ||
|
|
fa22c2ae3b | ||
|
|
ed6f5cbcf2 | ||
|
|
44cb1acbb2 | ||
|
|
f5f26e3840 | ||
|
|
485692b3f2 | ||
|
|
c20aa124d6 | ||
|
|
775bba8f7f | ||
|
|
b0074bf723 | ||
|
|
1e1f272e4c | ||
|
|
aa9149912d | ||
|
|
3054a809ce | ||
|
|
38d243c63f | ||
|
|
fb6bf87161 | ||
|
|
9ee43c0b7a | ||
|
|
846531363e | ||
|
|
91e369a840 | ||
|
|
81ff4416dc | ||
|
|
f7c5e1b8b2 | ||
|
|
f5c2901b3f | ||
|
|
dd4459f813 | ||
|
|
01d84fdacf | ||
|
|
9f8024d836 | ||
|
|
d4c1f14bd6 | ||
|
|
c40368b0fa | ||
|
|
1ed926b491 | ||
|
|
88b255c178 | ||
|
|
5dbeddf448 | ||
|
|
5d5affca33 | ||
|
|
8681e78e50 | ||
|
|
5a6d8aee65 | ||
|
|
27cf50044d | ||
|
|
dee9cfea85 | ||
|
|
8e02438bfb | ||
|
|
b823777e6d | ||
|
|
e1de0873cd | ||
|
|
4c30e03f1e | ||
|
|
df4069ba37 | ||
|
|
ce1507c296 | ||
|
|
7097e6ba83 | ||
|
|
a28f0e76b9 | ||
|
|
0cc8537d7d | ||
|
|
c20c362557 | ||
|
|
0d4b09a0a0 | ||
|
|
408c08d2a3 | ||
|
|
10f56129c1 | ||
|
|
bc6830cbdb | ||
|
|
c5f78077ff | ||
|
|
682a1404ca | ||
|
|
5318ec6dbf | ||
|
|
490ddd9a15 | ||
|
|
1675174b2a | ||
|
|
023781716f | ||
|
|
48ad6e6042 | ||
|
|
bedc9399c5 | ||
|
|
86d172d209 | ||
|
|
708ba160d5 | ||
|
|
b0979a8cf9 | ||
|
|
b397eea044 | ||
|
|
5d6d7d9c55 | ||
|
|
e5c3dcb179 | ||
|
|
c0f17b39a7 | ||
|
|
0824f342e4 | ||
|
|
3e5c74c4f2 | ||
|
|
8ee617ce1c | ||
|
|
1891b35eda | ||
|
|
ed29fe1aa9 | ||
|
|
5b15865d30 | ||
|
|
1dfddfde54 | ||
|
|
1ae2624197 | ||
|
|
8484d55a6a | ||
|
|
0a55cda0a9 | ||
|
|
2480a5eaa2 | ||
|
|
f79d4f9a40 | ||
|
|
ef3c1c878c | ||
|
|
2d5e49fa15 | ||
|
|
5b26934802 | ||
|
|
08eba8ccc1 |
2
.github/workflows/checks.yml
vendored
2
.github/workflows/checks.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
name: check tests
|
||||
if: github.repository_owner == 'mermaid'
|
||||
if: github.repository_owner == 'mermaid-js'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -22,4 +22,7 @@ Gemfile.lock
|
||||
/.vs
|
||||
|
||||
cypress/screenshots/
|
||||
cypress/snapshots/
|
||||
cypress/snapshots/
|
||||
|
||||
# eslint --cache file
|
||||
.eslintcache
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"endOfLine": "auto",
|
||||
"plugins": [
|
||||
"prettier-plugin-jsdoc"
|
||||
],
|
||||
"printWidth": 100,
|
||||
"singleQuote": true
|
||||
}
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 - 2021 Knut Sveidqvist
|
||||
Copyright (c) 2014 - 2022 Knut Sveidqvist
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
12
README.md
12
README.md
@@ -15,20 +15,20 @@ English | [简体中文](./README.zh-CN.md)
|
||||
## About
|
||||
|
||||
<!-- <Main description> -->
|
||||
Mermaid is a JavaScript based diagramming and charting tool that uses Markdown-inspired text definitions and a renderer to create and modify complex diagrams. The main purpose of Mermaid is to help documentation catch up with development.
|
||||
Mermaid is a JavaScript-based diagramming and charting tool that uses Markdown-inspired text definitions and a renderer to create and modify complex diagrams. The main purpose of Mermaid is to help documentation catch up with development.
|
||||
|
||||
> Doc-Rot is a Catch-22 that Mermaid helps to solve.
|
||||
|
||||
Diagramming and documentation costs precious developer time and gets outdated quickly.
|
||||
But not having diagrams or docs ruins productivity and hurts organizational learning.<br/>
|
||||
Mermaid addresses this problem by enabling users to create easily modifiable diagrams, it can also be made part of production scripts (and other pieces of code).<br/>
|
||||
Mermaid addresses this problem by enabling users to create easily modifiable diagrams. It can also be made part of production scripts (and other pieces of code).<br/>
|
||||
<br/>
|
||||
|
||||
Mermaid allows even non-programmers to easily create detailed diagrams through the [Mermaid Live Editor](https://mermaid.live/).<br/>
|
||||
[Tutorials](./docs/Tutorials.md) has video tutorials.
|
||||
Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./docs/integrations.md).
|
||||
|
||||
You can also use Mermaid within [GitHub](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) as well many of your other favorite applications, check out the list of [Integrations and Usages of Mermaid](./docs/integrations.md).
|
||||
You can also use Mermaid within [GitHub](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) as well many of your other favorite applications—check out the list of [Integrations and Usages of Mermaid](./docs/integrations.md).
|
||||
|
||||
For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](./docs/n00b-overview.md), [Usage](./docs/usage.md) and [Tutorials](./docs/Tutorials.md).
|
||||
|
||||
@@ -48,7 +48,7 @@ In our release process we rely heavily on visual regression tests using [applito
|
||||
|
||||
## Examples
|
||||
|
||||
__The following are some examples of the diagrams, charts and graphs that can be made using Mermaid. Click here jump into the [text syntax](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference).__
|
||||
__The following are some examples of the diagrams, charts and graphs that can be made using Mermaid. Click here to jump into the [text syntax](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference).__
|
||||
<!-- <Flowchart> -->
|
||||
|
||||
### Flowchart [<a href="https://mermaid-js.github.io/mermaid/#/flowchart">docs</a> - <a href="https://mermaid.live/edit#pako:eNpNkMtqwzAQRX9FzKqFJK7t1km8KDQP6KJQSLOLvZhIY1tgS0GWmgbb_165IaFaiXvOFTPqgGtBkEJR6zOv0Fj2scsU8-ft8I5G5Gw6fe339GN7tnrYaafE45WvRsLW3Ya4bKVWwzVe_xU-FfVsc9hR62rLwvw_2591z7Y3FuUwgYZMg1L4ObrRzMBW1FAGqb8KKtCLGWRq8Ko7CbS0FdJqA2mBdUsTQGf110VxSK1xdJM2EkuDzd2qNQrypQ7s5TQuXcrW-ie5VoUsx9yZ2seVtac2DYIRz0ppK3eccd0ErRTjD1XfyyRIomSBUUzJPMaXOBb8GC4XRfQcFmL-FEYIwzD8AggvcHE">live editor</a>]
|
||||
@@ -125,7 +125,7 @@ gantt
|
||||
classDiagram
|
||||
Class01 <|-- AveryLongClass : Cool
|
||||
<<Interface>> Class01
|
||||
Class09 --> C2 : Where am i?
|
||||
Class09 --> C2 : Where am I?
|
||||
Class09 --* C3
|
||||
Class09 --|> Class07
|
||||
Class07 : equals()
|
||||
@@ -143,7 +143,7 @@ class Class10 {
|
||||
classDiagram
|
||||
Class01 <|-- AveryLongClass : Cool
|
||||
<<Interface>> Class01
|
||||
Class09 --> C2 : Where am i?
|
||||
Class09 --> C2 : Where am I?
|
||||
Class09 --* C3
|
||||
Class09 --|> Class07
|
||||
Class07 : equals()
|
||||
|
||||
@@ -106,7 +106,7 @@ gantt
|
||||
classDiagram
|
||||
Class01 <|-- AveryLongClass : Cool
|
||||
<<Interface>> Class01
|
||||
Class09 --> C2 : Where am i?
|
||||
Class09 --> C2 : Where am I?
|
||||
Class09 --* C3
|
||||
Class09 --|> Class07
|
||||
Class07 : equals()
|
||||
@@ -124,7 +124,7 @@ class Class10 {
|
||||
classDiagram
|
||||
Class01 <|-- AveryLongClass : Cool
|
||||
<<Interface>> Class01
|
||||
Class09 --> C2 : Where am i?
|
||||
Class09 --> C2 : Where am I?
|
||||
Class09 --* C3
|
||||
Class09 --|> Class07
|
||||
Class07 : equals()
|
||||
|
||||
5
cypress/fixtures/example.json
Normal file
5
cypress/fixtures/example.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
@@ -43,6 +43,7 @@ export const imgSnapshotTest = (graphStr, _options, api = false, validation) =>
|
||||
options.fontSize = '16px';
|
||||
}
|
||||
const useAppli = Cypress.env('useAppli');
|
||||
//const useAppli = false;
|
||||
const branch = Cypress.env('codeBranch');
|
||||
cy.log('Hello ' + useAppli ? 'Appli' : 'image-snapshot');
|
||||
const name = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
|
||||
|
||||
@@ -4,7 +4,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_loose.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g#flowchart-Function-2').click();
|
||||
cy.get('body').find('g#flowchart-Function-4').click();
|
||||
|
||||
cy.get('.created-by-click').should('have.text', 'Clicked By Flow');
|
||||
});
|
||||
@@ -12,7 +12,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_loose.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g#flowchart-FunctionArg-18').click();
|
||||
cy.get('body').find('g#flowchart-FunctionArg-28').click();
|
||||
|
||||
cy.get('.created-by-click-2').should('have.text', 'Clicked By Flow: ARGUMENT');
|
||||
});
|
||||
@@ -20,7 +20,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_loose.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g[id="flowchart-FunctionArg-22"]').click();
|
||||
cy.get('body').find('g[id="flowchart-FunctionArg-34"]').click();
|
||||
|
||||
cy.get('.created-by-click-2').should('have.text', 'Clicked By Flow: ARGUMENT');
|
||||
});
|
||||
@@ -28,7 +28,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_loose.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('#flowchart-URL-3').click();
|
||||
cy.get('body').find('#flowchart-URL-5').click();
|
||||
|
||||
cy.location().should((location) => {
|
||||
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
|
||||
@@ -38,7 +38,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_loose.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g[id="flowchart-2URL-7"]').click();
|
||||
cy.get('body').find('g[id="flowchart-2URL-11"]').click();
|
||||
|
||||
cy.location().should((location) => {
|
||||
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
|
||||
@@ -49,7 +49,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_loose.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g#flowchart-Function-10').click();
|
||||
cy.get('body').find('g#flowchart-Function-16').click();
|
||||
|
||||
cy.get('.created-by-click').should('have.text', 'Clicked By Flow');
|
||||
});
|
||||
@@ -57,7 +57,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_loose.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g[id="flowchart-1Function-14"]').click();
|
||||
cy.get('body').find('g[id="flowchart-1Function-22"]').click();
|
||||
|
||||
cy.get('.created-by-click').should('have.text', 'Clicked By Flow');
|
||||
});
|
||||
@@ -65,7 +65,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_loose.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('#flowchart-URL-11').click();
|
||||
cy.get('body').find('#flowchart-URL-17').click();
|
||||
|
||||
cy.location().should((location) => {
|
||||
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
|
||||
@@ -75,7 +75,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_loose.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g[id="flowchart-2URL-15"]').click();
|
||||
cy.get('body').find('g[id="flowchart-2URL-23"]').click();
|
||||
|
||||
cy.location().should((location) => {
|
||||
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
|
||||
@@ -142,7 +142,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_strict.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g#flowchart-Function-2').click();
|
||||
cy.get('body').find('g#flowchart-Function-4').click();
|
||||
|
||||
cy.get('.created-by-click').should('not.exist');
|
||||
// cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');
|
||||
@@ -151,7 +151,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_strict.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g[id="flowchart-1Function-6"]').click();
|
||||
cy.get('body').find('g[id="flowchart-1Function-10"]').click();
|
||||
|
||||
// cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');
|
||||
cy.get('.created-by-click').should('not.exist');
|
||||
@@ -160,7 +160,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_strict.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g#flowchart-URL-3').click();
|
||||
cy.get('body').find('g#flowchart-URL-5').click();
|
||||
|
||||
cy.location().should((location) => {
|
||||
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
|
||||
@@ -170,7 +170,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_strict.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g[id="flowchart-2URL-7"]').click();
|
||||
cy.get('body').find('g[id="flowchart-2URL-11"]').click();
|
||||
|
||||
cy.location().should((location) => {
|
||||
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
|
||||
@@ -222,7 +222,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_other.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g#flowchart-Function-2').click();
|
||||
cy.get('body').find('g#flowchart-Function-4').click();
|
||||
|
||||
// cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');
|
||||
cy.get('.created-by-click').should('not.exist');
|
||||
@@ -231,7 +231,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_other.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g[id="flowchart-1Function-6"]').click();
|
||||
cy.get('body').find('g[id="flowchart-1Function-10"]').click();
|
||||
|
||||
cy.get('.created-by-click').should('not.exist');
|
||||
cy.get('.created-by-click').should('not.exist');
|
||||
@@ -240,7 +240,7 @@ describe('Interaction', () => {
|
||||
const url = 'http://localhost:9000/click_security_other.html';
|
||||
cy.viewport(1440, 1024);
|
||||
cy.visit(url);
|
||||
cy.get('body').find('g#flowchart-URL-3').click();
|
||||
cy.get('body').find('g#flowchart-URL-5').click();
|
||||
|
||||
cy.location().should((location) => {
|
||||
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
|
||||
@@ -112,7 +112,7 @@ describe('Entity Relationship Diagram', () => {
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
expect(svg).to.have.attr('width', '100%');
|
||||
expect(svg).to.have.attr('height', '465');
|
||||
// expect(svg).to.have.attr('height', '465');
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
@@ -134,7 +134,7 @@ describe('Entity Relationship Diagram', () => {
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
expect(width).to.be.within(140 * 0.95, 140 * 1.05);
|
||||
expect(svg).to.have.attr('height', '465');
|
||||
// expect(svg).to.have.attr('height', '465');
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
@@ -167,11 +167,26 @@ describe('Entity Relationship Diagram', () => {
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it.only('should render entities with generic and array attributes', () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
BOOK {
|
||||
string title
|
||||
string[] authors
|
||||
type~T~ type
|
||||
}
|
||||
`,
|
||||
{ logLevel: 1 }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should render entities and attributes with big and small entity names', () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
PRIVATE_FINANCIAL_INSTITUTION {
|
||||
PRIVATE_FINANCIAL_INSTITUTION {
|
||||
string name
|
||||
int turnover
|
||||
}
|
||||
@@ -191,9 +206,9 @@ describe('Entity Relationship Diagram', () => {
|
||||
string name PK
|
||||
}
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
|
||||
BOOK {
|
||||
BOOK {
|
||||
float price
|
||||
string author FK
|
||||
string author FK
|
||||
string title PK
|
||||
}
|
||||
`,
|
||||
@@ -210,8 +225,8 @@ describe('Entity Relationship Diagram', () => {
|
||||
string name "comment"
|
||||
}
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
|
||||
BOOK {
|
||||
string author
|
||||
BOOK {
|
||||
string author
|
||||
string title "author comment"
|
||||
float price "price comment"
|
||||
}
|
||||
@@ -229,11 +244,11 @@ describe('Entity Relationship Diagram', () => {
|
||||
string name PK "comment"
|
||||
}
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
|
||||
BOOK {
|
||||
BOOK {
|
||||
string description
|
||||
float price "price comment"
|
||||
string title PK "title comment"
|
||||
string author FK
|
||||
string author FK
|
||||
}
|
||||
`,
|
||||
{ logLevel: 1 }
|
||||
@@ -42,7 +42,7 @@ describe('Flowchart v2', () => {
|
||||
P3 --> P6
|
||||
P1.5 --> P5
|
||||
`,
|
||||
{ flowchart: { diagramPadding: 0 } }
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -60,7 +60,7 @@ describe('Flowchart v2', () => {
|
||||
C <-...-> E4
|
||||
C ======> E5
|
||||
`,
|
||||
{ flowchart: { diagramPadding: 0 } }
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('5: should render escaped without html labels', () => {
|
||||
@@ -92,10 +92,10 @@ describe('Flowchart v2', () => {
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
expect(svg).to.have.attr('width', '100%');
|
||||
expect(svg).to.have.attr('height');
|
||||
// expect(svg).to.have.attr('height');
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
@@ -114,10 +114,10 @@ describe('Flowchart v2', () => {
|
||||
{ flowchart: { useMaxWidth: false } }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
expect(width).to.be.within(290 * 0.95 - 1, 290 * 1.05);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
@@ -652,4 +652,15 @@ flowchart RL
|
||||
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||
);
|
||||
});
|
||||
it('2824: Clipping of edges', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
flowchart TD
|
||||
A --> B
|
||||
A --> C
|
||||
B --> C
|
||||
`,
|
||||
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -744,10 +744,10 @@ describe('Graph', () => {
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
expect(svg).to.have.attr('width', '100%');
|
||||
expect(svg).to.have.attr('height');
|
||||
// expect(svg).to.have.attr('height');
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
@@ -766,10 +766,10 @@ describe('Graph', () => {
|
||||
{ flowchart: { useMaxWidth: false } }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
expect(width).to.be.within(300 * 0.95, 300 * 1.05);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
@@ -163,6 +163,24 @@ describe('Gantt diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle milliseconds', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gantt
|
||||
title A Gantt Diagram
|
||||
dateFormat x
|
||||
axisFormat %L
|
||||
section Section
|
||||
A task :a1, 0, 30ms
|
||||
Another task :after a1, 20ms
|
||||
section Another
|
||||
Another another task :b1, 20, 12ms
|
||||
Another another another task :after b1, 24ms
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a gantt diagram when useMaxWidth is true (default)', () => {
|
||||
renderGraph(
|
||||
`
|
||||
@@ -200,10 +218,10 @@ describe('Gantt diagram', () => {
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
expect(svg).to.have.attr('width', '100%');
|
||||
expect(svg).to.have.attr('height');
|
||||
// expect(svg).to.have.attr('height');
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
expect(height).to.be.within(484 * 0.95, 484 * 1.05);
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
// expect(height).to.be.within(484 * 0.95, 484 * 1.05);
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
@@ -247,10 +265,10 @@ describe('Gantt diagram', () => {
|
||||
{ gantt: { useMaxWidth: false } }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
expect(height).to.be.within(484 * 0.95, 484 * 1.05);
|
||||
// expect(height).to.be.within(484 * 0.95, 484 * 1.05);
|
||||
expect(width).to.be.within(984 * 0.95, 984 * 1.05);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
@@ -74,7 +74,7 @@ describe('Git Graph diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('7: should render a simple gitgraph with three branches and merge commit', () => {
|
||||
it('7: should render a simple gitgraph with three branches and tagged merge commit', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id: "1"
|
||||
@@ -93,7 +93,7 @@ describe('Git Graph diagram', () => {
|
||||
checkout nice_feature
|
||||
commit id: "7"
|
||||
checkout main
|
||||
merge nice_feature
|
||||
merge nice_feature id: "12345" tag: "my merge commit"
|
||||
checkout very_nice_feature
|
||||
commit id: "8"
|
||||
checkout main
|
||||
@@ -207,4 +207,50 @@ describe('Git Graph diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('12: should render commits for more than 8 branches', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gitGraph
|
||||
checkout main
|
||||
commit
|
||||
checkout main
|
||||
branch branch1
|
||||
commit
|
||||
checkout main
|
||||
merge branch1
|
||||
branch branch2
|
||||
commit
|
||||
checkout main
|
||||
merge branch2
|
||||
branch branch3
|
||||
commit
|
||||
checkout main
|
||||
merge branch3
|
||||
branch branch4
|
||||
commit
|
||||
checkout main
|
||||
merge branch4
|
||||
branch branch5
|
||||
commit
|
||||
checkout main
|
||||
merge branch5
|
||||
branch branch6
|
||||
commit
|
||||
checkout main
|
||||
merge branch6
|
||||
branch branch7
|
||||
commit
|
||||
checkout main
|
||||
merge branch7
|
||||
branch branch8
|
||||
commit
|
||||
checkout main
|
||||
merge branch8
|
||||
branch branch9
|
||||
commit
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -42,8 +42,8 @@ section Checkout from website
|
||||
cy.get('svg').should((svg) => {
|
||||
expect(svg).to.have.attr('width', '100%');
|
||||
expect(svg).to.have.attr('height');
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
expect(height).to.eq(565);
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
// expect(height).to.eq(565);
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
@@ -48,9 +48,9 @@ describe('Pie Chart', () => {
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
expect(svg).to.have.attr('width', '100%');
|
||||
expect(svg).to.have.attr('height');
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
expect(height).to.eq(450);
|
||||
// expect(svg).to.have.attr('height');
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
// expect(height).to.eq(450);
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
@@ -68,9 +68,9 @@ describe('Pie Chart', () => {
|
||||
{ pie: { useMaxWidth: false } }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
expect(height).to.eq(450);
|
||||
// expect(height).to.eq(450);
|
||||
expect(width).to.eq(984);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
@@ -80,7 +80,7 @@ context('Sequence diagram', () => {
|
||||
loop Loopy
|
||||
Bob->>Alice: Pasten
|
||||
end `,
|
||||
{}
|
||||
{ wrap: true }
|
||||
);
|
||||
});
|
||||
context('font settings', () => {
|
||||
@@ -126,6 +126,17 @@ context('Sequence diagram', () => {
|
||||
{ sequence: { noteAlign: 'left' } }
|
||||
);
|
||||
});
|
||||
it('should render multi-line notes aligned to the left when configured', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
Alice->>Bob: I'm short
|
||||
note left of Alice: I am left aligned<br>but also<br>multiline
|
||||
Bob->>Alice: Short as well
|
||||
`,
|
||||
{ sequence: { noteAlign: 'left' } }
|
||||
);
|
||||
});
|
||||
it('should render notes aligned to the right when configured', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
@@ -137,6 +148,37 @@ context('Sequence diagram', () => {
|
||||
{ sequence: { noteAlign: 'right' } }
|
||||
);
|
||||
});
|
||||
it('should render multi-line notes aligned to the right when configured', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
Alice->>Bob: I'm short
|
||||
note left of Alice: I am right aligned<br>but also<br>multiline
|
||||
Bob->>Alice: Short as well
|
||||
`,
|
||||
{ sequence: { noteAlign: 'right' } }
|
||||
);
|
||||
});
|
||||
it('should render multi-line messages aligned to the left when configured', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
Alice->>Bob: I'm short<br>but also<br>multiline
|
||||
Bob->>Alice: Short as well<br>and also<br>multiline
|
||||
`,
|
||||
{ sequence: { messageAlign: 'left' } }
|
||||
);
|
||||
});
|
||||
it('should render multi-line messages aligned to the right when configured', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
Alice->>Bob: I'm short<br>but also<br>multiline
|
||||
Bob->>Alice: Short as well<br>and also<br>multiline
|
||||
`,
|
||||
{ sequence: { messageAlign: 'right' } }
|
||||
);
|
||||
});
|
||||
});
|
||||
context('auth width scaling', () => {
|
||||
it('should render long actor descriptions', () => {
|
||||
@@ -692,9 +734,9 @@ context('Sequence diagram', () => {
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
expect(svg).to.have.attr('width', '100%');
|
||||
expect(svg).to.have.attr('height');
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
expect(height).to.be.within(920, 971);
|
||||
// expect(svg).to.have.attr('height');
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
// expect(height).to.be.within(920, 971);
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
@@ -731,9 +773,9 @@ context('Sequence diagram', () => {
|
||||
{ sequence: { useMaxWidth: false } }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
expect(height).to.be.within(920, 971);
|
||||
// expect(height).to.be.within(920, 971);
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
expect(width).to.be.within(820 * 0.95, 820 * 1.05);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
@@ -480,14 +480,14 @@ stateDiagram-v2
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
expect(svg).to.have.attr('width', '100%');
|
||||
expect(svg).to.have.attr('height');
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
expect(height).to.be.within(177, 178);
|
||||
// expect(svg).to.have.attr('height');
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
// expect(height).to.be.within(177, 178);
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
expect(maxWidthValue).to.be.within(135 * 0.95, 135 * 1.05);
|
||||
expect(maxWidthValue).to.be.within(65, 85);
|
||||
});
|
||||
});
|
||||
it('v2 should render a state diagram when useMaxWidth is false', () => {
|
||||
@@ -501,12 +501,24 @@ stateDiagram-v2
|
||||
{ state: { useMaxWidth: false } }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
expect(height).to.be.within(177, 178);
|
||||
// expect(height).to.be.within(177, 178);
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
expect(width).to.be.within(135 * 0.95, 135 * 1.05);
|
||||
expect(width).to.be.within(65, 85);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
|
||||
it('v2 should render a state diagram and set the correct length of the labels', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
stateDiagram-v2
|
||||
[*] --> 1
|
||||
1 --> 2: test({ foo#colon; 'far' })
|
||||
2 --> [*]
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -357,16 +357,16 @@ describe('State diagram', () => {
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
expect(svg).to.have.attr('width', '100%');
|
||||
expect(svg).to.have.attr('height');
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
expect(height).to.be.within(176, 178);
|
||||
// expect(svg).to.have.attr('height');
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
// expect(height).to.be.within(176, 178);
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
// Todo investigate difference
|
||||
// expect(maxWidthValue).to.be.within(112 * .95, 112 * 1.05);
|
||||
expect(maxWidthValue).to.be.within(130, 140);
|
||||
expect(maxWidthValue).to.be.within(65, 85);
|
||||
});
|
||||
});
|
||||
it('should render a state diagram when useMaxWidth is false', () => {
|
||||
@@ -379,13 +379,13 @@ describe('State diagram', () => {
|
||||
{ state: { useMaxWidth: false } }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const height = parseFloat(svg.attr('height'));
|
||||
// const height = parseFloat(svg.attr('height'));
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
expect(height).to.be.within(176, 178);
|
||||
// expect(height).to.be.within(176, 178);
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
// Todo investigate difference
|
||||
// expect(width).to.be.within(112 * .95, 112 * 1.05);
|
||||
expect(width).to.be.within(130, 140);
|
||||
expect(width).to.be.within(65, 85);
|
||||
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
@@ -15,13 +15,20 @@
|
||||
/* font-size: 18px !important; */
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: 20px;
|
||||
}
|
||||
h1 { color: grey;}
|
||||
.mermaid2,.mermaid3 {
|
||||
display: none;
|
||||
}
|
||||
.mermaid {
|
||||
|
||||
}
|
||||
.mermaid svg {
|
||||
border: 1px solid purple;
|
||||
/* font-size: 18px !important; */
|
||||
fontFamily: 'courier'
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
@@ -31,41 +38,66 @@
|
||||
|
||||
|
||||
<div class="mermaid2" style="width: 50%;">
|
||||
journey
|
||||
title Adding journey diagram functionality to mermaid
|
||||
accTitle: Adding acc journey diagram functionality to mermaid
|
||||
accDescr {
|
||||
My multi-line description
|
||||
of the diagram
|
||||
}
|
||||
section Order from website
|
||||
flowchart LR
|
||||
classDef aPID stroke:#4e4403,fill:#fdde29,color:#4e4403,rx:5px,ry:5px;
|
||||
classDef crm stroke:#333333,fill:#DCDCDC,color:#333333,rx:5px,ry:5px;
|
||||
classDef type stroke:#502604,fill:#FAB565,color:#502604,rx:20px,ry:20px;;
|
||||
|
||||
O0("Joe")
|
||||
class O0 aPID;
|
||||
|
||||
O1("Person")
|
||||
class O1 crm;
|
||||
O0 -- has type -->O1["Person"]
|
||||
|
||||
O2("aat:300411314")
|
||||
class O2 type;
|
||||
click O2 function "Sorry the newline html tags are not being processed correctly<br/> So all of this appears on the <br/> same line."
|
||||
O0 -- has type -->O2["Bug"]
|
||||
click O0 function "Lots of great info about Joe<br>Lots of great info about Joe<br>burt<br>fred";
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 50%;">
|
||||
pie
|
||||
accTitle: My Pie Chart Accessibility Title
|
||||
accDescr: My Pie Chart Accessibility Description
|
||||
flowchart TD
|
||||
subgraph test
|
||||
direction TB
|
||||
subgraph test2
|
||||
direction LR
|
||||
F --> D
|
||||
end
|
||||
subgraph test3
|
||||
direction TB
|
||||
G --> H
|
||||
end
|
||||
end
|
||||
|
||||
title Key elements in Product X
|
||||
"Calcium" : 42.96
|
||||
"Potassium" : 50.05
|
||||
"Magnesium" : 10.01
|
||||
"Iron" : 5
|
||||
</div>
|
||||
<div class="mermaid" style="width: 50%;">
|
||||
flowchart TD
|
||||
id
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 50%;">
|
||||
gitGraph
|
||||
accTitle: My Gitgraph Accessibility Title
|
||||
accDescr: My Gitgraph Accessibility Description
|
||||
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
flowchart LR
|
||||
a["<strong>Haiya</strong>"]===>b
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 50%;">
|
||||
flowchart TD
|
||||
A --> B
|
||||
A --> C
|
||||
B --> C
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 50%;">
|
||||
flowchart TD
|
||||
A([stadium shape test])
|
||||
A -->|Get money| B([Go shopping])
|
||||
B --> C([Let me think...<br />Do I want something for work,<br />something to spend every free second with,<br />or something to get around?])
|
||||
C -->|One| D([Laptop])
|
||||
C -->|Two| E([iPhone])
|
||||
C -->|Three| F([Car<br/>wroom wroom])
|
||||
click A "index.html#link-clicked" "link test"
|
||||
click B testClick "click test"
|
||||
classDef someclass fill:#f96;
|
||||
class A someclass;
|
||||
class C someclass;
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 50%;">
|
||||
sequenceDiagram
|
||||
@@ -99,6 +131,9 @@ graph TD
|
||||
Sit down: 5: Me
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
info
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
requirementDiagram
|
||||
accTitle: My req Diagram
|
||||
accDescr: My req Diagram Description
|
||||
@@ -138,8 +173,41 @@ requirementDiagram
|
||||
test_req - traces -> test_req2
|
||||
test_req - contains -> test_req3
|
||||
test_req <- copies - test_entity2
|
||||
|
||||
</div>
|
||||
<div class="mermaid" style="width: 100%;">
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
gantt
|
||||
dateFormat YYYY-MM-DD
|
||||
title Adding GANTT diagram functionality to mermaid
|
||||
excludes weekends
|
||||
%% (`excludes` accepts specific dates in YYYY-MM-DD format, days of the week ("sunday") or "weekends", but not the word "weekdays".)
|
||||
|
||||
section A section
|
||||
Completed task :done, des1, 2014-01-06,2014-01-08
|
||||
Active task :active, des2, 2014-01-09, 3d
|
||||
Future task : des3, after des2, 5d
|
||||
Future task2 : des4, after des3, 5d
|
||||
|
||||
section Critical tasks
|
||||
Completed task in the critical line :crit, done, 2014-01-06,24h
|
||||
Implement parser and jison :crit, done, after des1, 2d
|
||||
Create tests for parser :crit, active, 3d
|
||||
Future task in critical line :crit, 5d
|
||||
Create tests for renderer :2d
|
||||
Add to mermaid :1d
|
||||
Functionality added :milestone, 2014-01-25, 0d
|
||||
|
||||
section Documentation
|
||||
Describe gantt syntax :active, a1, after des1, 3d
|
||||
Add gantt diagram to demo page :after a1 , 20h
|
||||
Add another diagram to demo page :doc1, after a1 , 48h
|
||||
|
||||
section Last section
|
||||
Describe gantt syntax :after doc1, 3d
|
||||
Add gantt diagram to demo page :20h
|
||||
Add another diagram to demo page :48h
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
stateDiagram
|
||||
state Active {
|
||||
Idle
|
||||
@@ -148,7 +216,7 @@ stateDiagram
|
||||
Active --> Active: LOG
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
graph TB
|
||||
flowchart TB
|
||||
accTitle: My flowchart
|
||||
accDescr: My flowchart Description
|
||||
subgraph One
|
||||
@@ -165,8 +233,7 @@ stateDiagram
|
||||
end
|
||||
end
|
||||
end
|
||||
B ->> A: Return
|
||||
</div>
|
||||
B ->> A: Return</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
classDiagram
|
||||
accTitle: My class diagram
|
||||
@@ -186,13 +253,41 @@ class Class10 {
|
||||
}
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
stateDiagram
|
||||
accTitle: Apa
|
||||
accDescr: One that can climb better then any man
|
||||
[*] --> S1
|
||||
state "Some long name" as S1
|
||||
%%{init: {'config': {'wrap': true }}}%%
|
||||
sequenceDiagram
|
||||
participant A as Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
A->>Bob: Hola
|
||||
Bob-->A: Pasten !
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
gitGraph
|
||||
commit id: "ZERO"
|
||||
branch develop
|
||||
commit id:"A"
|
||||
checkout main
|
||||
commit id:"ONE"
|
||||
checkout develop
|
||||
commit id:"B"
|
||||
branch featureA
|
||||
commit id:"FIX"
|
||||
commit id: "FIX-2"
|
||||
checkout main
|
||||
commit id:"TWO"
|
||||
cherry-pick id:"A"
|
||||
commit id:"THREE"
|
||||
cherry-pick id:"FIX"
|
||||
checkout develop
|
||||
commit id:"C"
|
||||
merge featureA
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
flowchart TD
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
B --> C{Let me think}
|
||||
C -->|One| D[Laptop]
|
||||
C -->|Two| E[iPhone]
|
||||
C -->|Three| F[fa:fa-car Car]
|
||||
</div> <div class="mermaid2" style="width: 100%;">
|
||||
classDiagram
|
||||
Animal "1" <|-- Duck
|
||||
Animal <|-- Fish
|
||||
@@ -215,6 +310,21 @@ class Class10 {
|
||||
+run()
|
||||
}
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
erDiagram
|
||||
CAR ||--o{ NAMED-DRIVER : allows
|
||||
CAR {
|
||||
string registrationNumber
|
||||
string make
|
||||
string model
|
||||
}
|
||||
PERSON ||--o{ NAMED-DRIVER : is
|
||||
PERSON {
|
||||
string firstName
|
||||
string lastName
|
||||
int age
|
||||
}
|
||||
</div>
|
||||
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
@@ -222,41 +332,17 @@ class Class10 {
|
||||
// console.error('Mermaid error: ', err);
|
||||
};
|
||||
mermaid.initialize({
|
||||
// theme: 'dark',
|
||||
// theme: 'forest',
|
||||
// arrowMarkerAbsolute: true,
|
||||
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
||||
flowchart: {
|
||||
nodeSpacing: 10,
|
||||
curve: 'cardinal',
|
||||
htmlLabels: true,
|
||||
useMaxWidth: false,
|
||||
// defaultRenderer: 'dagre-d3',
|
||||
},
|
||||
class: {
|
||||
// defaultRenderer: 'dagre-d3',
|
||||
htmlLabels: true,
|
||||
},
|
||||
// gantt: { axisFormat: '%m/%d/%Y' },
|
||||
// sequence: {
|
||||
// actorFontFamily: 'courier',
|
||||
// actorMargin: 50,
|
||||
// showSequenceNumbers: false,
|
||||
// // hideUnusedParticipants: true,
|
||||
// // forceMenus: true,
|
||||
// },
|
||||
// // sequenceDiagram: { actorMargin: 300, forceMenus: false }, // deprecated
|
||||
// fontFamily: '"times", sans-serif',
|
||||
// fontFamily: 'courier',
|
||||
state: {
|
||||
nodeSpacing: 50,
|
||||
rankSpacing: 50,
|
||||
},
|
||||
maxTextSize: 900000,
|
||||
startOnLoad: true,
|
||||
securityLevel: 'loose',
|
||||
logLevel: 0,
|
||||
fontSize: 18,
|
||||
curve: 'cardinal',
|
||||
// securityLevel: 'sandbox',
|
||||
// themeVariables: {relationLabelColor: 'red'}
|
||||
fontFamily: 'courier',
|
||||
flowchart: {
|
||||
// curve: 'curveLinear',
|
||||
useMaxWidth: true,
|
||||
htmlLabels: false,
|
||||
fontFamily: 'courier',
|
||||
},
|
||||
});
|
||||
function callback() {
|
||||
alert('It worked');
|
||||
|
||||
@@ -41,7 +41,10 @@
|
||||
<body>
|
||||
<div>Security check</div>
|
||||
<div class="flex">
|
||||
<div id="diagram" class="mermaid"></div>
|
||||
<div id="diagram" class="mermaid">
|
||||
sequenceDiagram
|
||||
Nothing:Valid;
|
||||
</div>
|
||||
<div id="res" class=""></div>
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
@@ -49,28 +52,6 @@
|
||||
// console.error('Mermaid error: ', err);
|
||||
};
|
||||
mermaid.initialize({
|
||||
theme: 'forest',
|
||||
arrowMarkerAbsolute: true,
|
||||
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
||||
logLevel: 0,
|
||||
state: {
|
||||
defaultRenderer: 'dagre-wrapper',
|
||||
},
|
||||
flowchart: {
|
||||
// defaultRenderer: 'dagre-wrapper',
|
||||
nodeSpacing: 10,
|
||||
curve: 'cardinal',
|
||||
htmlLabels: true,
|
||||
},
|
||||
htmlLabels: false,
|
||||
// gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
|
||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||
// fontFamily: '"times", sans-serif',
|
||||
// fontFamily: 'courier',
|
||||
fontSize: 18,
|
||||
curve: 'basis',
|
||||
securityLevel: 'strict',
|
||||
startOnLoad: false,
|
||||
// themeVariables: {relationLabelColor: 'red'}
|
||||
});
|
||||
@@ -78,19 +59,12 @@
|
||||
alert('It worked');
|
||||
}
|
||||
|
||||
var diagram = '%%{init: {"flowchart": {"htmlLabels": "false"}} }%%\n';
|
||||
diagram += 'flowchart\n';
|
||||
diagram += 'A["<ifra';
|
||||
diagram += "me srcdoc='<scrip";
|
||||
diagram += 't src=http://localhost:9000/exploit.js>';
|
||||
diagram += '</scr';
|
||||
diagram += 'ipt>\'></iframe>"]';
|
||||
|
||||
console.log(diagram);
|
||||
// document.querySelector('#diagram').innerHTML = diagram;
|
||||
mermaid.render('diagram', diagram, (res) => {
|
||||
document.querySelector('#res').innerHTML = res;
|
||||
});
|
||||
try {
|
||||
mermaid.initThrowsErrors(undefined, '#diagram');
|
||||
} catch (err) {
|
||||
console.log('Caught error:', err);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
32
cypress/plugins/index.js
Normal file
32
cypress/plugins/index.js
Normal file
@@ -0,0 +1,32 @@
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
// module.exports = (on, config) => {
|
||||
// // `on` is used to hook into various events Cypress emits
|
||||
// // `config` is the resolved Cypress config
|
||||
// }
|
||||
|
||||
const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin');
|
||||
require('@applitools/eyes-cypress')(module);
|
||||
|
||||
module.exports = (on, config) => {
|
||||
addMatchImageSnapshotPlugin(on, config);
|
||||
// copy any needed variables from process.env to config.env
|
||||
config.env.useAppli = process.env.USE_APPLI ? true : false;
|
||||
config.env.codeBranch = process.env.APPLI_BRANCH;
|
||||
|
||||
// do not forget to return the changed config object!
|
||||
return config;
|
||||
};
|
||||
|
||||
require('@applitools/eyes-cypress')(module);
|
||||
@@ -879,6 +879,31 @@ Enterprise_Boundary(b0, "BankBoundary0") {
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="mermaid">
|
||||
classDiagram
|
||||
Interface1 ()-- Interface1Impl
|
||||
</div>
|
||||
|
||||
<div class="mermaid">
|
||||
classDiagram
|
||||
direction LR
|
||||
Animal ()-- Dog
|
||||
Dog : bark()
|
||||
Dog : species()
|
||||
</div>
|
||||
|
||||
<div class="mermaid">
|
||||
classDiagram
|
||||
direction RL
|
||||
Fruit ()-- Apple
|
||||
Apple : color()
|
||||
Apple : -int leafCount()
|
||||
Fruit ()-- Pineapple
|
||||
Pineapple : color()
|
||||
Pineapple : -int leafCount()
|
||||
Pineapple : -int spikeCount()
|
||||
</div>
|
||||
|
||||
<div class="mermaid">
|
||||
stateDiagram
|
||||
accDescription This is a state diagram showing one state
|
||||
|
||||
@@ -31,28 +31,28 @@ The three levels of are Configuration, Global, Site and Current.
|
||||
|
||||
The modifiable parts of the Configuration are limited by the secure array, which is an array of immutable parameters, this array can be expanded by site owners.
|
||||
|
||||
**Notes**: secure arrays work like nesting dolls, with the Global Configurations’ secure array being the default and immutable list of immutable parameters, or the smallest doll, to which site owners may add to, but implementors may not modify it.
|
||||
**Notes**: secure arrays work like nesting dolls, with the Global Configurations’ secure array holding the default and immutable list of immutable parameters, or the smallest doll, to which site owners may add to, but implementors may not modify it.
|
||||
|
||||
# Secure Arrays
|
||||
|
||||
Site owners can add to the **secure** array using this command:
|
||||
mermaidAPI.initialize( { startOnLoad: true, secure: ['parameter1', 'parameter2'] } );
|
||||
|
||||
default values for the `secure array` consists of: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize']. These default values are immutable.
|
||||
Default values for the `secure array` consists of: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize']. These default values are immutable.
|
||||
|
||||
Implementors can only modify configurations using directives, but cannot change the `secure` array.
|
||||
Implementors can only modify configurations using directives, and cannot change the `secure` array.
|
||||
|
||||
# Modifying Configurations and directives:
|
||||
The Two types of directives: are `init` or `initialize` and `wrap`.
|
||||
The Two types of directives: are `init` (or `initialize`) and `wrap`.
|
||||
|
||||
```note
|
||||
All directives are enclosed in `%%{ }%%`
|
||||
```
|
||||
|
||||
Older versions of mermaid will not parse directives because `%%` will comment out the directive. This makes the update backward compatible.
|
||||
Older versions of mermaid will not parse directives because `%%` will comment out the directive. This makes the update backwards-compatible.
|
||||
|
||||
# Init
|
||||
`init`, or `initialize`: the init or initialize directive gives the user the ability to overwrite and change the values for configuration parameters, with respect to the secure array that is in effect.
|
||||
`init`, or `initialize`: this directive gives the user the ability to overwrite and change the values for any configuration parameters not set in the secure array.
|
||||
|
||||
| Parameter | Description |Type | Required | Values|
|
||||
| --- | --- | --- | --- | --- |
|
||||
@@ -67,7 +67,7 @@ The json object that is passed as {**argument** } must be valid, quoted json or
|
||||
|
||||
`%%{init: {"theme": "default", "logLevel": 1 }}%%`
|
||||
|
||||
Configurations that are passed through init cannot change the parameters in secure arrays of higher levels. In the event of a conflict, mermaid will give priority to secure arrays and parse the request, without changing the values of the parameters in conflict.
|
||||
Configurations that are passed through init cannot change the parameters in a secure array at a higher level. In the event of a collision, mermaid will give priority to secure arrays and parse the request without changing the values of those parameters in conflict.
|
||||
|
||||
When deployed within code, init is called before the graph/diagram description.
|
||||
```
|
||||
@@ -93,14 +93,14 @@ When deployed within code, init is called before the graph/diagram description.
|
||||
```note
|
||||
Wrap is a function that is currently only deployable for sequence diagrams.
|
||||
|
||||
wrap respects manually added <br\> so if the user wants to break up their text, they have full control over those breaks by adding their own <br\> tags.
|
||||
Wrap respects a manually added <br\>, so if the user wants to break up their text, they have full control over line breaks by adding <br\> tags.
|
||||
|
||||
It is a non-argument directive and can be executed thusly:
|
||||
|
||||
`%%{wrap}%%` .
|
||||
```
|
||||
|
||||
**an example of text wrapping in a sequence diagram**:
|
||||
**An example of text wrapping in a sequence diagram**:
|
||||
|
||||

|
||||
|
||||
@@ -108,16 +108,16 @@ It is a non-argument directive and can be executed thusly:
|
||||
# Resetting Configurations:
|
||||
There are two more functions in the mermaidAPI that can be called by site owners: **reset** and **globalReset**.
|
||||
|
||||
**reset**: resets the configuration to whatever the last configuration was. This can be done to undo more recent changes to the last mermaidAPI.initialize({...}) configuration.
|
||||
**reset**: resets the configuration to whatever the last configuration was. This can be done to undo more recent changes set from the last mermaidAPI.initialize({...}) configuration.
|
||||
|
||||
**globalReset** will reset both the current configuration AND the site configuration back to the global defaults.
|
||||
|
||||
**Notes**: both reset and globalReset are only available to site owners, as such implementors would have to edit their configs with init.
|
||||
**Notes**: Both `reset` and `globalReset` are only available to site owners, and as such implementors have to edit their configs using `init`.
|
||||
|
||||
# Additional Utils to mermaid
|
||||
• **memoize**: simple caching for computationally expensive functions. It reduces the rendering time for computationally intensive diagrams by about 90%.
|
||||
• **memoize**: simple caching for computationally expensive functions, reducing rendering time by about 90%.
|
||||
|
||||
• **assignWithDepth** - this is an improvement on previous functions with config.js and Object.assign. The purpose of this function is to provide a sane mechanism for merging objects, similar to object.assign, but with depth.
|
||||
• **assignWithDepth** - an improvement on previous functions with config.js and `Object.assign`. The purpose of this function is to provide a sane mechanism for merging objects, similar to `object.assign`, but with depth.
|
||||
|
||||
Example of **assignWithDepth**:
|
||||
|
||||
@@ -128,9 +128,9 @@ Example of **object.Assign**:
|
||||
|
||||

|
||||
|
||||
• **calculateTextDimensions, calculateTextWidth,** and **calculateTextHeight** - for measuring text dimensions, width and height.
|
||||
• **calculateTextDimensions**, **calculateTextWidth**, and **calculateTextHeight** - for measuring text dimensions, width and height.
|
||||
|
||||
**Notes**:For more information on usage, parameters, and return info for these new functions take a look at the jsdocs for them in the utils package.
|
||||
**Notes**: For more information on usage, parameters, and return info for these new functions take a look at the jsdocs for them in the utils package.
|
||||
|
||||
|
||||
# New API Requests Introduced in Version 8.6.0
|
||||
@@ -139,21 +139,21 @@ Example of **object.Assign**:
|
||||
|
||||
| Function | Description | Type | Values |Parameters|Returns|
|
||||
| --------- | ------------------- | ------- | ------------------ | ------------------ | ------------------ |
|
||||
| setSiteConfig|Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array|conf|siteConfig|
|
||||
| `setSiteConfig`|Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array|conf|siteConfig|
|
||||
|
||||
```note
|
||||
Sets the siteConfig. The siteConfig is a protected configuration for repeat use. Calls to reset() will reset
|
||||
the currentConfig to siteConfig. Calls to reset(configApi.defaultConfig) will reset siteConfig and currentConfig
|
||||
to the defaultConfig
|
||||
Note: currentConfig is set in this function
|
||||
Default value: At default, will mirror Global Config
|
||||
Note: currentConfig is set in this function。
|
||||
Default value: will mirror Global Config
|
||||
```
|
||||
|
||||
## getSiteConfig
|
||||
|
||||
| Function | Description | Type | Values |
|
||||
| --------- | ------------------- | ------- | ------------------ |
|
||||
| setSiteConfig|Returns the current siteConfig base configuration | Get Request | Returns Any Values in siteConfig|
|
||||
| `getSiteConfig`|Returns the current `siteConfig` base configuration | Get Request | Returns Any Values in `siteConfig`|
|
||||
|
||||
```note
|
||||
Returns any values in siteConfig.
|
||||
@@ -163,7 +163,7 @@ Returns any values in siteConfig.
|
||||
|
||||
| Function | Description | Type | Values |Parameters|Returns|
|
||||
| --------- | ------------------- | ------- | ------------------ |----------|-------|
|
||||
| setSiteConfig|Sets the siteConfig to desired values | Put Request| Any Values, those in secure array|conf|currentConfig merged with the sanitized conf|
|
||||
| `setConfig`|Sets the `currentConfig` to desired values | Put Request| Any Values, those in secure array|conf|`currentConfig` merged with the sanitized conf|
|
||||
|
||||
```note
|
||||
Sets the currentConfig. The parameter conf is sanitized based on the siteConfig.secure keys. Any
|
||||
@@ -175,7 +175,7 @@ siteConfig value.
|
||||
|
||||
| Function | Description | Type | Return Values |
|
||||
| --------- | ------------------- | ------- | ------------------ |
|
||||
| getConfig |Obtains the currentConfig | Get Request | Any Values from currentConfig|
|
||||
| `getConfig` |Obtains the `currentConfig` | Get Request | Any Values from `currentConfig`|
|
||||
|
||||
|
||||
```note
|
||||
@@ -186,7 +186,7 @@ Returns any values in currentConfig.
|
||||
|
||||
| Function | Description | Type | Values |
|
||||
| --------- | ------------------- | ------- | ------------------ |
|
||||
| sanitize |Sets the siteConfig to desired values. | Put Request(?) |None|
|
||||
| `sanitize` |Sets the `siteConfig` to desired values. | Put Request(?) |None|
|
||||
|
||||
```note
|
||||
modifies options in-place
|
||||
@@ -197,13 +197,13 @@ Ensures options parameter does not attempt to override siteConfig secure keys.
|
||||
|
||||
| Function | Description | Type | Required | Values |Parameter|
|
||||
| --------- | -------------------| ------- | -------- | ------------------ |---------|
|
||||
| reset|Resets currentConfig to conf| Put Request | Required | None| conf|
|
||||
| `reset`|Resets `currentConfig` to conf| Put Request | Required | None| conf|
|
||||
|
||||
## conf
|
||||
|
||||
| Parameter | Description |Type | Required | Values|
|
||||
| --- | --- | --- | --- | --- |
|
||||
| conf| base set of values, which currentConfig could be reset to.| Dictionary | Required | Any Values, with respect to the secure Array|
|
||||
| `conf`| base set of values, which `currentConfig` could be reset to.| Dictionary | Required | Any Values, with respect to the secure Array|
|
||||
|
||||
```note
|
||||
default: current siteConfig (optional, default `getSiteConfig()`)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Change Log
|
||||
|
||||
Here is the list of the newest versions in Descending Order, beginning from the latest version.
|
||||
All changes are in descending order, beginning with the newest (latest) version.
|
||||
|
||||
## Unreleased
|
||||
|
||||
|
||||
@@ -27,10 +27,11 @@ But not having diagrams or docs ruins productivity and hurts organizational lear
|
||||
Mermaid addresses this problem by enabling users to create easily modifiable diagrams, it can also be made part of production scripts (and other pieces of code).<br/>
|
||||
<br/>
|
||||
Mermaid allows even non-programmers to easily create detailed and diagrams through the [Mermaid Live Editor](https://mermaid.live/).<br/>
|
||||
[Tutorials](./docs/Tutorials.md) has video tutorials.
|
||||
Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./docs/integrations.md).
|
||||
[Tutorials](./Tutorials.md) has video tutorials.
|
||||
Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./integrations.md).
|
||||
|
||||
For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](./docs/n00b-overview.md) and [Usage](./docs/usage.md).
|
||||
|
||||
For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](./n00b-overview.md) and [Usage](./usage.md).
|
||||
|
||||
🌐 [CDN](https://unpkg.com/mermaid/) | 📖 [Documentation](https://mermaidjs.github.io) | 🙌 [Contribution](https://github.com/mermaid-js/mermaid/blob/develop/docs/development.md) | 📜 [Version Log](./CHANGELOG.md) | 🔌 [Plug-Ins](./integrations.md)
|
||||
|
||||
|
||||
@@ -72,9 +72,9 @@ Theme , the CSS style sheet
|
||||
|
||||
## securityLevel
|
||||
|
||||
| Parameter | Description | Type | Required | Values |
|
||||
| ------------- | --------------------------------- | ------ | -------- | ------------------------------- |
|
||||
| securitylevel | Level of trust for parsed diagram | string | Required | 'strict', 'loose', 'antiscript' |
|
||||
| Parameter | Description | Type | Required | Values |
|
||||
| ------------- | --------------------------------- | ------ | -------- | ------------------------------------------ |
|
||||
| securityLevel | Level of trust for parsed diagram | string | Required | 'sandbox', 'strict', 'loose', 'antiscript' |
|
||||
|
||||
**Notes**:
|
||||
|
||||
@@ -82,6 +82,9 @@ Theme , the CSS style sheet
|
||||
- **loose**: tags in text are allowed, click functionality is enabled
|
||||
- **antiscript**: html tags in text are allowed, (only script element is removed), click
|
||||
functionality is enabled
|
||||
- **sandbox**: With this security level all rendering takes place in a sandboxed iframe. This
|
||||
prevent any JavaScript from running in the context. This may hinder interactive functionality
|
||||
of the diagram like scripts, popups in sequence diagram or links to other tabs/targets etc.
|
||||
|
||||
## startOnLoad
|
||||
|
||||
@@ -1401,6 +1404,15 @@ This sets the auto-wrap padding for the diagram (sides only)
|
||||
|
||||
**Notes:** Default value: 0.
|
||||
|
||||
## parse
|
||||
|
||||
### Parameters
|
||||
|
||||
- `text`
|
||||
- `dia`
|
||||
|
||||
Returns **any**
|
||||
|
||||
## setSiteConfig
|
||||
|
||||
## setSiteConfig
|
||||
@@ -1420,14 +1432,6 @@ function _Default value: At default, will mirror Global Config_
|
||||
|
||||
Returns **[object][5]** The siteConfig
|
||||
|
||||
## parse
|
||||
|
||||
### Parameters
|
||||
|
||||
- `text`
|
||||
|
||||
Returns **any**
|
||||
|
||||
## getSiteConfig
|
||||
|
||||
## getSiteConfig
|
||||
@@ -1485,6 +1489,34 @@ options in-place
|
||||
|
||||
- `options` **any** The potential setConfig parameter
|
||||
|
||||
## render
|
||||
|
||||
Function that renders an svg with a graph from a chart definition. Usage example below.
|
||||
|
||||
```javascript
|
||||
mermaidAPI.initialize({
|
||||
startOnLoad: true,
|
||||
});
|
||||
$(function () {
|
||||
const graphDefinition = 'graph TB\na-->b';
|
||||
const cb = function (svgGraph) {
|
||||
console.log(svgGraph);
|
||||
};
|
||||
mermaidAPI.render('id1', graphDefinition, cb);
|
||||
});
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
- `id` **any** The id of the element to be rendered
|
||||
- `_txt` **any** The graph definition
|
||||
- `cb` **any** Callback which is called after rendering is finished with the svg code as inparam.
|
||||
- `container` **any** Selector to element in which a div with the graph temporarily will be
|
||||
inserted. If one is provided a hidden div will be inserted in the body of the page instead. The
|
||||
element will be removed when rendering is completed.
|
||||
|
||||
Returns **any**
|
||||
|
||||
## addDirective
|
||||
|
||||
Pushes in a directive to the configuration
|
||||
@@ -1509,44 +1541,12 @@ Pushes in a directive to the configuration
|
||||
|
||||
**Notes**: (default: current siteConfig ) (optional, default `getSiteConfig()`)
|
||||
|
||||
## render
|
||||
|
||||
Function that renders an svg with a graph from a chart definition. Usage example below.
|
||||
|
||||
```javascript
|
||||
mermaidAPI.initialize({
|
||||
startOnLoad: true,
|
||||
});
|
||||
$(function () {
|
||||
const graphDefinition = 'graph TB\na-->b';
|
||||
const cb = function (svgGraph) {
|
||||
console.log(svgGraph);
|
||||
};
|
||||
mermaidAPI.render('id1', graphDefinition, cb);
|
||||
});
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
- `id` **any** The id of the element to be rendered
|
||||
- `_txt` **any** The graph definition
|
||||
- `cb` **any** Callback which is called after rendering is finished with the svg code as inparam.
|
||||
- `container` **any** Selector to element in which a div with the graph temporarily will be
|
||||
inserted. In one is provided a hidden div will be inserted in the body of the page instead. The
|
||||
element will be removed when rendering is completed.
|
||||
|
||||
Returns **any**
|
||||
|
||||
## updateRendererConfigs
|
||||
|
||||
### Parameters
|
||||
|
||||
- `conf` **any**
|
||||
|
||||
## reinitialize
|
||||
|
||||
To be removed
|
||||
|
||||
## initialize
|
||||
|
||||
### Parameters
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
- 📊 Diagram Syntax
|
||||
- [Flowchart](flowchart.md)
|
||||
- [Sequence diagram](sequenceDiagram.md)
|
||||
- [Sequence Diagram](sequenceDiagram.md)
|
||||
- [Class Diagram](classDiagram.md)
|
||||
- [State Diagram](stateDiagram.md)
|
||||
- [Entity Relationship Diagram](entityRelationshipDiagram.md)
|
||||
@@ -25,6 +25,7 @@
|
||||
- [Mermaid API Configuration](Setup.md)
|
||||
- [Directives](directives.md)
|
||||
- [Theming](theming.md)
|
||||
- [Accessibility](accessibility.md)
|
||||
- [Mermaid CLI](mermaidCLI.md)
|
||||
- [Advanced usage](n00b-advanced.md)
|
||||
|
||||
|
||||
214
docs/accessibility.md
Normal file
214
docs/accessibility.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# Accessibility Options
|
||||
|
||||
**Edit this Page** [](https://github.com/mermaid-js/mermaid/blob/develop/docs/accessibility.md)
|
||||
|
||||
## Accessibility
|
||||
Now with Mermaid library is in much wider use, we have started to work towwards more accessible features, based on the feedback from the community.
|
||||
|
||||
TO begin with, we have added a new feature to Mermaid library, which is to support accessibility options, **Accessibility Title** and **Accessibility Description**.
|
||||
|
||||
This support for accessibility options is available for all the diagrams/chart types. Also, we have tired to keep the same format for the accessibility options, so that it is easy to understand and maintain.
|
||||
|
||||
|
||||
## Defining Accessibility Options
|
||||
|
||||
### Single line accessibility values
|
||||
The diagram authors can now add the accessibility options in the diagram definition, using the `accTitle` and `accDescr` keywords, where each keyword is followed by `:` and the string value for title and description like:
|
||||
- `accTitle: "Your Accessibility Title"` or
|
||||
- `accDescr: "Your Accessibility Description"`
|
||||
|
||||
**When these two options are defined, they will add a coressponding `<title>` and `<desc>` tag in the SVG.**
|
||||
|
||||
Let us take a look at the following example with a flowchart diagram:
|
||||
|
||||
```mermaid-example
|
||||
graph LR
|
||||
accTitle: Big decisions
|
||||
accDescr: Flow chart of the decision making process
|
||||
A[Hard] -->|Text| B(Round)
|
||||
B --> C{Decision}
|
||||
C -->|One| D[Result 1]
|
||||
|
||||
```
|
||||
See in the code snippet above, the `accTitle` and `accDescr` are defined in the diagram definition. They result in the following tags in SVG code:
|
||||
|
||||

|
||||
|
||||
|
||||
### Multi-line Accessibility title/description
|
||||
You can also define the accessibility options in a multi-line format, where the keyword is followed by opening curly bracket `{` and then mutltile lines, followed by a closing `}`.
|
||||
|
||||
`accTitle: My single line title value` (***single line format***)
|
||||
|
||||
vs
|
||||
|
||||
`accDescr: {
|
||||
My multi-line description
|
||||
of the diagram
|
||||
}` (***multi-line format***)
|
||||
|
||||
Let us look at it in the following example, with same flowchart:
|
||||
```mermaid-example
|
||||
graph LR
|
||||
accTitle: Big decisions
|
||||
|
||||
accDescr {
|
||||
My multi-line description
|
||||
of the diagram
|
||||
}
|
||||
|
||||
A[Hard] -->|Text| B(Round)
|
||||
B --> C{Decision}
|
||||
C -->|One| D[Result 1]
|
||||
|
||||
```
|
||||
See in the code snippet above, the `accTitle` and `accDescr` are defined in the diagram definition. They result in the following tags in SVG code:
|
||||
|
||||

|
||||
|
||||
### Sample Code Snippet for other diagram types
|
||||
|
||||
#### Sequence Diagram
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
accTitle: My Sequence Diagram
|
||||
accDescr: My Sequence Diagram Description
|
||||
|
||||
Alice->>John: Hello John, how are you?
|
||||
John-->>Alice: Great!
|
||||
Alice-)John: See you later!
|
||||
```
|
||||
|
||||
#### Class Diagram
|
||||
|
||||
```mermaid-example
|
||||
classDiagram
|
||||
accTitle: My Class Diagram
|
||||
accDescr: My Class Diagram Description
|
||||
|
||||
Vehicle <|-- Car
|
||||
```
|
||||
|
||||
#### State Diagram
|
||||
|
||||
```mermaid-example
|
||||
stateDiagram
|
||||
accTitle: My State Diagram
|
||||
accDescr: My State Diagram Description
|
||||
|
||||
s1 --> s2
|
||||
|
||||
```
|
||||
|
||||
#### Entity Relationship Diagram
|
||||
|
||||
```mermaid-example
|
||||
erDiagram
|
||||
accTitle: My Entity Relationship Diagram
|
||||
accDescr: My Entity Relationship Diagram Description
|
||||
|
||||
CUSTOMER ||--o{ ORDER : places
|
||||
ORDER ||--|{ LINE-ITEM : contains
|
||||
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
|
||||
|
||||
```
|
||||
|
||||
#### User Journey Diagram
|
||||
|
||||
```mermaid-example
|
||||
journey
|
||||
accTitle: My User Journey Diagram
|
||||
accDescr: My User Journey Diagram Description
|
||||
|
||||
title My working day
|
||||
section Go to work
|
||||
Make tea: 5: Me
|
||||
Go upstairs: 3: Me
|
||||
Do work: 1: Me, Cat
|
||||
section Go home
|
||||
Go downstairs: 5: Me
|
||||
Sit down: 5: Me
|
||||
|
||||
```
|
||||
|
||||
#### Gantt Chart
|
||||
|
||||
```mermaid-example
|
||||
gantt
|
||||
accTitle: My Gantt Chart Accessibility Title
|
||||
accDescr: My Gantt Chart Accessibility Description
|
||||
|
||||
title A Gantt Diagram
|
||||
dateFormat YYYY-MM-DD
|
||||
section Section
|
||||
A task :a1, 2014-01-01, 30d
|
||||
Another task :after a1 , 20d
|
||||
section Another
|
||||
Task in sec :2014-01-12 , 12d
|
||||
another task : 24d
|
||||
|
||||
```
|
||||
|
||||
#### Pie Chart
|
||||
|
||||
```mermaid-example
|
||||
pie
|
||||
accTitle: My Pie Chart Accessibility Title
|
||||
accDescr: My Pie Chart Accessibility Description
|
||||
|
||||
title Key elements in Product X
|
||||
"Calcium" : 42.96
|
||||
"Potassium" : 50.05
|
||||
"Magnesium" : 10.01
|
||||
"Iron" : 5
|
||||
|
||||
```
|
||||
#### Requirement Diagram
|
||||
|
||||
```mermaid-example
|
||||
requirementDiagram
|
||||
accTitle: My Requirement Diagram
|
||||
accDescr: My Requirement Diagram Description
|
||||
|
||||
requirement test_req {
|
||||
id: 1
|
||||
text: the test text.
|
||||
risk: high
|
||||
verifymethod: test
|
||||
}
|
||||
|
||||
element test_entity {
|
||||
type: simulation
|
||||
}
|
||||
|
||||
test_entity - satisfies -> test_req
|
||||
|
||||
```
|
||||
|
||||
#### Gitgraph
|
||||
|
||||
```mermaid-example
|
||||
gitGraph
|
||||
accTitle: My Gitgraph Accessibility Title
|
||||
accDescr: My Gitgraph Accessibility Description
|
||||
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ mermaid.initialize({
|
||||
|
||||
## #2
|
||||
|
||||
In old versions you need to add CSS file to your HTML:
|
||||
In old versions you needed to reference a CSS file in your HTML:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="mermaid.min.css">
|
||||
@@ -36,9 +36,9 @@ or
|
||||
<link rel="stylesheet" href="mermaid.forest.min.css">
|
||||
```
|
||||
|
||||
Now it is not needed to do so. And there are no more CSS files in distribution files.
|
||||
Now it is not needed, and there are no more CSS files in the distribution files.
|
||||
|
||||
You just
|
||||
You just:
|
||||
|
||||
```javascript
|
||||
mermaid.initialize({
|
||||
@@ -46,6 +46,4 @@ mermaid.initialize({
|
||||
})
|
||||
```
|
||||
|
||||
and it works like a charm.
|
||||
|
||||
This is because now the CSS is inline with SVG for portability.
|
||||
and it works like a charm because now the CSS is inline with the SVG to allow simpler portability.
|
||||
|
||||
@@ -260,7 +260,7 @@ UpdateRelStyle(customerA, bankA, $offsetY="60")
|
||||
System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
|
||||
|
||||
Container_Boundary(api, "API Application") {
|
||||
Component(sign, "Sign In Controller", "MVC Rest Controlle", "Allows users to sign in to the internet banking system")
|
||||
Component(sign, "Sign In Controller", "MVC Rest Controller", "Allows users to sign in to the internet banking system")
|
||||
Component(accounts, "Accounts Summary Controller", "MVC Rest Controller", "Provides customers with a summary of their bank accounts")
|
||||
Component(security, "Security Component", "Spring Bean", "Provides functionality related to singing in, changing passwords, etc.")
|
||||
Component(mbsfacade, "Mainframe Banking System Facade", "Spring Bean", "A facade onto the mainframe banking system.")
|
||||
@@ -364,4 +364,4 @@ UpdateRelStyle(customerA, bankA, $offsetY="60")
|
||||
UpdateRelStyle(api, db2, $offsetX="-40", $offsetY="-20")
|
||||
UpdateRelStyle(db, db2, $offsetY="-10")
|
||||
|
||||
```
|
||||
```
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
> "In software engineering, a class diagram in the Unified Modeling Language (UML) is a type of static structure diagram that describes the structure of a system by showing the system's classes, their attributes, operations (or methods), and the relationships among objects."
|
||||
> Wikipedia
|
||||
|
||||
The class diagram is the main building block of object-oriented modeling. It is used for general conceptual modeling of the structure of the application, and for detailed modeling translating the models into programming code. Class diagrams can also be used for data modeling. The classes in a class diagram represent both the main elements, interactions in the application, and the classes to be programmed.
|
||||
The class diagram is the main building block of object-oriented modeling. It is used for general conceptual modeling of the structure of the application, and for detailed modeling to translate the models into programming code. Class diagrams can also be used for data modeling. The classes in a class diagram represent both the main elements, interactions in the application, and the classes to be programmed.
|
||||
|
||||
Mermaid can render class diagrams.
|
||||
|
||||
@@ -56,8 +56,8 @@ classDiagram
|
||||
|
||||
There are two ways to define a class:
|
||||
|
||||
- Explicitly defining a class using keyword **class** like `class Animal`. This defines the Animal class
|
||||
- Define two classes via a **relationship** between them `Vehicle <|-- Car`. This defines two classes Vehicle and Car along with their relationship.
|
||||
- Explicitly using keyword **class** like `class Animal` which would define the Animal class.
|
||||
- Via a **relationship** which defines two classes at a time along with their relationship. For instance, `Vehicle <|-- Car`.
|
||||
|
||||
```mermaid-example
|
||||
classDiagram
|
||||
@@ -65,13 +65,13 @@ classDiagram
|
||||
Vehicle <|-- Car
|
||||
```
|
||||
|
||||
Naming convention: a class name should be composed of alphanumeric (unicode allowed) and underscore characters.
|
||||
Naming convention: a class name should be composed only of alphanumeric characters (including unicode), and underscores.
|
||||
|
||||
## Defining Members of a class
|
||||
|
||||
UML provides mechanisms to represent class members, such as attributes and methods, and additional information about them.
|
||||
UML provides mechanisms to represent class members such as attributes and methods, as well as additional information about them.
|
||||
|
||||
Mermaid distinguishes between attributes and functions/methods based on if the **parenthesis** `()` are present or not. The ones with `()` are treated as functions/methods, and others as attributes.
|
||||
Mermaid distinguishes between attributes and functions/methods based on if the **parenthesis** `()` are present or not. The ones with `()` are treated as functions/methods, and all others as attributes.
|
||||
|
||||
There are two ways to define the members of a class, and regardless of whichever syntax is used to define the members, the output will still be same. The two different ways are :
|
||||
|
||||
@@ -100,8 +100,7 @@ class BankAccount{
|
||||
|
||||
#### Return Type
|
||||
|
||||
Optionally you can end the method/function definition with the data type that will be returned (note: there must be a space between the final `)` of the method definition and return type
|
||||
example:
|
||||
Optionally you can end a method/function definition with the data type that will be returned (note: there must be a space between the final `)` and the return type). An example:
|
||||
|
||||
```mermaid-example
|
||||
classDiagram
|
||||
@@ -115,9 +114,9 @@ class BankAccount{
|
||||
|
||||
#### Generic Types
|
||||
|
||||
Members can be defined using generic types, such as `List<int>`, for fields, parameters and return types by enclosing the type within `~` (**tilde**). Note: **nested** type declarations (such as `List<List<int>>`) are not currently supported
|
||||
Members can be defined using generic types, such as `List<int>`, for fields, parameters, and return types by enclosing the type within `~` (**tilde**). Note: **nested** type declarations such as `List<List<int>>` are not currently supported.
|
||||
|
||||
This can be done as part of either class definition method:
|
||||
Generics can be represented as part of a class definition and also in the parameters or the return value of a method/function:
|
||||
|
||||
```mermaid-example
|
||||
classDiagram
|
||||
@@ -135,26 +134,25 @@ Square : +getMessages() List~string~
|
||||
|
||||
#### Return Type
|
||||
|
||||
Optionally you can end the method/function definition with the data type that will be returned
|
||||
Optionally you can end the method/function definition with the data type that will be returned.
|
||||
|
||||
#### Visibility
|
||||
|
||||
To specify the visibility of a class member (i.e. any attribute or method), these notations may be placed before the member's name, but it is optional:
|
||||
To describe the visibility (or encapsulation) of an attribute or method/function that is a part of a class (i.e. a class member), optional notation may be placed before that members' name:
|
||||
|
||||
- `+` Public
|
||||
- `-` Private
|
||||
- `#` Protected
|
||||
- `~` Package/Internal
|
||||
|
||||
> _note_ you can also include additional _classifiers_ to a method definition by adding the following notations to the end of the method, i.e.: after the `()`:
|
||||
> _note_ you can also include additional _classifiers_ to a method definition by adding the following notation to the _end_ of the method, i.e.: after the `()`:
|
||||
> - `*` Abstract e.g.: `someAbstractMethod()*`
|
||||
> - `$` Static e.g.: `someStaticMethod()$`
|
||||
|
||||
> _note_ you can also include additional _classifiers_ to a field definition by adding the following notations to the end of the field name:
|
||||
> _note_ you can also include additional _classifiers_ to a field definition by adding the following notation to the end of its name:
|
||||
> - `$` Static e.g.: `String someField$`
|
||||
|
||||
|
||||
|
||||
## Defining Relationship
|
||||
|
||||
A relationship is a general term covering the specific types of logical connections found on class and object diagrams.
|
||||
@@ -163,7 +161,7 @@ A relationship is a general term covering the specific types of logical connecti
|
||||
[classA][Arrow][ClassB]
|
||||
```
|
||||
|
||||
There are different types of relations defined for classes under UML which are currently supported:
|
||||
There are eight different types of relations defined for classes under UML which are currently supported:
|
||||
|
||||
| Type | Description |
|
||||
| ----- | ------------- |
|
||||
@@ -189,7 +187,7 @@ classO .. classP
|
||||
|
||||
```
|
||||
|
||||
We can use the labels to describe nature of relation between two classes. Also, arrowheads can be used in opposite directions as well :
|
||||
We can use the labels to describe the nature of the relation between two classes. Also, arrowheads can be used in the opposite direction as well:
|
||||
|
||||
```mermaid-example
|
||||
classDiagram
|
||||
@@ -206,7 +204,7 @@ classO .. classP : Link(Dashed)
|
||||
|
||||
### Labels on Relations
|
||||
|
||||
It is possible to add a label text to a relation:
|
||||
It is possible to add label text to a relation:
|
||||
|
||||
```
|
||||
[classA][Arrow][ClassB]:LabelText
|
||||
@@ -221,7 +219,7 @@ classE o-- classF : aggregation
|
||||
|
||||
### Two-way relations
|
||||
|
||||
Relations can go in multiple ways:
|
||||
Relations can logically represent an N:M association:
|
||||
|
||||
```mmd
|
||||
classDiagram
|
||||
@@ -255,9 +253,9 @@ And `Link` can be one of:
|
||||
|
||||
## Cardinality / Multiplicity on relations
|
||||
|
||||
Multiplicity or cardinality in class diagrams indicates the number of instances of one class linked to one instance of the other class. For example, one company will have one or more employees, but each employee works for just one company.
|
||||
Multiplicity or cardinality in class diagrams indicates the number of instances of one class that can be linked to an instance of the other class. For example, each company will have one or more employees (not zero), and each employee currently works for zero or one companies.
|
||||
|
||||
Multiplicity notations are placed near the ends of an association.
|
||||
Multiplicity notations are placed near the end of an association.
|
||||
|
||||
The different cardinality options are :
|
||||
|
||||
@@ -269,7 +267,7 @@ The different cardinality options are :
|
||||
- `0..n` zero to n {where n>1}
|
||||
- `1..n` one to n {where n>1}
|
||||
|
||||
Cardinality can be easily defined by placing cardinality text within quotes `"` before(optional) and after(optional) a given arrow.
|
||||
Cardinality can be easily defined by placing the text option within quotes `"` before or after a given arrow. For example:
|
||||
|
||||
```
|
||||
[classA] "cardinality1" [Arrow] "cardinality2" [ClassB]:LabelText
|
||||
@@ -284,16 +282,16 @@ classDiagram
|
||||
|
||||
## Annotations on classes
|
||||
|
||||
It is possible to annotate classes with a specific marker text which is like meta-data for the class, giving a clear indication about its nature. Some common annotations examples could be:
|
||||
It is possible to annotate classes with markers to provide additional metadata about the class. This can give a clearer indication about its nature. Some common annotations include:
|
||||
|
||||
- `<<Interface>>` To represent an Interface class
|
||||
- `<<abstract>>` To represent an abstract class
|
||||
- `<<Abstract>>` To represent an abstract class
|
||||
- `<<Service>>` To represent a service class
|
||||
- `<<enumeration>>` To represent an enum
|
||||
- `<<Enumeration>>` To represent an enum
|
||||
|
||||
Annotations are defined within the opening `<<` and closing `>>`. There are two ways to add an annotation to a class and regardless of the syntax used output will be same. The two ways are :
|
||||
Annotations are defined within the opening `<<` and closing `>>`. There are two ways to add an annotation to a class, and either way the output will be same:
|
||||
|
||||
- In a **_separate line_** after a class is defined. For example:
|
||||
- In a **_separate line_** after a class is defined:
|
||||
|
||||
```mermaid-example
|
||||
classDiagram
|
||||
@@ -303,7 +301,7 @@ Shape : noOfVertices
|
||||
Shape : draw()
|
||||
```
|
||||
|
||||
- In a **_nested structure_** along with class definition. For example:
|
||||
- In a **_nested structure_** along with the class definition:
|
||||
|
||||
```mermaid-example
|
||||
classDiagram
|
||||
@@ -325,7 +323,7 @@ class Color{
|
||||
|
||||
## Comments
|
||||
|
||||
Comments can be entered within a class diagram, which will be ignored by the parser. Comments need to be on their own line, and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any class diagram syntax
|
||||
Comments can be entered within a class diagram, which will be ignored by the parser. Comments need to be on their own line, and must be prefaced with `%%` (double percent signs). Any text until the next newline will be treated as a comment, including any class diagram syntax.
|
||||
|
||||
```mmd
|
||||
classDiagram
|
||||
@@ -335,12 +333,11 @@ class Shape{
|
||||
noOfVertices
|
||||
draw()
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Setting the direction of the diagram
|
||||
|
||||
With class diagrams you can use the direction statement to set the direction which the diagram will render like in this example.
|
||||
With class diagrams you can use the direction statement to set the direction in which the diagram will render:
|
||||
|
||||
```mermaid-example
|
||||
classDiagram
|
||||
@@ -362,7 +359,7 @@ classDiagram
|
||||
|
||||
## Interaction
|
||||
|
||||
It is possible to bind a click event to a node, the click can lead to either a javascript callback or to a link which will be opened in a new browser tab. **Note**: This functionality is disabled when using `securityLevel='strict'` and enabled when using `securityLevel='loose'`.
|
||||
It is possible to bind a click event to a node. The click can lead to either a javascript callback or to a link which will be opened in a new browser tab. **Note**: This functionality is disabled when using `securityLevel='strict'` and enabled when using `securityLevel='loose'`.
|
||||
|
||||
You would define these actions on a separate line after all classes have been declared.
|
||||
|
||||
@@ -421,7 +418,7 @@ classDiagram
|
||||
|
||||
> **Success** The tooltip functionality and the ability to link to urls are available from version 0.5.2.
|
||||
|
||||
Beginners tip, a full example using interactive links in an html context:
|
||||
Beginner's tip—a full example using interactive links in an HTML page:
|
||||
|
||||
```html
|
||||
<body>
|
||||
@@ -469,8 +466,7 @@ Beginners tip, a full example using interactive links in an html context:
|
||||
|
||||
### Styling a node
|
||||
|
||||
It is possible to apply specific styles such as a thicker border or a different background color to individual nodes. This is done by predefining classes in css styles that can be applied from the graph definition as in the example
|
||||
below:
|
||||
It is possible to apply specific styles such as a thicker border or a different background color to individual nodes. This is done by predefining classes in css styles that can be applied from the graph definition:
|
||||
|
||||
```html
|
||||
<style>
|
||||
@@ -482,7 +478,7 @@ below:
|
||||
</style>
|
||||
```
|
||||
|
||||
Then attaching that class to a specific node as per below:
|
||||
Then attaching that class to a specific node:
|
||||
|
||||
```
|
||||
cssClass "nodeId1" cssClass;
|
||||
@@ -494,7 +490,7 @@ It is also possible to attach a class to a list of nodes in one statement:
|
||||
cssClass "nodeId1,nodeId2" cssClass;
|
||||
```
|
||||
|
||||
A shorter form of adding a class is to attach the classname to the node using the `:::` operator as per below:
|
||||
A shorter form of adding a class is to attach the classname to the node using the `:::` operator:
|
||||
|
||||
```mmd
|
||||
classDiagram
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Configuration
|
||||
|
||||
When mermaid starts configuration is extracted to a configuration to be used for a diagram. There are 3 sources for configuration:
|
||||
When mermaid starts, configuration is extracted to determine a configuration to be used for a diagram. There are 3 sources for configuration:
|
||||
|
||||
* The default configuration
|
||||
* Overrides on the site level is set by the initialize call and will be applied to all diagrams in the site/app. The term for this is the **siteConfig**.
|
||||
* Directives - diagram authors can update select configuration parameters directly in the diagram code via directives and these are applied to the render config.
|
||||
* Overrides at the site level are set by the initialize call, and will be applied to all diagrams in the site/app. The term for this is the **siteConfig**.
|
||||
* Directives - diagram authors can update select configuration parameters directly in the diagram code via directives. These are applied to the render config.
|
||||
|
||||
**The render config** is configuration that is used when rendering by applying these configurations.
|
||||
|
||||
@@ -21,8 +21,8 @@ sequenceDiagram
|
||||
|
||||
## Initialize
|
||||
|
||||
Initialize call is called **only once**. It is called by the site integrator in order to override the default configuration on a site level.
|
||||
The initialize call is applied **only once**. It is called by the site integrator in order to override the default configuration at a site level.
|
||||
|
||||
## configApi.reset
|
||||
|
||||
This method resets the configuration for a diagram to the site configuration, the configuration provided by the site integrator. Before each rendering of a diagram reset is called in the very beginning of render.
|
||||
This method resets the configuration for a diagram to the overall site configuration, which is the configuration provided by the site integrator. Before each rendering of a diagram, reset is called at the very beginning.
|
||||
|
||||
@@ -7,16 +7,14 @@ title: Flowchart
|
||||
|
||||
## Graph
|
||||
|
||||
This statement declares the direction of the Flowchart.
|
||||
|
||||
This declares the graph is oriented from top to bottom (`TD` or `TB`).
|
||||
This statement declares the direction of the flowchart, either from top to bottom (`TD` or `TB`):
|
||||
|
||||
```mermaid-example
|
||||
graph TD
|
||||
Start --> Stop
|
||||
```
|
||||
|
||||
This declares the graph is oriented from left to right (`LR`).
|
||||
or left to right (`LR`):
|
||||
|
||||
```mermaid-example
|
||||
graph LR
|
||||
@@ -28,22 +26,21 @@ graph LR
|
||||
Possible FlowChart orientations are:
|
||||
|
||||
* TB - top to bottom
|
||||
* TD - top-down/ same as top to bottom
|
||||
* TD - top-down (same as top to bottom)
|
||||
* BT - bottom to top
|
||||
* RL - right to left
|
||||
* LR - left to right
|
||||
|
||||
|
||||
|
||||
## Flowcharts
|
||||
|
||||
This renders a flowchart that allows for features such as: more arrow types, multi directional arrows, and linking to and from subgraphs.
|
||||
|
||||
Apart from the graph type, the syntax is the same. This is currently experimental but when the beta period is over, both the graph and flowchart keywords will render in the new way. This means it is ok to start beta testing flowcharts.
|
||||
Apart from the graph type, the syntax is the same. This is currently experimental. When the beta period is over, both the graph and flowchart keywords will render in this new way. At this point it is OK to start beta testing flowcharts.
|
||||
|
||||
> **Important note** Do not type the word "end" as a Flowchart node. Capitalize all or any one the letters to keep the flowchart from breaking, i.e, "End" or "END". Or you can apply this [workaround](https://github.com/mermaid-js/mermaid/issues/1444#issuecomment-639528897).**
|
||||
|
||||
## Nodes & shapes
|
||||
## Nodes and shapes
|
||||
|
||||
### A node (default)
|
||||
|
||||
@@ -56,9 +53,9 @@ graph LR
|
||||
|
||||
### A node with text
|
||||
|
||||
It is also possible to set text in the box that differs from the id. If this is done several times, it is the last text
|
||||
found for the node that will be used. Also if you define edges for the node later on, you can omit text definitions. The
|
||||
one previously defined will be used when rendering the box.
|
||||
It is also possible to set text in the box that differs from the id. If this is done several times, only the last text
|
||||
found for the node will be rendered. Also if you define edges for the node later on, you can omit text definitions. The
|
||||
text previously defined will be used when rendering the box.
|
||||
|
||||
```mermaid-example
|
||||
graph LR
|
||||
@@ -108,7 +105,7 @@ graph LR
|
||||
graph LR
|
||||
id1>This is the text in the box]
|
||||
```
|
||||
Currently only the shape above is possible and not its mirror. *This might change with future releases.*
|
||||
Currently it is only possible to render the shape above, and not its mirror. *This might change with future releases.*
|
||||
|
||||
### A node (rhombus)
|
||||
|
||||
@@ -117,7 +114,7 @@ graph LR
|
||||
id1{This is the text in the box}
|
||||
```
|
||||
|
||||
### A hexagon node
|
||||
### A hexagonal node
|
||||
|
||||
```mermaid-example
|
||||
graph LR
|
||||
@@ -152,16 +149,16 @@ graph TD
|
||||
|
||||
## Links between nodes
|
||||
|
||||
Nodes can be connected with links/edges. It is possible to have different types of links or attach a text string to a link.
|
||||
Nodes can be connected with links/edges. It is possible to have different types of links, or attach a text string on a link.
|
||||
|
||||
### A link with arrow head
|
||||
### Link with arrow head
|
||||
|
||||
```mermaid-example
|
||||
graph LR
|
||||
A-->B
|
||||
```
|
||||
|
||||
### An open link
|
||||
### Open link
|
||||
|
||||
```mermaid-example
|
||||
graph LR
|
||||
@@ -182,7 +179,7 @@ graph LR
|
||||
A---|This is the text|B
|
||||
```
|
||||
|
||||
### A link with arrow head and text
|
||||
### Link with arrow head and text
|
||||
|
||||
```mermaid-example
|
||||
graph LR
|
||||
@@ -226,7 +223,7 @@ graph LR
|
||||
|
||||
### Chaining of links
|
||||
|
||||
It is possible to declare many links in the same line as per below:
|
||||
It is possible to declare many links on the same line as per below:
|
||||
```mermaid-example
|
||||
graph LR
|
||||
A -- text --> B -- text2 --> C
|
||||
@@ -243,10 +240,7 @@ You can then describe dependencies in a very expressive way. Like the one-liner
|
||||
graph TB
|
||||
A & B--> C & D
|
||||
```
|
||||
If you describe the same diagram using the the basic syntax, it will take four lines. A
|
||||
word of warning, one could go overboard with this making the graph harder to read in
|
||||
markdown form. The Swedish word `lagom` comes to mind. It means, not too much and not too little.
|
||||
This goes for expressive syntaxes as well.
|
||||
If you describe the same diagram using the the basic syntax, it will take four lines:
|
||||
```mmd
|
||||
graph TB
|
||||
A --> C
|
||||
@@ -254,6 +248,9 @@ graph TB
|
||||
B --> C
|
||||
B --> D
|
||||
```
|
||||
A word of warning, one could go overboard with this, making the graph harder to read in
|
||||
markdown form. The Swedish word `lagom` comes to mind. It means, not too much and not too little.
|
||||
This goes for expressive syntaxes as well.
|
||||
|
||||
### New arrow types
|
||||
|
||||
@@ -265,7 +262,6 @@ flowchart LR
|
||||
B --x C
|
||||
```
|
||||
|
||||
|
||||
### Multi directional arrows
|
||||
|
||||
When using flowchart instead of graph there is the possibility to use multidirectional arrows.
|
||||
@@ -297,8 +293,8 @@ graph TD
|
||||
B ---->|No| E[End];
|
||||
```
|
||||
|
||||
> **Note** Links may still be made longer than the requested number of ranks
|
||||
> by the rendering engine to accommodate other requests.
|
||||
> **Note** The rendering engine may cause some links to be longer than
|
||||
> the number of ranks requested in order to accommodate the overall topology.
|
||||
|
||||
When the link label is written in the middle of the link, the extra dashes must
|
||||
be added on the right side of the link. The following example is equivalent to
|
||||
@@ -327,7 +323,7 @@ as summed up in the following table:
|
||||
|
||||
## Special characters that break syntax
|
||||
|
||||
It is possible to put text within quotes in order to render more troublesome characters. As in the example below:
|
||||
Use quotes around text in order to render more troublesome characters, as in the example below:
|
||||
|
||||
```mermaid-example
|
||||
graph LR
|
||||
@@ -336,7 +332,7 @@ graph LR
|
||||
|
||||
### Entity codes to escape characters
|
||||
|
||||
It is possible to escape characters using the syntax exemplified here.
|
||||
Special characters (including Unicode) can be included by using HTML escaping syntax:
|
||||
|
||||
```mermaid-example
|
||||
graph LR
|
||||
@@ -351,7 +347,7 @@ subgraph title
|
||||
end
|
||||
```
|
||||
|
||||
An example below:
|
||||
An example:
|
||||
|
||||
```mermaid-example
|
||||
graph TB
|
||||
@@ -367,7 +363,7 @@ graph TB
|
||||
end
|
||||
```
|
||||
|
||||
You can also set an explicit id for the subgraph.
|
||||
You can also set an explicit id for the subgraph:
|
||||
|
||||
```mermaid-example
|
||||
graph TB
|
||||
@@ -377,9 +373,9 @@ graph TB
|
||||
end
|
||||
```
|
||||
|
||||
## flowcharts
|
||||
## Flowcharts
|
||||
|
||||
With the graphtype flowchart it is also possible to set edges to and from subgraphs as in the graph below.
|
||||
With the graphtype `flowchart` it is also possible to set edges to and from subgraphs:
|
||||
|
||||
```mermaid-example
|
||||
flowchart TB
|
||||
@@ -400,7 +396,7 @@ flowchart TB
|
||||
|
||||
## Interaction
|
||||
|
||||
It is possible to bind a click event to a node, the click can lead to either a JavaScript callback or to a link which will be opened in a new browser tab. **Note**: This functionality is disabled when using `securityLevel='strict'` and enabled when using `securityLevel='loose'`.
|
||||
A node can have click events bound that lead to either a JavaScript callback or to open a new browser tab. **Note**: This functionality is disabled when using `securityLevel='strict'` and enabled when using `securityLevel='loose'`.
|
||||
|
||||
```
|
||||
click nodeId callback
|
||||
@@ -408,18 +404,18 @@ click nodeId call callback()
|
||||
```
|
||||
|
||||
* nodeId is the id of the node
|
||||
* callback is the name of a JavaScript function defined on the page displaying the graph, the function will be called with the nodeId as parameter.
|
||||
|
||||
Examples of tooltip usage below:
|
||||
* `callback` is the name of a JavaScript function defined on the page displaying the graph. The function will be called with the nodeId as an incoming parameter.
|
||||
|
||||
```html
|
||||
<script>
|
||||
var callback = function () {
|
||||
alert('A callback was triggered');
|
||||
var callback = function (nodeId) {
|
||||
alert('A callback was triggered on ' + nodeId);
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
Examples of tooltip usage:
|
||||
|
||||
The tooltip text is surrounded in double quotes. The styles of the tooltip are set by the class .mermaidTooltip.
|
||||
|
||||
```mermaid-example
|
||||
@@ -449,7 +445,7 @@ graph LR;
|
||||
click D href "https://www.github.com" "Open this in a new tab" _blank
|
||||
```
|
||||
|
||||
Beginners tip, a full example using interactive links in a html context:
|
||||
Beginner's tip—here's a full example of using interactive links in HTML:
|
||||
|
||||
```html
|
||||
<body>
|
||||
@@ -484,7 +480,7 @@ Beginners tip, a full example using interactive links in a html context:
|
||||
|
||||
### Comments
|
||||
|
||||
Comments can be entered within a flow diagram, which will be ignored by the parser. Comments need to be on their own line, and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any flow syntax
|
||||
Comments can be entered within a flow diagram, which will be ignored by the parser. Comments need to be on their own line, and must be prefaced with `%%` (double percent signs). Any text until the next newline will be treated as a comment, including all punctuation and any flow syntax.
|
||||
|
||||
```mmd
|
||||
graph LR
|
||||
@@ -496,16 +492,15 @@ graph LR
|
||||
|
||||
### Styling links
|
||||
|
||||
It is possible to style links. For instance you might want to style a link that is going backwards in the flow. As links
|
||||
have no ids in the same way as nodes, some other way of deciding what style the links should be attached to is required.
|
||||
Instead of ids, the order number of when the link was defined in the graph is used. In the example below the style
|
||||
defined in the linkStyle statement will belong to the fourth link in the graph:
|
||||
It is possible to style links. For instance, you might want to style a link that is going backwards in the flow. As links
|
||||
have no ids in the same way as nodes, some other way of attaching style is required.
|
||||
So instead of ids, the order number of when the link was defined in the graph is used, starting with zero. Here's a linkStyle statement that would apply style to the fourth link in the graph:
|
||||
|
||||
```
|
||||
linkStyle 3 stroke:#ff3,stroke-width:4px,color:red;
|
||||
```
|
||||
|
||||
You can specify default to apply to all links, or you can give a list of link order numbers separated by a comma.
|
||||
You can specify a `default` to apply to all links, or you can give a comma-separated list of link order numbers.
|
||||
|
||||
Instead of giving a styles option, you can also use custom d3 curve types with the following syntax:
|
||||
|
||||
@@ -513,14 +508,14 @@ Instead of giving a styles option, you can also use custom d3 curve types with t
|
||||
linkStyle default|numList|num interpolate curveType
|
||||
```
|
||||
|
||||
If you want to add style options too, instead of writing:
|
||||
If you want to add both D3 and style options, instead of writing:
|
||||
|
||||
```
|
||||
linkStyle default interpolate cardinal
|
||||
linkStyle default stroke:#ff3,stroke-width:4px,color:red;
|
||||
```
|
||||
|
||||
You can combine them into:
|
||||
You can combine them:
|
||||
|
||||
```
|
||||
linkStyle default interpolate cardinal stroke:#ff3,stroke-width:4px,color:red;
|
||||
@@ -540,29 +535,27 @@ graph LR
|
||||
|
||||
#### Classes
|
||||
|
||||
More convenient then defining the style every time is to define a class of styles and attach this class to the nodes that
|
||||
should have a different look.
|
||||
|
||||
a class definition looks like the example below:
|
||||
More convenient than defining the style every time is to define a class of styles and attach this class reference to multiple nodes.
|
||||
|
||||
here's a class definition:
|
||||
|
||||
```
|
||||
classDef className fill:#f9f,stroke:#333,stroke-width:4px;
|
||||
```
|
||||
|
||||
Attachment of a class to a node is done as per below:
|
||||
and then attaching this class to a node is simply:
|
||||
|
||||
```
|
||||
class nodeId1 className;
|
||||
```
|
||||
|
||||
It is also possible to attach a class to a list of nodes in one statement:
|
||||
It is also possible to attach a class to multiple nodes in one statement:
|
||||
|
||||
```
|
||||
class nodeId1,nodeId2 className;
|
||||
```
|
||||
|
||||
A shorter form of adding a class is to attach the classname to the node using the `:::`operator as per below:
|
||||
An even shorter form of adding a class is to attach the classname to the node using the `:::`operator:
|
||||
|
||||
```mermaid-example
|
||||
graph LR
|
||||
@@ -573,8 +566,7 @@ graph LR
|
||||
|
||||
### Css classes
|
||||
|
||||
It is also possible to predefine classes in css styles that can be applied from the graph definition as in the example
|
||||
below:
|
||||
It is also possible to predefine classes in css styles that can be applied from the graph definition:
|
||||
|
||||
**Example style**
|
||||
|
||||
@@ -598,7 +590,7 @@ graph LR;
|
||||
|
||||
### Default class
|
||||
|
||||
If a class is named default it will be assigned to all classes without specific class definitions.
|
||||
If a class is named `default` it will be assigned to all nodes that do not have a specific class definition.
|
||||
|
||||
```
|
||||
classDef default fill:#f9f,stroke:#333,stroke-width:4px;
|
||||
@@ -607,9 +599,7 @@ If a class is named default it will be assigned to all classes without specific
|
||||
|
||||
## Basic support for fontawesome
|
||||
|
||||
It is possible to add icons from fontawesome.
|
||||
|
||||
The icons are accessed via the syntax fa:#icon class name#.
|
||||
It is possible to add icons from fontawesome. These are accessed via the syntax fa:#icon-class-name#.
|
||||
|
||||
```mermaid-example
|
||||
graph TD
|
||||
@@ -622,11 +612,11 @@ graph TD
|
||||
|
||||
## Graph declarations with spaces between vertices and link and without semicolon
|
||||
|
||||
* In graph declarations, the statements also can now end without a semicolon. After release 0.2.16, ending a graph statement with semicolon is just optional. So the below graph declaration is also valid along with the old declarations of the graph.
|
||||
* After release 0.2.16, graph declaration statements do not need to end with a semicolon. (And they can continue to have the ending semicolon—it has now just become optional.) So the below graph declaration is valid along with the old declarations.
|
||||
|
||||
* A single space is allowed between vertices and the link. However there should not be any space between a vertex and its text and a link and its text. The old syntax of graph declaration will also work and hence this new feature is optional and is introduce to improve readability.
|
||||
* A single space is allowed between vertices and the link, however there should not be any space between a vertex and its text, or a link and its text. The old syntax of graph declarations will also work, so this new feature is optional and is introduced to improve readability.
|
||||
|
||||
Below is the new declaration of the graph edges which is also valid along with the old declaration of the graph edges.
|
||||
Below is an example of the new way to declare graph edges. This is valid alongside any old-style declarations of graph edges.
|
||||
|
||||
```mermaid-example
|
||||
graph LR
|
||||
@@ -641,9 +631,8 @@ graph LR
|
||||
|
||||
Is it possible to adjust the width of the rendered flowchart.
|
||||
|
||||
This is done by defining **mermaid.flowchartConfig** or by the CLI to use a json file with the configuration. How to use
|
||||
the CLI is described in the mermaidCLI page.
|
||||
mermaid.flowchartConfig can be set to a JSON string with config parameters or the corresponding object.
|
||||
This is done by defining **mermaid.flowchartConfig**, or by the CLI to use a json file with the configuration (which is described in the mermaidCLI page).
|
||||
In Javascript config parameters can be set by using `mermaid.flowchartConfig`:
|
||||
|
||||
```javascript
|
||||
mermaid.flowchartConfig = {
|
||||
|
||||
@@ -471,7 +471,7 @@ flowchart LR
|
||||
click D href "https://www.github.com" "Open this in a new tab" _blank
|
||||
```
|
||||
|
||||
Beginners tip, a full example using interactive links in a html context:
|
||||
Beginner's tip—a full example using interactive links in a html context:
|
||||
```html
|
||||
<body>
|
||||
<div class="mermaid">
|
||||
@@ -513,7 +513,7 @@ flowchart LR
|
||||
|
||||
### Styling links
|
||||
|
||||
It is possible to style links. For instance you might want to style a link that is going backwards in the flow. As links
|
||||
It is possible to style links. For instance, you might want to style a link that is going backwards in the flow. As links
|
||||
have no ids in the same way as nodes, some other way of deciding what style the links should be attached to is required.
|
||||
Instead of ids, the order number of when the link was defined in the graph is used, or use default to apply to all links.
|
||||
In the example below the style defined in the linkStyle statement will belong to the fourth link in the graph:
|
||||
@@ -522,6 +522,22 @@ In the example below the style defined in the linkStyle statement will belong to
|
||||
linkStyle 3 stroke:#ff3,stroke-width:4px,color:red;
|
||||
```
|
||||
|
||||
### Styling line curves
|
||||
|
||||
It is possible to style the type of curve used for lines between items, if the default method does not meet your needs.
|
||||
Available curve styles include `basis`, `bump`, `linear`, `monotoneX`, `monotoneY`, `natural`, `step`, `stepAfter`,
|
||||
and `stepBefore`.
|
||||
|
||||
In this example, a left-to-right graph uses the `stepBefore` curve style:
|
||||
|
||||
```
|
||||
%%{ init: { 'flowchart': { 'curve': 'stepBefore' } } }%%
|
||||
graph LR
|
||||
```
|
||||
|
||||
For a full list of available curves, including an explanation of custom curves, refer to
|
||||
the [Shapes](https://github.com/d3/d3-shape/blob/main/README.md#curves) documentation in the
|
||||
[d3-shape](https://github.com/d3/d3-shape/) project.
|
||||
|
||||
### Styling a node
|
||||
|
||||
@@ -612,12 +628,14 @@ The icons are accessed via the syntax fa:#icon class name#.
|
||||
|
||||
```mermaid-example
|
||||
flowchart TD
|
||||
B["fa:fa-twitter for peace"]
|
||||
B["fab:fa-twitter for peace"]
|
||||
B-->C[fa:fa-ban forbidden]
|
||||
B-->D(fa:fa-spinner);
|
||||
B-->E(A fa:fa-camera-retro perhaps?)
|
||||
```
|
||||
|
||||
?> Mermaid is now only compatible with Font Awesome versions 4 and 5. Check that you are using the correct version of Font Awesome.
|
||||
|
||||
|
||||
## Graph declarations with spaces between vertices and link and without semicolon
|
||||
|
||||
|
||||
@@ -313,7 +313,7 @@ click taskId href URL
|
||||
* taskId is the id of the task
|
||||
* callback is the name of a javascript function defined on the page displaying the graph, the function will be called with the taskId as the parameter if no other arguments are specified.
|
||||
|
||||
Beginners tip, a full example using interactive links in an html context:
|
||||
Beginner's tip—a full example using interactive links in an html context:
|
||||
```html
|
||||
<body>
|
||||
<div class="mermaid">
|
||||
|
||||
@@ -182,6 +182,8 @@ After this we made use of the `checkout` keyword to set the current branch as `m
|
||||
After this we merge the `develop` branch onto the current branch `main`, resulting in a merge commit.
|
||||
Since the current branch at this point is still `main`, the last two commits are registered against that.
|
||||
|
||||
Additionally, you may add a tag to the merge commit, or override the default id: `merge branch id:"1234" tag:"v1.0.0"`
|
||||
|
||||
### Cherry Pick commit from another branch
|
||||
Similar to how 'git' allows you to cherry-pick a commit from **another branch** onto the **current** branch, Mermaid also supports this functionality. You can also cherry-pick a commit from another branch using the `cherry-pick` keyword.
|
||||
|
||||
|
||||
BIN
docs/img/accessibility-div-example-2.png
Normal file
BIN
docs/img/accessibility-div-example-2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
BIN
docs/img/accessibility-div-example.png
Normal file
BIN
docs/img/accessibility-div-example.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 119 KiB |
@@ -17,7 +17,8 @@
|
||||
/>
|
||||
<!-- <link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css"> -->
|
||||
<link rel="stylesheet" href="theme.css" />
|
||||
<script src="//cdn.jsdelivr.net/npm/mermaid@9.1.3/dist/mermaid.min.js"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css">
|
||||
<script src="//cdn.jsdelivr.net/npm/mermaid@9.1.6/dist/mermaid.min.js"></script>
|
||||
<!-- <script src="http://localhost:9000/mermaid.js"></script> -->
|
||||
<script>
|
||||
// prettier-ignore
|
||||
|
||||
@@ -30,6 +30,7 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
- [Mermaid Macro](https://www.redmine.org/plugins/redmine_mermaid_macro)
|
||||
- [redmine-mermaid](https://github.com/styz/redmine_mermaid)
|
||||
- [markdown-for-mermaid-plugin](https://github.com/jamieh-mongolian/markdown-for-mermaid-plugin)
|
||||
- [Jetsbrain IDE eg Pycharm](https://www.jetbrains.com/go/guide/tips/mermaid-js-support-in-markdown/)
|
||||
|
||||
## CRM/ERP/Similar
|
||||
|
||||
@@ -49,7 +50,6 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
|
||||
- [VuePress](https://vuepress.vuejs.org/)
|
||||
- [Plugin for Mermaid.js](https://github.com/eFrane/vuepress-plugin-mermaidjs)
|
||||
- [vuepress-plugin-mermaidjs-cli](https://github.com/gwleclerc/vuepress-plugin-mermaidjs-cli)
|
||||
- [Grav CMS](https://getgrav.org/)
|
||||
- [Mermaid Diagrams](https://github.com/DanielFlaum/grav-plugin-mermaid-diagrams)
|
||||
- [Gitlab Markdown Adapter](https://github.com/Goutte/grav-plugin-gitlab-markdown-adapter)
|
||||
@@ -110,13 +110,13 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
- [Mermaid Plugin](https://github.com/cldwalker/Mermaid)
|
||||
- [Draw.io](https://draw.io) - [Plugin](https://github.com/nopeslide/drawio_mermaid_plugin)
|
||||
- [Inkdrop](https://www.inkdrop.app) - [Plugin](https://github.com/inkdropapp/inkdrop-mermaid)
|
||||
- [Vim](https://vim.org)
|
||||
- [Vim](https://www.vim.org)
|
||||
- [Vim Diagram Syntax](https://github.com/zhaozg/vim-diagram)
|
||||
- [GNU Emacs](https://www.gnu.org/software/emacs/)
|
||||
- [Major mode for .mmd files](https://github.com/abrochard/mermaid-mode)
|
||||
- [Org-Mode integration](https://github.com/arnm/ob-mermaid)
|
||||
- [Brackets](https://brackets.io/)
|
||||
- [Mermaid Preview](https://s3.amazonaws.com/extend.brackets/alanhohn.mermaid-preview/alanhohn.mermaid-preview-1.0.2.zip)
|
||||
- [Mermaid Preview](https://github.com/AlanHohn/mermaid-preview)
|
||||
- [Iodide](https://github.com/iodide-project/iodide)
|
||||
- [iodide-mermaid-plugin](https://github.com/iodide-project/iodide-mermaid-plugin)
|
||||
- [Google docs](https://docs.google.com/)
|
||||
@@ -149,7 +149,7 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
|
||||
| Name | Chrome Web Store | Firefox Add-ons | Opera | Edge | Source/Repository |
|
||||
| -- | -- | -- | -- | -- | -- |
|
||||
| GitHub + Mermaid | [🎡🔗](https://chrome.google.com/webstore/detail/github-%20-mermaid/goiiopgdnkogdbjmncgedmgpoajilohe) | [🦊🔗](https://addons.mozilla.org/firefox/addon/github-mermaid/) | - | - | [🐙🔗](https://github.com/BackMarket/github-mermaid-extension)
|
||||
| GitHub + Mermaid | - | [🦊🔗](https://addons.mozilla.org/firefox/addon/github-mermaid/) | - | - | [🐙🔗](https://github.com/BackMarket/github-mermaid-extension)
|
||||
| Asciidoctor Live Preview | [🎡🔗](https://chrome.google.com/webstore/detail/asciidoctorjs-live-previe/iaalpfgpbocpdfblpnhhgllgbdbchmia) | - | - | [🌀🔗](https://microsoftedge.microsoft.com/addons/detail/asciidoctorjs-live-previ/pefkelkanablhjdekgdahplkccnbdggd?hl=en-US) | -|
|
||||
| Diagram Tab| -| - | - | - | [🐙🔗](https://github.com/khafast/diagramtab) |
|
||||
| Markdown Diagrams| [🎡🔗](https://chrome.google.com/webstore/detail/markdown-diagrams/pmoglnmodacnbbofbgcagndelmgaclel/) | [🦊🔗](https://addons.mozilla.org/en-US/firefox/addon/markdown-diagrams/) | [🔴🔗](https://addons.opera.com/en/extensions/details/markdown-diagrams/) | [🌀🔗](https://microsoftedge.microsoft.com/addons/detail/markdown-diagrams/hceenoomhhdkjjijnmlclkpenkapfihe) | [🐙🔗](https://github.com/marcozaccari/markdown-diagrams-browser-extension/tree/master/doc/examples) |
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
# Integrations
|
||||
|
||||
The following list is a compilation of different integrations and plugins that allow the rendering of mermaid definitions within other applications.
|
||||
|
||||
They also serve as proof of concept, for the variety of things that can be built with mermaid.
|
||||
|
||||
|
||||
## Productivity
|
||||
|
||||
- [GitLab](https://docs.gitlab.com/ee/user/markdown.html#diagrams-and-flowcharts) (**Native support**)
|
||||
- [Azure Devops](https://docs.microsoft.com/en-us/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) (**Native support**)
|
||||
- [Tuleap](https://docs.tuleap.org/user-guide/writing-in-tuleap.html#graphs) (**Native support**)
|
||||
- [Joplin](https://joplinapp.org) (**Native support**)
|
||||
- [Notion](https://notion.so) (**Native support**)
|
||||
- [GitHub](https://github.com)
|
||||
- [GitHub action: Compile mermaid to image](https://github.com/neenjaw/compile-mermaid-markdown-action)
|
||||
- [svg-generator](https://github.com/SimonKenyonShepard/mermaidjs-github-svg-generator)
|
||||
- [GitBook](https://gitbook.com)
|
||||
- [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid)
|
||||
- [Markdown with Mermaid CLI](https://github.com/miao1007/gitbook-plugin-mermaid-cli)
|
||||
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
|
||||
- [Atlassian Products](https://www.atlassian.com)
|
||||
- [Mermaid Plugin for Confluence](https://marketplace.atlassian.com/apps/1214124/mermaid-plugin-for-confluence?hosting=server&tab=overview)
|
||||
- [CloudScript.io Addon](https://marketplace.atlassian.com/apps/1219878/cloudscript-io-mermaid-addon?hosting=cloud&tab=overview)
|
||||
- [Auto convert diagrams in Jira](https://github.com/coddingtonbear/jirafs-mermaid)
|
||||
- [Redmine](https://redmine.org)
|
||||
- [Mermaid Macro](https://www.redmine.org/plugins/redmine_mermaid_macro)
|
||||
- [redmine-mermaid](https://github.com/styz/redmine_mermaid)
|
||||
- [markdown-for-mermaid-plugin](https://github.com/jamieh-mongolian/markdown-for-mermaid-plugin)
|
||||
|
||||
## CRM/ERP/Similar
|
||||
|
||||
- [coreBOS](https://blog.corebos.org/blog/december2019)
|
||||
|
||||
## Blogs
|
||||
|
||||
- [Wordpress](https://wordpress.org)
|
||||
- [WordPress Markdown Editor](https://wordpress.org/plugins/wp-githuber-md)
|
||||
- [WP-ReliableMD](https://wordpress.org/plugins/wp-reliablemd/)
|
||||
- [Hexo](https://hexo.io)
|
||||
- [hexo-filter-mermaid-diagrams](https://github.com/webappdevelp/hexo-filter-mermaid-diagrams)
|
||||
- [hexo-tag-mermaid](https://github.com/JameChou/hexo-tag-mermaid)
|
||||
- [hexo-mermaid-diagrams](https://github.com/mslxl/hexo-mermaid-diagrams)
|
||||
|
||||
## CMS
|
||||
|
||||
- [VuePress](https://vuepress.vuejs.org/)
|
||||
- [Plugin for Mermaid.js](https://github.com/eFrane/vuepress-plugin-mermaidjs)
|
||||
- [vuepress-plugin-mermaidjs-cli](https://github.com/gwleclerc/vuepress-plugin-mermaidjs-cli)
|
||||
- [Grav CMS](https://getgrav.org/)
|
||||
- [Mermaid Diagrams](https://github.com/DanielFlaum/grav-plugin-mermaid-diagrams)
|
||||
- [Gitlab Markdown Adapter](https://github.com/Goutte/grav-plugin-gitlab-markdown-adapter)
|
||||
|
||||
## Communication
|
||||
|
||||
- [Discourse](https://discourse.org)
|
||||
- [Mermaid Plugin](https://github.com/pnewell/discourse-mermaid), [And](https://github.com/unfoldingWord-dev/discourse-mermaid)
|
||||
- [Mattermost](https://mattermost.com/)
|
||||
- [Mermaid Plugin](https://github.com/SpikeTings/Mermaid)
|
||||
- [phpBB](https://phpbb.com)
|
||||
- [phpbb-ext-mermaid](https://github.com/AlfredoRamos/phpbb-ext-mermaid)
|
||||
- [NodeBB](https://nodebb.org)
|
||||
- [Mermaid Plugin](https://www.npmjs.com/package/nodebb-plugin-mermaid)
|
||||
|
||||
## Wikis
|
||||
|
||||
- [MediaWiki](https://www.mediawiki.org)
|
||||
- [Mermaid Extension](https://www.mediawiki.org/wiki/Extension:Mermaid)
|
||||
- [Flex Diagrams Extension](https://www.mediawiki.org/wiki/Extension:Flex_Diagrams)
|
||||
- [Semantic Media Wiki](https://semantic-mediawiki.org)
|
||||
- [Mermaid Plugin](https://github.com/SemanticMediaWiki/Mermaid)
|
||||
- [FosWiki](https://foswiki.org)
|
||||
- [Mermaid Plugin](https://foswiki.org/Extensions/MermaidPlugin)
|
||||
- [DokuWiki](https://dokuwiki.org)
|
||||
- [Flowcharts](https://www.dokuwiki.org/plugin:flowcharts?s[]=mermaid)
|
||||
- [ComboStrap](https://combostrap.com/mermaid)
|
||||
- [TiddlyWiki](https://tiddlywiki.com/)
|
||||
- [mermaid-tw5: full js library](https://github.com/efurlanm/mermaid-tw5)
|
||||
- [tw5-mermaid: wrapper for Mermaid Live](https://github.com/jasonmhoule/tw5-mermaid)
|
||||
|
||||
## Editor Plugins
|
||||
|
||||
- [Vs Code](https://code.visualstudio.com/)
|
||||
- [Markdown Preview Mermaid Support](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid)
|
||||
- [Mermaid Preview](https://marketplace.visualstudio.com/items?itemName=vstirbu.vscode-mermaid-preview)
|
||||
- [Mermaid Markdown Syntax Highlighting](https://marketplace.visualstudio.com/items?itemName=bpruitt-goddard.mermaid-markdown-syntax-highlighting)
|
||||
- [Mermaid Editor](https://marketplace.visualstudio.com/items?itemName=tomoyukim.vscode-mermaid-editor)
|
||||
- [Mermaid Export](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.mermaid-export)
|
||||
- [Markdown PDF](https://marketplace.visualstudio.com/items?itemName=yzane.markdown-pdf)
|
||||
- [Preview](https://marketplace.visualstudio.com/items?itemName=searKing.preview-vscode)
|
||||
- [Preview Sequence Diagrams](https://marketplace.visualstudio.com/items?itemName=arichika.previewseqdiag-vscode)
|
||||
- [Markdown-It](https://github.com/markdown-it/markdown-it)
|
||||
- [Textual UML Parser](https://github.com/manastalukdar/markdown-it-textual-uml)
|
||||
- [Mermaid Plugin](https://github.com/tylingsoft/markdown-it-mermaid)
|
||||
- [md-it-mermaid](https://github.com/iamcco/md-it-mermaid)
|
||||
- [markdown-it-mermaid-fence-new](https://github.com/Revomatico/markdown-it-mermaid-fence-new)
|
||||
- [markdown-it-mermaid-less](https://github.com/searKing/markdown-it-mermaid-less)
|
||||
- [Atom](https://atom.io)
|
||||
- [Markdown Preview Enhanced](https://atom.io/packages/markdown-preview-enhanced)
|
||||
- [Atom Mermaid](https://atom.io/packages/atom-mermaid)
|
||||
- [Language Mermaid Syntax Highlighter](https://atom.io/packages/language-mermaid)
|
||||
- [Sublime Text 3](https://sublimetext.com)
|
||||
- [Mermaid Package](https://packagecontrol.io/packages/Mermaid)
|
||||
- [Astah](https://astah.net)
|
||||
- [Export to Mermaid](https://github.com/Avens666/Astah_Jude_UML_export_to_Markdown-mermaid-Plantuml-)
|
||||
- [Light Table](http://lighttable.com/)
|
||||
- [Mermaid Plugin](https://github.com/cldwalker/Mermaid)
|
||||
- [Draw.io](https://draw.io) - [Plugin](https://github.com/nopeslide/drawio_mermaid_plugin)
|
||||
- [Inkdrop](https://www.inkdrop.app) - [Plugin](https://github.com/inkdropapp/inkdrop-mermaid)
|
||||
- [Vim](https://vim.org)
|
||||
- [Vim Diagram Syntax](https://github.com/zhaozg/vim-diagram)
|
||||
- [GNU Emacs](https://www.gnu.org/software/emacs/)
|
||||
- [Major mode for .mmd files](https://github.com/abrochard/mermaid-mode)
|
||||
- [Org-Mode integration](https://github.com/arnm/ob-mermaid)
|
||||
- [Brackets](https://brackets.io/)
|
||||
- [Mermaid Preview](https://s3.amazonaws.com/extend.brackets/alanhohn.mermaid-preview/alanhohn.mermaid-preview-1.0.2.zip)
|
||||
- [Iodide](https://github.com/iodide-project/iodide)
|
||||
- [iodide-mermaid-plugin](https://github.com/iodide-project/iodide-mermaid-plugin)
|
||||
- [Google docs](https://docs.google.com/)
|
||||
- [Mermaid plugin for google docs](https://workspace.google.com/marketplace/app/mermaid/636321283856)
|
||||
- [Podlite](https://github.com/zag/podlite-desktop)
|
||||
- [Named block =Diagram](https://github.com/zag/podlite/tree/main/packages/podlite-diagrams)
|
||||
- [GNU Nano](https://www.nano-editor.org/)
|
||||
- [Nano Mermaid](https://github.com/Yash-Singh1/nano-mermaid)
|
||||
|
||||
## Document Generation
|
||||
|
||||
- [Sphinx](https://www.sphinx-doc.org/en/master/)
|
||||
- [sphinxcontrib-mermaid](https://github.com/mgaitan/sphinxcontrib-mermaid)
|
||||
- [remark.js](https://remark.js.org/)
|
||||
- [remark-mermaid](https://github.com/temando/remark-mermaid)
|
||||
- [jSDoc](https://jsdoc.app/)
|
||||
- [jsdoc-mermaid](https://github.com/Jellyvision/jsdoc-mermaid)
|
||||
- [MkDocs](https://mkdocs.org)
|
||||
- [mkdocs-mermaid2-plugin](https://github.com/fralau/mkdocs-mermaid2-plugin)
|
||||
- [Type Doc](https://typedoc.org/)
|
||||
- [typedoc-plugin-mermaid](https://www.npmjs.com/package/typedoc-plugin-mermaid)
|
||||
- [Docsy Hugo Theme](https://www.docsy.dev/docs/adding-content/lookandfeel/#diagrams-with-mermaid) (Native support in theme)
|
||||
- [Codedoc](https://codedoc.cc/)
|
||||
- [codedoc-mermaid-plugin](https://www.npmjs.com/package/codedoc-mermaid-plugin)
|
||||
|
||||
## Browser Extensions
|
||||
|
||||
| Name | Chrome Web Store | Firefox Add-ons | Opera | Edge | Source/Repository |
|
||||
| -- | -- | -- | -- | -- | -- |
|
||||
| GitHub + Mermaid | [🎡🔗](https://chrome.google.com/webstore/detail/github-%20-mermaid/goiiopgdnkogdbjmncgedmgpoajilohe) | [🦊🔗](https://addons.mozilla.org/firefox/addon/github-mermaid/) | - | - | [🐙🔗](https://github.com/BackMarket/github-mermaid-extension)
|
||||
| Asciidoctor Live Preview | [🎡🔗](https://chrome.google.com/webstore/detail/asciidoctorjs-live-previe/iaalpfgpbocpdfblpnhhgllgbdbchmia) | - | - | [🌀🔗](https://microsoftedge.microsoft.com/addons/detail/asciidoctorjs-live-previ/pefkelkanablhjdekgdahplkccnbdggd?hl=en-US) | -|
|
||||
| Diagram Tab| -| - | - | - | [🐙🔗](https://github.com/khafast/diagramtab) |
|
||||
| Markdown Diagrams| [🎡🔗](https://chrome.google.com/webstore/detail/markdown-diagrams/pmoglnmodacnbbofbgcagndelmgaclel/) | [🦊🔗](https://addons.mozilla.org/en-US/firefox/addon/markdown-diagrams/) | [🔴🔗](https://addons.opera.com/en/extensions/details/markdown-diagrams/) | [🌀🔗](https://microsoftedge.microsoft.com/addons/detail/markdown-diagrams/hceenoomhhdkjjijnmlclkpenkapfihe) | [🐙🔗](https://github.com/marcozaccari/markdown-diagrams-browser-extension/tree/master/doc/examples) |
|
||||
| Markdown Viewer| - | [🦊🔗](https://addons.mozilla.org/en-US/firefox/addon/markdown-viewer-chrome/) | - | - | [🐙🔗](https://github.com/simov/markdown-viewer)|
|
||||
| Extensions for Mermaid| - | [🦊🔗](https://addons.mozilla.org/en-US/firefox/addon/markdown-viewer-chrome/) | [🔴🔗](https://addons.opera.com/en/extensions/details/extensions-for-mermaid/)| - | [🐙🔗](https://github.com/Stefan-S/mermaid-extension) |
|
||||
| Chrome Diagrammer| [🎡🔗](https://chrome.google.com/webstore/detail/chrome-diagrammer/bkpbgjmkomfoakfklcjeoegkklgjnnpk) | - |- | - | - |
|
||||
| Mermaid Diagrams | [🎡🔗](https://chrome.google.com/webstore/detail/mermaid-diagrams/phfcghedmopjadpojhmmaffjmfiakfil) | - | - | - | - |
|
||||
|Mermaid Markdown | [🎡🔗](https://chrome.google.com/webstore/detail/mermaid-markdown/mboeoikjijmjcjgpccghbcoegikliijg) | - | - | - | - |
|
||||
| Monkeys | [🎡🔗](https://chrome.google.com/webstore/detail/monkeys-mermaid-for-githu/cplfdpoajbclbgphaphphcldamfkjlgi) | - | - | - | - |
|
||||
| Mermaid Previewer | [🎡🔗](https://chrome.google.com/webstore/detail/mermaid-previewer/oidjnlhbegipkcklbdfnbkikplpghfdl) | - | - | - | - |
|
||||
|
||||
|
||||
## Other
|
||||
- [Jekyll](https://jekyllrb.com/)
|
||||
- [jekyll-mermaid](https://rubygems.org/gems/jekyll-mermaid)
|
||||
- [jekyll-mermaid-diagrams](https://github.com/fuzhibo/jekyll-mermaid-diagrams)
|
||||
- [Reveal.js](https://github.com/hakimel/reveal.js)
|
||||
- [reveal.js-mermaid-plugin](https://github.com/ludwick/reveal.js-mermaid-plugin)
|
||||
- [Bisheng](https://www.npmjs.com/package/bisheng)
|
||||
- [bisheng-plugin-mermaid](https://github.com/yct21/bisheng-plugin-mermaid)
|
||||
- [Reveal CK](https://github.com/jedcn/reveal-ck)
|
||||
- [reveal-ck-mermaid-plugin](https://github.com/tmtm/reveal-ck-mermaid-plugin)
|
||||
- [mermaid-server: Generate diagrams using a HTTP request](https://github.com/TomWright/mermaid-server)
|
||||
@@ -8,7 +8,7 @@ Diagram Examples can be found in the [Mermaid Live Editor](https://mermaid-js.gi
|
||||
## Syntax Structure
|
||||
One would notice that all **Diagrams definitions begin** with a declaration of the **diagram type**, followed by the definitions of the diagram and its contents. This declaration notifies the parser which kind of diagram the code is supposed to generate.
|
||||
|
||||
**Example** : The code below is for an Entity Relationship Diagram, specified by the `erDiagram` declaration. What follows is the definition of the different `Entities` represented in it.
|
||||
**Example** : The code below is for an Entity Relationship Diagram, specified by the `erDiagram` declaration. What follows is the definition of the different `Entities` represented in it.
|
||||
|
||||
```mermaid-example
|
||||
erDiagram
|
||||
|
||||
@@ -1,504 +0,0 @@
|
||||
# Sequence diagrams
|
||||
|
||||
**Edit this Page** [](https://github.com/mermaid-js/mermaid/blob/develop/docs/sequenceDiagram.md)
|
||||
> A Sequence diagram is an interaction diagram that shows how processes operate with one another and in what order.
|
||||
|
||||
Mermaid can render sequence diagrams.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->>John: Hello John, how are you?
|
||||
John-->>Alice: Great!
|
||||
Alice-)John: See you later!
|
||||
```
|
||||
|
||||
```note
|
||||
A note on nodes, the word "end" could potentially break the diagram, due to the way that the mermaid language is scripted.
|
||||
|
||||
If unavoidable, one must use parentheses(), quotation marks "", or brackets {},[], to enclose the word "end". i.e : (end), [end], {end}.
|
||||
```
|
||||
|
||||
## Syntax
|
||||
|
||||
### Participants
|
||||
|
||||
The participants can be defined implicitly as in the first example on this page. The participants or actors are
|
||||
rendered in order of appearance in the diagram source text. Sometimes you might want to show the participants in a
|
||||
different order than how they appear in the first message. It is possible to specify the actor's order of
|
||||
appearance by doing the following:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
participant Bob
|
||||
Alice->>Bob: Hi Bob
|
||||
Bob->>Alice: Hi Alice
|
||||
```
|
||||
|
||||
### Actors
|
||||
|
||||
If you specifically want to use the actor symbol instead of a rectangle with text you can do so by using actor statements as per below.
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
actor Alice
|
||||
actor Bob
|
||||
Alice->>Bob: Hi Bob
|
||||
Bob->>Alice: Hi Alice
|
||||
```
|
||||
|
||||
### Aliases
|
||||
|
||||
The actor can have a convenient identifier and a descriptive label.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant A as Alice
|
||||
participant J as John
|
||||
A->>J: Hello John, how are you?
|
||||
J->>A: Great!
|
||||
```
|
||||
|
||||
## Messages
|
||||
|
||||
Messages can be of two displayed either solid or with a dotted line.
|
||||
|
||||
```
|
||||
[Actor][Arrow][Actor]:Message text
|
||||
```
|
||||
|
||||
There are six types of arrows currently supported:
|
||||
|
||||
| Type | Description |
|
||||
| ---- | ------------------------------------------- |
|
||||
| -> | Solid line without arrow |
|
||||
| --> | Dotted line without arrow |
|
||||
| ->> | Solid line with arrowhead |
|
||||
| -->> | Dotted line with arrowhead |
|
||||
| -x | Solid line with a cross at the end |
|
||||
| --x | Dotted line with a cross at the end. |
|
||||
| -) | Solid line with an open arrow at the end (async) |
|
||||
| --) | Dotted line with a open arrow at the end (async) |
|
||||
|
||||
## Activations
|
||||
|
||||
It is possible to activate and deactivate an actor. (de)activation can be dedicated declarations:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->>John: Hello John, how are you?
|
||||
activate John
|
||||
John-->>Alice: Great!
|
||||
deactivate John
|
||||
```
|
||||
|
||||
There is also a shortcut notation by appending `+`/`-` suffix to the message arrow:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->>+John: Hello John, how are you?
|
||||
John-->>-Alice: Great!
|
||||
```
|
||||
|
||||
Activations can be stacked for same actor:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->>+John: Hello John, how are you?
|
||||
Alice->>+John: John, can you hear me?
|
||||
John-->>-Alice: Hi Alice, I can hear you!
|
||||
John-->>-Alice: I feel great!
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
It is possible to add notes to a sequence diagram. This is done by the notation
|
||||
Note [ right of | left of | over ] [Actor]: Text in note content
|
||||
|
||||
See the example below:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant John
|
||||
Note right of John: Text in note
|
||||
```
|
||||
|
||||
It is also possible to create notes spanning two participants:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->John: Hello John, how are you?
|
||||
Note over Alice,John: A typical interaction
|
||||
```
|
||||
|
||||
## Loops
|
||||
|
||||
It is possible to express loops in a sequence diagram. This is done by the notation
|
||||
|
||||
```
|
||||
loop Loop text
|
||||
... statements ...
|
||||
end
|
||||
```
|
||||
|
||||
See the example below:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->John: Hello John, how are you?
|
||||
loop Every minute
|
||||
John-->Alice: Great!
|
||||
end
|
||||
```
|
||||
|
||||
## Alt
|
||||
|
||||
It is possible to express alternative paths in a sequence diagram. This is done by the notation
|
||||
|
||||
```
|
||||
alt Describing text
|
||||
... statements ...
|
||||
else
|
||||
... statements ...
|
||||
end
|
||||
```
|
||||
|
||||
or if there is sequence that is optional (if without else).
|
||||
|
||||
```
|
||||
opt Describing text
|
||||
... statements ...
|
||||
end
|
||||
```
|
||||
|
||||
See the example below:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->>Bob: Hello Bob, how are you?
|
||||
alt is sick
|
||||
Bob->>Alice: Not so good :(
|
||||
else is well
|
||||
Bob->>Alice: Feeling fresh like a daisy
|
||||
end
|
||||
opt Extra response
|
||||
Bob->>Alice: Thanks for asking
|
||||
end
|
||||
```
|
||||
|
||||
## Parallel
|
||||
|
||||
It is possible to show actions that are happening in parallel.
|
||||
|
||||
This is done by the notation
|
||||
|
||||
```
|
||||
par [Action 1]
|
||||
... statements ...
|
||||
and [Action 2]
|
||||
... statements ...
|
||||
and [Action N]
|
||||
... statements ...
|
||||
end
|
||||
```
|
||||
|
||||
See the example below:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
par Alice to Bob
|
||||
Alice->>Bob: Hello guys!
|
||||
and Alice to John
|
||||
Alice->>John: Hello guys!
|
||||
end
|
||||
Bob-->>Alice: Hi Alice!
|
||||
John-->>Alice: Hi Alice!
|
||||
```
|
||||
|
||||
It is also possible to nest parallel blocks.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
par Alice to Bob
|
||||
Alice->>Bob: Go help John
|
||||
and Alice to John
|
||||
Alice->>John: I want this done today
|
||||
par John to Charlie
|
||||
John->>Charlie: Can we do this today?
|
||||
and John to Diana
|
||||
John->>Diana: Can you help us today?
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Background Highlighting
|
||||
|
||||
It is possible to highlight flows by providing colored background rects. This is done by the notation
|
||||
|
||||
The colors are defined using rgb and rgba syntax.
|
||||
|
||||
```
|
||||
rect rgb(0, 255, 0)
|
||||
... content ...
|
||||
end
|
||||
```
|
||||
|
||||
```
|
||||
rect rgba(0, 0, 255, .1)
|
||||
... content ...
|
||||
end
|
||||
```
|
||||
|
||||
See the examples below:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
participant John
|
||||
|
||||
rect rgb(191, 223, 255)
|
||||
note right of Alice: Alice calls John.
|
||||
Alice->>+John: Hello John, how are you?
|
||||
rect rgb(200, 150, 255)
|
||||
Alice->>+John: John, can you hear me?
|
||||
John-->>-Alice: Hi Alice, I can hear you!
|
||||
end
|
||||
John-->>-Alice: I feel great!
|
||||
end
|
||||
Alice ->>+ John: Did you want to go to the game tonight?
|
||||
John -->>- Alice: Yeah! See you there.
|
||||
|
||||
```
|
||||
|
||||
## Comments
|
||||
|
||||
Comments can be entered within a sequence diagram, which will be ignored by the parser. Comments need to be on their own line, and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any diagram syntax
|
||||
|
||||
```mmd
|
||||
sequenceDiagram
|
||||
Alice->>John: Hello John, how are you?
|
||||
%% this is a comment
|
||||
John-->>Alice: Great!
|
||||
```
|
||||
|
||||
## Entity codes to escape characters
|
||||
|
||||
It is possible to escape characters using the syntax exemplified here.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
A->>B: I #9829; you!
|
||||
B->>A: I #9829; you #infin; times more!
|
||||
```
|
||||
|
||||
Numbers given are base 10, so `#` can be encoded as `#35;`. It is also supported to use HTML character names.
|
||||
|
||||
Because semicolons can be used instead of line breaks to define the markup, you need to use `#59;` to include a semicolon in message text.
|
||||
|
||||
## sequenceNumbers
|
||||
|
||||
It is possible to get a sequence number attached to each arrow in a sequence diagram. This can be configured when adding mermaid to the website as shown below:
|
||||
|
||||
```html
|
||||
<script>
|
||||
mermaid.initialize({
|
||||
sequence: { showSequenceNumbers: true },
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
It can also be be turned on via the diagram code as in the diagram:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
Alice->>John: Hello John, how are you?
|
||||
loop Healthcheck
|
||||
John->>John: Fight against hypochondria
|
||||
end
|
||||
Note right of John: Rational thoughts!
|
||||
John-->>Alice: Great!
|
||||
John->>Bob: How about you?
|
||||
Bob-->>John: Jolly good!
|
||||
```
|
||||
|
||||
## Actor Menus
|
||||
|
||||
Actors can have popup-menus containing individualized links to external pages. For example, if an actor represented a web service, useful links might include a link to the service health dashboard, repo containing the code for the service, or a wiki page describing the service.
|
||||
|
||||
This can be configured by adding one or more link lines with the format:
|
||||
```
|
||||
link <actor>: <link-label> @ <link-url>
|
||||
```
|
||||
```mmd
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
participant John
|
||||
link Alice: Dashboard @ https://dashboard.contoso.com/alice
|
||||
link Alice: Wiki @ https://wiki.contoso.com/alice
|
||||
link John: Dashboard @ https://dashboard.contoso.com/john
|
||||
link John: Wiki @ https://wiki.contoso.com/john
|
||||
Alice->>John: Hello John, how are you?
|
||||
John-->>Alice: Great!
|
||||
Alice-)John: See you later!
|
||||
```
|
||||
|
||||
#### Advanced Menu Syntax
|
||||
There is an advanced syntax that relies on JSON formatting. If you are comfortable with JSON format, then this exists as well.
|
||||
|
||||
This can be configured by adding the links lines with the format:
|
||||
|
||||
```
|
||||
links <actor>: <json-formatted link-name link-url pairs>
|
||||
```
|
||||
|
||||
An example is below:
|
||||
|
||||
```mmd
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
participant John
|
||||
links Alice: {"Dashboard": "https://dashboard.contoso.com/alice", "Wiki": "https://wiki.contoso.com/alice"}
|
||||
links John: {"Dashboard": "https://dashboard.contoso.com/john", "Wiki": "https://wiki.contoso.com/john"}
|
||||
Alice->>John: Hello John, how are you?
|
||||
John-->>Alice: Great!
|
||||
Alice-)John: See you later!
|
||||
```
|
||||
|
||||
## Styling
|
||||
|
||||
Styling of a sequence diagram is done by defining a number of css classes. During rendering these classes are extracted from the file located at src/themes/sequence.scss
|
||||
|
||||
### Classes used
|
||||
|
||||
| Class | Description |
|
||||
| ------------ | ----------------------------------------------------------- |
|
||||
| actor | Style for the actor box at the top of the diagram. |
|
||||
| text.actor | Styles for text in the actor box at the top of the diagram. |
|
||||
| actor-line | The vertical line for an actor. |
|
||||
| messageLine0 | Styles for the solid message line. |
|
||||
| messageLine1 | Styles for the dotted message line. |
|
||||
| messageText | Defines styles for the text on the message arrows. |
|
||||
| labelBox | Defines styles label to left in a loop. |
|
||||
| labelText | Styles for the text in label for loops. |
|
||||
| loopText | Styles for the text in the loop box. |
|
||||
| loopLine | Defines styles for the lines in the loop box. |
|
||||
| note | Styles for the note box. |
|
||||
| noteText | Styles for the text on in the note boxes. |
|
||||
|
||||
### Sample stylesheet
|
||||
|
||||
```css
|
||||
body {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.actor {
|
||||
stroke: #ccccff;
|
||||
fill: #ececff;
|
||||
}
|
||||
text.actor {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
font-family: Helvetica;
|
||||
}
|
||||
|
||||
.actor-line {
|
||||
stroke: grey;
|
||||
}
|
||||
|
||||
.messageLine0 {
|
||||
stroke-width: 1.5;
|
||||
stroke-dasharray: '2 2';
|
||||
marker-end: 'url(#arrowhead)';
|
||||
stroke: black;
|
||||
}
|
||||
|
||||
.messageLine1 {
|
||||
stroke-width: 1.5;
|
||||
stroke-dasharray: '2 2';
|
||||
stroke: black;
|
||||
}
|
||||
|
||||
#arrowhead {
|
||||
fill: black;
|
||||
}
|
||||
|
||||
.messageText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.labelBox {
|
||||
stroke: #ccccff;
|
||||
fill: #ececff;
|
||||
}
|
||||
|
||||
.labelText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
}
|
||||
|
||||
.loopText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
}
|
||||
|
||||
.loopLine {
|
||||
stroke-width: 2;
|
||||
stroke-dasharray: '2 2';
|
||||
marker-end: 'url(#arrowhead)';
|
||||
stroke: #ccccff;
|
||||
}
|
||||
|
||||
.note {
|
||||
stroke: #decc93;
|
||||
fill: #fff5ad;
|
||||
}
|
||||
|
||||
.noteText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 14px;
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Is it possible to adjust the margins for rendering the sequence diagram.
|
||||
|
||||
This is done by defining `mermaid.sequenceConfig` or by the CLI to use a json file with the configuration.
|
||||
How to use the CLI is described in the [mermaidCLI](mermaidCLI) page.
|
||||
`mermaid.sequenceConfig` can be set to a JSON string with config parameters or the corresponding object.
|
||||
|
||||
```javascript
|
||||
mermaid.sequenceConfig = {
|
||||
diagramMarginX: 50,
|
||||
diagramMarginY: 10,
|
||||
boxTextMargin: 5,
|
||||
noteMargin: 10,
|
||||
messageMargin: 35,
|
||||
mirrorActors: true
|
||||
};
|
||||
```
|
||||
|
||||
### Possible configuration parameters:
|
||||
|
||||
| Parameter | Description | Default value |
|
||||
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------ |
|
||||
| mirrorActors | Turns on/off the rendering of actors below the diagram as well as above it | false |
|
||||
| bottomMarginAdj | Adjusts how far down the graph ended. Wide borders styles with css could generate unwanted clipping which is why this config param exists. | 1 |
|
||||
| actorFontSize | Sets the font size for the actor's description | 14 |
|
||||
| actorFontFamily | Sets the font family for the actor's description | "Open-Sans", "sans-serif" |
|
||||
| actorFontWeight | Sets the font weight for the actor's description | "Open-Sans", "sans-serif" |
|
||||
| noteFontSize | Sets the font size for actor-attached notes | 14 |
|
||||
| noteFontFamily | Sets the font family for actor-attached notes | "trebuchet ms", verdana, arial |
|
||||
| noteFontWeight | Sets the font weight for actor-attached notes | "trebuchet ms", verdana, arial |
|
||||
| noteAlign | Sets the text alignment for text in actor-attached notes | center |
|
||||
| messageFontSize | Sets the font size for actor<->actor messages | 16 |
|
||||
| messageFontFamily | Sets the font family for actor<->actor messages | "trebuchet ms", verdana, arial |
|
||||
| messageFontWeight | Sets the font weight for actor<->actor messages | "trebuchet ms", verdana, arial |
|
||||
@@ -249,3 +249,13 @@ stateDiagram-v2
|
||||
## Styling
|
||||
|
||||
Styling of the a state diagram is done by defining a number of css classes. During rendering these classes are extracted from the file located at src/themes/state.scss
|
||||
|
||||
## Spaces in state names
|
||||
|
||||
Spaces can be added to a state by defining it at the top and referencing the acronym later.
|
||||
|
||||
```mermaid-example
|
||||
stateDiagram-v2
|
||||
Yswsii: Your state with spaces in it
|
||||
[*] --> Yswsii
|
||||
```
|
||||
|
||||
@@ -64,7 +64,7 @@ Here is an example of how `%%init%%` can set the theme to 'base', this assumes t
|
||||
```
|
||||
# List of Themes
|
||||
|
||||
# Customizing Themes with `themeVariables`
|
||||
# Customizing Themes with `themeVariables`
|
||||
|
||||
The easiest way to make a custom theme is to start with the base theme, and just modify theme variables through `themeVariables`, via `%%init%%`.
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ We have compiled some Video [Tutorials](./Tutorials.md) on how to use the mermai
|
||||
**Using the npm package**
|
||||
|
||||
```
|
||||
1.You will need to install node v16, which would have npm.
|
||||
1. You will need to install node v16, which would have npm.
|
||||
|
||||
2. download yarn using npm.
|
||||
|
||||
@@ -107,7 +107,7 @@ Mermaid can load multiple diagrams, in the same page.
|
||||
|
||||
| Parameter | Description | Type | Required | Values |
|
||||
| ------------- | --------------------------------- | ------ | -------- | ------------------------- |
|
||||
| securityLevel | Level of trust for parsed diagram | String | Required | Strict, Loose, antiscript , sandbox|
|
||||
| securityLevel | Level of trust for parsed diagram | String | Required | 'sandbox', 'strict', 'loose', 'antiscript' |
|
||||
|
||||
Values:
|
||||
|
||||
@@ -118,7 +118,7 @@ Values:
|
||||
|
||||
|
||||
```note
|
||||
This changes the default behaviour of mermaid so that after upgrade to 8.2,unless the `securityLevel` is not changed, tags in flowcharts are encoded as tags and clicking is disabled.
|
||||
This changes the default behaviour of mermaid so that after upgrade to 8.2, unless the `securityLevel` is not changed, tags in flowcharts are encoded as tags and clicking is disabled.
|
||||
**sandbox** security level is still in the beta version.
|
||||
```
|
||||
|
||||
|
||||
26
package.json
26
package.json
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "mermaid",
|
||||
"version": "9.1.3",
|
||||
"version": "9.1.5",
|
||||
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
||||
"main": "dist/mermaid.core.js",
|
||||
"main": "dist/mermaid.min.js",
|
||||
"module": "dist/mermaid.esm.min.mjs",
|
||||
"exports": {
|
||||
".": {
|
||||
"require": "./dist/mermaid.core.js",
|
||||
"require": "./dist/mermaid.min.js",
|
||||
"import": "./dist/mermaid.esm.min.mjs"
|
||||
},
|
||||
"./*": "./*"
|
||||
@@ -27,7 +27,7 @@
|
||||
"postbuild": "documentation build src/mermaidAPI.js src/config.js src/defaultConfig.js --shallow -f md --markdown-toc false > docs/Setup.md",
|
||||
"build:watch": "yarn build:development --watch",
|
||||
"release": "yarn build",
|
||||
"lint": "eslint ./ --ext .js,.json,.html,.md",
|
||||
"lint": "eslint --cache ./ --ext .js,.json,.html,.md",
|
||||
"lint:fix": "yarn lint --fix",
|
||||
"e2e:depr": "yarn lint && jest e2e --config e2e/jest.config.js",
|
||||
"cypress": "cypress run",
|
||||
@@ -62,10 +62,10 @@
|
||||
"d3": "^7.0.0",
|
||||
"dagre": "^0.8.5",
|
||||
"dagre-d3": "^0.6.4",
|
||||
"dompurify": "2.3.8",
|
||||
"dompurify": "2.4.0",
|
||||
"graphlib": "^2.1.8",
|
||||
"khroma": "^2.0.0",
|
||||
"moment-mini": "^2.24.0",
|
||||
"moment-mini": "2.24.0",
|
||||
"stylis": "^4.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -76,27 +76,27 @@
|
||||
"@babel/register": "^7.14.5",
|
||||
"@commitlint/cli": "^17.0.0",
|
||||
"@commitlint/config-conventional": "^17.0.0",
|
||||
"babel-jest": "^28.0.3",
|
||||
"babel-jest": "^29.0.1",
|
||||
"babel-loader": "^8.2.2",
|
||||
"concurrently": "^7.0.0",
|
||||
"coveralls": "^3.0.2",
|
||||
"css-to-string-loader": "^0.1.3",
|
||||
"cypress": "10.2.0",
|
||||
"cypress": "9.7.0",
|
||||
"cypress-image-snapshot": "^4.0.1",
|
||||
"documentation": "13.2.0",
|
||||
"eslint": "^8.4.1",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-cypress": "^2.12.1",
|
||||
"eslint-plugin-html": "^6.2.0",
|
||||
"eslint-plugin-jest": "^26.0.0",
|
||||
"eslint-plugin-html": "^7.1.0",
|
||||
"eslint-plugin-jest": "^27.0.1",
|
||||
"eslint-plugin-jsdoc": "^39.1.0",
|
||||
"eslint-plugin-json": "^3.1.0",
|
||||
"eslint-plugin-markdown": "^2.2.1",
|
||||
"eslint-plugin-markdown": "^3.0.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"husky": "^8.0.0",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^28.0.3",
|
||||
"jest-environment-jsdom": "^28.0.2",
|
||||
"jest-environment-jsdom": "^29.0.1",
|
||||
"jison": "^0.4.18",
|
||||
"js-base64": "3.7.2",
|
||||
"lint-staged": "^13.0.0",
|
||||
@@ -122,4 +122,4 @@
|
||||
"**/*.css",
|
||||
"**/*.scss"
|
||||
]
|
||||
}
|
||||
}
|
||||
191
src/Diagram.js
191
src/Diagram.js
@@ -1,166 +1,67 @@
|
||||
import c4Db from './diagrams/c4/c4Db';
|
||||
import c4Renderer from './diagrams/c4/c4Renderer';
|
||||
import c4Parser from './diagrams/c4/parser/c4Diagram';
|
||||
import classDb from './diagrams/class/classDb';
|
||||
import classRenderer from './diagrams/class/classRenderer';
|
||||
import classRendererV2 from './diagrams/class/classRenderer-v2';
|
||||
import classParser from './diagrams/class/parser/classDiagram';
|
||||
import erDb from './diagrams/er/erDb';
|
||||
import erRenderer from './diagrams/er/erRenderer';
|
||||
import erParser from './diagrams/er/parser/erDiagram';
|
||||
import flowDb from './diagrams/flowchart/flowDb';
|
||||
import flowRenderer from './diagrams/flowchart/flowRenderer';
|
||||
import flowRendererV2 from './diagrams/flowchart/flowRenderer-v2';
|
||||
import flowParser from './diagrams/flowchart/parser/flow';
|
||||
import ganttDb from './diagrams/gantt/ganttDb';
|
||||
import ganttRenderer from './diagrams/gantt/ganttRenderer';
|
||||
import ganttParser from './diagrams/gantt/parser/gantt';
|
||||
import gitGraphAst from './diagrams/git/gitGraphAst';
|
||||
import gitGraphRenderer from './diagrams/git/gitGraphRenderer';
|
||||
import gitGraphParser from './diagrams/git/parser/gitGraph';
|
||||
import infoDb from './diagrams/info/infoDb';
|
||||
import infoRenderer from './diagrams/info/infoRenderer';
|
||||
import infoParser from './diagrams/info/parser/info';
|
||||
import pieParser from './diagrams/pie/parser/pie';
|
||||
import pieDb from './diagrams/pie/pieDb';
|
||||
import pieRenderer from './diagrams/pie/pieRenderer';
|
||||
import requirementParser from './diagrams/requirement/parser/requirementDiagram';
|
||||
import requirementDb from './diagrams/requirement/requirementDb';
|
||||
import requirementRenderer from './diagrams/requirement/requirementRenderer';
|
||||
import sequenceParser from './diagrams/sequence/parser/sequenceDiagram';
|
||||
import sequenceDb from './diagrams/sequence/sequenceDb';
|
||||
import sequenceRenderer from './diagrams/sequence/sequenceRenderer';
|
||||
import stateParser from './diagrams/state/parser/stateDiagram';
|
||||
import stateDb from './diagrams/state/stateDb';
|
||||
import stateRenderer from './diagrams/state/stateRenderer';
|
||||
import stateRendererV2 from './diagrams/state/stateRenderer-v2';
|
||||
import journeyDb from './diagrams/user-journey/journeyDb';
|
||||
import journeyRenderer from './diagrams/user-journey/journeyRenderer';
|
||||
import journeyParser from './diagrams/user-journey/parser/journey';
|
||||
import utils from './utils';
|
||||
import * as configApi from './config';
|
||||
import { log } from './logger';
|
||||
|
||||
import { getDiagrams } from './diagram-api/diagramAPI';
|
||||
import detectType from './diagram-api/detectType';
|
||||
class Diagram {
|
||||
type = 'graph';
|
||||
parser;
|
||||
renderer;
|
||||
db;
|
||||
constructor(txt) {
|
||||
const diagrams = getDiagrams();
|
||||
const cnf = configApi.getConfig();
|
||||
this.txt = txt;
|
||||
this.type = utils.detectType(txt, cnf);
|
||||
this.type = detectType(txt, cnf);
|
||||
log.debug('Type ' + this.type);
|
||||
switch (this.type) {
|
||||
case 'c4':
|
||||
this.parser = c4Parser;
|
||||
this.parser.parser.yy = c4Db;
|
||||
this.db = c4Db;
|
||||
this.renderer = c4Renderer;
|
||||
break;
|
||||
case 'gitGraph':
|
||||
this.parser = gitGraphParser;
|
||||
this.parser.parser.yy = gitGraphAst;
|
||||
this.db = gitGraphAst;
|
||||
this.renderer = gitGraphRenderer;
|
||||
break;
|
||||
case 'flowchart':
|
||||
flowDb.clear();
|
||||
this.parser = flowParser;
|
||||
this.parser.parser.yy = flowDb;
|
||||
this.db = flowDb;
|
||||
this.renderer = flowRenderer;
|
||||
break;
|
||||
case 'flowchart-v2':
|
||||
flowDb.clear();
|
||||
this.parser = flowParser;
|
||||
this.parser.parser.yy = flowDb;
|
||||
this.db = flowDb;
|
||||
this.renderer = flowRendererV2;
|
||||
break;
|
||||
case 'sequenceDiagram':
|
||||
case 'sequence':
|
||||
this.parser = sequenceParser;
|
||||
this.parser.parser.yy = sequenceDb;
|
||||
this.db = sequenceDb;
|
||||
this.renderer = sequenceRenderer;
|
||||
break;
|
||||
case 'gantt':
|
||||
this.parser = ganttParser;
|
||||
this.parser.parser.yy = ganttDb;
|
||||
this.db = ganttDb;
|
||||
this.renderer = ganttRenderer;
|
||||
break;
|
||||
case 'class':
|
||||
this.parser = classParser;
|
||||
this.parser.parser.yy = classDb;
|
||||
this.db = classDb;
|
||||
this.renderer = classRenderer;
|
||||
break;
|
||||
case 'classDiagram':
|
||||
this.parser = classParser;
|
||||
this.parser.parser.yy = classDb;
|
||||
this.db = classDb;
|
||||
this.renderer = classRendererV2;
|
||||
break;
|
||||
case 'state':
|
||||
this.parser = stateParser;
|
||||
this.parser.parser.yy = stateDb;
|
||||
this.db = stateDb;
|
||||
this.renderer = stateRenderer;
|
||||
break;
|
||||
case 'stateDiagram':
|
||||
this.parser = stateParser;
|
||||
this.parser.parser.yy = stateDb;
|
||||
this.db = stateDb;
|
||||
this.renderer = stateRendererV2;
|
||||
break;
|
||||
case 'info':
|
||||
log.debug('info info info');
|
||||
this.parser = infoParser;
|
||||
this.parser.parser.yy = infoDb;
|
||||
this.db = infoDb;
|
||||
this.renderer = infoRenderer;
|
||||
break;
|
||||
case 'pie':
|
||||
log.debug('pie');
|
||||
this.parser = pieParser;
|
||||
this.parser.parser.yy = pieDb;
|
||||
this.db = pieDb;
|
||||
this.renderer = pieRenderer;
|
||||
break;
|
||||
case 'er':
|
||||
log.debug('er');
|
||||
this.parser = erParser;
|
||||
this.parser.parser.yy = erDb;
|
||||
this.db = erDb;
|
||||
this.renderer = erRenderer;
|
||||
break;
|
||||
case 'journey':
|
||||
log.debug('Journey');
|
||||
this.parser = journeyParser;
|
||||
this.parser.parser.yy = journeyDb;
|
||||
this.db = journeyDb;
|
||||
this.renderer = journeyRenderer;
|
||||
break;
|
||||
case 'requirement':
|
||||
case 'requirementDiagram':
|
||||
log.debug('RequirementDiagram');
|
||||
this.parser = requirementParser;
|
||||
this.parser.parser.yy = requirementDb;
|
||||
this.db = requirementDb;
|
||||
this.renderer = requirementRenderer;
|
||||
break;
|
||||
default:
|
||||
log.error('Unkown graphtype');
|
||||
throw new Error('Unkown graphtype');
|
||||
|
||||
// console.log('this.type', this.type, diagrams[this.type]);
|
||||
// Setup diagram
|
||||
this.db = diagrams[this.type].db;
|
||||
this.db.clear?.();
|
||||
|
||||
this.renderer = diagrams[this.type].renderer;
|
||||
this.parser = diagrams[this.type].parser;
|
||||
this.parser.parser.yy = this.db;
|
||||
if (typeof diagrams[this.type].init === 'function') {
|
||||
diagrams[this.type].init(cnf);
|
||||
log.debug('Initialized diagram ' + this.type, cnf);
|
||||
}
|
||||
this.txt = this.txt + '\n';
|
||||
|
||||
this.parser.parser.yy.graphType = this.type;
|
||||
this.parser.parser.yy.parseError = (str, hash) => {
|
||||
const error = { str, hash };
|
||||
throw error;
|
||||
};
|
||||
this.parser.parse(txt);
|
||||
this.parser.parse(this.txt);
|
||||
}
|
||||
parse(text) {
|
||||
var parseEncounteredException = false;
|
||||
try {
|
||||
text = text + '\n';
|
||||
this.db.clear();
|
||||
|
||||
this.parser.parse(text);
|
||||
} catch (error) {
|
||||
parseEncounteredException = true;
|
||||
// Is this the correct way to access mermiad's parseError()
|
||||
// method ? (or global.mermaid.parseError()) ?
|
||||
if (global.mermaid.parseError) {
|
||||
if (error.str != undefined) {
|
||||
// handle case where error string and hash were
|
||||
// wrapped in object like`const error = { str, hash };`
|
||||
global.mermaid.parseError(error.str, error.hash);
|
||||
} else {
|
||||
// assume it is just error string and pass it on
|
||||
global.mermaid.parseError(error);
|
||||
}
|
||||
} else {
|
||||
// No mermaid.parseError() handler defined, so re-throw it
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
return !parseEncounteredException;
|
||||
}
|
||||
getParser() {
|
||||
return this.parser;
|
||||
|
||||
74
src/assignWithDepth.js
Normal file
74
src/assignWithDepth.js
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @function assignWithDepth Extends the functionality of {@link ObjectConstructor.assign} with the
|
||||
* ability to merge arbitrary-depth objects For each key in src with path `k` (recursively)
|
||||
* performs an Object.assign(dst[`k`], src[`k`]) with a slight change from the typical handling of
|
||||
* undefined for dst[`k`]: instead of raising an error, dst[`k`] is auto-initialized to {} and
|
||||
* effectively merged with src[`k`]<p> Additionally, dissimilar types will not clobber unless the
|
||||
* config.clobber parameter === true. Example:
|
||||
*
|
||||
* ```js
|
||||
* let config_0 = { foo: { bar: 'bar' }, bar: 'foo' };
|
||||
* let config_1 = { foo: 'foo', bar: 'bar' };
|
||||
* let result = assignWithDepth(config_0, config_1);
|
||||
* console.log(result);
|
||||
* //-> result: { foo: { bar: 'bar' }, bar: 'bar' }
|
||||
* ```
|
||||
*
|
||||
* Traditional Object.assign would have clobbered foo in config_0 with foo in config_1. If src is a
|
||||
* destructured array of objects and dst is not an array, assignWithDepth will apply each element
|
||||
* of src to dst in order.
|
||||
* @param dst
|
||||
* @param src
|
||||
* @param config
|
||||
* @param dst
|
||||
* @param src
|
||||
* @param config
|
||||
* @param dst
|
||||
* @param src
|
||||
* @param config
|
||||
* @param {any} dst - The destination of the merge
|
||||
* @param {any} src - The source object(s) to merge into destination
|
||||
* @param {{ depth: number; clobber: boolean }} [config={ depth: 2, clobber: false }] - Depth: depth
|
||||
* to traverse within src and dst for merging - clobber: should dissimilar types clobber (default:
|
||||
* { depth: 2, clobber: false }). Default is `{ depth: 2, clobber: false }`
|
||||
* @returns {any}
|
||||
*/
|
||||
const assignWithDepth = function (dst, src, config) {
|
||||
const { depth, clobber } = Object.assign({ depth: 2, clobber: false }, config);
|
||||
if (Array.isArray(src) && !Array.isArray(dst)) {
|
||||
src.forEach((s) => assignWithDepth(dst, s, config));
|
||||
return dst;
|
||||
} else if (Array.isArray(src) && Array.isArray(dst)) {
|
||||
src.forEach((s) => {
|
||||
if (dst.indexOf(s) === -1) {
|
||||
dst.push(s);
|
||||
}
|
||||
});
|
||||
return dst;
|
||||
}
|
||||
if (typeof dst === 'undefined' || depth <= 0) {
|
||||
if (dst !== undefined && dst !== null && typeof dst === 'object' && typeof src === 'object') {
|
||||
return Object.assign(dst, src);
|
||||
} else {
|
||||
return src;
|
||||
}
|
||||
}
|
||||
if (typeof src !== 'undefined' && typeof dst === 'object' && typeof src === 'object') {
|
||||
Object.keys(src).forEach((key) => {
|
||||
if (
|
||||
typeof src[key] === 'object' &&
|
||||
(dst[key] === undefined || typeof dst[key] === 'object')
|
||||
) {
|
||||
if (dst[key] === undefined) {
|
||||
dst[key] = Array.isArray(src[key]) ? [] : {};
|
||||
}
|
||||
dst[key] = assignWithDepth(dst[key], src[key], { depth: depth - 1, clobber });
|
||||
} else if (clobber || (typeof dst[key] !== 'object' && typeof src[key] !== 'object')) {
|
||||
dst[key] = src[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
return dst;
|
||||
};
|
||||
|
||||
export default assignWithDepth;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { assignWithDepth } from './utils';
|
||||
import assignWithDepth from './assignWithDepth';
|
||||
import { log } from './logger';
|
||||
import theme from './themes';
|
||||
import config from './defaultConfig';
|
||||
|
||||
@@ -2,6 +2,7 @@ import { select } from 'd3';
|
||||
import { log } from '../logger'; // eslint-disable-line
|
||||
import { getConfig } from '../config';
|
||||
import { sanitizeText, evaluate } from '../diagrams/common/common';
|
||||
import { decodeEntities } from '../mermaidAPI';
|
||||
|
||||
const sanitizeTxt = (txt) => sanitizeText(txt, getConfig());
|
||||
|
||||
@@ -52,7 +53,7 @@ const createLabel = (_vertexText, style, isTitle, isNode) => {
|
||||
log.info('vertexText' + vertexText);
|
||||
const node = {
|
||||
isNode,
|
||||
label: vertexText.replace(
|
||||
label: decodeEntities(vertexText).replace(
|
||||
/fa[lrsb]?:fa-[\w-]+/g,
|
||||
(s) => `<i class='${s.replace(':', ' ')}'></i>`
|
||||
),
|
||||
|
||||
@@ -510,6 +510,9 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
|
||||
case 'dependency':
|
||||
svgPath.attr('marker-start', 'url(' + url + '#' + diagramType + '-dependencyStart' + ')');
|
||||
break;
|
||||
case 'lollipop':
|
||||
svgPath.attr('marker-start', 'url(' + url + '#' + diagramType + '-lollipopStart' + ')');
|
||||
break;
|
||||
default:
|
||||
}
|
||||
switch (edge.arrowTypeEnd) {
|
||||
@@ -537,6 +540,9 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
|
||||
case 'dependency':
|
||||
svgPath.attr('marker-end', 'url(' + url + '#' + diagramType + '-dependencyEnd' + ')');
|
||||
break;
|
||||
case 'lollipop':
|
||||
svgPath.attr('marker-end', 'url(' + url + '#' + diagramType + '-lollipopEnd' + ')');
|
||||
break;
|
||||
default:
|
||||
}
|
||||
let paths = {};
|
||||
|
||||
@@ -119,6 +119,24 @@ const dependency = (elem, type) => {
|
||||
.append('path')
|
||||
.attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z');
|
||||
};
|
||||
const lollipop = (elem, type, id) => {
|
||||
elem
|
||||
.append('defs')
|
||||
.append('marker')
|
||||
.attr('id', type + '-lollipopStart')
|
||||
.attr('class', 'marker lollipop ' + type)
|
||||
.attr('refX', 0)
|
||||
.attr('refY', 7)
|
||||
.attr('markerWidth', 190)
|
||||
.attr('markerHeight', 240)
|
||||
.attr('orient', 'auto')
|
||||
.append('circle')
|
||||
.attr('stroke', 'black')
|
||||
.attr('fill', 'white')
|
||||
.attr('cx', 6)
|
||||
.attr('cy', 7)
|
||||
.attr('r', 6);
|
||||
};
|
||||
const point = (elem, type) => {
|
||||
elem
|
||||
.append('marker')
|
||||
@@ -250,6 +268,7 @@ const markers = {
|
||||
composition,
|
||||
aggregation,
|
||||
dependency,
|
||||
lollipop,
|
||||
point,
|
||||
circle,
|
||||
cross,
|
||||
|
||||
@@ -471,7 +471,7 @@ describe('sortNodesByHierarchy', function () {
|
||||
return {};
|
||||
});
|
||||
});
|
||||
it('it should sort proper en nodes are in reverse order', function () {
|
||||
it('should sort proper en nodes are in reverse order', function () {
|
||||
/*
|
||||
a -->b
|
||||
subgraph B
|
||||
@@ -488,7 +488,7 @@ describe('sortNodesByHierarchy', function () {
|
||||
g.setEdge('a', 'b', '1');
|
||||
expect(sortNodesByHierarchy(g)).toEqual(['a', 'A', 'B', 'b']);
|
||||
});
|
||||
it('it should sort proper en nodes are in correct order', function () {
|
||||
it('should sort proper en nodes are in correct order', function () {
|
||||
/*
|
||||
a -->b
|
||||
subgraph B
|
||||
|
||||
@@ -64,9 +64,9 @@ const config = {
|
||||
logLevel: 5,
|
||||
|
||||
/**
|
||||
* | Parameter | Description | Type | Required | Values |
|
||||
* | ------------- | --------------------------------- | ------ | -------- | ------------------------------- |
|
||||
* | securitylevel | Level of trust for parsed diagram | string | Required | 'strict', 'loose', 'antiscript' |
|
||||
* | Parameter | Description | Type | Required | Values |
|
||||
* | ------------- | --------------------------------- | ------ | -------- | ------------------------------------------ |
|
||||
* | securityLevel | Level of trust for parsed diagram | string | Required | 'sandbox', 'strict', 'loose', 'antiscript' |
|
||||
*
|
||||
* **Notes**:
|
||||
*
|
||||
@@ -74,6 +74,9 @@ const config = {
|
||||
* - **loose**: tags in text are allowed, click functionality is enabled
|
||||
* - **antiscript**: html tags in text are allowed, (only script element is removed), click
|
||||
* functionality is enabled
|
||||
* - **sandbox**: With this security level all rendering takes place in a sandboxed iframe. This
|
||||
* prevent any JavaScript from running in the context. This may hinder interactive functionality
|
||||
* of the diagram like scripts, popups in sequence diagram or links to other tabs/targets etc.
|
||||
*/
|
||||
securityLevel: 'strict',
|
||||
|
||||
@@ -817,6 +820,9 @@ const config = {
|
||||
},
|
||||
class: {
|
||||
arrowMarkerAbsolute: false,
|
||||
dividerMargin: 10,
|
||||
padding: 5,
|
||||
textHeight: 10,
|
||||
|
||||
/**
|
||||
* | Parameter | Description | Type | Required | Values |
|
||||
|
||||
100
src/diagram-api/detectType.js
Normal file
100
src/diagram-api/detectType.js
Normal file
@@ -0,0 +1,100 @@
|
||||
const directive =
|
||||
/[%]{2}[{]\s*(?:(?:(\w+)\s*:|(\w+))\s*(?:(?:(\w+))|((?:(?![}][%]{2}).|\r?\n)*))?\s*)(?:[}][%]{2})?/gi;
|
||||
const anyComment = /\s*%%.*\n/gm;
|
||||
const detectors = {};
|
||||
/**
|
||||
* @function detectType Detects the type of the graph text. Takes into consideration the possible
|
||||
* existence of an %%init directive
|
||||
*
|
||||
* ```mermaid
|
||||
* %%{initialize: {"startOnLoad": true, logLevel: "fatal" }}%%
|
||||
* graph LR
|
||||
* a-->b
|
||||
* b-->c
|
||||
* c-->d
|
||||
* d-->e
|
||||
* e-->f
|
||||
* f-->g
|
||||
* g-->h
|
||||
* ```
|
||||
* @param {string} text The text defining the graph
|
||||
* @param {{
|
||||
* class: { defaultRenderer: string } | undefined;
|
||||
* state: { defaultRenderer: string } | undefined;
|
||||
* flowchart: { defaultRenderer: string } | undefined;
|
||||
* }} [cnf]
|
||||
* @returns {string} A graph definition key
|
||||
*/
|
||||
const detectType = function (text, cnf) {
|
||||
text = text.replace(directive, '').replace(anyComment, '\n');
|
||||
if (text.match(/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/)) {
|
||||
return 'c4';
|
||||
}
|
||||
|
||||
if (text.match(/^\s*sequenceDiagram/)) {
|
||||
return 'sequence';
|
||||
}
|
||||
|
||||
if (text.match(/^\s*gantt/)) {
|
||||
return 'gantt';
|
||||
}
|
||||
if (text.match(/^\s*classDiagram-v2/)) {
|
||||
return 'classDiagram';
|
||||
}
|
||||
if (text.match(/^\s*classDiagram/)) {
|
||||
if (cnf && cnf.class && cnf.class.defaultRenderer === 'dagre-wrapper') return 'classDiagram';
|
||||
return 'class';
|
||||
}
|
||||
|
||||
if (text.match(/^\s*stateDiagram-v2/)) {
|
||||
return 'stateDiagram';
|
||||
}
|
||||
|
||||
if (text.match(/^\s*stateDiagram/)) {
|
||||
if (cnf && cnf.class && cnf.state.defaultRenderer === 'dagre-wrapper') return 'stateDiagram';
|
||||
return 'state';
|
||||
}
|
||||
|
||||
// if (text.match(/^\s*gitGraph/)) {
|
||||
// return 'gitGraph';
|
||||
// }
|
||||
if (text.match(/^\s*flowchart/)) {
|
||||
return 'flowchart-v2';
|
||||
}
|
||||
|
||||
if (text.match(/^\s*info/)) {
|
||||
return 'info';
|
||||
}
|
||||
if (text.match(/^\s*pie/)) {
|
||||
return 'pie';
|
||||
}
|
||||
|
||||
if (text.match(/^\s*erDiagram/)) {
|
||||
return 'er';
|
||||
}
|
||||
|
||||
if (text.match(/^\s*journey/)) {
|
||||
return 'journey';
|
||||
}
|
||||
|
||||
if (text.match(/^\s*requirement/) || text.match(/^\s*requirementDiagram/)) {
|
||||
return 'requirement';
|
||||
}
|
||||
if (cnf && cnf.flowchart && cnf.flowchart.defaultRenderer === 'dagre-wrapper')
|
||||
return 'flowchart-v2';
|
||||
const k = Object.keys(detectors);
|
||||
for (let i = 0; i < k.length; i++) {
|
||||
const key = k[i];
|
||||
const dia = detectors[key];
|
||||
if (dia && dia.detector(text)) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return 'flowchart';
|
||||
};
|
||||
export const addDetector = (key, detector) => {
|
||||
detectors[key] = {
|
||||
detector,
|
||||
};
|
||||
};
|
||||
export default detectType;
|
||||
32
src/diagram-api/diagram-orchestration.js
Normal file
32
src/diagram-api/diagram-orchestration.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import { registerDiagram } from './diagramAPI.js';
|
||||
// import mindmapDb from '../diagrams/mindmap/mindmapDb';
|
||||
// import mindmapRenderer from '../diagrams/mindmap/mindmapRenderer';
|
||||
// import mindmapParser from '../diagrams/mindmap/parser/mindmapDiagram';
|
||||
// import mindmapDetector from '../diagrams/mindmap/mindmapDetector';
|
||||
|
||||
import gitGraphDb from '../diagrams/git/gitGraphAst';
|
||||
import gitGraphRenderer from '../diagrams/git/gitGraphRenderer';
|
||||
import gitGraphParser from '../diagrams/git/parser/gitGraph';
|
||||
import gitGraphDetector from '../diagrams/git/gitGraphDetector';
|
||||
|
||||
// Register mindmap and other built-in diagrams
|
||||
// registerDiagram(
|
||||
// 'mindmap',
|
||||
// mindmapParser,
|
||||
// mindmapDb,
|
||||
// mindmapRenderer,
|
||||
// undefined,
|
||||
// mindmapRenderer,
|
||||
// mindmapDetector
|
||||
// );
|
||||
const addDiagrams = () => {
|
||||
registerDiagram(
|
||||
'gitGraph',
|
||||
gitGraphParser,
|
||||
gitGraphDb,
|
||||
gitGraphRenderer,
|
||||
undefined,
|
||||
gitGraphDetector
|
||||
);
|
||||
};
|
||||
export default addDiagrams;
|
||||
175
src/diagram-api/diagramAPI.js
Normal file
175
src/diagram-api/diagramAPI.js
Normal file
@@ -0,0 +1,175 @@
|
||||
import c4Db from '../diagrams/c4/c4Db';
|
||||
import c4Renderer from '../diagrams/c4/c4Renderer';
|
||||
import c4Parser from '../diagrams/c4/parser/c4Diagram';
|
||||
import classDb from '../diagrams/class/classDb';
|
||||
import classRenderer from '../diagrams/class/classRenderer';
|
||||
import classRendererV2 from '../diagrams/class/classRenderer-v2';
|
||||
import classParser from '../diagrams/class/parser/classDiagram';
|
||||
import erDb from '../diagrams/er/erDb';
|
||||
import erRenderer from '../diagrams/er/erRenderer';
|
||||
import erParser from '../diagrams/er/parser/erDiagram';
|
||||
import flowDb from '../diagrams/flowchart/flowDb';
|
||||
import flowRenderer from '../diagrams/flowchart/flowRenderer';
|
||||
import flowRendererV2 from '../diagrams/flowchart/flowRenderer-v2';
|
||||
import flowParser from '../diagrams/flowchart/parser/flow';
|
||||
import ganttDb from '../diagrams/gantt/ganttDb';
|
||||
import ganttRenderer from '../diagrams/gantt/ganttRenderer';
|
||||
import ganttParser from '../diagrams/gantt/parser/gantt';
|
||||
import infoDb from '../diagrams/info/infoDb';
|
||||
import infoRenderer from '../diagrams/info/infoRenderer';
|
||||
import infoParser from '../diagrams/info/parser/info';
|
||||
import pieParser from '../diagrams/pie/parser/pie';
|
||||
import pieDb from '../diagrams/pie/pieDb';
|
||||
import pieRenderer from '../diagrams/pie/pieRenderer';
|
||||
import requirementParser from '../diagrams/requirement/parser/requirementDiagram';
|
||||
import requirementDb from '../diagrams/requirement/requirementDb';
|
||||
import requirementRenderer from '../diagrams/requirement/requirementRenderer';
|
||||
import sequenceParser from '../diagrams/sequence/parser/sequenceDiagram';
|
||||
import sequenceDb from '../diagrams/sequence/sequenceDb';
|
||||
import sequenceRenderer from '../diagrams/sequence/sequenceRenderer';
|
||||
import stateParser from '../diagrams/state/parser/stateDiagram';
|
||||
import stateDb from '../diagrams/state/stateDb';
|
||||
import stateRenderer from '../diagrams/state/stateRenderer';
|
||||
import stateRendererV2 from '../diagrams/state/stateRenderer-v2';
|
||||
import journeyDb from '../diagrams/user-journey/journeyDb';
|
||||
import journeyRenderer from '../diagrams/user-journey/journeyRenderer';
|
||||
import journeyParser from '../diagrams/user-journey/parser/journey';
|
||||
import { addDetector } from './detectType';
|
||||
|
||||
const diagrams = {
|
||||
c4: {
|
||||
db: c4Db,
|
||||
renderer: c4Renderer,
|
||||
parser: c4Parser,
|
||||
init: (cnf) => {
|
||||
c4Renderer.setConf(cnf.c4);
|
||||
},
|
||||
},
|
||||
class: {
|
||||
db: classDb,
|
||||
renderer: classRenderer,
|
||||
parser: classParser,
|
||||
init: (cnf) => {
|
||||
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
classDb.clear();
|
||||
},
|
||||
},
|
||||
classDiagram: {
|
||||
db: classDb,
|
||||
renderer: classRendererV2,
|
||||
parser: classParser,
|
||||
init: (cnf) => {
|
||||
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
classDb.clear();
|
||||
},
|
||||
},
|
||||
er: {
|
||||
db: erDb,
|
||||
renderer: erRenderer,
|
||||
parser: erParser,
|
||||
},
|
||||
flowchart: {
|
||||
db: flowDb,
|
||||
renderer: flowRenderer,
|
||||
parser: flowParser,
|
||||
init: (cnf) => {
|
||||
flowRenderer.setConf(cnf.flowchart);
|
||||
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
flowDb.clear();
|
||||
flowDb.setGen('gen-1');
|
||||
},
|
||||
},
|
||||
'flowchart-v2': {
|
||||
db: flowDb,
|
||||
renderer: flowRendererV2,
|
||||
parser: flowParser,
|
||||
init: (cnf) => {
|
||||
flowRendererV2.setConf(cnf.flowchart);
|
||||
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
flowDb.clear();
|
||||
flowDb.setGen('gen-2');
|
||||
},
|
||||
},
|
||||
gantt: {
|
||||
db: ganttDb,
|
||||
renderer: ganttRenderer,
|
||||
parser: ganttParser,
|
||||
init: (cnf) => {
|
||||
ganttRenderer.setConf(cnf.gantt);
|
||||
},
|
||||
},
|
||||
// git: {
|
||||
// db: gitGraphAst,
|
||||
// renderer: gitGraphRenderer,
|
||||
// parser: gitGraphParser,
|
||||
// },
|
||||
info: {
|
||||
db: infoDb,
|
||||
renderer: infoRenderer,
|
||||
parser: infoParser,
|
||||
},
|
||||
pie: {
|
||||
db: pieDb,
|
||||
renderer: pieRenderer,
|
||||
parser: pieParser,
|
||||
},
|
||||
requirement: {
|
||||
db: requirementDb,
|
||||
renderer: requirementRenderer,
|
||||
parser: requirementParser,
|
||||
},
|
||||
sequence: {
|
||||
db: sequenceDb,
|
||||
renderer: sequenceRenderer,
|
||||
parser: sequenceParser,
|
||||
init: (cnf) => {
|
||||
cnf.sequence.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
if (cnf.sequenceDiagram) {
|
||||
// backwards compatibility
|
||||
sequenceRenderer.setConf(Object.assign(cnf.sequence, cnf.sequenceDiagram));
|
||||
console.error(
|
||||
'`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.'
|
||||
);
|
||||
}
|
||||
sequenceDb.setWrap(cnf.wrap);
|
||||
sequenceRenderer.setConf(cnf.sequence);
|
||||
},
|
||||
},
|
||||
state: {
|
||||
db: stateDb,
|
||||
renderer: stateRenderer,
|
||||
parser: stateParser,
|
||||
init: (cnf) => {
|
||||
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
stateDb.clear();
|
||||
},
|
||||
},
|
||||
stateDiagram: {
|
||||
db: stateDb,
|
||||
renderer: stateRendererV2,
|
||||
parser: stateParser,
|
||||
init: (cnf) => {
|
||||
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
stateDb.clear();
|
||||
},
|
||||
},
|
||||
journey: {
|
||||
db: journeyDb,
|
||||
renderer: journeyRenderer,
|
||||
parser: journeyParser,
|
||||
init: (cnf) => {
|
||||
journeyRenderer.setConf(cnf.journey);
|
||||
journeyDb.clear();
|
||||
},
|
||||
},
|
||||
};
|
||||
// console.log(sequenceDb);
|
||||
export const registerDiagram = (id, parser, db, renderer, init, detector) => {
|
||||
diagrams[id] = { parser, db, renderer, init };
|
||||
addDetector(id, detector);
|
||||
};
|
||||
|
||||
export const getDiagrams = () => {
|
||||
// console.log('diagrams', diagrams);
|
||||
return diagrams;
|
||||
};
|
||||
@@ -5,13 +5,8 @@ import { parser } from './parser/c4Diagram';
|
||||
import common from '../common/common';
|
||||
import c4Db from './c4Db';
|
||||
import * as configApi from '../../config';
|
||||
import utils, {
|
||||
wrapLabel,
|
||||
calculateTextWidth,
|
||||
calculateTextHeight,
|
||||
assignWithDepth,
|
||||
configureSvgSize,
|
||||
} from '../../utils';
|
||||
import assignWithDepth from '../../assignWithDepth';
|
||||
import { wrapLabel, calculateTextWidth, calculateTextHeight, configureSvgSize } from '../../utils';
|
||||
import addSVGAccessibilityFields from '../../accessibility';
|
||||
|
||||
let globalBoundaryMaxX = 0,
|
||||
@@ -25,7 +20,7 @@ parser.yy = c4Db;
|
||||
let conf = {};
|
||||
|
||||
class Bounds {
|
||||
constructor() {
|
||||
constructor(diagObj) {
|
||||
this.name = '';
|
||||
this.data = {};
|
||||
this.data.startx = undefined;
|
||||
@@ -41,7 +36,7 @@ class Bounds {
|
||||
this.nextData.stopy = undefined;
|
||||
this.nextData.cnt = 0;
|
||||
|
||||
setConf(parser.yy.getConfig());
|
||||
setConf(diagObj.db.getConfig());
|
||||
}
|
||||
|
||||
setData(startx, stopx, starty, stopy) {
|
||||
@@ -96,7 +91,7 @@ class Bounds {
|
||||
this.updateVal(this.nextData, 'stopy', _stopy, Math.max);
|
||||
}
|
||||
|
||||
init() {
|
||||
init(diagObj) {
|
||||
this.name = '';
|
||||
this.data = {
|
||||
startx: undefined,
|
||||
@@ -112,7 +107,7 @@ class Bounds {
|
||||
stopy: undefined,
|
||||
cnt: 0,
|
||||
};
|
||||
setConf(parser.yy.getConfig());
|
||||
setConf(diagObj.db.getConfig());
|
||||
}
|
||||
|
||||
bumpLastMargin(margin) {
|
||||
@@ -411,13 +406,13 @@ let getIntersectPoints = function (fromNode, endNode) {
|
||||
return { startPoint: startPoint, endPoint: endPoint };
|
||||
};
|
||||
|
||||
export const drawRels = function (diagram, rels, getC4ShapeObj) {
|
||||
export const drawRels = function (diagram, rels, getC4ShapeObj, diagObj) {
|
||||
let i = 0;
|
||||
for (let rel of rels) {
|
||||
i = i + 1;
|
||||
let relTextWrap = rel.wrap && conf.wrap;
|
||||
let relConf = messageFont(conf);
|
||||
let diagramType = parser.yy.getC4Type();
|
||||
let diagramType = diagObj.db.getC4Type();
|
||||
if (diagramType === 'C4Dynamic') rel.label.text = i + ': ' + rel.label.text;
|
||||
let textLimitWidth = calculateTextWidth(rel.label.text, relConf);
|
||||
calcC4ShapeTextWH('label', rel, relTextWrap, relConf, textLimitWidth);
|
||||
@@ -446,9 +441,10 @@ export const drawRels = function (diagram, rels, getC4ShapeObj) {
|
||||
* @param parentBoundaryAlias
|
||||
* @param parentBounds
|
||||
* @param currentBoundarys
|
||||
* @param diagObj
|
||||
*/
|
||||
function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentBoundarys) {
|
||||
let currentBounds = new Bounds();
|
||||
function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentBoundarys, diagObj) {
|
||||
let currentBounds = new Bounds(diagObj);
|
||||
// Calculate the width limit of the boundar. label/type 的长度,
|
||||
currentBounds.data.widthLimit =
|
||||
parentBounds.data.widthLimit / Math.min(c4BoundaryInRow, currentBoundarys.length);
|
||||
@@ -527,8 +523,8 @@ function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentB
|
||||
currentBounds.setData(_x, _x, _y, _y);
|
||||
}
|
||||
currentBounds.name = currentBoundary.alias;
|
||||
let currentPersonOrSystemArray = parser.yy.getC4ShapeArray(currentBoundary.alias);
|
||||
let currentPersonOrSystemKeys = parser.yy.getC4ShapeKeys(currentBoundary.alias);
|
||||
let currentPersonOrSystemArray = diagObj.db.getC4ShapeArray(currentBoundary.alias);
|
||||
let currentPersonOrSystemKeys = diagObj.db.getC4ShapeKeys(currentBoundary.alias);
|
||||
|
||||
if (currentPersonOrSystemKeys.length > 0) {
|
||||
drawC4ShapeArray(
|
||||
@@ -539,13 +535,19 @@ function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentB
|
||||
);
|
||||
}
|
||||
parentBoundaryAlias = currentBoundary.alias;
|
||||
let nextCurrentBoundarys = parser.yy.getBoundarys(parentBoundaryAlias);
|
||||
let nextCurrentBoundarys = diagObj.db.getBoundarys(parentBoundaryAlias);
|
||||
|
||||
if (nextCurrentBoundarys.length > 0) {
|
||||
// draw boundary inside currentBoundary
|
||||
// bounds.init();
|
||||
// parentBoundaryWidthLimit = bounds.data.stopx - bounds.startx;
|
||||
drawInsideBoundary(diagram, parentBoundaryAlias, currentBounds, nextCurrentBoundarys);
|
||||
drawInsideBoundary(
|
||||
diagram,
|
||||
parentBoundaryAlias,
|
||||
currentBounds,
|
||||
nextCurrentBoundarys,
|
||||
diagObj
|
||||
);
|
||||
}
|
||||
// draw boundary
|
||||
if (currentBoundary.alias !== 'global') drawBoundary(diagram, currentBoundary, currentBounds);
|
||||
@@ -566,9 +568,12 @@ function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentB
|
||||
* Draws a sequenceDiagram in the tag with id: id based on the graph definition in text.
|
||||
*
|
||||
* @param {any} text
|
||||
* @param _text
|
||||
* @param {any} id
|
||||
* @param _version
|
||||
* @param diagObj
|
||||
*/
|
||||
export const draw = function (text, id) {
|
||||
export const draw = function (_text, id, _version, diagObj) {
|
||||
conf = configApi.getConfig().c4;
|
||||
const securityLevel = configApi.getConfig().securityLevel;
|
||||
// Handle root and Document for when rendering in sanbox mode
|
||||
@@ -580,13 +585,10 @@ export const draw = function (text, id) {
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
let db = parser.yy;
|
||||
let db = diagObj.db;
|
||||
|
||||
parser.yy.clear();
|
||||
parser.yy.setWrap(conf.wrap);
|
||||
parser.parse(text + '\n');
|
||||
diagObj.db.setWrap(conf.wrap);
|
||||
|
||||
c4ShapeInRow = db.getC4ShapeInRow();
|
||||
c4BoundaryInRow = db.getC4BoundaryInRow();
|
||||
@@ -600,7 +602,7 @@ export const draw = function (text, id) {
|
||||
svgDraw.insertDatabaseIcon(diagram);
|
||||
svgDraw.insertClockIcon(diagram);
|
||||
|
||||
let screenBounds = new Bounds();
|
||||
let screenBounds = new Bounds(diagObj);
|
||||
|
||||
screenBounds.setData(
|
||||
conf.diagramMarginX,
|
||||
@@ -613,12 +615,12 @@ export const draw = function (text, id) {
|
||||
globalBoundaryMaxX = conf.diagramMarginX;
|
||||
globalBoundaryMaxY = conf.diagramMarginY;
|
||||
|
||||
const title = parser.yy.getTitle();
|
||||
const c4type = parser.yy.getC4Type();
|
||||
let currentBoundarys = parser.yy.getBoundarys('');
|
||||
const title = diagObj.db.getTitle();
|
||||
const c4type = diagObj.db.getC4Type();
|
||||
let currentBoundarys = diagObj.db.getBoundarys('');
|
||||
// switch (c4type) {
|
||||
// case 'C4Context':
|
||||
drawInsideBoundary(diagram, '', screenBounds, currentBoundarys);
|
||||
drawInsideBoundary(diagram, '', screenBounds, currentBoundarys, diagObj);
|
||||
// break;
|
||||
// }
|
||||
|
||||
@@ -628,7 +630,7 @@ export const draw = function (text, id) {
|
||||
svgDraw.insertArrowCrossHead(diagram);
|
||||
svgDraw.insertArrowFilledHead(diagram);
|
||||
|
||||
drawRels(diagram, parser.yy.getRels(), parser.yy.getC4Shape);
|
||||
drawRels(diagram, diagObj.db.getRels(), diagObj.db.getC4Shape, diagObj);
|
||||
|
||||
screenBounds.data.stopx = globalBoundaryMaxX;
|
||||
screenBounds.data.stopy = globalBoundaryMaxY;
|
||||
|
||||
84
src/diagrams/c4/parser/flow.spec.js
Normal file
84
src/diagrams/c4/parser/flow.spec.js
Normal file
@@ -0,0 +1,84 @@
|
||||
import flowDb from '../c4Db';
|
||||
import flow from './c4Diagram.jison';
|
||||
import { setConfig } from '../../../config';
|
||||
|
||||
setConfig({
|
||||
securityLevel: 'strict',
|
||||
});
|
||||
|
||||
describe('parsing a flow chart', function () {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
it('should parse a C4 diagram with one Person correctly', function () {
|
||||
flow.parser.parse(`C4Context
|
||||
title System Context diagram for Internet Banking System
|
||||
Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")`);
|
||||
|
||||
const yy = flow.parser.yy;
|
||||
expect(yy.getC4Type()).toBe('C4Context');
|
||||
expect(yy.getTitle()).toBe('System Context diagram for Internet Banking System');
|
||||
|
||||
const shapes = yy.getC4ShapeArray();
|
||||
expect(shapes.length).toBe(1);
|
||||
const onlyShape = shapes[0];
|
||||
|
||||
expect(onlyShape).toEqual({
|
||||
alias: 'customerA',
|
||||
descr: {
|
||||
text: 'A customer of the bank, with personal bank accounts.',
|
||||
},
|
||||
label: {
|
||||
text: 'Banking Customer A',
|
||||
},
|
||||
parentBoundary: 'global',
|
||||
typeC4Shape: {
|
||||
text: 'person',
|
||||
},
|
||||
wrap: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle a trailing whitespaces after statements', function () {
|
||||
const whitespace = ' ';
|
||||
const rendered = flow.parser.parse(`C4Context${whitespace}
|
||||
title System Context diagram for Internet Banking System${whitespace}
|
||||
Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")${whitespace}`);
|
||||
|
||||
expect(rendered).toBe(true);
|
||||
});
|
||||
|
||||
it('should handle parameter names that are keywords', function () {
|
||||
flow.parser.parse(`C4Context
|
||||
title title
|
||||
Person(Person, "Person", "Person")`);
|
||||
|
||||
const yy = flow.parser.yy;
|
||||
expect(yy.getTitle()).toBe('title');
|
||||
|
||||
const shapes = yy.getC4ShapeArray();
|
||||
expect(shapes.length).toBe(1);
|
||||
const onlyShape = shapes[0];
|
||||
|
||||
expect(onlyShape.alias).toBe('Person');
|
||||
expect(onlyShape.descr.text).toBe('Person');
|
||||
expect(onlyShape.label.text).toBe('Person');
|
||||
});
|
||||
|
||||
it('should allow default in the parameters', function () {
|
||||
flow.parser.parse(`C4Context
|
||||
Person(default, "default", "default")`);
|
||||
|
||||
const yy = flow.parser.yy;
|
||||
|
||||
const shapes = yy.getC4ShapeArray();
|
||||
expect(shapes.length).toBe(1);
|
||||
const onlyShape = shapes[0];
|
||||
|
||||
expect(onlyShape.alias).toBe('default');
|
||||
expect(onlyShape.descr.text).toBe('default');
|
||||
expect(onlyShape.label.text).toBe('default');
|
||||
});
|
||||
});
|
||||
@@ -206,7 +206,9 @@ const setTooltip = function (ids, tooltip) {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const getTooltip = function (id) {
|
||||
return classes[id].tooltip;
|
||||
};
|
||||
/**
|
||||
* Called by parser when a link is found. Adds the URL to the vertex data.
|
||||
*
|
||||
@@ -311,6 +313,7 @@ export const relationType = {
|
||||
EXTENSION: 1,
|
||||
COMPOSITION: 2,
|
||||
DEPENDENCY: 3,
|
||||
LOLLIPOP: 4,
|
||||
};
|
||||
|
||||
const setupToolTips = function (element) {
|
||||
@@ -337,6 +340,7 @@ const setupToolTips = function (element) {
|
||||
.text(el.attr('title'))
|
||||
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
|
||||
.style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px');
|
||||
tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '<br/>'));
|
||||
el.classed('hover', true);
|
||||
})
|
||||
.on('mouseout', function () {
|
||||
@@ -378,6 +382,7 @@ export default {
|
||||
setClickEvent,
|
||||
setCssClass,
|
||||
setLink,
|
||||
getTooltip,
|
||||
setTooltip,
|
||||
lookUpDomId,
|
||||
};
|
||||
|
||||
@@ -14,7 +14,16 @@ describe('class diagram, ', function () {
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
xit('should handle a leading newline axa', function () {
|
||||
const str = '\nclassDiagram\n' + 'class Car';
|
||||
|
||||
try {
|
||||
parser.parse(str);
|
||||
// Fail test if above expression doesn't throw anything.
|
||||
} catch (e) {
|
||||
expect(true).toBe(false);
|
||||
}
|
||||
});
|
||||
it('should handle relation definitions', function () {
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import { select } from 'd3';
|
||||
import dagre from 'dagre';
|
||||
import graphlib from 'graphlib';
|
||||
import { log } from '../../logger';
|
||||
import classDb, { lookUpDomId } from './classDb';
|
||||
import { parser } from './parser/classDiagram';
|
||||
import svgDraw from './svgDraw';
|
||||
import { getConfig } from '../../config';
|
||||
import { render } from '../../dagre-wrapper/index.js';
|
||||
// import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
|
||||
@@ -13,14 +9,12 @@ import { interpolateToCurve, getStylesFromArray, setupGraphViewbox } from '../..
|
||||
import common from '../common/common';
|
||||
import addSVGAccessibilityFields from '../../accessibility';
|
||||
|
||||
parser.yy = classDb;
|
||||
|
||||
let idCache = {};
|
||||
const padding = 20;
|
||||
|
||||
const sanitizeText = (txt) => common.sanitizeText(txt, getConfig());
|
||||
|
||||
const conf = {
|
||||
let conf = {
|
||||
dividerMargin: 10,
|
||||
padding: 5,
|
||||
textHeight: 10,
|
||||
@@ -35,8 +29,10 @@ const conf = {
|
||||
* >} classes
|
||||
* Object containing the vertices.
|
||||
* @param {SVGGElement} g The graph that is to be drawn.
|
||||
* @param _id
|
||||
* @param diagObj
|
||||
*/
|
||||
export const addClasses = function (classes, g) {
|
||||
export const addClasses = function (classes, g, _id, diagObj) {
|
||||
// const svg = select(`[id="${svgId}"]`);
|
||||
const keys = Object.keys(classes);
|
||||
log.info('keys:', keys);
|
||||
@@ -114,6 +110,7 @@ export const addClasses = function (classes, g) {
|
||||
style: styles.style,
|
||||
id: vertex.id,
|
||||
domId: vertex.domId,
|
||||
tooltip: diagObj.db.getTooltip(vertex.id) || '',
|
||||
haveCallback: vertex.haveCallback,
|
||||
link: vertex.link,
|
||||
width: vertex.type === 'group' ? 500 : undefined,
|
||||
@@ -144,6 +141,7 @@ export const addClasses = function (classes, g) {
|
||||
* @param {object} g The graph object
|
||||
*/
|
||||
export const addRelations = function (relations, g) {
|
||||
const conf = getConfig().flowchart;
|
||||
let cnt = 0;
|
||||
|
||||
let defaultStyle;
|
||||
@@ -269,16 +267,18 @@ export const setConf = function (cnf) {
|
||||
*
|
||||
* @param {string} text
|
||||
* @param {string} id
|
||||
* @param _version
|
||||
* @param diagObj
|
||||
*/
|
||||
export const draw = function (text, id) {
|
||||
export const draw = function (text, id, _version, diagObj) {
|
||||
log.info('Drawing class - ', id);
|
||||
classDb.clear();
|
||||
// const parser = classDb.parser;
|
||||
// diagObj.db.clear();
|
||||
// const parser = diagObj.db.parser;
|
||||
// parser.yy = classDb;
|
||||
|
||||
// Parse the graph definition
|
||||
// try {
|
||||
parser.parse(text);
|
||||
// parser.parse(text);
|
||||
// } catch (err) {
|
||||
// log.debug('Parsing failed');
|
||||
// }
|
||||
@@ -298,7 +298,7 @@ export const draw = function (text, id) {
|
||||
compound: true,
|
||||
})
|
||||
.setGraph({
|
||||
rankdir: classDb.getDirection(),
|
||||
rankdir: diagObj.db.getDirection(),
|
||||
nodesep: nodeSpacing,
|
||||
ranksep: rankSpacing,
|
||||
marginx: 8,
|
||||
@@ -318,11 +318,11 @@ export const draw = function (text, id) {
|
||||
// }
|
||||
|
||||
// Fetch the vertices/nodes and edges/links from the parsed graph definition
|
||||
const classes = classDb.getClasses();
|
||||
const relations = classDb.getRelations();
|
||||
const classes = diagObj.db.getClasses();
|
||||
const relations = diagObj.db.getRelations();
|
||||
|
||||
log.info(relations);
|
||||
addClasses(classes, g, id);
|
||||
addClasses(classes, g, id, diagObj);
|
||||
addRelations(relations, g);
|
||||
|
||||
// Add custom shapes
|
||||
@@ -338,11 +338,16 @@ export const draw = function (text, id) {
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const svg = root.select(`[id="${id}"]`);
|
||||
svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
const element = root.select('#' + id + ' g');
|
||||
render(element, g, ['aggregation', 'extension', 'composition', 'dependency'], 'classDiagram', id);
|
||||
render(
|
||||
element,
|
||||
g,
|
||||
['aggregation', 'extension', 'composition', 'dependency', 'lollipop'],
|
||||
'classDiagram',
|
||||
id
|
||||
);
|
||||
|
||||
setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth);
|
||||
|
||||
@@ -367,7 +372,7 @@ export const draw = function (text, id) {
|
||||
}
|
||||
}
|
||||
|
||||
addSVGAccessibilityFields(parser.yy, svg, id);
|
||||
addSVGAccessibilityFields(diagObj.db, svg, id);
|
||||
// If node has a link, wrap it in an anchor SVG object.
|
||||
// const keys = Object.keys(classes);
|
||||
// keys.forEach(function(key) {
|
||||
@@ -424,6 +429,9 @@ function getArrowMarker(type) {
|
||||
case 3:
|
||||
marker = 'dependency';
|
||||
break;
|
||||
case 4:
|
||||
marker = 'lollipop';
|
||||
break;
|
||||
default:
|
||||
marker = 'none';
|
||||
}
|
||||
|
||||
@@ -2,19 +2,15 @@ import { select } from 'd3';
|
||||
import dagre from 'dagre';
|
||||
import graphlib from 'graphlib';
|
||||
import { log } from '../../logger';
|
||||
import classDb, { lookUpDomId } from './classDb';
|
||||
import { parser } from './parser/classDiagram';
|
||||
import svgDraw from './svgDraw';
|
||||
import { configureSvgSize } from '../../utils';
|
||||
import { getConfig } from '../../config';
|
||||
import addSVGAccessibilityFields from '../../accessibility';
|
||||
|
||||
parser.yy = classDb;
|
||||
|
||||
let idCache = {};
|
||||
const padding = 20;
|
||||
|
||||
const conf = {
|
||||
const confa = {
|
||||
dividerMargin: 10,
|
||||
padding: 5,
|
||||
textHeight: 10,
|
||||
@@ -141,29 +137,20 @@ const insertMarkers = function (elem) {
|
||||
.attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z');
|
||||
};
|
||||
|
||||
/**
|
||||
* Merges the value of `conf` with the passed `cnf`
|
||||
*
|
||||
* @param {object} cnf Config to merge
|
||||
*/
|
||||
export const setConf = function (cnf) {
|
||||
const keys = Object.keys(cnf);
|
||||
|
||||
keys.forEach(function (key) {
|
||||
conf[key] = cnf[key];
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a flowchart in the tag with id: id based on the graph definition in text.
|
||||
*
|
||||
* @param {string} text
|
||||
* @param {string} id
|
||||
* @param version
|
||||
* @param _version
|
||||
* @param diagObj
|
||||
*/
|
||||
export const draw = function (text, id) {
|
||||
export const draw = function (text, id, _version, diagObj) {
|
||||
const conf = getConfig().class;
|
||||
idCache = {};
|
||||
parser.yy.clear();
|
||||
parser.parse(text);
|
||||
// diagObj.db.clear();
|
||||
// diagObj.parser.parse(text);
|
||||
|
||||
log.info('Rendering diagram ' + text);
|
||||
|
||||
@@ -181,7 +168,6 @@ export const draw = function (text, id) {
|
||||
|
||||
// Fetch the default direction, use TD if none was found
|
||||
const diagram = root.select(`[id='${id}']`);
|
||||
diagram.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
insertMarkers(diagram);
|
||||
|
||||
// Layout graph, Create a new directed graph
|
||||
@@ -199,12 +185,12 @@ export const draw = function (text, id) {
|
||||
return {};
|
||||
});
|
||||
|
||||
const classes = classDb.getClasses();
|
||||
const classes = diagObj.db.getClasses();
|
||||
const keys = Object.keys(classes);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const classDef = classes[keys[i]];
|
||||
const node = svgDraw.drawClass(diagram, classDef, conf);
|
||||
const node = svgDraw.drawClass(diagram, classDef, conf, diagObj);
|
||||
idCache[node.id] = node;
|
||||
|
||||
// Add nodes to the graph. The first argument is the node id. The second is
|
||||
@@ -215,7 +201,7 @@ export const draw = function (text, id) {
|
||||
log.info('Org height: ' + node.height);
|
||||
}
|
||||
|
||||
const relations = classDb.getRelations();
|
||||
const relations = diagObj.db.getRelations();
|
||||
relations.forEach(function (relation) {
|
||||
log.info(
|
||||
'tjoho' + getGraphId(relation.id1) + getGraphId(relation.id2) + JSON.stringify(relation)
|
||||
@@ -235,7 +221,7 @@ export const draw = function (text, id) {
|
||||
if (typeof v !== 'undefined' && typeof g.node(v) !== 'undefined') {
|
||||
log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v)));
|
||||
root
|
||||
.select('#' + lookUpDomId(v))
|
||||
.select('#' + diagObj.db.lookUpDomId(v))
|
||||
.attr(
|
||||
'transform',
|
||||
'translate(' +
|
||||
@@ -250,7 +236,7 @@ export const draw = function (text, id) {
|
||||
g.edges().forEach(function (e) {
|
||||
if (typeof e !== 'undefined' && typeof g.edge(e) !== 'undefined') {
|
||||
log.debug('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(g.edge(e)));
|
||||
svgDraw.drawEdge(diagram, g.edge(e), g.edge(e).relation, conf);
|
||||
svgDraw.drawEdge(diagram, g.edge(e), g.edge(e).relation, conf, diagObj);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -264,10 +250,9 @@ export const draw = function (text, id) {
|
||||
const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`;
|
||||
log.debug(`viewBox ${vBox}`);
|
||||
diagram.attr('viewBox', vBox);
|
||||
addSVGAccessibilityFields(parser.yy, diagram, id);
|
||||
addSVGAccessibilityFields(diagObj.db, diagram, id);
|
||||
};
|
||||
|
||||
export default {
|
||||
setConf,
|
||||
draw,
|
||||
};
|
||||
|
||||
@@ -44,6 +44,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
||||
"classDiagram-v2" return 'CLASS_DIAGRAM';
|
||||
"classDiagram" return 'CLASS_DIAGRAM';
|
||||
[{] { this.begin("struct"); /*console.log('Starting struct');*/ return 'STRUCT_START';}
|
||||
<INITIAL,struct>"[*]" { /*console.log('EDGE_STATE=',yytext);*/ return 'EDGE_STATE';}
|
||||
<struct><<EOF>> return "EOF_IN_STRUCT";
|
||||
<struct>[{] return "OPEN_IN_STRUCT";
|
||||
<struct>[}] { /*console.log('Ending struct');*/this.popState(); return 'STRUCT_STOP';}}
|
||||
@@ -104,6 +105,7 @@ Function arguments are optional: 'call <callback_name>()' simply executes 'callb
|
||||
\s*\< return 'DEPENDENCY';
|
||||
\s*\* return 'COMPOSITION';
|
||||
\s*o return 'AGGREGATION';
|
||||
\s*\(\) return 'LOLLIPOP';
|
||||
\-\- return 'LINE';
|
||||
\.\. return 'DOTTED_LINE';
|
||||
":"{1}[^:\n;]+ return 'LABEL';
|
||||
@@ -310,6 +312,7 @@ relationType
|
||||
| EXTENSION { $$=yy.relationType.EXTENSION;}
|
||||
| COMPOSITION { $$=yy.relationType.COMPOSITION;}
|
||||
| DEPENDENCY { $$=yy.relationType.DEPENDENCY;}
|
||||
| LOLLIPOP { $$=yy.relationType.LOLLIPOP;}
|
||||
;
|
||||
|
||||
lineType
|
||||
|
||||
@@ -128,6 +128,18 @@ g.classGroup line {
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
#lollipopStart, .lollipop {
|
||||
fill: ${options.mainBkg} !important;
|
||||
stroke: ${options.lineColor} !important;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
#lollipopEnd, .lollipop {
|
||||
fill: ${options.mainBkg} !important;
|
||||
stroke: ${options.lineColor} !important;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.edgeTerminals {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import { line, curveBasis } from 'd3';
|
||||
import { lookUpDomId, relationType } from './classDb';
|
||||
import utils from '../../utils';
|
||||
import { log } from '../../logger';
|
||||
import { parseGenericTypes } from '../common/common';
|
||||
|
||||
let edgeCount = 0;
|
||||
export const drawEdge = function (elem, path, relation, conf) {
|
||||
export const drawEdge = function (elem, path, relation, conf, diagObj) {
|
||||
const getRelationType = function (type) {
|
||||
switch (type) {
|
||||
case relationType.AGGREGATION:
|
||||
case diagObj.db.relationType.AGGREGATION:
|
||||
return 'aggregation';
|
||||
case relationType.EXTENSION:
|
||||
case diagObj.db.EXTENSION:
|
||||
return 'extension';
|
||||
case relationType.COMPOSITION:
|
||||
case diagObj.db.COMPOSITION:
|
||||
return 'composition';
|
||||
case relationType.DEPENDENCY:
|
||||
case diagObj.db.DEPENDENCY:
|
||||
return 'dependency';
|
||||
case diagObj.db.LOLLIPOP:
|
||||
return 'lollipop';
|
||||
}
|
||||
};
|
||||
|
||||
@@ -150,10 +152,11 @@ export const drawEdge = function (elem, path, relation, conf) {
|
||||
* @param {SVGSVGElement} elem The element to draw it into
|
||||
* @param classDef
|
||||
* @param conf
|
||||
* @param diagObj
|
||||
* @todo Add more information in the JSDOC here
|
||||
*/
|
||||
export const drawClass = function (elem, classDef, conf) {
|
||||
log.info('Rendering class ' + classDef);
|
||||
export const drawClass = function (elem, classDef, conf, diagObj) {
|
||||
log.debug('Rendering class ', classDef, conf);
|
||||
|
||||
const id = classDef.id;
|
||||
const classInfo = {
|
||||
@@ -164,7 +167,7 @@ export const drawClass = function (elem, classDef, conf) {
|
||||
};
|
||||
|
||||
// add class group
|
||||
const g = elem.append('g').attr('id', lookUpDomId(id)).attr('class', 'classGroup');
|
||||
const g = elem.append('g').attr('id', diagObj.db.lookUpDomId(id)).attr('class', 'classGroup');
|
||||
|
||||
// add title
|
||||
let title;
|
||||
@@ -412,29 +415,6 @@ const addTspan = function (textEl, txt, isFirst, conf) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes generics in typescript syntax
|
||||
*
|
||||
* @example <caption>Array of array of strings in typescript syntax</caption>
|
||||
* // returns "Array<Array<string>>"
|
||||
* parseGenericTypes('Array~Array~string~~');
|
||||
*
|
||||
* @param {string} text The text to convert
|
||||
* @returns {string} The converted string
|
||||
*/
|
||||
const parseGenericTypes = function (text) {
|
||||
let cleanedText = text;
|
||||
|
||||
if (text.indexOf('~') != -1) {
|
||||
cleanedText = cleanedText.replace('~', '<');
|
||||
cleanedText = cleanedText.replace('~', '>');
|
||||
|
||||
return parseGenericTypes(cleanedText);
|
||||
} else {
|
||||
return cleanedText;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gives the styles for a classifier
|
||||
*
|
||||
|
||||
@@ -57,11 +57,11 @@ export const removeScript = (txt) => {
|
||||
}
|
||||
}
|
||||
let decodedText = removeEscapes(rs);
|
||||
decodedText = decodedText.replaceAll(/script>/gi, '#');
|
||||
decodedText = decodedText.replaceAll(/javascript:/gi, '#');
|
||||
decodedText = decodedText.replaceAll(/javascript&colon/gi, '#');
|
||||
decodedText = decodedText.replaceAll(/onerror=/gi, 'onerror:');
|
||||
decodedText = decodedText.replaceAll(/<iframe/gi, '');
|
||||
decodedText = decodedText.replace(/script>/gi, '#');
|
||||
decodedText = decodedText.replace(/javascript:/gi, '#');
|
||||
decodedText = decodedText.replace(/javascript&colon/gi, '#');
|
||||
decodedText = decodedText.replace(/onerror=/gi, 'onerror:');
|
||||
decodedText = decodedText.replace(/<iframe/gi, '');
|
||||
return decodedText;
|
||||
};
|
||||
|
||||
@@ -182,6 +182,29 @@ const getUrl = (useAbsolute) => {
|
||||
*/
|
||||
export const evaluate = (val) => (val === 'false' || val === false ? false : true);
|
||||
|
||||
/**
|
||||
* Makes generics in typescript syntax
|
||||
*
|
||||
* @example <caption>Array of array of strings in typescript syntax</caption>
|
||||
* // returns "Array<Array<string>>"
|
||||
* parseGenericTypes('Array~Array~string~~');
|
||||
*
|
||||
* @param {string} text The text to convert
|
||||
* @returns {string} The converted string
|
||||
*/
|
||||
export const parseGenericTypes = function (text) {
|
||||
let cleanedText = text;
|
||||
|
||||
if (text.indexOf('~') != -1) {
|
||||
cleanedText = cleanedText.replace('~', '<');
|
||||
cleanedText = cleanedText.replace('~', '>');
|
||||
|
||||
return parseGenericTypes(cleanedText);
|
||||
} else {
|
||||
return cleanedText;
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
getRows,
|
||||
sanitizeText,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { sanitizeText, removeScript, removeEscapes } from './common';
|
||||
import { sanitizeText, removeScript, removeEscapes, parseGenericTypes } from './common';
|
||||
|
||||
describe('when securityLevel is antiscript, all script must be removed', function () {
|
||||
/**
|
||||
@@ -103,3 +103,10 @@ describe('Sanitize text', function () {
|
||||
expect(result).not.toContain('javascript:alert(1)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('generic parser', function () {
|
||||
it('should parse generic types', function () {
|
||||
const result = parseGenericTypes('test~T~');
|
||||
expect(result).toEqual('test<T>');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import graphlib from 'graphlib';
|
||||
import { line, curveBasis, select } from 'd3';
|
||||
import erDb from './erDb';
|
||||
import erParser from './parser/erDiagram';
|
||||
// import erDb from './erDb';
|
||||
// import erParser from './parser/erDiagram';
|
||||
import dagre from 'dagre';
|
||||
import { getConfig } from '../../config';
|
||||
import { log } from '../../logger';
|
||||
import erMarkers from './erMarkers';
|
||||
import { configureSvgSize } from '../../utils';
|
||||
import addSVGAccessibilityFields from '../../accessibility';
|
||||
import { parseGenericTypes } from '../common/common';
|
||||
|
||||
const conf = {};
|
||||
let conf = {};
|
||||
|
||||
/**
|
||||
* Allows the top-level API module to inject config specific to this renderer, storing it in the
|
||||
@@ -63,6 +64,8 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
|
||||
const attrPrefix = `${entityTextNode.node().id}-attr-${attrNum}`;
|
||||
let nodeHeight = 0;
|
||||
|
||||
const attributeType = parseGenericTypes(item.attributeType);
|
||||
|
||||
// Add a text node for the attribute type
|
||||
const typeNode = groupNode
|
||||
.append('text')
|
||||
@@ -76,7 +79,7 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
|
||||
'style',
|
||||
'font-family: ' + getConfig().fontFamily + '; font-size: ' + attrFontSize + 'px'
|
||||
)
|
||||
.text(item.attributeType);
|
||||
.text(attributeType);
|
||||
|
||||
// Add a text node for the attribute name
|
||||
const nameNode = groupNode
|
||||
@@ -409,8 +412,9 @@ let relCnt = 0;
|
||||
* @param g The graph containing the edge information
|
||||
* @param insert The insertion point in the svg DOM (because relationships have markers that need to
|
||||
* sit 'behind' opaque entity boxes)
|
||||
* @param diagObj
|
||||
*/
|
||||
const drawRelationshipFromLayout = function (svg, rel, g, insert) {
|
||||
const drawRelationshipFromLayout = function (svg, rel, g, insert, diagObj) {
|
||||
relCnt++;
|
||||
|
||||
// Find the edge relating to this relationship
|
||||
@@ -435,7 +439,7 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert) {
|
||||
.attr('fill', 'none');
|
||||
|
||||
// ...and with dashes if necessary
|
||||
if (rel.relSpec.relType === erDb.Identification.NON_IDENTIFYING) {
|
||||
if (rel.relSpec.relType === diagObj.db.Identification.NON_IDENTIFYING) {
|
||||
svgPath.attr('stroke-dasharray', '8,8');
|
||||
}
|
||||
|
||||
@@ -457,40 +461,40 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert) {
|
||||
|
||||
// Note that the 'A' entity's marker is at the end of the relationship and the 'B' entity's marker is at the start
|
||||
switch (rel.relSpec.cardA) {
|
||||
case erDb.Cardinality.ZERO_OR_ONE:
|
||||
case diagObj.db.Cardinality.ZERO_OR_ONE:
|
||||
svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.ZERO_OR_ONE_END + ')');
|
||||
break;
|
||||
case erDb.Cardinality.ZERO_OR_MORE:
|
||||
case diagObj.db.Cardinality.ZERO_OR_MORE:
|
||||
svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.ZERO_OR_MORE_END + ')');
|
||||
break;
|
||||
case erDb.Cardinality.ONE_OR_MORE:
|
||||
case diagObj.db.Cardinality.ONE_OR_MORE:
|
||||
svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.ONE_OR_MORE_END + ')');
|
||||
break;
|
||||
case erDb.Cardinality.ONLY_ONE:
|
||||
case diagObj.db.Cardinality.ONLY_ONE:
|
||||
svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.ONLY_ONE_END + ')');
|
||||
break;
|
||||
}
|
||||
|
||||
switch (rel.relSpec.cardB) {
|
||||
case erDb.Cardinality.ZERO_OR_ONE:
|
||||
case diagObj.db.Cardinality.ZERO_OR_ONE:
|
||||
svgPath.attr(
|
||||
'marker-start',
|
||||
'url(' + url + '#' + erMarkers.ERMarkers.ZERO_OR_ONE_START + ')'
|
||||
);
|
||||
break;
|
||||
case erDb.Cardinality.ZERO_OR_MORE:
|
||||
case diagObj.db.Cardinality.ZERO_OR_MORE:
|
||||
svgPath.attr(
|
||||
'marker-start',
|
||||
'url(' + url + '#' + erMarkers.ERMarkers.ZERO_OR_MORE_START + ')'
|
||||
);
|
||||
break;
|
||||
case erDb.Cardinality.ONE_OR_MORE:
|
||||
case diagObj.db.Cardinality.ONE_OR_MORE:
|
||||
svgPath.attr(
|
||||
'marker-start',
|
||||
'url(' + url + '#' + erMarkers.ERMarkers.ONE_OR_MORE_START + ')'
|
||||
);
|
||||
break;
|
||||
case erDb.Cardinality.ONLY_ONE:
|
||||
case diagObj.db.Cardinality.ONLY_ONE:
|
||||
svgPath.attr('marker-start', 'url(' + url + '#' + erMarkers.ERMarkers.ONLY_ONE_START + ')');
|
||||
break;
|
||||
}
|
||||
@@ -540,12 +544,14 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert) {
|
||||
*
|
||||
* @param text The text of the diagram
|
||||
* @param id The unique id of the DOM node that contains the diagram
|
||||
* @param _version
|
||||
* @param diag
|
||||
* @param diagObj
|
||||
*/
|
||||
export const draw = function (text, id) {
|
||||
export const draw = function (text, id, _version, diagObj) {
|
||||
conf = getConfig().er;
|
||||
log.info('Drawing ER diagram');
|
||||
erDb.clear();
|
||||
const parser = erParser.parser;
|
||||
parser.yy = erDb;
|
||||
// diag.db.clear();
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and Document for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
@@ -556,14 +562,14 @@ export const draw = function (text, id) {
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
// const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
// Parse the text to populate erDb
|
||||
try {
|
||||
parser.parse(text);
|
||||
} catch (err) {
|
||||
log.debug('Parsing failed');
|
||||
}
|
||||
// try {
|
||||
// parser.parse(text);
|
||||
// } catch (err) {
|
||||
// log.debug('Parsing failed');
|
||||
// }
|
||||
|
||||
// Get a reference to the svg node that contains the text
|
||||
const svg = root.select(`[id='${id}']`);
|
||||
@@ -612,12 +618,12 @@ export const draw = function (text, id) {
|
||||
|
||||
// Draw the entities (at 0,0), returning the first svg node that got
|
||||
// inserted - this represents the insertion point for relationship paths
|
||||
const firstEntity = drawEntities(svg, erDb.getEntities(), g);
|
||||
const firstEntity = drawEntities(svg, diagObj.db.getEntities(), g);
|
||||
|
||||
// TODO: externalise the addition of entities to the graph - it's a bit 'buried' in the above
|
||||
|
||||
// Add all the relationships to the graph
|
||||
const relationships = addRelationships(erDb.getRelationships(), g);
|
||||
const relationships = addRelationships(diagObj.db.getRelationships(), g);
|
||||
|
||||
dagre.layout(g); // Node and edge positions will be updated
|
||||
|
||||
@@ -626,7 +632,7 @@ export const draw = function (text, id) {
|
||||
|
||||
// Draw the relationships
|
||||
relationships.forEach(function (rel) {
|
||||
drawRelationshipFromLayout(svg, rel, g, firstEntity);
|
||||
drawRelationshipFromLayout(svg, rel, g, firstEntity, diagObj);
|
||||
});
|
||||
|
||||
const padding = conf.diagramPadding;
|
||||
@@ -639,7 +645,7 @@ export const draw = function (text, id) {
|
||||
|
||||
svg.attr('viewBox', `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`);
|
||||
|
||||
addSVGAccessibilityFields(parser.yy, svg, id);
|
||||
addSVGAccessibilityFields(diagObj.db, svg, id);
|
||||
}; // draw
|
||||
|
||||
export default {
|
||||
|
||||
@@ -29,7 +29,8 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
||||
"{" { this.begin("block"); return 'BLOCK_START'; }
|
||||
<block>\s+ /* skip whitespace in block */
|
||||
<block>\b((?:PK)|(?:FK))\b return 'ATTRIBUTE_KEY'
|
||||
<block>[A-Za-z][A-Za-z0-9\-_]* return 'ATTRIBUTE_WORD'
|
||||
<block>(.*?)[~](.*?)*[~] return 'ATTRIBUTE_WORD';
|
||||
<block>[A-Za-z][A-Za-z0-9\-_\[\]]* return 'ATTRIBUTE_WORD'
|
||||
<block>\"[^"]*\" return 'COMMENT';
|
||||
<block>[\n]+ /* nothing */
|
||||
<block>"}" { this.popState(); return 'BLOCK_STOP'; }
|
||||
|
||||
@@ -85,6 +85,31 @@ describe('when parsing ER diagram it...', function () {
|
||||
expect(entities[entity].attributes.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should allow an entity with attribute that has a generic type', function () {
|
||||
const entity = 'BOOK';
|
||||
const attribute1 = 'type~T~ type';
|
||||
const attribute2 = 'option~T~ readable "comment"';
|
||||
const attribute3 = 'string id PK';
|
||||
|
||||
erDiagram.parser.parse(
|
||||
`erDiagram\n${entity} {\n${attribute1}\n${attribute2}\n${attribute3}\n}`
|
||||
);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should allow an entity with attribute that is an array', function () {
|
||||
const entity = 'BOOK';
|
||||
const attribute1 = 'string[] readers FK "comment"';
|
||||
const attribute2 = 'string[] authors FK';
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity} {\n${attribute1}\n${attribute2}\n}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(2);
|
||||
});
|
||||
|
||||
it('should allow an entity with multiple attributes to be defined', function () {
|
||||
const entity = 'BOOK';
|
||||
const attribute1 = 'string title';
|
||||
|
||||
@@ -409,6 +409,7 @@ const setupToolTips = function (element) {
|
||||
.text(el.attr('title'))
|
||||
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
|
||||
.style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px');
|
||||
tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '<br/>'));
|
||||
el.classed('hover', true);
|
||||
})
|
||||
.on('mouseout', function () {
|
||||
@@ -489,7 +490,6 @@ export const addSubGraph = function (_id, list, _title) {
|
||||
const { nodeList: nl, dir } = uniq(nodeList.concat.apply(nodeList, list));
|
||||
nodeList = nl;
|
||||
if (version === 'gen-1') {
|
||||
log.warn('LOOKING UP');
|
||||
for (let i = 0; i < nodeList.length; i++) {
|
||||
nodeList[i] = lookUpDomId(nodeList[i]);
|
||||
}
|
||||
|
||||
@@ -28,8 +28,9 @@ export const setConf = function (cnf) {
|
||||
* @param svgId
|
||||
* @param root
|
||||
* @param doc
|
||||
* @param diagObj
|
||||
*/
|
||||
export const addVertices = function (vert, g, svgId, root, doc) {
|
||||
export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
|
||||
const svg = root.select(`[id="${svgId}"]`);
|
||||
const keys = Object.keys(vert);
|
||||
|
||||
@@ -152,8 +153,8 @@ export const addVertices = function (vert, g, svgId, root, doc) {
|
||||
id: vertex.id,
|
||||
link: vertex.link,
|
||||
linkTarget: vertex.linkTarget,
|
||||
tooltip: flowDb.getTooltip(vertex.id) || '',
|
||||
domId: flowDb.lookUpDomId(vertex.id),
|
||||
tooltip: diagObj.db.getTooltip(vertex.id) || '',
|
||||
domId: diagObj.db.lookUpDomId(vertex.id),
|
||||
haveCallback: vertex.haveCallback,
|
||||
width: vertex.type === 'group' ? 500 : undefined,
|
||||
dir: vertex.dir,
|
||||
@@ -171,7 +172,7 @@ export const addVertices = function (vert, g, svgId, root, doc) {
|
||||
class: classStr,
|
||||
style: styles.style,
|
||||
id: vertex.id,
|
||||
domId: flowDb.lookUpDomId(vertex.id),
|
||||
domId: diagObj.db.lookUpDomId(vertex.id),
|
||||
width: vertex.type === 'group' ? 500 : undefined,
|
||||
type: vertex.type,
|
||||
dir: vertex.dir,
|
||||
@@ -186,8 +187,9 @@ export const addVertices = function (vert, g, svgId, root, doc) {
|
||||
*
|
||||
* @param {object} edges The edges to add to the graph
|
||||
* @param {object} g The graph object
|
||||
* @param diagObj
|
||||
*/
|
||||
export const addEdges = function (edges, g) {
|
||||
export const addEdges = function (edges, g, diagObj) {
|
||||
log.info('abc78 edges = ', edges);
|
||||
let cnt = 0;
|
||||
let linkIdCnt = {};
|
||||
@@ -304,11 +306,7 @@ export const addEdges = function (edges, g) {
|
||||
edgeData.arrowheadStyle = 'fill: #333';
|
||||
edgeData.labelpos = 'c';
|
||||
}
|
||||
// if (evaluate(getConfig().flowchart.htmlLabels) && false) {
|
||||
// // eslint-disable-line
|
||||
// edgeData.labelType = 'html';
|
||||
// edgeData.label = `<span id="L-${linkId}" class="edgeLabel L-${linkNameStart}' L-${linkNameEnd}">${edge.text}</span>`;
|
||||
// } else {
|
||||
|
||||
edgeData.labelType = 'text';
|
||||
edgeData.label = edge.text.replace(common.lineBreakRegex, '\n');
|
||||
|
||||
@@ -317,7 +315,6 @@ export const addEdges = function (edges, g) {
|
||||
}
|
||||
|
||||
edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:');
|
||||
// }
|
||||
|
||||
edgeData.id = linkId;
|
||||
edgeData.classes = 'flowchart-link ' + linkNameStart + ' ' + linkNameEnd;
|
||||
@@ -331,22 +328,19 @@ export const addEdges = function (edges, g) {
|
||||
* Returns the all the styles from classDef statements in the graph definition.
|
||||
*
|
||||
* @param text
|
||||
* @param diagObj
|
||||
* @returns {object} ClassDef styles
|
||||
*/
|
||||
export const getClasses = function (text) {
|
||||
export const getClasses = function (text, diagObj) {
|
||||
log.info('Extracting classes');
|
||||
flowDb.clear();
|
||||
const parser = flow.parser;
|
||||
parser.yy = flowDb;
|
||||
|
||||
diagObj.db.clear();
|
||||
try {
|
||||
// Parse the graph definition
|
||||
parser.parse(text);
|
||||
diagObj.parse(text);
|
||||
return diagObj.db.getClasses();
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
return flowDb.getClasses();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -356,22 +350,15 @@ export const getClasses = function (text) {
|
||||
* @param id
|
||||
*/
|
||||
|
||||
export const draw = function (text, id) {
|
||||
export const draw = function (text, id, _version, diagObj) {
|
||||
log.info('Drawing flowchart');
|
||||
flowDb.clear();
|
||||
diagObj.db.clear();
|
||||
flowDb.setGen('gen-2');
|
||||
const parser = flow.parser;
|
||||
parser.yy = flowDb;
|
||||
|
||||
// Parse the graph definition
|
||||
// try {
|
||||
parser.parse(text);
|
||||
// } catch (err) {
|
||||
// log.debug('Parsing failed');
|
||||
// }
|
||||
diagObj.parser.parse(text);
|
||||
|
||||
// Fetch the default direction, use TD if none was found
|
||||
let dir = flowDb.getDirection();
|
||||
let dir = diagObj.db.getDirection();
|
||||
if (typeof dir === 'undefined') {
|
||||
dir = 'TD';
|
||||
}
|
||||
@@ -401,26 +388,26 @@ export const draw = function (text, id) {
|
||||
rankdir: dir,
|
||||
nodesep: nodeSpacing,
|
||||
ranksep: rankSpacing,
|
||||
marginx: 8,
|
||||
marginy: 8,
|
||||
marginx: 0,
|
||||
marginy: 0,
|
||||
})
|
||||
.setDefaultEdgeLabel(function () {
|
||||
return {};
|
||||
});
|
||||
|
||||
let subG;
|
||||
const subGraphs = flowDb.getSubGraphs();
|
||||
const subGraphs = diagObj.db.getSubGraphs();
|
||||
log.info('Subgraphs - ', subGraphs);
|
||||
for (let i = subGraphs.length - 1; i >= 0; i--) {
|
||||
subG = subGraphs[i];
|
||||
log.info('Subgraph - ', subG);
|
||||
flowDb.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir);
|
||||
diagObj.db.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir);
|
||||
}
|
||||
|
||||
// Fetch the vertices/nodes and edges/links from the parsed graph definition
|
||||
const vert = flowDb.getVertices();
|
||||
const vert = diagObj.db.getVertices();
|
||||
|
||||
const edges = flowDb.getEdges();
|
||||
const edges = diagObj.db.getEdges();
|
||||
|
||||
log.info(edges);
|
||||
let i = 0;
|
||||
@@ -435,18 +422,17 @@ export const draw = function (text, id) {
|
||||
g.setParent(subG.nodes[j], subG.id);
|
||||
}
|
||||
}
|
||||
addVertices(vert, g, id, root, doc);
|
||||
addEdges(edges, g);
|
||||
addVertices(vert, g, id, root, doc, diagObj);
|
||||
addEdges(edges, g, diagObj);
|
||||
|
||||
// Add custom shapes
|
||||
// flowChartShapes.addToRenderV2(addShape);
|
||||
|
||||
// Set up an SVG group so that we can translate the final graph.
|
||||
const svg = root.select(`[id="${id}"]`);
|
||||
svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
|
||||
// Adds title and description to the flow chart
|
||||
addSVGAccessibilityFields(parser.yy, svg, id);
|
||||
addSVGAccessibilityFields(diagObj.db, svg, id);
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
const element = root.select('#' + id + ' g');
|
||||
@@ -455,7 +441,7 @@ export const draw = function (text, id) {
|
||||
setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth);
|
||||
|
||||
// Index nodes
|
||||
flowDb.indexNodes('subGraph' + i);
|
||||
diagObj.db.indexNodes('subGraph' + i);
|
||||
|
||||
// Add label rects for non html labels
|
||||
if (!conf.htmlLabels) {
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import graphlib from 'graphlib';
|
||||
import { select, curveLinear, selectAll } from 'd3';
|
||||
|
||||
import flowDb from './flowDb';
|
||||
import flow from './parser/flow';
|
||||
import { getConfig } from '../../config';
|
||||
|
||||
import dagreD3 from 'dagre-d3';
|
||||
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
|
||||
import { log } from '../../logger';
|
||||
@@ -30,8 +26,9 @@ export const setConf = function (cnf) {
|
||||
* @param root
|
||||
* @param doc
|
||||
* @param _doc
|
||||
* @param diagObj
|
||||
*/
|
||||
export const addVertices = function (vert, g, svgId, root, _doc) {
|
||||
export const addVertices = function (vert, g, svgId, root, _doc, diagObj) {
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
|
||||
const svg = !root ? select(`[id="${svgId}"]`) : root.select(`[id="${svgId}"]`);
|
||||
@@ -144,7 +141,7 @@ export const addVertices = function (vert, g, svgId, root, _doc) {
|
||||
}
|
||||
// Add the node
|
||||
log.warn('Adding node', vertex.id, vertex.domId);
|
||||
g.setNode(flowDb.lookUpDomId(vertex.id), {
|
||||
g.setNode(diagObj.db.lookUpDomId(vertex.id), {
|
||||
labelType: 'svg',
|
||||
labelStyle: styles.labelStyle,
|
||||
shape: _shape,
|
||||
@@ -153,7 +150,7 @@ export const addVertices = function (vert, g, svgId, root, _doc) {
|
||||
ry: radious,
|
||||
class: classStr,
|
||||
style: styles.style,
|
||||
id: flowDb.lookUpDomId(vertex.id),
|
||||
id: diagObj.db.lookUpDomId(vertex.id),
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -163,8 +160,9 @@ export const addVertices = function (vert, g, svgId, root, _doc) {
|
||||
*
|
||||
* @param {object} edges The edges to add to the graph
|
||||
* @param {object} g The graph object
|
||||
* @param diagObj
|
||||
*/
|
||||
export const addEdges = function (edges, g) {
|
||||
export const addEdges = function (edges, g, diagObj) {
|
||||
let cnt = 0;
|
||||
|
||||
let defaultStyle;
|
||||
@@ -264,7 +262,7 @@ export const addEdges = function (edges, g) {
|
||||
edgeData.minlen = edge.length || 1;
|
||||
|
||||
// Add the edge to the graph
|
||||
g.setEdge(flowDb.lookUpDomId(edge.start), flowDb.lookUpDomId(edge.end), edgeData, cnt);
|
||||
g.setEdge(diagObj.db.lookUpDomId(edge.start), diagObj.db.lookUpDomId(edge.end), edgeData, cnt);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -272,18 +270,16 @@ export const addEdges = function (edges, g) {
|
||||
* Returns the all the styles from classDef statements in the graph definition.
|
||||
*
|
||||
* @param text
|
||||
* @param diagObj
|
||||
* @returns {object} ClassDef styles
|
||||
*/
|
||||
export const getClasses = function (text) {
|
||||
export const getClasses = function (text, diagObj) {
|
||||
log.info('Extracting classes');
|
||||
flowDb.clear();
|
||||
diagObj.db.clear();
|
||||
try {
|
||||
const parser = flow.parser;
|
||||
parser.yy = flowDb;
|
||||
|
||||
// Parse the graph definition
|
||||
parser.parse(text);
|
||||
return flowDb.getClasses();
|
||||
diagObj.parse(text);
|
||||
return diagObj.db.getClasses();
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
@@ -294,14 +290,12 @@ export const getClasses = function (text) {
|
||||
*
|
||||
* @param text
|
||||
* @param id
|
||||
* @param _version
|
||||
* @param diagObj
|
||||
*/
|
||||
export const draw = function (text, id) {
|
||||
export const draw = function (text, id, _version, diagObj) {
|
||||
log.info('Drawing flowchart');
|
||||
flowDb.clear();
|
||||
flowDb.setGen('gen-1');
|
||||
const parser = flow.parser;
|
||||
parser.yy = flowDb;
|
||||
|
||||
diagObj.db.clear();
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
@@ -314,14 +308,14 @@ export const draw = function (text, id) {
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
// Parse the graph definition
|
||||
// try {
|
||||
parser.parse(text);
|
||||
// } catch (err) {
|
||||
// log.debug('Parsing failed');
|
||||
// }
|
||||
try {
|
||||
diagObj.parser.parse(text);
|
||||
} catch (err) {
|
||||
log.debug('Parsing failed');
|
||||
}
|
||||
|
||||
// Fetch the default direction, use TD if none was found
|
||||
let dir = flowDb.getDirection();
|
||||
let dir = diagObj.db.getDirection();
|
||||
if (typeof dir === 'undefined') {
|
||||
dir = 'TD';
|
||||
}
|
||||
@@ -347,17 +341,17 @@ export const draw = function (text, id) {
|
||||
});
|
||||
|
||||
let subG;
|
||||
const subGraphs = flowDb.getSubGraphs();
|
||||
const subGraphs = diagObj.db.getSubGraphs();
|
||||
for (let i = subGraphs.length - 1; i >= 0; i--) {
|
||||
subG = subGraphs[i];
|
||||
flowDb.addVertex(subG.id, subG.title, 'group', undefined, subG.classes);
|
||||
diagObj.db.addVertex(subG.id, subG.title, 'group', undefined, subG.classes);
|
||||
}
|
||||
|
||||
// Fetch the vertices/nodes and edges/links from the parsed graph definition
|
||||
const vert = flowDb.getVertices();
|
||||
const vert = diagObj.db.getVertices();
|
||||
log.warn('Get vertices', vert);
|
||||
|
||||
const edges = flowDb.getEdges();
|
||||
const edges = diagObj.db.getEdges();
|
||||
|
||||
let i = 0;
|
||||
for (i = subGraphs.length - 1; i >= 0; i--) {
|
||||
@@ -369,14 +363,14 @@ export const draw = function (text, id) {
|
||||
log.warn(
|
||||
'Setting subgraph',
|
||||
subG.nodes[j],
|
||||
flowDb.lookUpDomId(subG.nodes[j]),
|
||||
flowDb.lookUpDomId(subG.id)
|
||||
diagObj.db.lookUpDomId(subG.nodes[j]),
|
||||
diagObj.db.lookUpDomId(subG.id)
|
||||
);
|
||||
g.setParent(flowDb.lookUpDomId(subG.nodes[j]), flowDb.lookUpDomId(subG.id));
|
||||
g.setParent(diagObj.db.lookUpDomId(subG.nodes[j]), diagObj.db.lookUpDomId(subG.id));
|
||||
}
|
||||
}
|
||||
addVertices(vert, g, id, root, doc);
|
||||
addEdges(edges, g);
|
||||
addVertices(vert, g, id, root, doc, diagObj);
|
||||
addEdges(edges, g, diagObj);
|
||||
|
||||
// Create the renderer
|
||||
const Render = dagreD3.render;
|
||||
@@ -425,31 +419,30 @@ export const draw = function (text, id) {
|
||||
|
||||
// Set up an SVG group so that we can translate the final graph.
|
||||
const svg = root.select(`[id="${id}"]`);
|
||||
svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
|
||||
// Adds title and description to the flow chart
|
||||
addSVGAccessibilityFields(parser.yy, svg, id);
|
||||
addSVGAccessibilityFields(diagObj.db, svg, id);
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
const element = root.select('#' + id + ' g');
|
||||
render(element, g);
|
||||
|
||||
element.selectAll('g.node').attr('title', function () {
|
||||
return flowDb.getTooltip(this.id);
|
||||
return diagObj.db.getTooltip(this.id);
|
||||
});
|
||||
|
||||
// Index nodes
|
||||
flowDb.indexNodes('subGraph' + i);
|
||||
diagObj.db.indexNodes('subGraph' + i);
|
||||
|
||||
// reposition labels
|
||||
for (i = 0; i < subGraphs.length; i++) {
|
||||
subG = subGraphs[i];
|
||||
if (subG.title !== 'undefined') {
|
||||
const clusterRects = doc.querySelectorAll(
|
||||
'#' + id + ' [id="' + flowDb.lookUpDomId(subG.id) + '"] rect'
|
||||
'#' + id + ' [id="' + diagObj.db.lookUpDomId(subG.id) + '"] rect'
|
||||
);
|
||||
const clusterEl = doc.querySelectorAll(
|
||||
'#' + id + ' [id="' + flowDb.lookUpDomId(subG.id) + '"]'
|
||||
'#' + id + ' [id="' + diagObj.db.lookUpDomId(subG.id) + '"]'
|
||||
);
|
||||
|
||||
const xPos = clusterRects[0].x.baseVal.value;
|
||||
@@ -493,7 +486,7 @@ export const draw = function (text, id) {
|
||||
const vertex = vert[key];
|
||||
|
||||
if (vertex.link) {
|
||||
const node = root.select('#' + id + ' [id="' + flowDb.lookUpDomId(key) + '"]');
|
||||
const node = root.select('#' + id + ' [id="' + diagObj.db.lookUpDomId(key) + '"]');
|
||||
if (node) {
|
||||
const link = doc.createElementNS('http://www.w3.org/2000/svg', 'a');
|
||||
link.setAttributeNS('http://www.w3.org/2000/svg', 'class', vertex.classes.join(' '));
|
||||
|
||||
@@ -28,6 +28,13 @@ describe('the flowchart renderer', function () {
|
||||
['group', 'rect'],
|
||||
].forEach(function ([type, expectedShape, expectedRadios = 0]) {
|
||||
it(`should add the correct shaped node to the graph for vertex type ${type}`, function () {
|
||||
const fakeDiag = {
|
||||
db: {
|
||||
lookUpDomId: () => {
|
||||
return 'my-node-id';
|
||||
},
|
||||
},
|
||||
};
|
||||
const addedNodes = [];
|
||||
const mockG = {
|
||||
setNode: function (id, object) {
|
||||
@@ -45,7 +52,10 @@ describe('the flowchart renderer', function () {
|
||||
},
|
||||
},
|
||||
mockG,
|
||||
'svg-id'
|
||||
'svg-id',
|
||||
undefined,
|
||||
undefined,
|
||||
fakeDiag
|
||||
);
|
||||
expect(addedNodes).toHaveLength(1);
|
||||
expect(addedNodes[0][0]).toEqual('my-node-id');
|
||||
@@ -62,6 +72,13 @@ describe('the flowchart renderer', function () {
|
||||
) {
|
||||
it('should handle multiline texts with different line breaks', function () {
|
||||
const addedNodes = [];
|
||||
const fakeDiag = {
|
||||
db: {
|
||||
lookUpDomId: () => {
|
||||
return 'my-node-id';
|
||||
},
|
||||
},
|
||||
};
|
||||
const mockG = {
|
||||
setNode: function (id, object) {
|
||||
addedNodes.push([id, object]);
|
||||
@@ -78,7 +95,10 @@ describe('the flowchart renderer', function () {
|
||||
},
|
||||
},
|
||||
mockG,
|
||||
'svg-id'
|
||||
'svg-id',
|
||||
false,
|
||||
document,
|
||||
fakeDiag
|
||||
);
|
||||
expect(addedNodes).toHaveLength(1);
|
||||
expect(addedNodes[0][0]).toEqual('my-node-id');
|
||||
@@ -103,6 +123,13 @@ describe('the flowchart renderer', function () {
|
||||
].forEach(function ([style, expectedStyle, expectedLabelStyle]) {
|
||||
it(`should add the styles to style and/or labelStyle for style ${style}`, function () {
|
||||
const addedNodes = [];
|
||||
const fakeDiag = {
|
||||
db: {
|
||||
lookUpDomId: () => {
|
||||
return 'my-node-id';
|
||||
},
|
||||
},
|
||||
};
|
||||
const mockG = {
|
||||
setNode: function (id, object) {
|
||||
addedNodes.push([id, object]);
|
||||
@@ -119,7 +146,10 @@ describe('the flowchart renderer', function () {
|
||||
},
|
||||
},
|
||||
mockG,
|
||||
'svg-id'
|
||||
'svg-id',
|
||||
undefined,
|
||||
undefined,
|
||||
fakeDiag
|
||||
);
|
||||
expect(addedNodes).toHaveLength(1);
|
||||
expect(addedNodes[0][0]).toEqual('my-node-id');
|
||||
@@ -137,11 +167,18 @@ describe('the flowchart renderer', function () {
|
||||
addedNodes.push([id, object]);
|
||||
},
|
||||
};
|
||||
const fakeDiag = {
|
||||
db: {
|
||||
lookUpDomId: () => {
|
||||
return 'my-node-id';
|
||||
},
|
||||
},
|
||||
};
|
||||
addVertices(
|
||||
{
|
||||
v1: {
|
||||
type: 'rect',
|
||||
id: 'defaultNode',
|
||||
id: 'my-node-id',
|
||||
classes: [],
|
||||
styles: [],
|
||||
text: 'my vertex text',
|
||||
@@ -155,12 +192,15 @@ describe('the flowchart renderer', function () {
|
||||
},
|
||||
},
|
||||
mockG,
|
||||
'svg-id'
|
||||
'svg-id',
|
||||
undefined,
|
||||
undefined,
|
||||
fakeDiag
|
||||
);
|
||||
expect(addedNodes).toHaveLength(2);
|
||||
expect(addedNodes[0][0]).toEqual('defaultNode');
|
||||
expect(addedNodes[0][0]).toEqual('my-node-id');
|
||||
expect(addedNodes[0][1]).toHaveProperty('class', 'default');
|
||||
expect(addedNodes[1][0]).toEqual('myNode');
|
||||
expect(addedNodes[1][0]).toEqual('my-node-id');
|
||||
expect(addedNodes[1][1]).toHaveProperty('class', 'myClass');
|
||||
});
|
||||
});
|
||||
@@ -168,6 +208,13 @@ describe('the flowchart renderer', function () {
|
||||
describe('when adding edges to a graph', function () {
|
||||
it('should handle multiline texts and set centered label position', function () {
|
||||
const addedEdges = [];
|
||||
const fakeDiag = {
|
||||
db: {
|
||||
lookUpDomId: () => {
|
||||
return 'my-node-id';
|
||||
},
|
||||
},
|
||||
};
|
||||
const mockG = {
|
||||
setEdge: function (s, e, data, c) {
|
||||
addedEdges.push(data);
|
||||
@@ -185,7 +232,7 @@ describe('the flowchart renderer', function () {
|
||||
{ style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi<br\t/>Line' },
|
||||
],
|
||||
mockG,
|
||||
'svg-id'
|
||||
fakeDiag
|
||||
);
|
||||
|
||||
addedEdges.forEach(function (edge) {
|
||||
@@ -206,12 +253,19 @@ describe('the flowchart renderer', function () {
|
||||
].forEach(function ([style, expectedStyle, expectedLabelStyle]) {
|
||||
it(`should add the styles to style and/or labelStyle for style ${style}`, function () {
|
||||
const addedEdges = [];
|
||||
const fakeDiag = {
|
||||
db: {
|
||||
lookUpDomId: () => {
|
||||
return 'my-node-id';
|
||||
},
|
||||
},
|
||||
};
|
||||
const mockG = {
|
||||
setEdge: function (s, e, data, c) {
|
||||
addedEdges.push(data);
|
||||
},
|
||||
};
|
||||
addEdges([{ style: style, text: 'styling' }], mockG, 'svg-id');
|
||||
addEdges([{ style: style, text: 'styling' }], mockG, fakeDiag);
|
||||
|
||||
expect(addedEdges).toHaveLength(1);
|
||||
expect(addedEdges[0]).toHaveProperty('style', expectedStyle);
|
||||
|
||||
@@ -14,7 +14,7 @@ describe('[Interactions] when parsing', () => {
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
it('it should be possible to use click to a callback', function () {
|
||||
it('should be possible to use click to a callback', function () {
|
||||
spyOn(flowDb, 'setClickEvent');
|
||||
const res = flow.parser.parse('graph TD\nA-->B\nclick A callback');
|
||||
|
||||
@@ -24,7 +24,7 @@ describe('[Interactions] when parsing', () => {
|
||||
expect(flowDb.setClickEvent).toHaveBeenCalledWith('A', 'callback');
|
||||
});
|
||||
|
||||
it('it should be possible to use click to a click and call callback', function () {
|
||||
it('should be possible to use click to a click and call callback', function () {
|
||||
spyOn(flowDb, 'setClickEvent');
|
||||
const res = flow.parser.parse('graph TD\nA-->B\nclick A call callback()');
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('[Interactions] when parsing', () => {
|
||||
expect(flowDb.setClickEvent).toHaveBeenCalledWith('A', 'callback');
|
||||
});
|
||||
|
||||
it('it should be possible to use click to a callback with toolip', function () {
|
||||
it('should be possible to use click to a callback with toolip', function () {
|
||||
spyOn(flowDb, 'setClickEvent');
|
||||
spyOn(flowDb, 'setTooltip');
|
||||
const res = flow.parser.parse('graph TD\nA-->B\nclick A callback "tooltip"');
|
||||
@@ -46,7 +46,7 @@ describe('[Interactions] when parsing', () => {
|
||||
expect(flowDb.setTooltip).toHaveBeenCalledWith('A', 'tooltip');
|
||||
});
|
||||
|
||||
it('it should be possible to use click to a click and call callback with toolip', function () {
|
||||
it('should be possible to use click to a click and call callback with toolip', function () {
|
||||
spyOn(flowDb, 'setClickEvent');
|
||||
spyOn(flowDb, 'setTooltip');
|
||||
const res = flow.parser.parse('graph TD\nA-->B\nclick A call callback() "tooltip"');
|
||||
@@ -58,7 +58,7 @@ describe('[Interactions] when parsing', () => {
|
||||
expect(flowDb.setTooltip).toHaveBeenCalledWith('A', 'tooltip');
|
||||
});
|
||||
|
||||
it('it should be possible to use click to a callback with an arbitrary number of args', function () {
|
||||
it('should be possible to use click to a callback with an arbitrary number of args', function () {
|
||||
spyOn(flowDb, 'setClickEvent');
|
||||
const res = flow.parser.parse('graph TD\nA-->B\nclick A call callback("test0", test1, test2)');
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ describe('[Lines] when parsing', () => {
|
||||
});
|
||||
|
||||
describe('it should handle new line type notation', function () {
|
||||
it('it should handle regular lines', function () {
|
||||
it('should handle regular lines', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -98,7 +98,7 @@ describe('[Lines] when parsing', () => {
|
||||
expect(edges[0].stroke).toBe('normal');
|
||||
});
|
||||
|
||||
it('it should handle dotted lines', function () {
|
||||
it('should handle dotted lines', function () {
|
||||
const res = flow.parser.parse('graph TD;A-.->B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -107,7 +107,7 @@ describe('[Lines] when parsing', () => {
|
||||
expect(edges[0].stroke).toBe('dotted');
|
||||
});
|
||||
|
||||
it('it should handle dotted lines', function () {
|
||||
it('should handle dotted lines', function () {
|
||||
const res = flow.parser.parse('graph TD;A==>B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
@@ -13,7 +13,7 @@ describe('[Text] when parsing', () => {
|
||||
});
|
||||
|
||||
describe('it should handle text on edges', function () {
|
||||
it('it should handle text without space', function () {
|
||||
it('should handle text without space', function () {
|
||||
const res = flow.parser.parse('graph TD;A--x|textNoSpace|B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -22,7 +22,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
});
|
||||
|
||||
it('should handle with space', function () {
|
||||
it('should handle with space', function () {
|
||||
const res = flow.parser.parse('graph TD;A--x|text including space|B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -31,7 +31,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
});
|
||||
|
||||
it('it should handle text with /', function () {
|
||||
it('should handle text with /', function () {
|
||||
const res = flow.parser.parse('graph TD;A--x|text with / should work|B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -40,7 +40,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].text).toBe('text with / should work');
|
||||
});
|
||||
|
||||
it('it should handle space and space between vertices and link', function () {
|
||||
it('should handle space and space between vertices and link', function () {
|
||||
const res = flow.parser.parse('graph TD;A --x|textNoSpace| B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -159,12 +159,6 @@ describe('[Text] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
expect(vert['a'].text).toBe('v');
|
||||
});
|
||||
it('should handle keywords', function () {
|
||||
const res = flow.parser.parse('graph TD;V-->a[v]');
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
expect(vert['a'].text).toBe('v');
|
||||
});
|
||||
it('should handle quoted text', function () {
|
||||
const res = flow.parser.parse('graph TD;V-- "test string()" -->a[v]');
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -174,7 +168,7 @@ describe('[Text] when parsing', () => {
|
||||
});
|
||||
|
||||
describe('it should handle text on lines', () => {
|
||||
it('it should handle normal text on lines', function () {
|
||||
it('should handle normal text on lines', function () {
|
||||
const res = flow.parser.parse('graph TD;A-- test text with == -->B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -182,7 +176,7 @@ describe('[Text] when parsing', () => {
|
||||
|
||||
expect(edges[0].stroke).toBe('normal');
|
||||
});
|
||||
it('it should handle dotted text on lines (TD3)', function () {
|
||||
it('should handle dotted text on lines (TD3)', function () {
|
||||
const res = flow.parser.parse('graph TD;A-. test text with == .->B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -190,7 +184,7 @@ describe('[Text] when parsing', () => {
|
||||
|
||||
expect(edges[0].stroke).toBe('dotted');
|
||||
});
|
||||
it('it should handle thick text on lines', function () {
|
||||
it('should handle thick text on lines', function () {
|
||||
const res = flow.parser.parse('graph TD;A== test text with - ==>B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -201,7 +195,7 @@ describe('[Text] when parsing', () => {
|
||||
});
|
||||
|
||||
describe('it should handle text on edges using the new notation', function () {
|
||||
it('it should handle text without space', function () {
|
||||
it('should handle text without space', function () {
|
||||
const res = flow.parser.parse('graph TD;A-- textNoSpace --xB;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -210,7 +204,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
});
|
||||
|
||||
it('it should handle text with multiple leading space', function () {
|
||||
it('should handle text with multiple leading space', function () {
|
||||
const res = flow.parser.parse('graph TD;A-- textNoSpace --xB;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -219,7 +213,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
});
|
||||
|
||||
it('should handle with space', function () {
|
||||
it('should handle with space', function () {
|
||||
const res = flow.parser.parse('graph TD;A-- text including space --xB;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -228,7 +222,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
});
|
||||
|
||||
it('it should handle text with /', function () {
|
||||
it('should handle text with /', function () {
|
||||
const res = flow.parser.parse('graph TD;A -- text with / should work --x B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -237,7 +231,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].text).toBe('text with / should work');
|
||||
});
|
||||
|
||||
it('it should handle space and space between vertices and link', function () {
|
||||
it('should handle space and space between vertices and link', function () {
|
||||
const res = flow.parser.parse('graph TD;A -- textNoSpace --x B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -302,7 +296,7 @@ describe('[Text] when parsing', () => {
|
||||
});
|
||||
|
||||
describe('it should handle text in vertices, ', function () {
|
||||
it('it should handle space', function () {
|
||||
it('should handle space', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(Chimpansen hoppar);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -311,7 +305,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(vert['C'].type).toBe('round');
|
||||
expect(vert['C'].text).toBe('Chimpansen hoppar');
|
||||
});
|
||||
it('it should handle åäö and minus', function () {
|
||||
it('should handle åäö and minus', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C{Chimpansen hoppar åäö-ÅÄÖ};');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -321,7 +315,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(vert['C'].text).toBe('Chimpansen hoppar åäö-ÅÄÖ');
|
||||
});
|
||||
|
||||
it('it should handle with åäö, minus and space and br', function () {
|
||||
it('should handle with åäö, minus and space and br', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(Chimpansen hoppar åäö <br> - ÅÄÖ);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -330,7 +324,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(vert['C'].type).toBe('round');
|
||||
expect(vert['C'].text).toBe('Chimpansen hoppar åäö <br> - ÅÄÖ');
|
||||
});
|
||||
// xit('it should handle åäö, minus and space and br',function(){
|
||||
// xit('should handle åäö, minus and space and br',function(){
|
||||
// const res = flow.parser.parse('graph TD; A[Object(foo,bar)]-->B(Thing);');
|
||||
//
|
||||
// const vert = flow.parser.yy.getVertices();
|
||||
@@ -339,21 +333,21 @@ describe('[Text] when parsing', () => {
|
||||
// expect(vert['C'].type).toBe('round');
|
||||
// expect(vert['C'].text).toBe(' A[Object(foo,bar)]-->B(Thing);');
|
||||
// });
|
||||
it('it should handle unicode chars', function () {
|
||||
it('should handle unicode chars', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(Начало);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
expect(vert['C'].text).toBe('Начало');
|
||||
});
|
||||
it('it should handle backslask', function () {
|
||||
it('should handle backslask', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(c:\\windows);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
expect(vert['C'].text).toBe('c:\\windows');
|
||||
});
|
||||
it('it should handle CAPS', function () {
|
||||
it('should handle CAPS', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(some CAPS);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -362,7 +356,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(vert['C'].type).toBe('round');
|
||||
expect(vert['C'].text).toBe('some CAPS');
|
||||
});
|
||||
it('it should handle directions', function () {
|
||||
it('should handle directions', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(some URL);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
@@ -233,6 +233,9 @@ const getStartDate = function (prevTime, dateFormat, str) {
|
||||
const durationToDate = function (durationStatement, relativeTime) {
|
||||
if (durationStatement !== null) {
|
||||
switch (durationStatement[2]) {
|
||||
case 'ms':
|
||||
relativeTime.add(durationStatement[1], 'milliseconds');
|
||||
break;
|
||||
case 's':
|
||||
relativeTime.add(durationStatement[1], 'seconds');
|
||||
break;
|
||||
@@ -267,7 +270,7 @@ const getEndDate = function (prevTime, dateFormat, str, inclusive) {
|
||||
return mDate.toDate();
|
||||
}
|
||||
|
||||
return durationToDate(/^([\d]+)([wdhms])/.exec(str.trim()), moment(prevTime));
|
||||
return durationToDate(/^([\d]+)([wdhms]|ms)$/.exec(str.trim()), moment(prevTime));
|
||||
};
|
||||
|
||||
let taskCnt = 0;
|
||||
|
||||
@@ -99,6 +99,27 @@ describe('when using the ganttDb', function () {
|
||||
}
|
||||
);
|
||||
|
||||
it('should handle milliseconds', function () {
|
||||
ganttDb.setDateFormat('x');
|
||||
ganttDb.addSection('testa1');
|
||||
ganttDb.addTask('test1', 'id1,0,20ms');
|
||||
ganttDb.addTask('test2', 'id2,after id1,5ms');
|
||||
ganttDb.addSection('testa2');
|
||||
ganttDb.addTask('test3', 'id3,20,10ms');
|
||||
ganttDb.addTask('test4', 'id4,after id3,5ms');
|
||||
|
||||
const tasks = ganttDb.getTasks();
|
||||
|
||||
expect(tasks[0].startTime.toISOString()).toEqual('1970-01-01T00:00:00.000Z');
|
||||
expect(tasks[0].endTime.toISOString()).toEqual('1970-01-01T00:00:00.020Z');
|
||||
expect(tasks[1].startTime.toISOString()).toEqual('1970-01-01T00:00:00.020Z');
|
||||
expect(tasks[1].endTime.toISOString()).toEqual('1970-01-01T00:00:00.025Z');
|
||||
expect(tasks[2].startTime.toISOString()).toEqual('1970-01-01T00:00:00.020Z');
|
||||
expect(tasks[2].endTime.toISOString()).toEqual('1970-01-01T00:00:00.030Z');
|
||||
expect(tasks[3].startTime.toISOString()).toEqual('1970-01-01T00:00:00.030Z');
|
||||
expect(tasks[3].endTime.toISOString()).toEqual('1970-01-01T00:00:00.035Z');
|
||||
});
|
||||
|
||||
it('should handle relative start date based on id regardless of sections', function () {
|
||||
ganttDb.setDateFormat('YYYY-MM-DD');
|
||||
ganttDb.addSection('testa1');
|
||||
|
||||
@@ -11,23 +11,20 @@ import {
|
||||
axisTop,
|
||||
timeFormat,
|
||||
} from 'd3';
|
||||
import { parser } from './parser/gantt';
|
||||
import common from '../common/common';
|
||||
import ganttDb from './ganttDb';
|
||||
import { getConfig } from '../../config';
|
||||
import { configureSvgSize } from '../../utils';
|
||||
import addSVGAccessibilityFields from '../../accessibility';
|
||||
|
||||
parser.yy = ganttDb;
|
||||
export const setConf = function () {
|
||||
log.debug('Something is calling, setConf, remove the call');
|
||||
};
|
||||
|
||||
let w;
|
||||
export const draw = function (text, id) {
|
||||
export const draw = function (text, id, version, diagObj) {
|
||||
const conf = getConfig().gantt;
|
||||
parser.yy.clear();
|
||||
parser.parse(text);
|
||||
// diagObj.db.clear();
|
||||
// parser.parse(text);
|
||||
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and Document for when rendering in sanbox mode
|
||||
@@ -52,7 +49,7 @@ export const draw = function (text, id) {
|
||||
w = conf.useWidth;
|
||||
}
|
||||
|
||||
const taskArray = parser.yy.getTasks();
|
||||
const taskArray = diagObj.db.getTasks();
|
||||
|
||||
// Set height based on number of tasks
|
||||
const h = taskArray.length * (conf.barHeight + conf.barGap) + 2 * conf.topPadding;
|
||||
@@ -109,12 +106,12 @@ export const draw = function (text, id) {
|
||||
|
||||
svg
|
||||
.append('text')
|
||||
.text(parser.yy.getDiagramTitle())
|
||||
.text(diagObj.db.getDiagramTitle())
|
||||
.attr('x', w / 2)
|
||||
.attr('y', conf.titleTopMargin)
|
||||
.attr('class', 'titleText');
|
||||
|
||||
addSVGAccessibilityFields(parser.yy, svg, id);
|
||||
addSVGAccessibilityFields(diagObj.db, svg, id);
|
||||
|
||||
/**
|
||||
* @param tasks
|
||||
@@ -139,8 +136,8 @@ export const draw = function (text, id) {
|
||||
pageWidth,
|
||||
pageHeight,
|
||||
tasks,
|
||||
parser.yy.getExcludes(),
|
||||
parser.yy.getIncludes()
|
||||
diagObj.db.getExcludes(),
|
||||
diagObj.db.getIncludes()
|
||||
);
|
||||
makeGrid(leftPadding, topPadding, pageWidth, pageHeight);
|
||||
drawRects(tasks, gap, topPadding, leftPadding, barHeight, colorScale, pageWidth, pageHeight);
|
||||
@@ -187,7 +184,7 @@ export const draw = function (text, id) {
|
||||
// Draw the rects representing the tasks
|
||||
const rectangles = svg.append('g').selectAll('rect').data(theArray).enter();
|
||||
|
||||
const links = ganttDb.getLinks();
|
||||
const links = diagObj.db.getLinks();
|
||||
|
||||
// Render the tasks with links
|
||||
// Render the other tasks
|
||||
@@ -430,14 +427,14 @@ export const draw = function (text, id) {
|
||||
0
|
||||
);
|
||||
const maxTime = tasks.reduce((max, { endTime }) => (max ? Math.max(max, endTime) : endTime), 0);
|
||||
const dateFormat = parser.yy.getDateFormat();
|
||||
const dateFormat = diagObj.db.getDateFormat();
|
||||
if (!minTime || !maxTime) return;
|
||||
|
||||
const excludeRanges = [];
|
||||
let range = null;
|
||||
let d = moment(minTime);
|
||||
while (d.valueOf() <= maxTime) {
|
||||
if (parser.yy.isInvalidDate(d, dateFormat, excludes, includes)) {
|
||||
if (diagObj.db.isInvalidDate(d, dateFormat, excludes, includes)) {
|
||||
if (!range) {
|
||||
range = {
|
||||
start: d.clone(),
|
||||
@@ -495,7 +492,7 @@ export const draw = function (text, id) {
|
||||
function makeGrid(theSidePad, theTopPad, w, h) {
|
||||
let bottomXAxis = axisBottom(timeScale)
|
||||
.tickSize(-h + theTopPad + conf.gridLineStartPadding)
|
||||
.tickFormat(timeFormat(parser.yy.getAxisFormat() || conf.axisFormat || '%Y-%m-%d'));
|
||||
.tickFormat(timeFormat(diagObj.db.getAxisFormat() || conf.axisFormat || '%Y-%m-%d'));
|
||||
|
||||
svg
|
||||
.append('g')
|
||||
@@ -509,10 +506,10 @@ export const draw = function (text, id) {
|
||||
.attr('font-size', 10)
|
||||
.attr('dy', '1em');
|
||||
|
||||
if (ganttDb.topAxisEnabled() || conf.topAxis) {
|
||||
if (diagObj.db.topAxisEnabled() || conf.topAxis) {
|
||||
let topXAxis = axisTop(timeScale)
|
||||
.tickSize(-h + theTopPad + conf.gridLineStartPadding)
|
||||
.tickFormat(timeFormat(parser.yy.getAxisFormat() || conf.axisFormat || '%Y-%m-%d'));
|
||||
.tickFormat(timeFormat(diagObj.db.getAxisFormat() || conf.axisFormat || '%Y-%m-%d'));
|
||||
|
||||
svg
|
||||
.append('g')
|
||||
@@ -592,7 +589,7 @@ export const draw = function (text, id) {
|
||||
* @param h
|
||||
*/
|
||||
function drawToday(theSidePad, theTopPad, w, h) {
|
||||
const todayMarker = ganttDb.getTodayMarker();
|
||||
const todayMarker = diagObj.db.getTodayMarker();
|
||||
if (todayMarker === 'off') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -148,8 +148,17 @@ export const branch = function (name, order) {
|
||||
}
|
||||
};
|
||||
|
||||
export const merge = function (otherBranch, tag) {
|
||||
/**
|
||||
* Creates a merge commit.
|
||||
*
|
||||
* @param {string} otherBranch - Target branch to merge to.
|
||||
* @param {string} [tag] - Git tag to use on this merge commit.
|
||||
* @param {string} [id] - Git commit id.
|
||||
*/
|
||||
export const merge = function (otherBranch, tag, id) {
|
||||
otherBranch = common.sanitizeText(otherBranch, configApi.getConfig());
|
||||
id = common.sanitizeText(id, configApi.getConfig());
|
||||
|
||||
const currentCommit = commits[branches[curBranch]];
|
||||
const otherCommit = commits[branches[otherBranch]];
|
||||
if (curBranch === otherBranch) {
|
||||
@@ -219,7 +228,7 @@ export const merge = function (otherBranch, tag) {
|
||||
// } else {
|
||||
// create merge commit
|
||||
const commit = {
|
||||
id: seq + '-' + getId(),
|
||||
id: id || seq + '-' + getId(),
|
||||
message: 'merged branch ' + otherBranch + ' into ' + curBranch,
|
||||
seq: seq++,
|
||||
parents: [head == null ? null : head.id, branches[otherBranch]],
|
||||
|
||||
8
src/diagrams/git/gitGraphDetector.js
Normal file
8
src/diagrams/git/gitGraphDetector.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const detector = (txt) => {
|
||||
if (txt.match(/^\s*gitGraph/)) {
|
||||
return 'gitGraph';
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export default detector;
|
||||
@@ -115,7 +115,7 @@ describe('when parsing a gitGraph', function() {
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master');
|
||||
});
|
||||
|
||||
it('it should reset a branch', function() {
|
||||
it('should reset a branch', function() {
|
||||
const str =
|
||||
'gitGraph:\n' +
|
||||
'commit\n' +
|
||||
@@ -153,7 +153,7 @@ describe('when parsing a gitGraph', function() {
|
||||
expect(parser.yy.getHead().id).toEqual(master.parent);
|
||||
});
|
||||
|
||||
it('it should handle fast forwardable merges', function() {
|
||||
it('should handle fast forwardable merges', function() {
|
||||
const str =
|
||||
'gitGraph:\n' +
|
||||
'commit\n' +
|
||||
@@ -173,7 +173,7 @@ describe('when parsing a gitGraph', function() {
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch']);
|
||||
});
|
||||
|
||||
it('it should handle cases when merge is a noop', function() {
|
||||
it('should handle cases when merge is a noop', function() {
|
||||
const str =
|
||||
'gitGraph:\n' +
|
||||
'commit\n' +
|
||||
@@ -192,7 +192,7 @@ describe('when parsing a gitGraph', function() {
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch']);
|
||||
});
|
||||
|
||||
it('it should handle merge with 2 parents', function() {
|
||||
it('should handle merge with 2 parents', function() {
|
||||
const str =
|
||||
'gitGraph:\n' +
|
||||
'commit\n' +
|
||||
@@ -213,7 +213,7 @@ describe('when parsing a gitGraph', function() {
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['master']);
|
||||
});
|
||||
|
||||
it('it should handle ff merge when history walk has two parents (merge commit)', function() {
|
||||
it('should handle ff merge when history walk has two parents (merge commit)', function() {
|
||||
const str =
|
||||
'gitGraph:\n' +
|
||||
'commit\n' +
|
||||
@@ -239,7 +239,7 @@ describe('when parsing a gitGraph', function() {
|
||||
parser.yy.prettyPrint();
|
||||
});
|
||||
|
||||
it('it should generate a secure random ID for commits', function() {
|
||||
it('should generate a secure random ID for commits', function() {
|
||||
const str = 'gitGraph:\n' + 'commit\n' + 'commit\n';
|
||||
const EXPECTED_LENGTH = 7;
|
||||
const EXPECTED_CHARACTERS = '0123456789abcdef';
|
||||
@@ -267,7 +267,7 @@ describe('when parsing a gitGraph', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('it should generate an array of known branches', function() {
|
||||
it('should generate an array of known branches', function() {
|
||||
const str =
|
||||
'gitGraph:\n' +
|
||||
'commit\n' +
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user