Compare commits

..

58 Commits
8.4.0 ... 8.4.2

Author SHA1 Message Date
Knut Sveidqvist
1ecf0f4c23 Updated version 2019-11-07 21:16:43 +01:00
Knut Sveidqvist
fa7d1ac554 #1023 Fix for interaction tests 2019-11-07 19:42:09 +01:00
Knut Sveidqvist
48ce7a9b78 #1023 Fix for tests 2019-11-07 19:19:44 +01:00
Knut Sveidqvist
09bf54f9af #1038 Updated prefix for the internal dom id 2019-11-07 19:14:06 +01:00
Erik Ellingsen
43b9bcdb0b version update 2019-11-07 18:39:57 +01:00
knsv
a3017b8456 Merge branch 'release/8.4.1' 2019-11-06 10:52:10 -08:00
Christian Klemm
1f8480f0af Added npm badge (#1047) 2019-11-03 16:18:43 +01:00
Nacho
3674e27e0f Reworked readme (#1045) 2019-11-01 13:38:00 -04:00
Knut Sveidqvist
e4486420ce Update some path changes after repo move 2019-10-30 20:21:35 +01:00
Knut Sveidqvist
fe64cc697b Updated version 2019-10-30 20:01:54 +01:00
Knut Sveidqvist
97177dffd6 Updated coveralls badge 2019-10-30 19:54:47 +01:00
Knut Sveidqvist
061a02dddc Merge branch 'develop' of github.com:knsv/mermaid into develop 2019-10-30 19:48:43 +01:00
Knut Sveidqvist
1f72c3e720 Updating the repo path after migration to mermaid-js 2019-10-30 19:48:37 +01:00
Knut Sveidqvist
8270469652 Update README.md 2019-10-30 19:44:53 +01:00
Knut Sveidqvist
5e6590a0f7 Fix of travis badge for new org 2019-10-30 19:40:02 +01:00
Knut Sveidqvist
06dfd13927 Merge pull request #1041 from mermaid-js/maintainence_pie
Maintainance pie
2019-10-30 19:34:19 +01:00
ashishjain0512
486cc92f2e Merge pull request #1039 from lf-novelt/master
Support for underscore in classDiagrams class names
2019-10-30 19:01:11 +01:00
Ashish Jain
e8d649b152 Updated documentation for Pie Chart 2019-10-30 18:32:07 +01:00
Ashish Jain
e96bd14d21 Updated Examples for Pie Chart 2019-10-30 18:30:14 +01:00
Ashish Jain
e4a2d2a290 Updated Jest test cases for Pie diagram 2019-10-30 18:29:26 +01:00
Louis Frament
d8d5d0fa61 update classDiagram documentation:
fix typos and describe naming convention
2019-10-29 17:50:19 +01:00
Louis Frament
e010a03dd5 package-lock version update 2019-10-29 17:39:39 +01:00
Louis Frament
427aea73e7 test pass with underscore in a class name 2019-10-29 17:39:15 +01:00
Louis Frament
c4436b7a1e ALPHA pattern now include underscore 2019-10-29 17:20:25 +01:00
Knut Sveidqvist
d098051047 Merge pull request #1035 from knsv/bug/1033_state_diagram_new_lines_in_notes
Bug/1033 state diagram new lines in notes
2019-10-28 06:56:33 +01:00
Knut Sveidqvist
034a7c424d #1033 Better handling of multiline notes 2019-10-27 17:16:29 +01:00
Knut Sveidqvist
b113436055 #1033 Fix for diagram bounds and viewbox 2019-10-27 16:58:32 +01:00
Knut Sveidqvist
e550d974da Merge pull request #1032 from knsv/bug/1031_stricter_code_checks
Fix for Bug/1031 stricter code checks
2019-10-27 15:33:48 +01:00
Knut Sveidqvist
bc34ef4b66 Merge pull request #1028 from knsv/Issue-1027_Pie-Chart-Legends
#1027  Updated Pie chart to render percentages and labels separately …
2019-10-27 15:26:54 +01:00
Knut Sveidqvist
a5cc1e804b #1031 Adding stricter code checks 2019-10-27 15:24:56 +01:00
Knut Sveidqvist
aac51979cc Merge branch 'develop' of github.com:knsv/mermaid into develop 2019-10-24 19:47:14 +02:00
Knut Sveidqvist
8f8638fb7c #1029 Linting fixes 2019-10-24 19:46:42 +02:00
Knut Sveidqvist
d1c74070ab #1029 Fix for issues after switching to master branch of dagre-d3 2019-10-24 19:33:13 +02:00
Nacho
ee01d09af5 Merge pull request #1008
Added e2e tests to prepublish task
2019-10-24 08:52:05 -04:00
Nacho
caaf4e3e40 Merge pull request #1010
Delete package-lock.json
2019-10-24 08:49:41 -04:00
Nacho
34037e58e5 Added package-lock to gitignore 2019-10-24 08:48:55 -04:00
Knut Sveidqvist
66152b42ae #1023 New line in transition labels, basic support 2019-10-23 21:16:59 +02:00
Ashish Jain
76c8737485 #1027 Updated Pie chart to render percentages and labels separately as legends 2019-10-23 21:00:33 +02:00
Knut Sveidqvist
4a1eb55127 #1022 Fix for long names for state diagrams 2019-10-23 19:22:36 +02:00
Knut Sveidqvist
c87637c6f4 #1024 Removal of leftover loggings 2019-10-23 18:47:41 +02:00
Knut Sveidqvist
364b81a1b9 Merge pull request #1018 from pravi/switch-to-dagre-d3
Use dagre-d3 master branch (for d3v5)
2019-10-23 18:38:45 +02:00
Nacho
d4c8cf66ef Merge pull request #1025
Spelling, markdown lint cleanup
2019-10-23 09:21:30 -04:00
Doug Hill
08762bc066 Spelling, markdown lint cleanup
Fixed spelling errors. Applied some markdown lint standards.
2019-10-22 20:10:35 -10:00
Nacho
0add11a257 Merge pull request #1021 from knsv/master
Keeping development branch up to date
2019-10-21 13:45:47 -04:00
Pirate Praveen
ca5e60b38b Use dagre-d3 master branch (for d3v5) 2019-10-21 22:46:20 +05:30
Knut Sveidqvist
0e7876536d Highlighting state diagrams and class diagrams in the readme 2019-10-21 22:46:19 +05:30
Nacho
be61a03a98 Removed gitter and added slack badge 2019-10-21 22:46:19 +05:30
abeaton
50c707ba51 Fix typos in CONTRIBUTING.md 2019-10-21 22:46:18 +05:30
Sakis bal
2a2fd7a8b1 Small gramatical mistake 2019-10-21 22:46:18 +05:30
Kolja Markwardt
ad126c838e reference the CONTRIBUTING.md in README 2019-10-21 22:46:18 +05:30
Knut Sveidqvist
cafc18a78f Highlighting state diagrams and class diagrams in the readme 2019-10-21 12:38:01 -04:00
Nacho
ffca12a8b0 Removed gitter and added slack badge 2019-10-21 12:38:01 -04:00
abeaton
137f57ad9c Fix typos in CONTRIBUTING.md 2019-10-21 12:38:01 -04:00
Sakis bal
153b3322a6 Small gramatical mistake 2019-10-21 12:38:01 -04:00
Kolja Markwardt
575535bdbd reference the CONTRIBUTING.md in README 2019-10-21 12:38:01 -04:00
Knut Sveidqvist
61a3802494 Highlighting state diagrams and class diagrams in the readme 2019-10-19 17:45:56 +02:00
Christian Klemm
c3db9032f3 Delete package-lock.json 2019-10-16 23:53:19 +02:00
Christian Klemm
42b8ac1235 Added e2e tests to prepublish task 2019-10-16 22:00:57 +02:00
52 changed files with 720 additions and 19270 deletions

1
.eslintignore Normal file
View File

@@ -0,0 +1 @@
**/*.spec.js

View File

@@ -1,7 +1,8 @@
{
"env": {
"browser": true,
"es6": true
"es6": true,
"node": true
},
"parserOptions": {
"ecmaFeatures": {
@@ -10,7 +11,7 @@
},
"sourceType": "module"
},
"extends": ["prettier"],
"extends": ["prettier", "eslint:recommended"],
"plugins": ["prettier"],
"rules": {
"prettier/prettier": ["error"]

View File

@@ -33,8 +33,8 @@ jobs:
echo $VERSION
npm version --no-git-tag-version --allow-same-version $VERSION
npm set //npm.pkg.github.com/:_authToken ${{ secrets.GITHUB_TOKEN }}
npm set registry https://npm.pkg.github.com/knsv
json -I -f package.json -e 'this.name="@knsv/mermaid"' # Package name needs to be set to a scoped one because GitHub registry requires this
json -I -f package.json -e 'this.repository="git://github.com/knsv/mermaid"' # Repo url needs to have a specific format too
npm set registry https://npm.pkg.github.com/mermaid-js
json -I -f package.json -e 'this.name="@mermaid-js/mermaid"' # Package name needs to be set to a scoped one because GitHub registry requires this
json -I -f package.json -e 'this.repository="git://github.com/mermaid-js/mermaid"' # Repo url needs to have a specific format too
npm publish

2
.gitignore vendored
View File

@@ -10,3 +10,5 @@ dist/*.map
yarn-error.log
.npmrc
token
package-lock.json

View File

@@ -86,7 +86,7 @@ Finally, if it is not in the documentation, no one will know about it and then *
The docs are located in the docs folder and are ofc written in markdown. Just pick the right section and start typing. If you want to add to the structure as in adding a new section and new file you do that via the _navbar.md.
The changes in master is reflected in http://knsv.github.io/mermaid/ once released the updates are commited to https://mermaidjs.github.io/#/
The changes in master is reflected in http://mermaid-js.github.io/mermaid/ once released the updates are commited to https://mermaid-js.github.io/#/
## Last words

362
README.md
View File

@@ -1,92 +1,89 @@
<!-- <Remove this in the future> -->
| :mega: :mega: :mega: |
| :----: |
| * If you're upgrading from a version __< v8.2.0__, there are [non-backward-compatible changes](http://mermaid-js.github.io/mermaid/#/usage?id=to-enable-click-event-and-tags-in-nodes) related to security issues. Default behaviour of the library might have changed for your implementation.|
<!-- </Remove this in the future> -->
# mermaid [![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/Mermaid/mermaid)
<!-- <Main description> -->
__Generate diagrams, charts, graphs or flows from markdown-like text via javascript.__
See our [documentation](http://mermaid-js.github.io/mermaid/) and start simplifying yours. Play in our [live editor](https://mermaidjs.github.io/mermaid-live-editor/) or jump straight to the [installation and usage](http://mermaid-js.github.io/mermaid/#/usage).
<!-- </Main description> -->
# mermaid [![Build Status](https://travis-ci.org/knsv/mermaid.svg?branch=master)](https://travis-ci.org/knsv/mermaid) [![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/Mermaid/mermaid)
:trophy: _"The most exciting use of technology"_ - [JS Open Source Awards (2019)](https://osawards.com/javascript/#nominees)
## Special note regarding version 8.2
In version 8.2 a security improvement was introduced. A securityLevel configuration was introduced which sets the level of trust to be used on the parsed diagrams.
* **`strict`**: (default) tags in text are encoded, click functionality is disabled
* `loose`: tags in text are allowed, click functionality is enabled
⚠️ **Note** : This changes the default behaviour of mermaid so that after upgrade to 8.2, if the securityLevel is not configured, tags in flowcharts are encoded as tags and clicking is prohibited.
If your application is taking responsibility for the diagram source security you can set the securityLevel accordingly. By doing this clicks and tags are again allowed.
```javascript
mermaidAPI.initialize({
securityLevel: 'loose'
});
```
**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/knsv/mermaid/issues/866)**
![banner](./img/header.png)
Generation of diagrams and flowcharts from text in a similar manner as markdown.
Ever wanted to simplify documentation and avoid heavy tools like Visio when explaining your code?
This is why mermaid was born, a simple markdown-like script language for generating charts from text via javascript.
**Mermaid was nominated and won the JS Open Source Awards (2019) in the category _The most exciting use of technology_!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.**
### Flowchart
```
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
```
![Flowchart](./img/flow.png)
### Sequence diagram
```
<table>
<!-- <Flowchart> -->
<tr><td colspan=2 align="center">
<b>Flow</b></br>
[<a href="http://mermaid-js.github.io/mermaid/#/flowchart">docs</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ3JhcGggVERcbiAgICBBW0hhcmRdIC0tPnxUZXh0fCBCKFJvdW5kKVxuICAgIEIgLS0-IEN7RGVjaXNpb259XG4gICAgQyAtLT58T25lfCBEW1Jlc3VsdCAxXVxuICAgIEMgLS0-fFR3b3wgRVtSZXN1bHQgMl0iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
</td></tr>
<tr>
<td><pre>
graph TD
A[Hard] -->|Text| B(Round)
B --> C{Decision}
C -->|One| D[Result 1]
C -->|Two| E[Result 2]
</pre></td>
<td align="center">
<img src="./img/gray-flow.png" />
</td>
</tr>
<!-- </Flowchart> -->
<!-- <Sequence> -->
<tr><td colspan=2 align="center">
<b>Sequence</b><br />
[<a href="http://mermaid-js.github.io/mermaid/#/sequenceDiagram">docs</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG5BbGljZS0-PkpvaG46IEhlbGxvIEpvaG4sIGhvdyBhcmUgeW91P1xubG9vcCBIZWFsdGhjaGVja1xuICAgIEpvaG4tPj5Kb2huOiBGaWdodCBhZ2FpbnN0IGh5cG9jaG9uZHJpYVxuZW5kXG5Ob3RlIHJpZ2h0IG9mIEpvaG46IFJhdGlvbmFsIHRob3VnaHRzIVxuSm9obi0tPj5BbGljZTogR3JlYXQhXG5Kb2huLT4-Qm9iOiBIb3cgYWJvdXQgeW91P1xuQm9iLS0-PkpvaG46IEpvbGx5IGdvb2QhIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
</td></tr>
<tr>
<td><pre>
sequenceDiagram
participant Alice
participant Bob
Alice->>John: Hello John, how are you?
loop Healthcheck
John->>John: Fight against hypochondria
end
Note right of John: Rational thoughts <br/>prevail!
John-->>Alice: Great!
John->>Bob: How about you?
Bob-->>John: Jolly good!
```
![Sequence diagram](./img/sequence.png)
### Gantt diagram
```
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!
</pre></td>
<td align="center">
<img src="./img/gray-sequence.png" />
</td>
</tr>
<!-- </Sequence> -->
<!-- <Gantt> -->
<tr><td colspan=2 align="center">
<b>Gantt</b><br />
[<a href="http://mermaid-js.github.io/mermaid/#/gantt">docs</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ2FudHRcbnNlY3Rpb24gU2VjdGlvblxuQ29tcGxldGVkIDpkb25lLCAgICBkZXMxLCAyMDE0LTAxLTA2LDIwMTQtMDEtMDhcbkFjdGl2ZSAgICAgICAgOmFjdGl2ZSwgIGRlczIsIDIwMTQtMDEtMDcsIDNkXG5QYXJhbGxlbCAxICAgOiAgICAgICAgIGRlczMsIGFmdGVyIGRlczEsIDFkXG5QYXJhbGxlbCAyICAgOiAgICAgICAgIGRlczQsIGFmdGVyIGRlczEsIDFkXG5QYXJhbGxlbCAzICAgOiAgICAgICAgIGRlczUsIGFmdGVyIGRlczMsIDFkXG5QYXJhbGxlbCA0ICAgOiAgICAgICAgIGRlczYsIGFmdGVyIGRlczQsIDFkIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
</td></tr>
<tr>
<td><pre>
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram to mermaid
excludes weekdays 2014-01-10
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
```
![Gantt diagram](./img/gantt.png)
### Class diagram - :exclamation: experimental
```
section Section
Completed :done, des1, 2014-01-06,2014-01-08
Active :active, des2, 2014-01-07, 3d
Parallel 1 : des3, after des1, 1d
Parallel 2 : des4, after des1, 1d
Parallel 3 : des5, after des3, 1d
Parallel 4 : des6, after des4, 1d
</pre></td>
<td align="center">
<img src="./img/gray-gantt.png" />
</td>
</tr>
<!-- </Gantt> -->
<!-- <Class> -->
<tr><td colspan=2 align="center">
<b>Class</b><br />
[<a href="http://mermaid-js.github.io/mermaid/#/classDiagram">docs</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiY2xhc3NEaWFncmFtXG5DbGFzczAxIDx8LS0gQXZlcnlMb25nQ2xhc3MgOiBDb29sXG48PGludGVyZmFjZT4-IENsYXNzMDFcbkNsYXNzMDkgLS0-IEMyIDogV2hlcmUgYW0gaT9cbkNsYXNzMDkgLS0qIEMzXG5DbGFzczA5IC0tfD4gQ2xhc3MwN1xuQ2xhc3MwNyA6IGVxdWFscygpXG5DbGFzczA3IDogT2JqZWN0W10gZWxlbWVudERhdGFcbkNsYXNzMDEgOiBzaXplKClcbkNsYXNzMDEgOiBpbnQgY2hpbXBcbkNsYXNzMDEgOiBpbnQgZ29yaWxsYVxuY2xhc3MgQ2xhc3MxMCB7XG4gID4-c2VydmljZT4-XG4gIGludCBpZFxuICBzaXplKClcbn0iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
</td></tr>
<tr>
<td><pre>
classDiagram
Class01 <|-- AveryLongClass : Cool
<<interface>> Class01
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class01 &lt;|-- AveryLongClass : Cool
&lt;&lt;interface>> Class01
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
@@ -95,147 +92,84 @@ Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10 {
<<service>>
&lt;&lt;service>>
int id
size()
}
```
![Class diagram](./img/class.png)
</pre></td>
<td align="center">
<img src="./img/gray-class.png" />
</td>
</tr>
<!-- </Class> -->
<!-- <State> -->
<tr><td colspan=2 align="center">
<b>State</b><br />
[<a href="http://mermaid-js.github.io/mermaid/#/stateDiagram">docs</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoic3RhdGVEaWFncmFtXG4gICAgWypdIC0tPiBTdGlsbFxuICAgIFN0aWxsIC0tPiBbKl1cbiAgICBTdGlsbCAtLT4gTW92aW5nXG4gICAgTW92aW5nIC0tPiBTdGlsbFxuICAgIE1vdmluZyAtLT4gQ3Jhc2hcbiAgICBDcmFzaCAtLT4gWypdIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
</td></tr>
<tr>
<td><pre>
stateDiagram
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
</pre></td>
<td align="center">
<img src="./img/gray-state.png" />
</td>
</tr>
<!-- </State> -->
<!-- <Pie> -->
<tr><td colspan=2 align="center">
<b>Pie</b><br />
[<a href="http://mermaid-js.github.io/mermaid/#/pie">docs</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoicGllXG5cIkRvZ3NcIiA6IDQyLjk2XG5cIkNhdHNcIiA6IDUwLjA1XG5cIlJhdHNcIiA6IDEwLjAxIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
</td></tr>
<tr>
<td><pre>
pie
"Dogs" : 386
"Cats" : 85
"Rats" : 15
</pre></td>
<td align="center">
<img src="./img/gray-pie.png" />
</td>
</tr>
<!-- </Pie> -->
<!-- <Git> -->
<tr><td colspan=2 align="center">
<b>Git</b><br />
[experimental - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ2l0R3JhcGg6XG5vcHRpb25zXG57XG4gICAgXCJub2RlU3BhY2luZ1wiOiAxNTAsXG4gICAgXCJub2RlUmFkaXVzXCI6IDEwXG59XG5lbmRcbmNvbW1pdFxuYnJhbmNoIG5ld2JyYW5jaFxuY2hlY2tvdXQgbmV3YnJhbmNoXG5jb21taXRcbmNvbW1pdFxuY2hlY2tvdXQgbWFzdGVyXG5jb21taXRcbmNvbW1pdFxubWVyZ2UgbmV3YnJhbmNoXG4iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
</td></tr>
<tr>
<td colspan="2" align="center"><i>Coming soon!</i></td>
</tr>
<!-- </Git> -->
</table>
## Related projects
### Git graph - :exclamation: experimental
- [Command Line Interface](https://github.com/mermaid-js/mermaid.cli)
- [Live Editor](https://github.com/mermaid-js/mermaid-live-editor)
```
gitGraph:
options
{
"nodeSpacing": 150,
"nodeRadius": 10
}
end
commit
branch newbranch
checkout newbranch
commit
commit
checkout master
commit
commit
merge newbranch
# Contributors [![Help wanted](https://img.shields.io/github/labels/mermaid-js/mermaid/Help%20wanted!)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Help+wanted%21%22) [![Contributors](https://img.shields.io/github/contributors/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) [![Commits](https://img.shields.io/github/commit-activity/m/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors)
```
Mermaid is a growing community and is always accepting new contributors. There's a lot of different ways to help out and we're always looking for extra hands! Look at [this issue](https://github.com/mermaid-js/mermaid/issues/866) if you want to know where to start helping out.
![Git graph](./img/git.png)
Detailed information about how to contribute can be found in the [contribution guide](CONTRIBUTING.md)
# Appreciation
A quick note from Knut Sveidqvist:
>*Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries!*
>*Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering.*
>*Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017.*
>
>*Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!*
## Installation
### CDN
https://unpkg.com/mermaid@<version>/dist/
Replace `<version>` with expected version number.
Example: https://unpkg.com/mermaid@7.1.0/dist/
### Node.js
yarn add mermaid
### Preview builds
Preview builds are created automatically for each release. They can be found in the [GitHub registry](https://github.com/knsv/mermaid/packages).
Make sure to configure npm to use the GitHub package registry. Steps for that can be found [here](https://help.github.com/en/articles/configuring-npm-for-use-with-github-package-registry).
If you want to get the latest preview for the next release
```
yarn add @knsv/mermaid
```
If you want to get the latest preview for a specific version
```
yarn add @knsv/mermaid@<version>
```
## Documentation
https://mermaidjs.github.io
## Sibling projects
- [mermaid CLI](https://github.com/mermaidjs/mermaid.cli)
- [mermaid live editor](https://github.com/mermaidjs/mermaid-live-editor)
- [mermaid webpack demo](https://github.com/mermaidjs/mermaid-webpack-demo)
- [mermaid Parcel demo](https://github.com/mermaidjs/mermaid-parcel-demo)
# Request for assistance
Things are piling up and I have hard time keeping up. To remedy this
it would be great if we could form a core team of developers to cooperate
with the future development mermaid.
As part of this team you would get write access to the repository and would
represent the project when answering questions and issues.
Together we could continue the work with things like:
* adding more types of diagrams like mindmaps, ert diagrams etc
* improving existing diagrams
Don't hesitate to contact me if you want to get involved.
# For contributors
Detailed information about contributing can be found in the [Contribution guide](CONTRIBUTING.md)
## Setup
yarn install
## Build
yarn build:watch
## Lint
yarn lint
We use [eslint](https://eslint.org/).
We recommend you installing [editor plugins](https://eslint.org/docs/user-guide/integrations) so you can get real time lint result.
## Test
yarn test
Manual test in browser:
open dist/index.html
## Release
For those who have the permission to do so:
Update version number in `package.json`.
npm publish
Command above generates files into the `dist` folder and publishes them to npmjs.org.
# Credits
Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries!
Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering.
---
*Mermaid was created by Knut Sveidqvist for easier documentation.*
*[Tyler Long](https://github.com/tylerlong) has became a collaborator since April 2017.*
Here is the full list of the projects [contributors](https://github.com/knsv/mermaid/graphs/contributors).

View File

@@ -16,7 +16,7 @@ describe('Interaction', () => {
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#s1Function')
.find('g#mermaid-dom-id-1Function')
.click();
cy.get('.created-by-click').should('have.text', 'Clicked By Flow');
@@ -38,7 +38,7 @@ describe('Interaction', () => {
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#s2URL')
.find('g#mermaid-dom-id-2URL')
.click();
cy.location().should(location => {
@@ -108,7 +108,7 @@ describe('Interaction', () => {
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#s1Function')
.find('g#mermaid-dom-id-1Function')
.click();
cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');
@@ -130,7 +130,7 @@ describe('Interaction', () => {
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#s2URL')
.find('g#mermaid-dom-id-2URL')
.click();
cy.location().should(location => {
@@ -200,7 +200,7 @@ describe('Interaction', () => {
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#s1Function')
.find('g#mermaid-dom-id-1Function')
.click();
cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');

View File

@@ -0,0 +1,20 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util';
describe('State diagram', () => {
it('should render a flowchart full of circles', () => {
imgSnapshotTest(
`
stateDiagram
State1: The state with a note
note right of State1
Important information! You\ncan write
notes with multiple lines...
Here is another line...
And another line...
end note
`,
{}
);
});
});

View File

@@ -2,7 +2,7 @@
import { imgSnapshotTest } from '../../helpers/util';
describe('Flowcart', () => {
it('should render a simple flowchart no htmlLabels', () => {
it('1: should render a simple flowchart no htmlLabels', () => {
imgSnapshotTest(
`graph TD
A[Christmas] -->|Get money| B(Go shopping)
@@ -14,7 +14,7 @@ describe('Flowcart', () => {
{ flowchart: { htmlLabels: false } }
);
});
it('should render a simple flowchart with htmlLabels', () => {
it('2: should render a simple flowchart with htmlLabels', () => {
imgSnapshotTest(
`graph TD
A[Christmas] -->|Get money| B(Go shopping)
@@ -26,7 +26,7 @@ describe('Flowcart', () => {
{ flowchart: { htmlLabels: true } }
);
});
it('should render a simple flowchart with line breaks', () => {
it('3: should render a simple flowchart with line breaks', () => {
imgSnapshotTest(
`
graph TD
@@ -40,7 +40,7 @@ describe('Flowcart', () => {
);
});
it('should render a simple flowchart with trapezoid and inverse trapezoid vertex options.', () => {
it('4: should render a simple flowchart with trapezoid and inverse trapezoid vertex options.', () => {
imgSnapshotTest(
`
graph TD
@@ -55,7 +55,7 @@ describe('Flowcart', () => {
);
});
it('should style nodes via a class.', () => {
it('4: should style nodes via a class.', () => {
imgSnapshotTest(
`
graph TD
@@ -71,7 +71,7 @@ describe('Flowcart', () => {
);
});
it('should render a flowchart full of circles', () => {
it('5: should render a flowchart full of circles', () => {
imgSnapshotTest(
`
graph LR
@@ -99,7 +99,7 @@ describe('Flowcart', () => {
{}
);
});
it('should render a flowchart full of icons', () => {
it('6: should render a flowchart full of icons', () => {
imgSnapshotTest(
`
graph TD
@@ -170,7 +170,7 @@ describe('Flowcart', () => {
);
});
it('should render labels with numbers at the start', () => {
it('7: should render labels with numbers at the start', () => {
imgSnapshotTest(
`
graph TB;subgraph "number as labels";1;end;
@@ -178,7 +178,7 @@ describe('Flowcart', () => {
{}
);
});
it('should render subgraphs', () => {
it('8: should render subgraphs', () => {
imgSnapshotTest(
`
graph TB
@@ -190,7 +190,7 @@ describe('Flowcart', () => {
);
});
it('should render subgraphs with a title startign with a digit', () => {
it('9: should render subgraphs with a title startign with a digit', () => {
imgSnapshotTest(
`
graph TB
@@ -202,7 +202,7 @@ describe('Flowcart', () => {
);
});
it('should render styled subgraphs', () => {
it('10: should render styled subgraphs', () => {
imgSnapshotTest(
`
graph TB
@@ -237,7 +237,7 @@ describe('Flowcart', () => {
);
});
it('should render a flowchart with ling sames and class definitoins', () => {
it('11: should render a flowchart with ling sames and class definitoins', () => {
imgSnapshotTest(
`graph LR
sid-B3655226-6C29-4D00-B685-3D5C734DC7E1["
@@ -339,7 +339,7 @@ describe('Flowcart', () => {
);
});
it('should render color of styled nodes', () => {
it('12: should render color of styled nodes', () => {
imgSnapshotTest(
`
graph LR
@@ -356,4 +356,25 @@ describe('Flowcart', () => {
}
);
});
it('13: should render hexagons', () => {
imgSnapshotTest(
`
graph TD
A[Christmas] -->|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]
click A "index.html#link-clicked" "link test"
click B testClick "click test"
classDef someclass fill:#f96;
class A someclass;
`,
{
listUrl: false,
listId: 'color styling',
logLevel: 0
}
);
});
});

View File

@@ -12,5 +12,29 @@ describe('Pie Chart', () => {
`,
{}
);
cy.get('svg');
});
it('should render a simple pie diagram with long labels', () => {
imgSnapshotTest(
`
pie title NETFLIX
"Time spent looking for movie" : 90
"Time spent watching it" : 10
`,
{}
);
cy.get('svg');
});
it('should render a simple pie diagram with capital letters for labels', () => {
imgSnapshotTest(
`
pie title What Voldemort doesn't have?
"FRIENDS" : 2
"FAMILY" : 3
"NOSE" : 45
`,
{}
);
cy.get('svg');
});
});

View File

@@ -13,6 +13,30 @@ describe('State diagram', () => {
);
cy.get('svg');
});
it('should render a long descriptions instead of id when available', () => {
imgSnapshotTest(
`
stateDiagram
[*] --> S1
state "Some long name" as S1
`,
{ logLevel: 0 }
);
cy.get('svg');
});
it('should render a long descriptions with additional descriptions', () => {
imgSnapshotTest(
`
stateDiagram
[*] --> S1
state "Some long name" as S1: The description
`,
{ logLevel: 0 }
);
cy.get('svg');
});
it('should render a single state with short descr', () => {
imgSnapshotTest(
`
@@ -24,6 +48,20 @@ describe('State diagram', () => {
);
cy.get('svg');
});
it('should render a transition descrions with new lines', () => {
imgSnapshotTest(
`
stateDiagram
[*] --> S1
S1 --> S2: long line using<br/>should work
S1 --> S3: long line using <br>should work
S1 --> S4: long line using \\nshould work
`,
{ logLevel: 0 }
);
cy.get('svg');
});
it('should render a state with a note', () => {
imgSnapshotTest(
`

View File

@@ -1,7 +1,7 @@
<html>
<head>
<script src="/e2e.js"></script>
<link href="https://fonts.googleapis.com/css?family=Mansalva&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Mansalva&display=swap" rel="stylesheet" />
<style>
body {
/* font-family: 'Mansalva', cursive;
@@ -17,6 +17,9 @@
--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive;
--mermaid-font-family: '"Lucida Console", Monaco, monospace';
} */
svg {
border: 2px solid darkred;
}
</style>
</head>
<body>

View File

@@ -4,12 +4,20 @@
# mermaid
## New diagrams in 8.4
With version 8.4 class diagrams has got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram
type, state diagrams.
![Image show the two new diagram types](./img/new-diagrams.png)
## Special note regarding version 8.2
In version 8.2 a security improvement was introduced. A securityLevel configuration was introduced wich sets the level of trust to be used on the parsed diagrams.
* **true**: (default) tags in text are encoded, click functionality is disabled
* false: tags in text are allowed, click functionality is enabledClosed issues:
* false: tags in text are allowed, click functionality is enabledClosed issues:
⚠️ **Note** : This changes the default behaviour of mermaid so that after upgrade to 8.2, if the securityLevel is not configured, tags in flowcharts are encoded as tags and clicking is prohibited.

View File

@@ -44,7 +44,7 @@ Mermaid can render class diagrams.
+String beakColor
+swim()
+quack()
}
}
class Fish{
-int sizeInFeet
-canEat()
@@ -69,7 +69,7 @@ A single instance of a class in the diagram contains three compartments:
```
classDiagram
class BankAccount
BankAccount : +String onwer
BankAccount : +String owner
BankAccount : +Bigdecimal balance
BankAccount : +deposit(amount)
BankAccount : +withdrawl(amount)
@@ -77,7 +77,7 @@ classDiagram
```mermaid
classDiagram
class BankAccount
BankAccount : +String onwer
BankAccount : +String owner
BankAccount : +BigDecimal balance
BankAccount : +deposit(amount)
BankAccount : +withdrawl(amount)
@@ -98,6 +98,9 @@ classDiagram
class Animal
Vehicle <|-- Car
```
Naming convention: a class name should be composed of alphanumeric (unicode allowed) and underscore characters.
## Defining Members of a class
UML provides mechanisms to represent class members, such as attributes and methods, and additional information about them.
@@ -117,7 +120,7 @@ There are two ways to define the members of a class, and regardless of the which
```
class BankAccount
BankAccount : +String onwer
BankAccount : +String owner
BankAccount : +BigDecimal balance
BankAccount : +deposit(amount)
BankAccount : +withdrawl(amount)
@@ -125,7 +128,7 @@ There are two ways to define the members of a class, and regardless of the which
```mermaid
classDiagram
class BankAccount
BankAccount : +String onwer
BankAccount : +String owner
BankAccount : +BigDecimal balance
BankAccount : +deposit(amount)
BankAccount : +withdrawl(amount)
@@ -134,7 +137,7 @@ There are two ways to define the members of a class, and regardless of the which
- Associate members of a class using **{}** brackets, where members are grouped within curly brackets. Suitable for defining multiple members at once. For example:
```
class BankAccount{
+String onwer
+String owner
+BigDecimal balance
+deposit(amount)
+withdrawl(amount)
@@ -143,7 +146,7 @@ class BankAccount{
```mermaid
classDiagram
class BankAccount{
+String onwer
+String owner
+BigDecimal balance
+deposit(amount)
+withdrawl(amount)

View File

@@ -1,3 +1,27 @@
## Basic Pie Chart
```
pie title NETFLIX
"Time spent looking for movie" : 90
"Time spent watching it" : 10
```
``` mermaid
pie title NETFLIX
"Time spent looking for movie" : 90
"Time spent watching it" : 10
```
```
pie title What Voldemort doesn't have?
"FRIENDS" : 2
"FAMILY" : 3
"NOSE" : 45
```
```mermaid
pie title What Voldemort doesn't have?
"FRIENDS" : 2
"FAMILY" : 3
"NOSE" : 45
```
## Basic sequence diagram
```

BIN
docs/img/new-diagrams.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@@ -7,7 +7,7 @@
<meta name="description" content="Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
<script src="//cdn.jsdelivr.net/npm/mermaid@8.4.0/dist/mermaid.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/mermaid@8.4.1/dist/mermaid.min.js"></script>
<!-- <script src="//localhost:9000/mermaid.js"></script> -->
<style>
.markdown-section {

View File

@@ -1,11 +1,12 @@
# Pie chart diagrams
> A pie chart (or a circle chart) is a circular statistical graphic, which is divided into slices to illustrate numerical proportion. In a pie chart, the arc length of each slice (and consequently its central angle and area), is proportional to the quantity it represents. While it is named for its resemblance to a pie which has been sliced, there are variations on the way it can be presented. The earliest known pie chart is generally credited to William Playfair's Statistical Breviary of 1801
-Wikipedia
Mermaid can render Pie Chart diagrams.
```
pie
pie title Pets adopted by volunteers
"Dogs" : 386
"Cats" : 85
"Rats" : 15
@@ -19,17 +20,34 @@ pie title Pets adopted by volunteers
## Syntax
Drawing a pie chart is really simple in mermaid.
- Start with `pie` keyword to begin the diagram
- Followed by `title` keyword and its value in string to give a title to the pie-chart. This is ***OPTIONAL***
- Followed by dataSet
- `label` for a section in the pie diagram within `" "` quotes.
- Followed by `:` semi-colon as separator
- Followed by `positive numeric value` (supported upto two decimal places)
[pie]
[title] [titlevalue] (OPTIONAL)
"[datakey1]" : [dataValue1]
"[datakey2]" : [dataValue2]
"[datakey3]" : [dataValue3]
.
.
## Example
```
pie
"DataKey1" : Positive numeric value (upto two decimal places)
title Key elements in Product X
"Calcium" : 42.96
"Potassium" : 50.05
"Magnesium" : 10.01
"Iron" : 5
```
```mermaid
pie title Key elements in Product X
pie
title Key elements in Product X
"Calcium" : 42.96
"Potassium" : 50.05
"Magnesium" : 25.01

View File

@@ -2,10 +2,9 @@
> "A state diagram is a type of diagram used in computer science and related fields to describe the behavior of systems. State diagrams require that the system described is composed of a finite number of states; sometimes, this is indeed the case, while at other times this is a reasonable abstraction." Wikipedia
Mermaid can render state diagrams. The syntax tries to be compliant with the syntax used in plantUml as this will make it easier for users to
share diagrams between mermaid and plantUml.
Mermaid can render state diagrams. The syntax tries to be compliant with the syntax used in plantUml as this will make it easier for users to share diagrams between mermaid and plantUml.
```
```markdown
stateDiagram
[*] --> Still
Still --> [*]
@@ -15,6 +14,7 @@ stateDiagram
Moving --> Crash
Crash --> [*]
```
```mermaid
stateDiagram
[*] --> Still
@@ -25,53 +25,58 @@ stateDiagram
Moving --> Crash
Crash --> [*]
```
In state diagrams systems are described in terms of its states and how the systems state can change to another state via a transitions. The example diagram above shows three states **Still**, **Moving** and **Crash**. You start in the state of Still. From Still you can change the state to Moving. In Moving you can change the state either back to Still or to Crash. There is no transition from Still to Crash.
## States
A state can be declares in multiple ways. The simplest way is to define a state id as a description.
```
```markdown
stateDiagram
s1
```
```mermaid
stateDiagram
s1
```
Another way is by using the state keyword with a description as per below:
```
```markdown
stateDiagram
state "This ia state decription" as s2
state "This is a state description" as s2
```
```mermaid
stateDiagram
state "This ia state decription" as s2
state "This is a state description" as s2
```
Another way to define a state with a description is to define the state id followed by a colon and the description:
```
```markdown
stateDiagram
s2 : This ia state decription
```
```mermaid
stateDiagram
s2 : This ia state decription
s2 : This is a state description
```
```mermaid
stateDiagram
s2 : This is a state description
```
## Transitions
Transitions are path/edges when one state passes into another. This is represented using text arrow, "-->".
Transitions are path/edges when one state passes into another. This is represented using text arrow, "\-\-\>".
When you define a transition between two states and the states are not already defined the undefined states are defined with the id
from the transition. You can later add descriptions to states defined this way.
When you define a transition between two states and the states are not already defined the undefined states are defined with the id from the transition. You can later add descriptions to states defined this way.
```
```markdown
stateDiagram
s1 --> s2
```
```mermaid
stateDiagram
s1 --> s2
@@ -79,39 +84,40 @@ stateDiagram
It is possible to add text to a transition. To describe what it represents.
```
```markdown
stateDiagram
s1 --> s2: A transition
```
```mermaid
stateDiagram
s1 --> s2: A transition
```
## Start and end
## Start and End
There are two special states indicating the start and stop of the diagram. These are written with the [*] syntax and the direction of the transition to it defines it either as a start or a stop state.
There are two special states indicating the start and stop of the diagram. These are written with the [\*] syntax and the direction of the transition to it defines it either as a start or a stop state.
```
```markdown
stateDiagram
[*] --> s1
s1 --> [*]
```
```mermaid
stateDiagram
[*] --> s1
s1 --> [*]
```
## Composit states
## Composite states
In a real world use of state diagrams you often end up with diagrams that are multi-dimensional as one state can
have several internal states. These are called composit states in this terminology.
have several internal states. These are called composite states in this terminology.
In order to define a composit state you need to use the state keyword followed by and id and the body of the composit state between {}. See the example below:
In order to define a composite state you need to use the state keyword followed by and id and the body of the composite state between \{\}. See the example below:
```
```markdown
stateDiagram
[*] --> First
state First {
@@ -119,6 +125,7 @@ stateDiagram
second --> [*]
}
```
```mermaid
stateDiagram
[*] --> First
@@ -130,7 +137,7 @@ stateDiagram
You can do this in several layers:
```
```markdown
stateDiagram
[*] --> First
@@ -148,6 +155,7 @@ stateDiagram
}
}
```
```mermaid
stateDiagram
[*] --> First
@@ -166,9 +174,9 @@ stateDiagram
}
```
You can also define transitions also between composit states:
You can also define transitions also between composite states:
```
```markdown
stateDiagram
[*] --> First
First --> Second
@@ -187,6 +195,7 @@ stateDiagram
thi --> [*]
}
```
```mermaid
stateDiagram
[*] --> First
@@ -207,13 +216,13 @@ stateDiagram
}
```
*You can not define transitions between internal states belonging to different composit states*
*You can not define transitions between internal states belonging to different composite states*
## Forks
It is possible to specify a fork in the diagram using &lt;&lt;fork&gt;&gt; &lt;&lt;join&gt;&gt;.
```
```markdown
stateDiagram
state fork_state <<fork>>
[*] --> fork_state
@@ -226,6 +235,7 @@ It is possible to specify a fork in the diagram using &lt;&lt;fork&gt;&gt; &lt;&
join_state --> State4
State4 --> [*]
```
```mermaid
stateDiagram
state fork_state <<fork>>
@@ -247,7 +257,7 @@ Sometimes nothing says it better then a Post-it note. That is also the case in s
Here you can choose to put the note to the *right of* or to the *left of* a node.
```
```markdown
stateDiagram
State1: The state with a note
note right of State1
@@ -257,6 +267,7 @@ Here you can choose to put the note to the *right of* or to the *left of* a node
State1 --> State2
note left of State2 : This is the note to the left.
```
```mermaid
stateDiagram
State1: The state with a note
@@ -272,7 +283,8 @@ Here you can choose to put the note to the *right of* or to the *left of* a node
## Concurrency
As in plantUml you can specify concurrency using the -- symbol.
```
```markdown
stateDiagram
[*] --> Active
@@ -291,7 +303,6 @@ As in plantUml you can specify concurrency using the -- symbol.
}
```
```mermaid
stateDiagram
[*] --> Active

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

BIN
img/gray-class.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
img/gray-flow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
img/gray-gantt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
img/gray-pie.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
img/gray-sequence.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
img/gray-state.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

18816
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "mermaid",
"version": "8.4.0",
"version": "8.4.2",
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"main": "dist/mermaid.core.js",
"keywords": [
@@ -26,7 +26,7 @@
"dev": "webpack-dev-server --config webpack.config.e2e.js",
"test": "yarn lint && jest src",
"test:watch": "jest --watch src",
"prepublishOnly": "yarn build && yarn release && yarn test",
"prepublishOnly": "yarn build && yarn release && yarn test && yarn e2e",
"prepush": "yarn test"
},
"repository": {
@@ -49,9 +49,9 @@
"@braintree/sanitize-url": "^3.1.0",
"crypto-random-string": "^3.0.1",
"d3": "^5.7.0",
"dagre-d3-renderer": "^0.5.8",
"dagre-layout": "^0.8.8",
"graphlibrary": "^2.2.0",
"dagre-d3": "dagrejs/dagre-d3",
"dagre": "^0.8.4",
"graphlib": "^2.1.7",
"he": "^1.2.0",
"lodash": "^4.17.11",
"minify": "^4.1.1",

View File

@@ -64,7 +64,7 @@ describe('class diagram, ', function() {
it('should handle parsing of method statements grouped by brackets', function() {
const str =
'classDiagram\n' +
'class Dummy {\n' +
'class Dummy_Class {\n' +
'String data\n' +
' void methods()\n' +
'}\n' +

View File

@@ -1,6 +1,6 @@
import * as d3 from 'd3';
import dagre from 'dagre-layout';
import graphlib from 'graphlibrary';
import dagre from 'dagre';
import graphlib from 'graphlib';
import { logger } from '../../logger';
import classDb from './classDb';
import utils from '../../utils';
@@ -204,14 +204,12 @@ const drawEdge = function(elem, path, relation) {
x = labalPosition.x;
y = labalPosition.y;
let p1_card_x,
p1_card_y,
p1_card_padd_x = conf.padding * 2,
p1_card_padd_y = conf.padding;
let p2_card_x,
p2_card_y,
p2_card_padd_x = conf.padding * 2,
p2_card_padd_y = -conf.padding / 2;
let p1_card_x, p1_card_y;
// p1_card_padd_x = conf.padding * 2,
// p1_card_padd_y = conf.padding;
let p2_card_x, p2_card_y;
// p2_card_padd_x = conf.padding * 2,
// p2_card_padd_y = -conf.padding / 2;
if (l % 2 !== 0 && l > 1) {
let cardinality_1_point = utils.calcCardinalityPosition(
relation.relation.type1 !== 'none',
@@ -258,8 +256,7 @@ const drawEdge = function(elem, path, relation) {
logger.info('Rendering relation ' + JSON.stringify(relation));
if (typeof relation.relationTitle1 !== 'undefined' && relation.relationTitle1 !== 'none') {
const g = elem.append('g').attr('class', 'cardinality');
const label = g
.append('text')
g.append('text')
.attr('class', 'type1')
.attr('x', p1_card_x)
.attr('y', p1_card_y)
@@ -269,8 +266,7 @@ const drawEdge = function(elem, path, relation) {
}
if (typeof relation.relationTitle2 !== 'undefined' && relation.relationTitle2 !== 'none') {
const g = elem.append('g').attr('class', 'cardinality');
const label = g
.append('text')
g.append('text')
.attr('class', 'type2')
.attr('x', p2_card_x)
.attr('y', p2_card_y)
@@ -323,8 +319,6 @@ const drawClass = function(elem, classDef) {
isFirst = false;
});
console.warn('classDef.id', classDef.id);
console.warn('isFirst', isFirst);
// add class title
const classTitle = title
.append('tspan')
@@ -348,7 +342,6 @@ const drawClass = function(elem, classDef) {
.attr('y', titleHeight + conf.dividerMargin + conf.textHeight)
.attr('fill', 'white')
.attr('class', 'classText');
console.warn(classDef.id, titleHeight, conf.dividerMargin, conf.textHeight);
isFirst = true;
classDef.members.forEach(function(member) {

View File

@@ -43,8 +43,8 @@
\% return 'PCT';
"=" return 'EQUALS';
\= return 'EQUALS';
[A-Za-z]+ return 'ALPHA';
[!"#$%&'*+,-.`?\\_/] return 'PUNCTUATION';
\w+ return 'ALPHA';
[!"#$%&'*+,-.`?\\/] return 'PUNCTUATION';
[0-9]+ return 'NUM';
[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|
[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|
@@ -163,7 +163,7 @@ members
methodStatement
: className {/*console.log('Rel found',$1);*/}
| className LABEL {yy.addMember($1,yy.cleanupLabel($2));}
| MEMBER {console.warn('Member',$1);}
| MEMBER {/*console.warn('Member',$1);*/}
| SEPARATOR {/*console.log('sep found',$1);*/}
;

View File

@@ -1,4 +1,4 @@
import dagreD3 from 'dagre-d3-renderer';
import dagreD3 from 'dagre-d3';
function question(parent, bbox, node) {
const w = bbox.width;

View File

@@ -4,6 +4,8 @@ import { logger } from '../../logger';
import utils from '../../utils';
import { getConfig } from '../../config';
const MERMAID_DOM_ID_PREFIX = 'mermaid-dom-id-';
const config = getConfig();
let vertices = {};
let edges = [];
@@ -48,7 +50,7 @@ export const addVertex = function(_id, text, type, style, classes) {
return;
}
if (id[0].match(/\d/)) id = 's' + id;
if (id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (typeof vertices[id] === 'undefined') {
vertices[id] = { id: id, styles: [], classes: [] };
@@ -96,8 +98,8 @@ export const addVertex = function(_id, text, type, style, classes) {
export const addLink = function(_start, _end, type, linktext) {
let start = _start;
let end = _end;
if (start[0].match(/\d/)) start = 's' + start;
if (end[0].match(/\d/)) end = 's' + end;
if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start;
if (end[0].match(/\d/)) end = MERMAID_DOM_ID_PREFIX + end;
logger.info('Got edge...', start, end);
const edge = { start: start, end: end, type: undefined, text: '' };
@@ -194,7 +196,7 @@ export const setDirection = function(dir) {
export const setClass = function(ids, className) {
ids.split(',').forEach(function(_id) {
let id = _id;
if (_id[0].match(/\d/)) id = 's' + id;
if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (typeof vertices[id] !== 'undefined') {
vertices[id].classes.push(className);
}
@@ -215,7 +217,7 @@ const setTooltip = function(ids, tooltip) {
const setClickFun = function(_id, functionName) {
let id = _id;
if (_id[0].match(/\d/)) id = 's' + id;
if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (config.securityLevel !== 'loose') {
return;
}
@@ -223,7 +225,7 @@ const setClickFun = function(_id, functionName) {
return;
}
if (typeof vertices[id] !== 'undefined') {
funs.push(function(element) {
funs.push(function() {
const elem = document.querySelector(`[id="${id}"]`);
if (elem !== null) {
elem.addEventListener(
@@ -247,7 +249,7 @@ const setClickFun = function(_id, functionName) {
export const setLink = function(ids, linkStr, tooltip) {
ids.split(',').forEach(function(_id) {
let id = _id;
if (_id[0].match(/\d/)) id = 's' + id;
if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (typeof vertices[id] !== 'undefined') {
if (config.securityLevel !== 'loose') {
vertices[id].link = sanitizeUrl(linkStr); // .replace(/javascript:.*/g, '')
@@ -395,7 +397,7 @@ export const addSubGraph = function(_id, list, _title) {
return false;
}
if (type in prims) {
return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true); // eslint-disable-line
} else {
return objs.indexOf(item) >= 0 ? false : objs.push(item);
}
@@ -406,11 +408,11 @@ export const addSubGraph = function(_id, list, _title) {
nodeList = uniq(nodeList.concat.apply(nodeList, list));
for (let i = 0; i < nodeList.length; i++) {
if (nodeList[i][0].match(/\d/)) nodeList[i] = 's' + nodeList[i];
if (nodeList[i][0].match(/\d/)) nodeList[i] = MERMAID_DOM_ID_PREFIX + nodeList[i];
}
id = id || 'subGraph' + subCount;
if (id[0].match(/\d/)) id = 's' + id;
if (id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
title = title || '';
title = sanitize(title);
subCount = subCount + 1;

View File

@@ -1,11 +1,16 @@
import graphlib from 'graphlibrary';
import graphlib from 'graphlib';
import * as d3 from 'd3';
import flowDb from './flowDb';
import flow from './parser/flow';
import { getConfig } from '../../config';
import dagreD3 from 'dagre-d3-renderer';
import addHtmlLabel from 'dagre-d3-renderer/lib/label/add-html-label.js';
const newDagreD3 = true;
import dagreD3 from 'dagre-d3';
// const newDagreD3 = false;
// import dagreD3 from '../../../../dagre-d3-renderer/dist/dagre-d3.core.js';
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
import { logger } from '../../logger';
import { interpolateToCurve } from '../../utils';
import flowChartShapes from './flowChartShapes';
@@ -291,18 +296,35 @@ export const draw = function(text, id) {
}
// Create the input mermaid.graph
const g = new graphlib.Graph({
multigraph: true,
compound: true
})
.setGraph({
rankdir: dir,
marginx: 20,
marginy: 20
let g;
// Todo remove newDagreD3 when properly verified
if (newDagreD3) {
g = new graphlib.Graph({
multigraph: true,
compound: true
})
.setDefaultEdgeLabel(function() {
return {};
});
.setGraph({
rankdir: dir,
marginx: 8,
marginy: 8
})
.setDefaultEdgeLabel(function() {
return {};
});
} else {
g = new graphlib.Graph({
multigraph: true,
compound: true
})
.setGraph({
rankdir: dir,
marginx: 20,
marginy: 20
})
.setDefaultEdgeLabel(function() {
return {};
});
}
let subG;
const subGraphs = flowDb.getSubGraphs();
@@ -354,7 +376,7 @@ export const draw = function(text, id) {
};
// Override normal arrowhead defined in d3. Remove style & add class to allow css styling.
render.arrows().normal = function normal(parent, id, edge, type) {
render.arrows().normal = function normal(parent, id) {
const marker = parent
.append('marker')
.attr('id', id)
@@ -386,22 +408,50 @@ export const draw = function(text, id) {
});
const conf = getConfig().flowchart;
const padding = 8;
const width = g.maxX - g.minX + padding * 2;
const height = g.maxY - g.minY + padding * 2;
// Todo remove newDagreD3 when properly verified
if (newDagreD3) {
const svgBounds = svg.node().getBBox();
const width = svgBounds.width + padding * 2;
const height = svgBounds.height + padding * 2;
logger.debug(
`new ViewBox 0 0 ${width} ${height}`,
`translate(${padding - g._label.marginx}, ${padding - g._label.marginy})`
);
if (conf.useMaxWidth) {
svg.attr('width', '100%');
svg.attr('style', `max-width: ${width}px;`);
if (conf.useMaxWidth) {
svg.attr('width', '100%');
svg.attr('style', `max-width: ${width}px;`);
} else {
svg.attr('height', height);
svg.attr('width', width);
}
svg.attr('viewBox', `0 0 ${width} ${height}`);
svg
.select('g')
.attr('transform', `translate(${padding - g._label.marginx}, ${padding - svgBounds.y})`);
} else {
svg.attr('height', height);
svg.attr('width', width);
const width = g.maxX - g.minX + padding * 2;
const height = g.maxY - g.minY + padding * 2;
if (conf.useMaxWidth) {
svg.attr('width', '100%');
svg.attr('style', `max-width: ${width}px;`);
} else {
svg.attr('height', height);
svg.attr('width', width);
}
logger.debug(
`Org ViewBox 0 0 ${width} ${height}`,
`translate(${padding - g.minX}, ${padding - g.minY})\n${location.href}`
);
svg.attr('viewBox', `0 0 ${width} ${height}`);
svg.select('g').attr('transform', `translate(${padding - g.minX}, ${padding - g.minY})`);
// svg.select('g').attr('transform', `translate(${padding - minX}, ${padding - minY})`);
}
svg.attr('viewBox', `0 0 ${width} ${height}`);
svg.select('g').attr('transform', `translate(${padding - g.minX}, ${padding - g.minY})`);
// Index nodes
flowDb.indexNodes('subGraph' + i);

View File

@@ -168,7 +168,7 @@ describe('[Singlenodes] when parsing', () => {
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert['s1'].text).toBe('1');
expect(vert['mermaid-dom-id-1'].text).toBe('1');
});
it('should handle a single node with a single digit in a subgraph', function() {
@@ -180,7 +180,7 @@ describe('[Singlenodes] when parsing', () => {
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert['s1'].text).toBe('1');
expect(vert['mermaid-dom-id-1'].text).toBe('1');
});
it('should handle a single node with alphanumerics starting on a num', function() {
@@ -191,7 +191,7 @@ describe('[Singlenodes] when parsing', () => {
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert['s1id'].styles.length).toBe(0);
expect(vert['mermaid-dom-id-1id'].styles.length).toBe(0);
});
it('should handle a single node with alphanumerics containing a minus sign', function() {

View File

@@ -83,7 +83,7 @@ describe('when parsing subgraphs', function() {
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(1);
expect(subgraph.nodes[0]).toBe('A');
expect(subgraph.id).toBe('s1test');
expect(subgraph.id).toBe('mermaid-dom-id-1test');
});
it('should handle subgraphs1', function() {

View File

@@ -387,10 +387,11 @@ const compileTasks = function() {
const task = rawTasks[pos];
let startTime = '';
switch (rawTasks[pos].raw.startTime.type) {
case 'prevTaskEnd':
case 'prevTaskEnd': {
const prevTask = findTaskById(task.prevTaskId);
task.startTime = prevTask.endTime;
break;
}
case 'getStartDate':
startTime = getStartDate(undefined, dateFormat, rawTasks[pos].raw.startTime.startData);
if (startTime) {
@@ -501,7 +502,7 @@ const setClickFun = function(id, functionName, functionArgs) {
* @param callbackFunction A function to be executed when clicked on the task or the task's text
*/
const pushFun = function(id, callbackFunction) {
funs.push(function(element) {
funs.push(function() {
// const elem = d3.select(element).select(`[id="${id}"]`)
const elem = document.querySelector(`[id="${id}"]`);
if (elem !== null) {
@@ -510,7 +511,7 @@ const pushFun = function(id, callbackFunction) {
});
}
});
funs.push(function(element) {
funs.push(function() {
// const elem = d3.select(element).select(`[id="${id}-text"]`)
const elem = document.querySelector(`[id="${id}-text"]`);
if (elem !== null) {

View File

@@ -102,7 +102,7 @@ export const draw = function(text, id) {
drawToday(leftPadding, topPadding, pageWidth, pageHeight);
}
function drawRects(theArray, theGap, theTopPad, theSidePad, theBarHeight, theColorScale, w, h) {
function drawRects(theArray, theGap, theTopPad, theSidePad, theBarHeight, theColorScale, w) {
// Draw background rects covering the entire width of the graph, these form the section rows.
svg
.append('g')
@@ -401,7 +401,7 @@ export const draw = function(text, id) {
const hash = {};
const result = [];
for (let i = 0, l = arr.length; i < l; ++i) {
if (!hash.hasOwnProperty(arr[i])) {
if (!hash.hasOwnProperty(arr[i])) { // eslint-disable-line
// it works with objects! in FF, at least
hash[arr[i]] = true;
result.push(arr[i]);

View File

@@ -21,7 +21,7 @@ export const setConf = function(cnf) {
* @param id
*/
let w;
export const draw = (txt, id, ver) => {
export const draw = (txt, id) => {
try {
const parser = pieParser.parser;
parser.yy = pieData;
@@ -50,6 +50,8 @@ export const draw = (txt, id, ver) => {
var width = w; // 450
var height = 450;
var margin = 40;
var legendRectSize = 18;
var legendSpacing = 4;
var radius = Math.min(width, height) / 2 - margin;
@@ -62,6 +64,10 @@ export const draw = (txt, id, ver) => {
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
var data = pieData.getSections();
var sum = 0;
Object.keys(data).forEach(function(key) {
sum += data[key];
});
logger.info(data);
// set the color scale
@@ -75,7 +81,6 @@ export const draw = (txt, id, ver) => {
return d.value;
});
var dataReady = pie(d3.entries(data));
// Now I know that group A goes from 0 degrees to x degrees and so on.
// shape helper to build arcs:
var arcGenerator = d3
@@ -97,14 +102,14 @@ export const draw = (txt, id, ver) => {
.style('stroke-width', '2px')
.style('opacity', 0.7);
// Now add the annotation. Use the centroid method to get the best coordinates
// Now add the Percentage. Use the centroid method to get the best coordinates
svg
.selectAll('mySlices')
.data(dataReady)
.enter()
.append('text')
.text(function(d) {
return d.data.key;
return ((d.data.value / sum) * 100).toFixed(0) + '%';
})
.attr('transform', function(d) {
return 'translate(' + arcGenerator.centroid(d) + ')';
@@ -119,6 +124,36 @@ export const draw = (txt, id, ver) => {
.attr('x', 0)
.attr('y', -(h - 50) / 2)
.attr('class', 'pieTitleText');
//Add the slegend/annotations for each section
var legend = svg
.selectAll('.legend')
.data(color.domain())
.enter()
.append('g')
.attr('class', 'legend')
.attr('transform', function(d, i) {
var height = legendRectSize + legendSpacing;
var offset = (height * color.domain().length) / 2;
var horz = 12 * legendRectSize;
var vert = i * height - offset;
return 'translate(' + horz + ',' + vert + ')';
});
legend
.append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.style('fill', color)
.style('stroke', color);
legend
.append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.text(function(d) {
return d;
});
} catch (e) {
logger.error('Error while rendering info diagram');
logger.error(e.message);

View File

@@ -514,11 +514,12 @@ export const draw = function(text, id) {
bounds.newLoop(undefined, msg.message);
bounds.bumpVerticalPos(conf.boxMargin);
break;
case parser.yy.LINETYPE.RECT_END:
case parser.yy.LINETYPE.RECT_END: {
const rectData = bounds.endLoop();
svgDraw.drawBackgroundRect(diagram, rectData);
bounds.bumpVerticalPos(conf.boxMargin);
break;
}
case parser.yy.LINETYPE.OPT_START:
bounds.bumpVerticalPos(conf.boxMargin);
bounds.newLoop(msg.message);

View File

@@ -16,7 +16,7 @@ export const drawRect = function(elem, rectData) {
return rectElem;
};
export const drawText = function(elem, textData, width) {
export const drawText = function(elem, textData) {
// Remove and ignore br:s
const nText = textData.text.replace(/<br\/?>/gi, ' ');
@@ -374,7 +374,7 @@ const _drawTextCandidateFunc = (function() {
function _setTextAttrs(toText, fromTextAttrsDict) {
for (const key in fromTextAttrsDict) {
if (fromTextAttrsDict.hasOwnProperty(key)) {
if (fromTextAttrsDict.hasOwnProperty(key)) { // eslint-disable-line
toText.attr(key, fromTextAttrsDict[key]);
}
}

View File

@@ -43,10 +43,10 @@
<SCALE>\s+"width" {this.popState();}
<INITIAL,struct>"state"\s+ { this.pushState('STATE'); }
<STATE>.*"<<fork>>" {this.popState();yytext=yytext.slice(0,-8).trim(); console.warn('Fork Fork: ',yytext);return 'FORK';}
<STATE>.*"<<join>>" {this.popState();yytext=yytext.slice(0,-8).trim();console.warn('Fork Join: ',yytext);return 'JOIN';}
<STATE>.*"[[fork]]" {this.popState();yytext=yytext.slice(0,-8).trim();console.warn('Fork Fork: ',yytext);return 'FORK';}
<STATE>.*"[[join]]" {this.popState();yytext=yytext.slice(0,-8).trim();console.warn('Fork Join: ',yytext);return 'JOIN';}
<STATE>.*"<<fork>>" {this.popState();yytext=yytext.slice(0,-8).trim(); /*console.warn('Fork Fork: ',yytext);*/return 'FORK';}
<STATE>.*"<<join>>" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Join: ',yytext);*/return 'JOIN';}
<STATE>.*"[[fork]]" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Fork: ',yytext);*/return 'FORK';}
<STATE>.*"[[join]]" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Join: ',yytext);*/return 'JOIN';}
<STATE>["] this.begin("STATE_STRING");
<STATE>"as"\s* {this.popState();this.pushState('STATE_ID');return "AS";}
<STATE_ID>[^\n\{]* {this.popState();/* console.log('STATE_ID', yytext);*/return "ID";}
@@ -133,7 +133,17 @@ statement
/* console.warn('Adding document for state without id ', $1);*/
$$={ stmt: 'state', id: $1, type: 'default', description: '', doc: $3 }
}
| STATE_DESCR AS ID { $$={stmt: 'state', id: $3, type: 'default', description: $1.trim()};}
| STATE_DESCR AS ID {
var id=$3;
var description = $1.trim();
if($3.match(':')){
var parts = $3.split(':');
id=parts[0];
description = [description, parts[1]];
}
$$={stmt: 'state', id: id, type: 'default', description: description};
}
| STATE_DESCR AS ID STRUCT_START document STRUCT_STOP
{
//console.warn('Adding document for state with id ', $3, $4); yy.addDocument($3);

View File

@@ -2,7 +2,7 @@ import * as d3 from 'd3';
import idCache from './id-cache.js';
import stateDb from './stateDb';
import utils from '../../utils';
import { getConfig, conf } from '../../config';
import { getConfig } from '../../config';
// let conf;
@@ -76,7 +76,7 @@ export const drawDescrState = (g, stateDef) => {
.attr('y', getConfig().state.textHeight + 1.5 * getConfig().state.padding)
.attr('font-size', getConfig().state.fontSize)
.attr('class', 'state-title')
.text(stateDef.id);
.text(stateDef.descriptions[0]);
const titleBox = title.node().getBBox();
const titleHeight = titleBox.height;
@@ -94,8 +94,12 @@ export const drawDescrState = (g, stateDef) => {
.attr('class', 'state-description');
let isFirst = true;
let isSecond = true;
stateDef.descriptions.forEach(function(descr) {
addTspan(description, descr, isFirst);
if (!isFirst) {
addTspan(description, descr, isSecond);
isSecond = false;
}
isFirst = false;
});
@@ -106,7 +110,6 @@ export const drawDescrState = (g, stateDef) => {
.attr('y2', getConfig().state.padding + titleHeight + getConfig().state.dividerMargin / 2)
.attr('class', 'descr-divider');
const descrBox = description.node().getBBox();
console.warn(descrBox.width, titleBox.width);
const width = Math.max(descrBox.width, titleBox.width);
descrLine.attr('x2', width + 3 * getConfig().state.padding);
@@ -128,15 +131,15 @@ export const drawDescrState = (g, stateDef) => {
*/
export const addIdAndBox = (g, stateDef) => {
// TODO Move hardcodings to conf
const addTspan = function(textEl, txt, isFirst) {
const tSpan = textEl
.append('tspan')
.attr('x', 2 * getConfig().state.padding)
.text(txt);
if (!isFirst) {
tSpan.attr('dy', getConfig().state.textHeight);
}
};
// const addTspan = function(textEl, txt, isFirst) {
// const tSpan = textEl
// .append('tspan')
// .attr('x', 2 * getConfig().state.padding)
// .text(txt);
// if (!isFirst) {
// tSpan.attr('dy', getConfig().state.textHeight);
// }
// };
const title = g
.append('text')
.attr('x', 2 * getConfig().state.padding)
@@ -145,7 +148,7 @@ export const addIdAndBox = (g, stateDef) => {
.attr('class', 'state-title')
.text(stateDef.id);
const titleHeight = title.node().getBBox().height;
const titleBox = title.node().getBBox();
const lineY = 1 - getConfig().state.textHeight;
const descrLine = g
@@ -156,7 +159,7 @@ export const addIdAndBox = (g, stateDef) => {
.attr('class', 'descr-divider');
const graphBox = g.node().getBBox();
title.attr('x', graphBox.width / 2 - title.node().getBBox().width / 2);
title.attr('x', graphBox.width / 2 - titleBox.width / 2);
descrLine.attr('x2', graphBox.width + getConfig().state.padding);
// White color
@@ -238,7 +241,7 @@ const drawForkJoinState = (g, stateDef) => {
.attr('y', getConfig().state.padding);
};
export const drawText = function(elem, textData, width) {
export const drawText = function(elem, textData) {
// Remove and ignore br:s
const nText = textData.text.replace(/<br\/?>/gi, ' ');
@@ -261,7 +264,7 @@ export const drawText = function(elem, textData, width) {
const _drawLongText = (_text, x, y, g) => {
let textHeight = 0;
let textWidth = 0;
const textElem = g.append('text');
textElem.style('text-anchor', 'start');
textElem.attr('class', 'noteText');
@@ -269,17 +272,22 @@ const _drawLongText = (_text, x, y, g) => {
let text = _text.replace(/\r\n/g, '<br/>');
text = text.replace(/\n/g, '<br/>');
const lines = text.split(/<br\/?>/gi);
let tHeight = 1.25 * getConfig().state.noteMargin;
for (const line of lines) {
const txt = line.trim();
if (txt.length > 0) {
const span = textElem.append('tspan');
span.text(txt);
const textBounds = span.node().getBBox();
textHeight += textBounds.height;
if (tHeight === 0) {
const textBounds = span.node().getBBox();
tHeight += textBounds.height;
}
// console.warn('textBounds', textBounds);
textHeight += tHeight;
span.attr('x', x + getConfig().state.noteMargin);
span.attr('y', y + textHeight + 1.25 * getConfig().state.noteMargin);
// textWidth = Math.max(textBounds.width, textWidth);
}
}
return { textWidth: textElem.node().getBBox().width, textHeight };
@@ -314,8 +322,7 @@ export const drawNote = (text, g) => {
* @param {*} stateDef
*/
let cnt = 0;
export const drawState = function(elem, stateDef, graph, doc) {
export const drawState = function(elem, stateDef) {
const id = stateDef.id;
const stateInfo = {
id: id,
@@ -347,6 +354,12 @@ export const drawState = function(elem, stateDef, graph, doc) {
return stateInfo;
};
const getRows = s => {
let str = s.replace(/<br\/?>/gi, '#br#');
str = str.replace(/\\n/g, '#br#');
return str.split('#br#');
};
let edgeCount = 0;
export const drawEdge = function(elem, path, relation) {
const getRelationType = function(type) {
@@ -401,20 +414,48 @@ export const drawEdge = function(elem, path, relation) {
);
if (typeof relation.title !== 'undefined') {
const g = elem.append('g').attr('class', 'stateLabel');
const label = g
.append('text')
.attr('text-anchor', 'middle')
.text(relation.title);
const label = elem.append('g').attr('class', 'stateLabel');
const { x, y } = utils.calcLabelPosition(path.points);
label.attr('x', x).attr('y', y);
const rows = getRows(relation.title);
// console.warn(rows);
let titleHeight = 0;
const titleRows = [];
for (let i = 0; i <= rows.length; i++) {
const title = label
.append('text')
.attr('text-anchor', 'middle')
.text(rows[i])
.attr('x', x)
.attr('y', y + titleHeight);
if (titleHeight === 0) {
const titleBox = title.node().getBBox();
titleHeight = titleBox.height;
}
titleRows.push(title);
}
if (rows.length > 1) {
const heightAdj = rows.length * titleHeight * 0.25;
titleRows.forEach((title, i) => title.attr('y', y + i * titleHeight - heightAdj));
}
const bounds = label.node().getBBox();
g.insert('rect', ':first-child')
label
.insert('rect', ':first-child')
.attr('class', 'box')
.attr('x', bounds.x - getConfig().state.padding / 2)
.attr('y', bounds.y - getConfig().state.padding / 2)
.attr('width', bounds.width + getConfig().state.padding)
.attr('height', bounds.height + getConfig().state.padding);
//label.attr('transform', '0 -' + (bounds.y / 2));
// Debug points
// path.points.forEach(point => {
// g.append('circle')

View File

@@ -9,7 +9,7 @@ const setRootDoc = o => {
const getRootDoc = () => rootDoc;
const extract = doc => {
const res = { states: [], relations: [] };
// const res = { states: [], relations: [] };
clear();
doc.forEach(item => {
@@ -37,8 +37,8 @@ let documents = {
let currentDocument = documents.root;
let startCnt = 0;
let endCnt = 0;
let stateCnt = 0;
let endCnt = 0; // eslint-disable-line
// let stateCnt = 0;
/**
* Function called by parser when a node definition has been found.
@@ -64,7 +64,14 @@ export const addState = function(id, type, doc, descr, note) {
currentDocument.states[id].type = type;
}
}
if (descr) addDescription(id, descr.trim());
if (descr) {
if (typeof descr === 'string') addDescription(id, descr.trim());
if (typeof descr === 'object') {
descr.forEach(des => addDescription(id, des.trim()));
}
}
if (note) currentDocument.states[id].note = note;
};

View File

@@ -1,18 +1,15 @@
import * as d3 from 'd3';
import dagre from 'dagre-layout';
import graphlib from 'graphlibrary';
import dagre from 'dagre';
import graphlib from 'graphlib';
import { logger } from '../../logger';
import stateDb from './stateDb';
import { parser } from './parser/stateDiagram';
import utils from '../../utils';
import idCache from './id-cache';
import { drawState, addIdAndBox, drawEdge, drawNote } from './shapes';
// import idCache from './id-cache';
import { drawState, addIdAndBox, drawEdge } from './shapes';
import { getConfig } from '../../config';
parser.yy = stateDb;
let total = 0;
// TODO Move conf object to main conf in mermaidAPI
let conf;
// {
@@ -28,20 +25,20 @@ let conf;
const transformationLog = {};
export const setConf = function(cnf) {};
export const setConf = function() {};
// Todo optimize
const getGraphId = function(label) {
const keys = idCache.keys();
// const getGraphId = function(label) {
// const keys = idCache.keys();
for (let i = 0; i < keys.length; i++) {
if (idCache.get(keys[i]).label === label) {
return keys[i];
}
}
// for (let i = 0; i < keys.length; i++) {
// if (idCache.get(keys[i]).label === label) {
// return keys[i];
// }
// }
return undefined;
};
// return undefined;
// };
/**
* Setup arrow head and define the marker. The result is appended to the svg.
@@ -90,24 +87,49 @@ export const draw = function(text, id) {
});
const rootDoc = stateDb.getRootDoc();
const n = renderDoc(rootDoc, diagram);
renderDoc(rootDoc, diagram);
const padding = conf.padding;
const bounds = diagram.node().getBBox();
diagram.attr('height', '100%');
diagram.attr('style', `width: ${bounds.width * 3 + conf.padding * 2};`);
console.warn(bounds);
const width = bounds.width + padding * 2;
const height = bounds.height + padding * 2;
// diagram.attr('height', '100%');
// diagram.attr('style', `width: ${bounds.width * 3 + conf.padding * 2};`);
// diagram.attr('height', height);
// Zoom in a bit
diagram.attr('width', width * 2);
// diagram.attr('height', bounds.height * 3 + conf.padding * 2);
diagram.attr(
'viewBox',
`${conf.padding * -1} ${conf.padding * -1} ` +
(bounds.width * 1.5 + conf.padding * 2) +
' ' +
(bounds.height + conf.padding * 5)
`${bounds.x - conf.padding} ${bounds.y - conf.padding} ` + width + ' ' + height
);
// diagram.attr('transform', `translate(, 0)`);
// diagram.attr(
// 'viewBox',
// `${conf.padding * -1} ${conf.padding * -1} ` +
// (bounds.width * 1.5 + conf.padding * 2) +
// ' ' +
// (bounds.height + conf.padding * 5)
// );
};
const getLabelWidth = text => {
return text ? text.length * conf.fontSizeFactor : 1;
};
/* TODO: REMOVE DUPLICATION, SEE SHAPES */
const getRows = s => {
if (!s) return 1;
let str = s.replace(/<br\/?>/gi, '#br#');
str = str.replace(/\\n/g, '#br#');
return str.split('#br#');
};
const renderDoc = (doc, diagram, parentId) => {
// // Layout graph, Create a new directed graph
const graph = new graphlib.Graph({
@@ -121,7 +143,6 @@ const renderDoc = (doc, diagram, parentId) => {
// multigraph: false,
compound: true,
// acyclicer: 'greedy',
rankdir: 'LR',
ranker: 'tight-tree',
ranksep: conf.edgeLengthFactor
// isMultiGraph: false
@@ -151,7 +172,6 @@ const renderDoc = (doc, diagram, parentId) => {
const keys = Object.keys(states);
total = keys.length;
let first = true;
for (let i = 0; i < keys.length; i++) {
@@ -221,7 +241,7 @@ const renderDoc = (doc, diagram, parentId) => {
graph.setEdge(relation.id1, relation.id2, {
relation: relation,
width: getLabelWidth(relation.title),
height: conf.labelHeight,
height: conf.labelHeight * getRows(relation.title).length,
labelpos: 'c'
});
});
@@ -278,7 +298,7 @@ const renderDoc = (doc, diagram, parentId) => {
});
stateBox = svgElem.getBBox();
console.warn('Diagram node', svgElem.id);
const stateInfo = {
id: parentId ? parentId : 'root',
label: parentId ? parentId : 'root',

View File

@@ -310,14 +310,13 @@ const config = {
state: {
dividerMargin: 10,
sizeUnit: 5,
padding: 5,
padding: 8,
textHeight: 10,
titleShift: -15,
noteMargin: 10,
forkWidth: 70,
forkHeight: 7,
// Used
padding: 5,
miniPadding: 2,
// Font size factor, this is used to guess the width of the edges labels before rendering by dagre
// layout. This might need updating if/when switching font
@@ -366,8 +365,6 @@ function parse(text) {
break;
case 'info':
logger.debug('info info info');
console.warn('In API', pkg.version);
parser = infoParser;
parser.parser.yy = infoDb;
break;

View File

@@ -122,7 +122,7 @@ const calcLabelPosition = points => {
const calcCardinalityPosition = (isRelationTypePresent, points, initialPosition) => {
let prevPoint;
let totalDistance = 0;
let totalDistance = 0; // eslint-disable-line
if (points[0] !== initialPosition) {
points = points.reverse();
}

View File

@@ -3319,7 +3319,7 @@ d3-zoom@1:
d3-selection "1"
d3-transition "1"
d3@^5.7.0:
d3@^5.12, d3@^5.7.0:
version "5.12.0"
resolved "https://registry.yarnpkg.com/d3/-/d3-5.12.0.tgz#0ddeac879c28c882317cd439b495290acd59ab61"
integrity sha512-flYVMoVuhPFHd9zVCe2BxIszUWqBcd5fvQGMNRmSiBrgdnh6Vlruh60RJQTouAK9xPbOB0plxMvBm4MoyODXNg==
@@ -3356,21 +3356,22 @@ d3@^5.7.0:
d3-voronoi "1"
d3-zoom "1"
dagre-d3-renderer@^0.5.8:
version "0.5.8"
resolved "https://registry.yarnpkg.com/dagre-d3-renderer/-/dagre-d3-renderer-0.5.8.tgz#aa071bb71d3c4d67426925906f3f6ddead49c1a3"
integrity sha512-XH2a86isUHRxzIYbjQVEuZtJnWEufb64H5DuXIUmn8esuB40jgLEbUUclulWOW62/ZoXlj2ZDyL8SJ+YRxs+jQ==
dagre-d3@dagrejs/dagre-d3:
version "0.6.4-pre"
resolved "https://codeload.github.com/dagrejs/dagre-d3/tar.gz/e1a00e5cb518f5d2304a35647e024f31d178e55b"
dependencies:
dagre-layout "^0.8.8"
lodash "^4.17.5"
d3 "^5.12"
dagre "^0.8.4"
graphlib "^2.1.7"
lodash "^4.17.15"
dagre-layout@^0.8.8:
version "0.8.8"
resolved "https://registry.yarnpkg.com/dagre-layout/-/dagre-layout-0.8.8.tgz#9b6792f24229f402441c14162c1049e3f261f6d9"
integrity sha512-ZNV15T9za7X+fV8Z07IZquUKugCxm5owoiPPxfEx6OJRD331nkiIaF3vSt0JEY5FkrY0KfRQxcpQ3SpXB7pLPQ==
dagre@^0.8.4:
version "0.8.4"
resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.4.tgz#26b9fb8f7bdc60c6110a0458c375261836786061"
integrity sha512-Dj0csFDrWYKdavwROb9FccHfTC4fJbyF/oJdL9LNZJ8WUvl968P6PAKEriGqfbdArVJEmmfA+UyumgWEwcHU6A==
dependencies:
graphlibrary "^2.2.0"
lodash "^4.17.5"
graphlib "^2.1.7"
lodash "^4.17.4"
dashdash@^1.12.0:
version "1.14.1"
@@ -5132,10 +5133,10 @@ graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02"
integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==
graphlibrary@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/graphlibrary/-/graphlibrary-2.2.0.tgz#017a14899775228dec4497a39babfdd6bf56eac6"
integrity sha512-XTcvT55L8u4MBZrM37zXoUxsgxs/7sow7YSygd9CIwfWTVO8RVu7AYXhhCiTuFEf+APKgx6Jk4SuQbYR0vYKmQ==
graphlib@^2.1.7:
version "2.1.7"
resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.7.tgz#b6a69f9f44bd9de3963ce6804a2fc9e73d86aecc"
integrity sha512-TyI9jIy2J4j0qgPmOOrHTCtpPqJGN/aurBwc6ZT+bRii+di1I+Wv3obRhVrmBEXet+qkMaEX67dXrwsd3QQM6w==
dependencies:
lodash "^4.17.5"
@@ -7044,7 +7045,7 @@ lodash@4.17.11:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10:
lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==