Compare commits

...

648 Commits
8.3.0 ... 8.4.8

Author SHA1 Message Date
Knut Sveidqvist
1c07e550bb Merge pull request #1267 from mermaid-js/bug/1261_removal_of_cosole.log-calls
Bug/1261 removal of console.log calls
2020-02-21 10:23:37 +01:00
Knut Sveidqvist
50c71ebb01 #1261 Removal of emojis making rendering tests give false warnings from time to time 2020-02-21 10:08:52 +01:00
Knut Sveidqvist
348d086c11 #1261 Tmp reversal of build.yml to get make release possible 2020-02-21 10:00:36 +01:00
Knut Sveidqvist
89c1853977 #1261 Removed calls to console.log 2020-02-21 09:50:04 +01:00
Knut Sveidqvist
3acff54837 Merge pull request #1260 from mermaid-js/chris579-patch-1
Build action fix
2020-02-17 17:13:25 +01:00
Christian Klemm
c7466f7a1a adj 2020-02-16 19:54:29 +01:00
Christian Klemm
6420ad9f69 Merge remote-tracking branch 'origin/chris579-patch-1' into chris579-patch-1 2020-02-16 19:47:55 +01:00
Christian Klemm
b30823d5ac mermaid upgrade 2020-02-16 19:47:14 +01:00
Christian Klemm
864472d648 Update build.yml 2020-02-16 19:41:52 +01:00
Christian Klemm
36b02ec008 adj 2020-02-16 19:32:10 +01:00
Knut Sveidqvist
aad080aa1b Merge pull request #1259 from mermaid-js/bug/1257_autonumbering
#1257 Adding the autonumber keyword + tests and docs
2020-02-16 17:13:59 +01:00
Christian Klemm
7b7a6e10f8 adj 2020-02-16 17:11:13 +01:00
Christian Klemm
aeccf92375 Update build.yml 2020-02-16 16:52:15 +01:00
Christian Klemm
f90d271739 Update build.yml 2020-02-16 16:40:43 +01:00
Christian Klemm
9c2fde940d Update build.yml 2020-02-16 16:35:59 +01:00
Christian Klemm
2b57cc6be8 Update build.yml 2020-02-16 16:31:37 +01:00
Christian Klemm
b62819e3fb Update build.yml 2020-02-16 16:26:29 +01:00
Christian Klemm
3eb5f2c65b Update build.yml 2020-02-16 16:10:47 +01:00
Christian Klemm
41be7f951c Update build.yml 2020-02-16 16:04:20 +01:00
Christian Klemm
7812fdb6ed Merge pull request #1258 from mermaid-js/actions-fix
Actions fix
2020-02-16 15:54:55 +01:00
Christian Klemm
4eeb2a0583 lockfile update 2020-02-16 15:46:45 +01:00
Knut Sveidqvist
3dd0c537ee Font update for e2e tests 2020-02-16 15:39:52 +01:00
Christian Klemm
e0aa42f695 Update package.json 2020-02-16 15:39:20 +01:00
Christian Klemm
5dddf2f757 Update build.yml 2020-02-16 15:38:52 +01:00
Knut Sveidqvist
f8137ea7c1 #1257 Adding the autonumber keyword + tests and docs 2020-02-16 15:26:08 +01:00
Knut Sveidqvist
cf6f1a083e Upgarding version in docs 2020-02-16 14:19:27 +01:00
Knut Sveidqvist
f9cfeacc67 Version bump 2020-02-16 13:56:37 +01:00
Knut Sveidqvist
98229a47b2 Renabling build for node 10 2020-02-16 12:46:23 +01:00
Knut Sveidqvist
530ace1507 Disabling e2e tests in github actions 2020-02-16 12:39:05 +01:00
Knut Sveidqvist
792c657ff2 Modified build.yml 2020-02-16 09:42:57 +01:00
Knut Sveidqvist
5aa07439a8 Modified build.yml 2020-02-16 09:40:35 +01:00
Knut Sveidqvist
bf2862f164 Updated packages 2020-02-16 09:30:08 +01:00
Knut Sveidqvist
d9ef227435 Updated packages, trying to fix e2e tests in build 2020-02-16 09:17:17 +01:00
Knut Sveidqvist
324c845dc4 Disabling Static tests action due to issues with cypress 2020-02-16 09:06:05 +01:00
Knut Sveidqvist
5d0c44e84b Adding @babel/preset-env inorder to help build action 2020-02-16 08:54:17 +01:00
GDFaber
01a71c3dbb Merge pull request #1254 from xbojch/patch-1
Typos
2020-02-15 23:54:05 +01:00
Bojan Bedrac
b018f026e3 Typo
- fixes a typo
2020-02-13 15:51:00 +01:00
Knut Sveidqvist
0a38e3557d Merge pull request #1248 from DCsunset/bug/1247_ssr_error
Bug/1247 Fix "window is not defined" with ssr
2020-02-11 07:02:50 +01:00
DCsunset
6f450272b8 #1247 fix "window is not defined" with ssr 2020-02-06 20:26:09 -08:00
Knut Sveidqvist
7e01f9be6e Merge pull request #1245 from mermaid-js/feature/1224_styling_of_subgraphs
Feature/1224 styling of subgraphs
2020-02-05 20:06:22 +01:00
Knut Sveidqvist
00d2a1fe9f Merge branch 'develop' of github.com:mermaid-js/mermaid into develop 2020-02-05 19:42:13 +01:00
Knut Sveidqvist
18d0d435c6 Merge pull request #1241 from jgreywolf/1240-ClassDiagramRefactor
1240 class diagram refactor
2020-02-05 19:42:01 +01:00
Knut Sveidqvist
f298c154e2 Merge branch 'develop' of github.com:mermaid-js/mermaid into develop 2020-02-05 19:40:18 +01:00
Knut Sveidqvist
822df37f8c #1224 Possibility to style text color of nodes and subgraphs as well as apply classes to subgraphs 2020-02-05 19:39:50 +01:00
Knut Sveidqvist
73cac95255 Merge pull request #1238 from GDFaber/feature/962_flowchart_line_label_color_from_linkstyle
Set text color for flowchart link labels according to linkStyle definitions
2020-02-05 19:36:12 +01:00
Marc Faber
a0e7789d50 #962 added color setting for default link style 2020-02-04 22:07:10 +01:00
Justin Greywolf
c825b37cc6 1240-refactor for class renderer
prep for future functionality work
2020-02-03 16:04:59 -08:00
Marc Faber
2dd4aa31e5 #962 moved "style from array" function to utils.js, added unit test 2020-02-04 00:24:50 +01:00
Marc Faber
c95adfaf74 #962 Set text color for flowchart link labels according to linkStyle definitions 2020-02-02 22:59:59 +01:00
Justin Greywolf
9da8ea5967 Merge pull request #16 from mermaid-js/develop
Merge from parent
2020-01-30 10:20:14 -08:00
Knut Sveidqvist
4d5ecc5518 Merge pull request #1203 from jgreywolf/1179-SupportGenericTypesForMembers
1179 support generic types for members
2020-01-29 21:08:41 +01:00
Knut Sveidqvist
963a0fcd77 Merge branch 'develop' into 1179-SupportGenericTypesForMembers 2020-01-29 21:08:31 +01:00
Ashish Jain
fbd8dfa5be Merge pull request #1230 from mermaid-js/bug/1223_multiple_transitions_in_statediagram
Bug/1223 multiple transitions in statediagram
2020-01-29 21:02:14 +01:00
Knut Sveidqvist
c43f791b29 #1223 Removing/updating some logging, adding current.html to .gitignore 2020-01-29 20:44:15 +01:00
Ashish Jain
39b873cd5f Merge pull request #1229 from mermaid-js/bug/1217_fix_for_keyword_as_in_stateDiagram
#1217 Better matching of words beginning with as as matching token
2020-01-29 20:24:28 +01:00
Knut Sveidqvist
ec90537181 #1223 Adding support for multiple transitions to a node from another node 2020-01-29 20:01:21 +01:00
Knut Sveidqvist
4709195a1d #1223 Adding support for multiple transitions to a node from another node 2020-01-29 19:57:59 +01:00
Knut Sveidqvist
0082c23a90 #1217 Better matchingof words beginning with as as matching token AS in stateDiagram's state definition. 2020-01-29 19:05:51 +01:00
Knut Sveidqvist
c7b559f449 Update todo.md 2020-01-27 20:28:43 +01:00
Knut Sveidqvist
d571c7e08e Merge pull request #1225 from jgreywolf/1058-ClassDiagramScaling
1058 class diagram scaling
2020-01-27 20:14:39 +01:00
Knut Sveidqvist
b6f0b25f24 Merge pull request #1222 from GDFaber/bug/1218_fix_link_click_events
Fix anchor and script support in link click events
2020-01-27 20:13:07 +01:00
Knut Sveidqvist
5ea6bd5980 Merge branch 'develop' into bug/1218_fix_link_click_events 2020-01-27 20:06:00 +01:00
Knut Sveidqvist
ea29b67c5c Merge pull request #1221 from mermaid-js/bug/1216_dodging_huge_diagrams
#1216 Fix for issue when mermaid freezes the browser tab due to large…
2020-01-27 20:01:54 +01:00
Knut Sveidqvist
1f851bc04c Merge pull request #1219 from GDFaber/feature/487_flowchart_node_text_color_from_style
#487 Set text color for flowchart nodes according to style definitions
2020-01-27 20:01:19 +01:00
Justin Greywolf
0921007d92 1058-Set diagram dimensions appropriately
Make sure height and width are set so that all of the diagram is displayed
2020-01-27 10:27:05 -08:00
Justin Greywolf
4a2e0bfa00 Merge branch 'develop' into 1179-SupportGenericTypesForMembers 2020-01-27 09:44:12 -08:00
Justin Greywolf
8ebc587fb5 Merge pull request #15 from mermaid-js/develop
Merge from parent
2020-01-27 09:43:46 -08:00
Marc Faber
c7b46f4fba #1218 Fix anchor and script support in link click events 2020-01-26 16:56:42 +01:00
Knut Sveidqvist
4ad354a561 #1216 Fix for issue when mermaid freezes the browser tab due to large diagrams 2020-01-25 13:35:11 +01:00
Justin Greywolf
587592449a 1179 Add ability to use generics for members
Created new class to handle parsing of members with regex to handle determining type of member and the different elements within.  Also moved addTSpan in drawClass method to this new file.  Finally, I added a "catch all" section in case something fails in the regex to make sure everything gets formatted correctly.

Added more tests and documentation

updating gitignore

Tired of constantly having to ignore files and stash/pop when switching between branches
2020-01-24 16:01:04 -08:00
Justin Greywolf
425b071a50 Merge pull request #14 from mermaid-js/develop
merge from
2020-01-24 15:58:42 -08:00
Marc Faber
4dd72e6793 Trigger tests again 2020-01-24 01:42:46 +01:00
Marc Faber
d2d4a24229 #487 Set text color for flowchart nodes according to style definitions 2020-01-24 01:24:47 +01:00
Knut Sveidqvist
4805394e61 New version in the docs 2020-01-22 19:22:37 +01:00
Knut Sveidqvist
5cbd723f8d Merge branch 'release/8.4.6' 2020-01-22 19:07:20 +01:00
Knut Sveidqvist
28153656d7 Updated docs with info on chaining of nodes and using ::: to attach a class 2020-01-22 18:52:16 +01:00
Knut Sveidqvist
d2eaf16751 Updating version to 8.4.6 2020-01-22 18:33:33 +01:00
Knut Sveidqvist
e0d98b2e14 Merge pull request #1214 from GDFaber/bug/1212_apply_classDef_to_flowchart_nodes_with_links
Fix styling of flowchart nodes with links when class definitions are assigned
2020-01-22 17:59:53 +01:00
Marc Faber
c38f053294 #1212 Class definition is not applied to flowchart nodes with links 2020-01-19 18:10:14 +01:00
Knut Sveidqvist
921d274579 Merge pull request #1208 from mermaid-js/feature/Issue-1206_Parsing_Crashing_Browser_In_Class_Diagram
Feature/issue 1206 parsing crashing browser in class diagram
2020-01-15 20:55:21 +01:00
Ashish Jain
c9f95a1866 Merge pull request #1207 from mermaid-js/bug/1205_activations_error
#1205 Adding parsing exception for then an inactive participant is inactivated
2020-01-15 20:48:36 +01:00
Ashish Jain
99469f8404 #1206 Added test case to verify parsing fails to allow EOF until first '{' is closed 2020-01-15 20:34:41 +01:00
Ashish Jain
417d2c0336 #1206 Added test case to verify parsing fails to allow another '{' until first one is closed 2020-01-15 20:33:23 +01:00
Ashish Jain
2a3de1a090 #1206 Updated the classDiagram JISON to not allow EOF or another '{' until first one is closed 2020-01-15 20:29:13 +01:00
Knut Sveidqvist
d9318c5af3 #1205 Adding parsing exception for then an inactive participant is inactivated 2020-01-15 20:27:31 +01:00
Justin Greywolf
0e02cf5c86 Merge pull request #1195 from fgrandel/bug/1193_allow_multiple_relations
fix(#1193): render multiple relations
2020-01-15 09:29:02 -08:00
Knut Sveidqvist
45277affe8 Merge pull request #1204 from GDFaber/bug/1196_keep_flowchart_label_text_when_style_is_applied
Keep flowchart node label text (if already defined) when a style is applied
2020-01-15 18:27:48 +01:00
Knut Sveidqvist
c564a843fa Merge pull request #1202 from GDFaber/bug/1200_unify_regex_for_br_tags
Unify regex for finding <br> tags throughout mermaid
2020-01-15 16:53:06 +01:00
Knut Sveidqvist
efa810da91 Merge pull request #1199 from GDFaber/bug/fix_mermaidAPI_configuration_example_in_the_docs
Fix mermaidAPI configuration example in the docs
2020-01-15 16:50:11 +01:00
Knut Sveidqvist
c0e1c90497 Merge pull request #1198 from GDFaber/bug/add_docs_and_defaults_for_node_spacing
Add docs and default values for node spacing in mermaidAPI
2020-01-15 16:48:58 +01:00
Marc Faber
b1bfdec473 #1196 Keep flowchart node label text (if already defined) when a style is applied 2020-01-14 23:37:30 +01:00
Justin Greywolf
244f423baf Merge pull request #1194 from fgrandel/bug/1192_relation_cut_off
fix(#1192): relation got cut off
2020-01-14 09:35:00 -08:00
Justin Greywolf
8897b32cd3 Merge pull request #13 from mermaid-js/develop
sync
2020-01-13 16:01:40 -08:00
Marc Faber
5493fadc9e #1200 Unify regex for finding <br> tags throughout mermaid 2020-01-13 22:04:47 +01:00
Knut Sveidqvist
eade3d0a2d Merge pull request #1178 from jgreywolf/1119-SpecifyMethodReturnTypeInClassDiagram
1119 specify method return type in class diagram
2020-01-13 19:55:47 +01:00
Marc Faber
36f9eca33e Example 2 is not shown in mermaidAPI configuration section of the docs 2020-01-12 14:38:57 +01:00
Marc Faber
4dd90e56b1 Add docs and default values for node spacing in mermaidAPI 2020-01-12 14:09:24 +01:00
Knut Sveidqvist
5e7484a12d Update mermaidAPI.md 2020-01-12 01:04:15 -08:00
Knut Sveidqvist
fdbc44e41b Update mermaidAPI.md 2020-01-12 01:03:46 -08:00
Knut Sveidqvist
e0d16dcb22 Version 8.4.5 2020-01-11 10:07:41 +01:00
Knut Sveidqvist
0a5ee0634f Merge branch 'master' of github.com:mermaid-js/mermaid
# Conflicts:
#	docs/classDiagram.md
2020-01-11 09:47:51 +01:00
Justin Greywolf
fa1331ffd5 Fix after removing other code 2020-01-10 10:24:04 -08:00
Justin Greywolf
57b5b9a7a6 Added conditional to fallback to old style 2020-01-10 09:50:21 -08:00
Justin Greywolf
58fbfc3c38 1119 Support method return types
Small refactor to split out logic for determining method display text and style. Updated documentation
Used regex to parse method statements in class diagrams to extract discrete elements to set display appropriately. Added tests and updated docs
2020-01-10 09:50:21 -08:00
Justin Greywolf
0af5e0b795 Address code style issues 2020-01-10 09:50:21 -08:00
Justin Greywolf
d7771eb4b6 1119 Add ability to define return type for methods
Updated ClassRenderer to check for `[]` to indicate return type for method. Small refactor to split out logic for determining method display text and style. Updated documentation
2020-01-10 09:50:21 -08:00
Justin Greywolf
fc0902c290 Merge pull request #12 from mermaid-js/develop
sync
2020-01-10 09:47:16 -08:00
Florian Grandel
75890f88fa fix(#1193): render multiple relations 2020-01-09 17:00:34 +01:00
Florian Grandel
9a6b07e1e1 fix(#1192): relation got cut off 2020-01-09 16:24:47 +01:00
Knut Sveidqvist
ce02d1dc98 Merge pull request #1190 from mermaid-js/Issue-1092_Mangled_Multiple_Class_Diagrams
#1092 Fix for mangling of multiple classDiagrams
2020-01-08 21:05:42 +01:00
Knut Sveidqvist
7760e63b47 Merge pull request #1189 from GDFaber/maintenance/1182_flowchart_remove_newDagreD3
Maintenance/Remove "newDagreD3" switch from the flowchart renderer
2020-01-08 20:56:54 +01:00
Christian Klemm
a483f2466f added artifact to build action 2020-01-08 20:52:39 +01:00
Ashish Jain
48c345a403 #1092 Fix for mangling of multiple classDiagrams 2020-01-08 20:48:57 +01:00
Marc Faber
82b79aa332 Trigger tests once more 2020-01-08 20:42:58 +01:00
Marc Faber
ffbf9f265f #1182: remove "newDagreD3" switch from the flowchart renderer 2020-01-08 20:27:33 +01:00
Knut Sveidqvist
144f65c459 Merge pull request #1176 from GDFaber/feature/1152_flowchart_node_spacing
Feature/Add node spacing to flowchart configuration
2020-01-08 18:16:03 +01:00
Ashish Jain
18204586e1 Merge pull request #1188 from GDFaber/feature/743_gantt_multiline_section_titles
Feature/Handle multiline section titles in gantt diagrams
2020-01-08 18:06:29 +01:00
Marc Faber
1f3c970e7a Trigger tests once more 2020-01-08 14:03:16 +01:00
Marc Faber
1cfd93640c #743 handle multiline section titles in gantt diagrams 2020-01-08 13:50:58 +01:00
Marc Faber
553ea4971f Trigger tests one more time 2020-01-07 01:24:24 +01:00
Justin Greywolf
ac8b01a94c Merge pull request #11 from mermaid-js/develop
sync
2020-01-06 10:08:43 -08:00
Marc Faber
b3934c9788 #1152 add node spacing to flowchart configuration 2020-01-05 22:03:53 +01:00
Knut Sveidqvist
37ae863443 Merge pull request #1170 from jgreywolf/1064-ClickEventInClassDiagram
1064 click event in class diagram
2020-01-05 12:07:34 +01:00
Knut Sveidqvist
f57356006d Merge pull request #1171 from mermaid-js/feature/Issue-1146_Dashed_Line_For_Class_Diagram
Feature/issue 1146 dashed line for class diagram
2020-01-05 12:02:36 +01:00
Justin Greywolf
591a104c80 1064 Class diagram interactivity docs
Updated documentation for Class Diagram with details for interactivity
2020-01-03 10:14:07 -08:00
Justin Greywolf
38097c9095 code style 2020-01-02 11:27:56 -08:00
Justin Greywolf
7f31e624ca Addressing code style issues 2020-01-02 11:24:06 -08:00
Justin Greywolf
e6fbfcb1e8 1064 Adding tooltip and function calls to click evens in class diagrams 2020-01-02 11:06:29 -08:00
Justin Greywolf
00687f21cd Merge pull request #10 from mermaid-js/develop
sync fork
2020-01-02 11:05:54 -08:00
Ashish Jain
96fc0d043e #1146 Added cypress test for dash line (dependecy) rendering 2020-01-02 19:57:11 +01:00
Ashish Jain
190353785e #1146 Added jest test for dash line (dependecy) parsing 2020-01-02 19:51:25 +01:00
Ashish Jain
f54adb4a3e #1146 Updated classDiagram documentation with new relation types 2020-01-02 19:35:22 +01:00
Ashish Jain
f2a5d92398 #1146 Added stroke-dasharray style for Dependency relation 2020-01-02 19:29:17 +01:00
Ashish Jain
b14c768fa2 #1146 Fix for dashed line (Dependency) support for classDiagram 2020-01-02 19:25:31 +01:00
Ashish Jain
851d2f2d91 Merge pull request #1168 from mermaid-js/feature/834_linking_to_multiple_nodes
#834 Using & as a separator for the multiple nodes
2020-01-02 19:13:22 +01:00
Knut Sveidqvist
4e6aad5115 #834 Using & as a separator for the multiple nodes 2020-01-02 18:52:50 +01:00
Knut Sveidqvist
7bd1408de0 Merge pull request #1165 from jgreywolf/1064-ClickEventInClassDiagram
1064 click event in class diagram
2020-01-02 08:10:48 -08:00
Justin Greywolf
d63eb396e1 Fix code style issues 2020-01-02 07:59:36 -08:00
Knut Sveidqvist
465e99ab5d Merge pull request #1167 from mermaid-js/feature/921_adding_interaction_tests
Adding interaction tests for gantt callbacks with arguments
2020-01-01 03:41:14 -08:00
Knut Sveidqvist
33916cfbd3 Adding interaction tests for gantt callbacks with arguments 2020-01-01 12:03:29 -08:00
Knut Sveidqvist
a1626927cc Merge pull request #1136 from keenanjt33/feature/921_callback_params
Gantt: Add support for callback with parameters
2020-01-01 00:29:00 -08:00
Knut Sveidqvist
75e2abe242 Merge pull request #1166 from GDFaber/feature/flowchart_add_cylindric_shape
#1154 Flow diagram DB shape request
2020-01-01 00:24:56 -08:00
Knut Sveidqvist
2db8075e3f Merge pull request #1163 from GDFaber/bug/891_make_link_clickable_on_the_entire_node
Bug/Clicking on a link only works directly on the node text
2019-12-31 07:58:47 -08:00
Knut Sveidqvist
413876644c Merge pull request #1162 from sdankel/bug/1060_date_infinite_loop
Fix infinite loop caused by date iteration
2019-12-31 07:57:16 -08:00
Knut Sveidqvist
d5e9f2e23e Merge pull request #1156 from gene1wood/extend_br_tag_regex
Extend the `br` tag regex
2019-12-31 07:56:21 -08:00
Marc Faber
bc59d015e6 #1154 Flow diagram DB shape request 2019-12-31 16:30:03 +01:00
Justin Greywolf
2decf94ad0 1064- Add click functionality to class diagrams
modified interaction functionality from flowcharts to work with class diagrams
2019-12-30 17:27:20 -08:00
Justin Greywolf
b52744ae18 Merge pull request #9 from mermaid-js/develop
update fork
2019-12-30 17:26:40 -08:00
Knut Sveidqvist
6cbbf0af2f Merge pull request #1159 from DavertMik/develop
Check tests on PR
2019-12-29 08:47:08 +01:00
Christian Klemm
5d7ef149aa Merge pull request #1161 from wfnuser/fix/typos-in-flowDb
Error typos in flowDb
2019-12-26 16:26:02 +01:00
Marc Faber
7ce0974767 #891 Clicking on a link only works directly on the node text 2019-12-26 15:38:53 +01:00
Sophie Dankel
7b12c7a07d Fix infinite loop caused by date iteration 2019-12-24 19:01:29 -08:00
Christian Klemm
728e3fd2f0 Added task list to pull request template 2019-12-24 23:37:18 +01:00
wfnuser
4eedeebd46 other/typos in flowDb 2019-12-24 16:14:42 +08:00
Michael Bodnarchuk
85fb12155b Create checks.yml (#1)
* Create checks.yml

* Update checks.yml
2019-12-24 00:08:38 +02:00
Justin Greywolf
f99daa696e Merge pull request #8 from mermaid-js/develop
merge from base
2019-12-23 12:21:44 -08:00
Gene Wood
b4f9dd46a9 Add tests for <br \t> case
This adds tests for the case where
* multiple pieces of whitespace are used
* one of those whitespace characters is a tab
2019-12-23 08:52:15 -08:00
Nacho
ffe16f89bb Merge pull request #1157
Fix mispelling
2019-12-23 11:33:49 -05:00
Gene Wood
7604d92d5c Fix mispelling 2019-12-23 08:11:47 -08:00
Gene Wood
3abd77a1e6 Extend the br tag regex
This extends the `br` tag regex to accommodate an arbitrary amount of
any type of whitespace instead of a single space character, which holds
more closely to the HTML spec[1]

This extends the fix to #702 added in #1153

[1]: http://www.w3.org/TR/REC-xml/#sec-starttags
2019-12-23 08:02:11 -08:00
Knut Sveidqvist
d96b79a9ba Merge pull request #1153 from GDFaber/bug/702_br_tags_in_sequence_diagrams
Bug/702 br tags in sequence diagrams
2019-12-23 10:04:30 +01:00
Knut Sveidqvist
14bb888c21 Merge pull request #1151 from Progressive-Insurance/bug/git-graph-clear
Git graph not clearing
2019-12-23 10:03:16 +01:00
Knut Sveidqvist
c8f59ea1a7 Merge pull request #1140 from jdavis61/docs/1124_incorrect_include
Removed docs reference to mermaidAPI.js
2019-12-23 08:56:40 +01:00
Marc Faber
233520b797 #702 improve handling of different "br" tag notations for multiline texts in sequence diagrams 2019-12-21 20:39:32 +01:00
GDFaber
061d31af33 Merge pull request #6 from mermaid-js/develop
sync fork
2019-12-21 00:02:01 +01:00
Matthew Schott
ec742d3180 fix git graph not clearing 2019-12-20 14:48:36 -05:00
Nacho
1bc62cfba4 Merge pull request #1150 2019-12-19 13:45:21 -05:00
erinleck@gmail.com
028d9a2667 changes tick contrast for gantt chart 2019-12-19 09:52:46 -07:00
Knut Sveidqvist
d53e00ffe0 Change of broken docs 2019-12-18 19:43:35 +01:00
Knut Sveidqvist
b90fcc1b71 test commit 2019-12-18 19:40:50 +01:00
Knut Sveidqvist
a4e7305d52 #834 Adding unit tests and rendering tests 2019-12-18 19:13:56 +01:00
Knut Sveidqvist
a3378f8d03 Merge pull request #1149 from mermaid-js/other/1143_utilze_browser_console_object_better
#1143 Adding support in grammar for multiple nodes in dependency decl…
2019-12-18 18:41:45 +01:00
Knut Sveidqvist
5716d163ec Merge branch 'develop' into other/1143_utilze_browser_console_object_better 2019-12-18 18:41:14 +01:00
Knut Sveidqvist
42ef035241 #834 Using space as separator, simplfifying the grammar some more, reomving some logging 2019-12-18 18:36:34 +01:00
Knut Sveidqvist
b6157195b3 Merge pull request #1148 from mermaid-js/other/1142_simplify_flowshart_grammar
#1142 Simplified arrows/edges in the grammar
2019-12-18 18:12:55 +01:00
GDFaber
b8ee68034d Merge pull request #5 from mermaid-js/develop
fork sync
2019-12-16 17:18:15 +01:00
Knut Sveidqvist
6598b1b10d #1143 Adding support in grammar for multiple nodes in dependency declarations 2019-12-15 18:10:52 +01:00
Knut Sveidqvist
4ff4058244 #1142 Simplified arrows/edges in the grammar 2019-12-15 13:34:35 +01:00
Knut Sveidqvist
dddd5af830 Merge pull request #1144 from mermaid-js/other/1143_utilze_browser_console_object_better
#1143 Fixing up the color output of the logger
2019-12-15 10:09:27 +01:00
Knut Sveidqvist
26fac9507e #1143 Fixing up the color putput of the logger 2019-12-15 09:50:24 +01:00
GDFaber
1f1c9698ce Merge pull request #4 from mermaid-js/develop
sync my fork
2019-12-15 02:18:38 +01:00
GitHub actions
56f7459617 Release 8.4.4 2019-12-14 08:50:41 +00:00
GitHub actions
86604b5de1 Bump version 8.4.4 2019-12-14 08:50:41 +00:00
Knut Sveidqvist
0544dbe891 Merge branch 'master' into develop 2019-12-14 09:27:38 +01:00
Knut Sveidqvist
6365cea0b2 Upgrading docs to 8.4.4 2019-12-14 09:26:21 +01:00
Knut Sveidqvist
7fef13346e Bumping version to 8.4.4 2019-12-14 09:00:53 +01:00
Knut Sveidqvist
81216e6ece Merge branch 'release/8.4.4' 2019-12-14 08:52:40 +01:00
James Davis
1d0b305332 Readded call to mermaidAPI in docs 2019-12-12 22:25:07 -05:00
James Davis
c10ccc011f Removed reference to mermaidAPI.js 2019-12-12 07:47:36 -05:00
Christian Klemm
3fe7995060 Merge pull request #1137 from mermaid-js/master
Master sync
2019-12-12 01:30:51 +01:00
Knut Sveidqvist
c441d04e8a Merge branch 'itprdev-issue-552' into develop 2019-12-11 21:31:33 +01:00
Knut Sveidqvist
52d84a99ac #552 Adding docs 2019-12-11 21:28:07 +01:00
Knut Sveidqvist
fcf20215a6 #552 Adding rendering test 2019-12-11 21:12:48 +01:00
Knut Sveidqvist
aa2f9622f8 Merge branch 'issue-552' of https://github.com/itprdev/mermaid into itprdev-issue-552 2019-12-11 21:10:11 +01:00
Knut Sveidqvist
1811318dea #1088 Adding rendering tests 2019-12-11 20:17:51 +01:00
Knut Sveidqvist
5eb50cb2b6 Merge pull request #1132 from GDFaber/develop_Bugfixes_linkStyle_910_1088
Flow: Bugfixes for link style
2019-12-11 20:04:32 +01:00
Knut Sveidqvist
f6ef6ff7db Merge pull request #1130 from GDFaber/develop
Flow: Add stadium shape for nodes
2019-12-11 19:48:47 +01:00
Knut Sveidqvist
2f33a80e1e Merge pull request #1131 from jgreywolf/1104(b)-SupportForAbstractMethodInClassDiagram
Class: Support for abstract methods
2019-12-11 19:43:32 +01:00
Justin Greywolf
363d49b655 Renumber render tests 2019-12-11 10:34:51 -08:00
Justin Greywolf
de8c6d5572 Merge branch 'develop' into 1104(b)-SupportForAbstractMethodInClassDiagram 2019-12-11 10:31:27 -08:00
Justin Greywolf
9406bda93d Merge pull request #7 from mermaid-js/develop
update fork
2019-12-11 10:24:17 -08:00
Knut Sveidqvist
d17a447a5f Merge pull request #1128 from mermaid-js/bug/1123_Upgrade_serialize-javascript
#1127 Ugrading of webpack and adding newer terser-webpack-plugin
2019-12-11 19:18:45 +01:00
Knut Sveidqvist
5b4e95484e Merge pull request #1120 from jgreywolf/1063-GenericTypeSupportInClassDiagrams
Class: Generic type support
2019-12-11 19:09:19 +01:00
Knut Sveidqvist
bebea41e19 Merge pull request #1121 from mermaid-js/pr_template
Add pull request template
2019-12-11 19:04:29 +01:00
Keenan Tullis
442474fc44 Merge branch 'develop' of https://github.com/mermaid-js/mermaid into feature/921_callback_params 2019-12-10 19:13:02 -05:00
Keenan Tullis
0d9112a4c1 Adds basic documentation for interaction with gantt 2019-12-10 19:04:42 -05:00
Keenan Tullis
d504e00e18 Adds simple tests for parsing callbacks wrt args 2019-12-10 18:27:06 -05:00
Justin Greywolf
74c8e7fad9 another style fix 2019-12-10 15:21:25 -08:00
Justin Greywolf
4b781d3827 remove extra space 2019-12-10 15:18:26 -08:00
Justin Greywolf
9fbcc5c32d Code style fix 2019-12-10 15:12:37 -08:00
Keenan Tullis
c7ec8190fb Gantt callback: default to node id as callback arg 2019-12-10 15:25:28 -05:00
Christian Klemm
b73a6d84ee Set release drafter sorting direction 2019-12-10 20:52:00 +01:00
Justin Greywolf
2eaa7f1ab6 Generic Type support for classes
Fixed typos after refactor
2019-12-10 11:39:25 -08:00
Marc Faber
608445e64f #910 set correct position and style for edge labels when using linkStyle, #1088 handle multiline texts in edge labels when using linkStyle 2019-12-10 03:51:37 +01:00
Marc Faber
1f4be77662 Revert "#910 set correct position and style for edge labels when using linkStyle, #1088 handle multiline texts in edge labels when using linkStyle" - Sorry, forgot to push to a new branch.
This reverts commit 0deae4abf9.
2019-12-10 03:48:12 +01:00
Marc Faber
0deae4abf9 #910 set correct position and style for edge labels when using linkStyle, #1088 handle multiline texts in edge labels when using linkStyle 2019-12-10 03:34:40 +01:00
Justin Greywolf
5b2f9351c7 Add support for abstract methods
Added logic to allow rendering of a method name with italics or underline based on modifier at beginning of name to set css style
2019-12-09 18:13:06 -08:00
Justin Greywolf
6fdf30357c 1104-Add support to designate a method as abstract
Added logic to allow rendering of a method name with italics or underline based on modifier at beginning of name to set css style
2019-12-09 17:41:26 -08:00
Justin Greywolf
cf5d7478fc Merge pull request #6 from mermaid-js/develop
Merge
2019-12-09 11:42:26 -08:00
Marc Faber
9a0df5afb0 #723 Add stadium shape for flowchart nodes 2019-12-08 16:51:47 +01:00
GDFaber
813b2fcb38 Merge pull request #3 from mermaid-js/develop
sync develop branch
2019-12-08 16:43:28 +01:00
Christian Klemm
08cbc0f187 Merge pull request #1129 from mermaid-js/master
Master sync
2019-12-08 13:14:32 +01:00
Knut Sveidqvist
d8251c8f79 Merge pull request #1126 from mermaid-js/bug/935_styling_of_dotted_think_links
#935 Fix for stylink of links. Default theme colors are picked up and…
2019-12-08 10:51:28 +01:00
Knut Sveidqvist
5ea70baa6f #1127 Ugrading of webpack and adding newer terser-webpack-plugin 2019-12-08 10:42:41 +01:00
Knut Sveidqvist
d23ce9fb63 #935 Fix for stylink of links. Default theme colors are picked up and styling via themeCSS works 2019-12-08 10:10:03 +01:00
Knut Sveidqvist
ddf8016a0c Merge pull request #1125 from mermaid-js/bug/903_flochart_escaping_in_non_html_mode
Bug/903 flowchart escaping in non html mode
2019-12-08 09:57:48 +01:00
Knut Sveidqvist
ab191abd5a #903 Fix for broken build 2019-12-07 15:06:44 +01:00
Knut Sveidqvist
c2e5e94b37 #903 Allowing >,< and = characters in svg. Updating xss tests to handle both htmlLabels and non htmlLabels 2019-12-07 12:19:45 +01:00
Justin Greywolf
6a9b251be1 Fix code style errors 2019-12-06 20:35:22 -08:00
Christian Klemm
6b5185abfb Create pull_request_template.md 2019-12-06 21:41:16 +01:00
Justin Greywolf
2a41280076 Add support for Generic class definitions
Added support in parser to translate characters surrounded by `~` into generic type definition ie: `Class01~T~` would turn into `Class01<T>`
2019-12-05 12:59:22 -08:00
Justin Greywolf
91d986970b Merge pull request #5 from mermaid-js/develop
Develop
2019-12-05 12:58:48 -08:00
Christian Klemm
b4192bba7a Added skip changelog label to release drafter 2019-12-04 19:35:25 +01:00
Knut Sveidqvist
9fe0aa0604 Merge pull request #1116 from mermaid-js/bug/1110_state_diagram_rendering_composit_state
Bug/1110 state diagram rendering composit state
2019-12-04 19:15:06 +01:00
Knut Sveidqvist
fc528749f8 Merge pull request #1114 from mermaid-js/feature/1112_revert_offical_dagre_d3
Feature/1112 Revert to offical dagre d3
2019-12-04 19:14:35 +01:00
Knut Sveidqvist
5c71a3c85b #1110 Fix for transparent rect under edge title, was misaligned 2019-12-04 18:20:28 +01:00
Knut Sveidqvist
94e768dd01 #1110 Cleanup and removal of loggings 2019-12-04 18:04:56 +01:00
Knut Sveidqvist
0fb91d6bcc #1110 Fixing height issue 2019-12-03 23:38:51 +01:00
Knut Sveidqvist
02854881b4 #1110 Zoom in a bit 2019-12-03 22:48:55 +01:00
Christian Klemm
4254781391 Adjusted imports 2019-12-03 22:09:43 +01:00
Christian Klemm
31f4f4096e upgraded packages 2019-12-03 22:05:39 +01:00
Christian Klemm
e95e016378 switched to official dagre d3 2019-12-03 21:59:28 +01:00
Knut Sveidqvist
c337c9128c Merge branch 'master' into bug/1110_state_diagram_rendering_composit_state 2019-12-03 21:04:18 +01:00
Knut Sveidqvist
5a38562bfc #1110 Handling case with concurrency lines 2019-12-03 20:59:17 +01:00
Justin Greywolf
a3dd0e5f7d Merge pull request #4 from mermaid-js/develop
Merge from main
2019-12-02 16:00:32 -08:00
Knut Sveidqvist
fcd1e106a5 #1110 Handling case when title is less wide then subgraph 2019-12-02 21:22:22 +01:00
Knut Sveidqvist
346328156a #1110 Adding tests for this case and some calcuations for width 2019-12-02 21:10:37 +01:00
Christian Klemm
3239f99ea8 Set develop branch for release drafter 2019-12-02 14:48:16 +01:00
Christian Klemm
93c32d3f29 Set develop branch for release drafter 2019-12-02 14:47:34 +01:00
Christian Klemm
98449dac3f Set develop branch for release drafter 2019-12-02 14:43:55 +01:00
Knut Sveidqvist
32b60edda7 Merge branch 'develop' 2019-12-01 13:36:04 +01:00
Knut Sveidqvist
823c95bd9c Updated mermaid version 2019-12-01 13:34:43 +01:00
Knut Sveidqvist
e99d872f2b Create FUNDING.yml 2019-12-01 09:15:56 +01:00
Knut Sveidqvist
de8f8b02dc Merge branch 'master' into develop 2019-12-01 07:54:02 +01:00
Knut Sveidqvist
eec45dfff9 Merge branch 'release/8.4.3' 2019-12-01 07:52:44 +01:00
Knut Sveidqvist
cce86c8e96 Merge pull request #1107 from chris579/feature/1106_release_management
Feature/1106 Release management
2019-12-01 07:34:59 +01:00
Christian Klemm
aabdc47c38 small fixes 2019-12-01 01:06:00 +01:00
Knut Sveidqvist
cb07a729e5 Merge pull request #1098 from mermaid-js/feature/1053_documentation-update
Feature/1053 documentation update
2019-12-01 00:42:41 +01:00
Knut Sveidqvist
df10f7fbe7 Merge pull request #1103 from penenkel/patch-2
Bug/1030 Adjust babel config to account for IE11
2019-12-01 00:42:02 +01:00
Knut Sveidqvist
71c531240f Merge pull request #1089 from jgreywolf/1073-CommentsInClassDiagrams
Bug/1073 Comments in class diagrams
2019-12-01 00:39:33 +01:00
Christian Klemm
1e83207dac small fixes 2019-12-01 00:39:09 +01:00
Christian Klemm
3311fcdc8e Reenable yarn install 2019-12-01 00:21:12 +01:00
Christian Klemm
f368be925f Removed release branch deletion 2019-12-01 00:18:49 +01:00
Christian Klemm
075c57ca06 Check out branches 2019-12-01 00:03:06 +01:00
Christian Klemm
49fc80d506 Prepare git for push 2019-11-30 23:54:42 +01:00
Christian Klemm
74fc2fcfa9 Release tag fixes 2019-11-30 23:49:04 +01:00
Christian Klemm
7cc427e28d Disable yarn install 2019-11-30 23:36:13 +01:00
Christian Klemm
87c571412c version fix 2019-11-30 23:35:39 +01:00
Christian Klemm
ab093b2cde Remove v from release tag 2019-11-30 23:28:48 +01:00
Christian Klemm
bbc4ede768 Added first workflows 2019-11-30 23:23:09 +01:00
penenkel
64c20dc528 Bug/1030 Adjust babel config to account for IE11
An attempt at adding IE11 compatibility (`ie >= 11`) while preserving the current requirements (`current node`) and following browserlist [best practices](https://github.com/browserslist/browserslist#best-practices) (`defaults`).
2019-11-29 23:06:49 +01:00
Knut Sveidqvist
50ea9bda89 Removed loggin 2019-11-28 11:41:54 -05:00
Nacho
2cf8c4e37a Absolute URIs in readme images 2019-11-28 11:41:54 -05:00
Knut Sveidqvist
fe4719f656 Added analytics for docs 2019-11-28 11:41:54 -05:00
James A. Bednar
1d43b7b316 Fixed typos 2019-11-28 11:41:54 -05:00
Itprdev
78e4fead49 Feature request 552. Gnatt chart task with multiple dependencies 2019-11-28 16:53:33 +02:00
Nacho
02d5143ff2 Merge pull request #1095 from mermaid-js/fixes/readme-uris
Absolute URIs in readme images
2019-11-28 08:28:12 -05:00
Erik Ellingsen
d9c92b2c6d syntax error 2019-11-28 13:22:02 +01:00
Erik Ellingsen
27ac9bbaf3 polish 2019-11-28 13:14:29 +01:00
Erik Ellingsen
11cdd393f2 Knuts comments 2019-11-28 13:13:26 +01:00
Erik Ellingsen
1ca8578035 polish 2019-11-28 13:07:14 +01:00
Erik Ellingsen
2516718882 Clarification 2019-11-28 13:06:16 +01:00
Erik Ellingsen
5283314c4f Polish 2019-11-28 13:03:58 +01:00
Erik Ellingsen
dcae8da0d1 Better header 2019-11-28 13:01:24 +01:00
Erik Ellingsen
34f2a1a02f polish 2019-11-28 13:00:12 +01:00
Erik Ellingsen
ee5a68a23c Better intro 2019-11-28 12:59:34 +01:00
Erik Ellingsen
6c706ccd9f Diagram references 2019-11-28 12:57:55 +01:00
Erik Ellingsen
94106f5825 Added syntax reference link 2019-11-28 12:53:33 +01:00
Erik Ellingsen
72ab2b8011 Added coming soon 2019-11-28 12:44:37 +01:00
Erik Ellingsen
8978ab5917 Links added 2019-11-28 12:43:55 +01:00
Erik Ellingsen
94577316f9 Drafting advanced usage 2019-11-28 12:38:42 +01:00
Erik Ellingsen
91650fb052 Script bug and clarifications 2019-11-28 12:34:26 +01:00
Knut Sveidqvist
e9aa037230 Removed loggin 2019-11-27 20:15:21 +01:00
Nacho
871e6f691c Absolute URIs in readme images 2019-11-27 14:12:34 -05:00
Knut Sveidqvist
fe60836a89 Added analytics for docs 2019-11-27 20:08:54 +01:00
Knut Sveidqvist
bea2e73b82 #1065 Updated dependency of dagre-d3 to unofficial release 2019-11-27 19:09:14 +01:00
Nacho
481e55e8da Merge pull request #1090 from jgreywolf/1074-CommentsDocumentation
Bug/1074 Comments documentation
2019-11-27 11:23:50 -05:00
Justin Greywolf
d26a67297a Updated documentation with comment syntax 2019-11-26 15:34:52 -08:00
Justin Greywolf
753bd7e1d9 Update class diagrams to handle comments
updated regex in parser to correctly handle comments in class diagrams.  Also updated flowchart parser to remove unused elements for comments, as well as modifying the regex to match
2019-11-26 11:23:07 -08:00
Justin Greywolf
b57492c1c6 Initial checkin 2019-11-26 11:22:21 -08:00
Justin Greywolf
4ff5c3b455 Merge pull request #3 from mermaid-js/develop
Develop
2019-11-26 11:20:20 -08:00
Knut Sveidqvist
f62c47a757 Updating version to 8.4.3 2019-11-23 13:10:27 +01:00
Knut Sveidqvist
a85bb0d86f Merge pull request #1086 from chris579/bug/1085_coveralls_build_fix
Bug/1085 Coveralls not working for GitHub builds
2019-11-21 20:58:49 +01:00
Knut Sveidqvist
5736d523dd Merge pull request #1081 from jgreywolf/Bug1061-CannotMarkMembersAsProtectedInClassDiagram
Bug/1061 Cannot mark members as protected in class diagram
2019-11-21 20:54:15 +01:00
Justin Greywolf
5004b5723d Added separate render test 2019-11-21 11:17:53 -08:00
Knut Sveidqvist
ad2802d8e8 Merge pull request #1084 from mermaid-js/bug/1078_handling_of_arrowMarkerAbsolute
Bug/1078 handling of arrow marker absolute
2019-11-20 21:50:50 +01:00
Christian Klemm
3fedd452a5 added parallel build support 2019-11-20 21:18:19 +01:00
Christian Klemm
292bc3c4e5 Switched to coveralls action 2019-11-20 21:11:48 +01:00
Knut Sveidqvist
512ba8e733 Merge pull request #1077 from mermaid-js/bug/1076_remove_jest_packages
Bug/1076 Remove jest packages
2019-11-20 19:42:55 +01:00
Knut Sveidqvist
9a87ff684d Removed logging 2019-11-20 19:33:42 +01:00
Knut Sveidqvist
f79fc21bfc Merge branch 'develop' into bug/1078_handling_of_arrowMarkerAbsolute 2019-11-20 19:22:10 +01:00
Knut Sveidqvist
ffddd58b6b Merge branch 'develop' of github.com:knsv/mermaid into develop 2019-11-20 19:21:34 +01:00
Knut Sveidqvist
087e5eaa32 #1055 Fix for tests 2019-11-20 19:21:19 +01:00
Knut Sveidqvist
cbd27831df #1078 Lint fixes 2019-11-20 19:14:32 +01:00
Knut Sveidqvist
f6028b63b6 #1078 Using the configuration of the arrowMarkerAbsolute 2019-11-20 19:06:46 +01:00
Justin Greywolf
a60e01db97 Corrected typo in test 2019-11-19 13:02:08 -08:00
Justin Greywolf
68c2ea38c9 Bug1061-CannotMarkMembersAsProtectedInClassDiagram
Using # to indicate protected status of a member or method causing parser error when not used inside class declaration brackets {}.  Removed '#' from `LABEL` regex
2019-11-19 12:49:59 -08:00
Justin Greywolf
3469cfca2f Merge pull request #2 from mermaid-js/develop
Develop
2019-11-19 12:49:39 -08:00
Christian Klemm
afd189d24c removed packages 2019-11-19 21:02:56 +01:00
Knut Sveidqvist
06cb09c267 Merge pull request #1049 from mermaid-js/feature/1048_build_workflows
Feature/1048 Build workflows
2019-11-19 19:45:27 +01:00
Nacho
e461b57a48 Merge pull request #1075 from jbednar/master
Fixed typos
2019-11-19 08:33:22 -05:00
James A. Bednar
eca9d49575 Fixed typos 2019-11-18 09:32:39 -06:00
Nacho
15a37a5062 Merge pull request #1070 from GDFaber/develop
Bug/1062 Parallelogram shaped nodes are not in documentation
2019-11-18 08:41:24 -05:00
Christian Klemm
3f8f9eb92c remove debugging 2019-11-17 22:20:53 +01:00
Christian Klemm
33de2bda9e cypress cache folder fix 2019-11-17 22:13:02 +01:00
Christian Klemm
94d913fbab debug 2019-11-17 22:04:50 +01:00
Christian Klemm
beb1fcc176 debug 2019-11-17 21:58:53 +01:00
Christian Klemm
1e1a6e3a2d debug 2019-11-17 21:54:15 +01:00
Christian Klemm
6e7c21e439 debug 2019-11-17 21:47:05 +01:00
Christian Klemm
cfe9aaf639 adjusts 2019-11-17 21:41:55 +01:00
Christian Klemm
69e701befb adjusts 2019-11-17 21:27:30 +01:00
Christian Klemm
5174a085b7 test path pattern adjust 2019-11-17 21:21:25 +01:00
Christian Klemm
15fab69eca cache adjusts 2019-11-17 21:03:08 +01:00
Christian Klemm
20b103a0fb cache adjusts 2019-11-17 21:00:55 +01:00
Christian Klemm
8ebe7ee81a cache adjusts 2019-11-17 20:57:55 +01:00
Marc Faber
1d747f664b #1062 added parallelogram nodes to documentation 2019-11-17 17:37:30 +01:00
GDFaber
dbf5988c28 Merge pull request #2 from mermaid-js/develop
sync fork
2019-11-17 17:14:49 +01:00
Christian Klemm
31ab0e4b7d Clear cache 2019-11-12 22:15:49 +01:00
Christian Klemm
35ea7083bb fix cypress cache 2019-11-12 22:12:53 +01:00
Christian Klemm
bf90e8bf44 switched caching method 2019-11-12 22:10:16 +01:00
Christian Klemm
b1305644f4 fixed cypress cache folder 2019-11-12 22:04:47 +01:00
Christian Klemm
34707a057b temp delete cache 2019-11-12 21:58:05 +01:00
Christian Klemm
f5e90252f1 force reinstalling packages 2019-11-12 21:52:50 +01:00
Christian Klemm
e75acf69aa Adjusted cache location 2019-11-12 21:43:11 +01:00
Christian Klemm
3ad3fc2622 Cache adjusts 2019-11-12 21:24:35 +01:00
Christian Klemm
a59468d6c1 Caching adjusts 2019-11-12 21:20:05 +01:00
Christian Klemm
86e63b1614 Add caching 2019-11-12 21:14:42 +01:00
Knut Sveidqvist
3f8f9f6711 #1055 Better selectors 2019-11-08 20:15:48 +01:00
Knut Sveidqvist
d01f494277 Merge branch 'master' into develop 2019-11-08 19:32:54 +01:00
Knut Sveidqvist
4db525c6a9 #1050 Merge of PR 2019-11-08 11:42:26 +01:00
Erik Ellingsen
8b5f8b0cb4 grammar 2019-11-08 10:36:41 +01:00
Erik Ellingsen
d0c9b5e98f grammar 2019-11-08 10:35:38 +01:00
Knut Sveidqvist
e313625ccb Fixing the conflict 2019-11-08 08:54:48 +01:00
erelling
7dead548f3 Update n00b-gettingStarted.md 2019-11-08 01:59:44 +01:00
erelling
8db46ff762 Update n00b-overview.md 2019-11-08 01:57:18 +01:00
erelling
93f54a997a Update n00b-gettingStarted.md 2019-11-08 01:53:58 +01:00
erelling
1353491952 Update n00b-gettingStarted.md 2019-11-08 01:47:34 +01:00
erelling
00802ffe7a Update n00b-gettingStarted.md 2019-11-08 01:45:29 +01:00
erelling
78e556aaf7 Update n00b-gettingStarted.md 2019-11-08 01:44:12 +01:00
erelling
e34988d65a Update n00b-gettingStarted.md 2019-11-08 01:32:09 +01:00
erelling
07f5c7c89c Update n00b-gettingStarted.md 2019-11-08 01:31:21 +01:00
erelling
7319d8941a Update n00b-gettingStarted.md 2019-11-08 01:25:41 +01:00
erelling
3d7933135b Update n00b-gettingStarted.md 2019-11-08 01:23:33 +01:00
erelling
a778472461 Update n00b-gettingStarted.md 2019-11-08 01:21:50 +01:00
erelling
cbe2a7446d Update n00b-gettingStarted.md 2019-11-08 01:17:21 +01:00
erelling
8251dc5cd1 Update n00b-gettingStarted.md 2019-11-08 01:16:16 +01:00
erelling
5a4103a248 Update n00b-gettingStarted.md 2019-11-08 01:15:41 +01:00
erelling
d7996f5c1a Update n00b-gettingStarted.md 2019-11-08 01:14:38 +01:00
erelling
db4229f033 Update n00b-gettingStarted.md 2019-11-08 01:13:14 +01:00
erelling
e103664963 Update n00b-gettingStarted.md 2019-11-08 01:12:14 +01:00
erelling
fbf3936ddc Update n00b-overview.md 2019-11-08 01:11:07 +01:00
erelling
62d03f1976 Update n00b-overview.md 2019-11-08 01:10:24 +01:00
erelling
f3ea159c6b Update n00b-overview.md 2019-11-08 01:08:14 +01:00
erelling
3c99294a3a Update n00b-overview.md 2019-11-08 01:06:57 +01:00
erelling
7a2a8cffbb Update n00b-overview.md 2019-11-08 01:06:20 +01:00
erelling
6d90f87b2f Update n00b-overview.md 2019-11-08 01:04:21 +01:00
erelling
f506d24a82 Update n00b-overview.md 2019-11-08 01:01:37 +01:00
Erik Ellingsen
ddb0d23ca7 grammar 2019-11-08 00:04:53 +01:00
Erik Ellingsen
763be9bb95 better instruction 2019-11-07 23:52:47 +01:00
Erik Ellingsen
77109144e7 grammar 2019-11-07 23:47:34 +01:00
Erik Ellingsen
840e7bd985 clarification 2019-11-07 23:47:08 +01:00
Erik Ellingsen
a6c12f4b25 clarification 2019-11-07 23:46:30 +01:00
Erik Ellingsen
e8e9a4d07b simplification 2019-11-07 23:45:23 +01:00
Erik Ellingsen
ba00182ce4 Clarification 2019-11-07 23:44:47 +01:00
Erik Ellingsen
2ad78ee3b8 grammar 2019-11-07 23:42:56 +01:00
Erik Ellingsen
4995d59499 Knuts comments 2019-11-07 23:42:07 +01:00
Erik Ellingsen
d58ef7aa36 Removed redundant heading 2019-11-07 23:40:13 +01:00
Erik Ellingsen
dc59632fb3 Polishing 2019-11-07 23:37:46 +01:00
Erik Ellingsen
1542e15a1b Introduction and getting started howtos 2019-11-07 23:15:53 +01:00
Ashish Jain
5b5be40dd5 Fixing the binding function error 2019-11-07 22:09:34 +01:00
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
MATSUDA Takashi
aac915b285 #1044 fix: Multiple class diagrams are not rendered correctly 2019-11-05 18:00:52 +09:00
MATSUDA Takashi
7208f045c1 add test for multiple class diagram 2019-11-05 17:54:52 +09:00
MATSUDA Takashi
f7a3c42da1 e2e support multiple diagram 2019-11-05 17:54:52 +09:00
Christian Klemm
4d1c53eb1e added percy token 2019-11-03 19:40:15 +01:00
Christian Klemm
7bcc9b19ac fixed vars 2019-11-03 18:30:01 +01:00
Christian Klemm
7cfc729679 added coveralls vars 2019-11-03 18:28:27 +01:00
Christian Klemm
1f8480f0af Added npm badge (#1047) 2019-11-03 16:18:43 +01:00
Christian Klemm
ec3b68ad28 Added build workflow 2019-11-03 15:20:10 +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
knsv
0157f665a3 Merge branch 'release/8.4.0' 2019-10-19 07:59:04 -07:00
Knut Sveidqvist
d366605d91 Merge branch 'release/8.4.0' of github.com:knsv/mermaid into release/8.4.0 2019-10-19 16:19:56 +02:00
Knut Sveidqvist
fd5bcad5d6 Fixes after verification, version upgrade 2019-10-19 14:44:54 +02:00
Knut Sveidqvist
7adb80b35b Fixes after verification, font-family set to label of transitions in statediagram 2019-10-19 14:43:26 +02:00
Knut Sveidqvist
dc88e7a2c2 Fixes after verification, documentation of stateDiagram 2019-10-19 14:42:34 +02:00
Nacho
dd68a7151f Removed gitter and added slack badge 2019-10-18 09:57:51 -04:00
Nacho
bf2497ea3e Merge pull request #1014
Fix typos in CONTRIBUTING.md
2019-10-18 09:46:36 -04:00
abeaton
202c889246 Fix typos in CONTRIBUTING.md 2019-10-18 09:41:51 -04:00
Knut Sveidqvist
ec0e93bd6f Merge pull request #1012 from knsv/develop
Moving resolution for #1001 to the release branch for proper prerelease publish
2019-10-17 19:43:31 +02:00
Knut Sveidqvist
def9bef988 Merge pull request #1002 from knsv/feature/1001_alpha_releases_for_release_branches
Feature/1001 preview releases for release branches
2019-10-17 19:31:56 +02:00
Christian Klemm
c3db9032f3 Delete package-lock.json 2019-10-16 23:53:19 +02:00
Christian Klemm
016dc17d94 clean up branch 2019-10-16 22:16:25 +02:00
Christian Klemm
8e1672568a added preview builds to readme 2019-10-16 22:09:33 +02:00
Christian Klemm
42b8ac1235 Added e2e tests to prepublish task 2019-10-16 22:00:57 +02:00
Christian Klemm
2348f9d785 finished ci 2019-10-16 21:57:35 +02:00
Christian Klemm
04f86ef130 testing 2019-10-16 21:50:06 +02:00
Nacho
f436086aae Merge pull request #1004
Small gramatical mistake
2019-10-16 08:32:08 -04:00
Sakis bal
1b813d371d Small gramatical mistake 2019-10-16 10:08:24 +03:00
Knut Sveidqvist
8f49d96c3a Merge pull request #1000 from edekadigital/doc-contributing
reference the CONTRIBUTING.md in README
2019-10-16 08:48:02 +02:00
Christian Klemm
49f5b8d150 testing 2019-10-16 03:42:37 +02:00
Christian Klemm
f0bbb063dd testing 2019-10-16 03:34:22 +02:00
Christian Klemm
d95a9469ac testing 2019-10-16 03:23:22 +02:00
Christian Klemm
6e088d17fd testing 2019-10-16 03:15:33 +02:00
Christian Klemm
42aeafc907 testing 2019-10-16 02:54:11 +02:00
Christian Klemm
3073b6559c testing 2019-10-16 02:44:22 +02:00
Christian Klemm
af57da8e6b testing 2019-10-16 02:40:09 +02:00
Christian Klemm
56e9abfc92 testing 2019-10-15 23:28:16 +02:00
Christian Klemm
61b4c6d3ac testing 2019-10-15 23:24:13 +02:00
Christian Klemm
7e6b43236a testing 2019-10-15 23:19:05 +02:00
Christian Klemm
6a33ac05a3 workflow adjusts 2019-10-15 23:18:26 +02:00
Christian Klemm
5f1246280c Added alpha release build ci 2019-10-15 22:43:36 +02:00
Kolja Markwardt
ecef0c78d2 reference the CONTRIBUTING.md in README 2019-10-15 22:22:01 +02:00
Knut Sveidqvist
0ce42e6185 Merge pull request #994 from edekadigital/bug-478
#478 API crashes on 2nd render() call
2019-10-15 19:40:29 +02:00
Knut Sveidqvist
3709d9d5c8 Merge pull request #996 from edekadigital/bug-783
#783 Hard to customize font-size for gantt charts
2019-10-15 19:38:20 +02:00
Knut Sveidqvist
e65f916ba5 Merge pull request #992 from edekadigital/enhancement-958
#958 Cannot center-justify text in nodes
2019-10-15 18:54:28 +02:00
Knut Sveidqvist
f9c8ce1ac7 Merge branch 'master' into develop 2019-10-15 18:50:11 +02:00
Knut Sveidqvist
b881e5c69c Merge pull request #991 from christopherkade/feature/divided-flow-tests
#906 Divided flow unit tests
2019-10-15 18:43:39 +02:00
Knut Sveidqvist
51a89c80aa Merge pull request #985 from knsv/bug/984_bracket_syntax_properties_reversed_order
bug/984 Class diagram: properties with bracket syntax are reversed in order
2019-10-15 18:39:20 +02:00
Knut Sveidqvist
97a5f408d2 Merge pull request #978 from aledileo/bugfix/node12
Updates node-sass to 4.12 and regenerates lockfiles
2019-10-15 18:38:47 +02:00
Knut Sveidqvist
2f00d7d145 Merge branch 'master' of github.com:knsv/mermaid 2019-10-15 18:36:55 +02:00
Kolja Markwardt
d743838716 #478 API crashes on 2nd render() call
- add e2e test for (re)rendering by api
2019-10-15 17:36:02 +02:00
Kolja Markwardt
069b4854f8 #478 API crashes on 2nd render() call
- remove element from DOM before rendering to avoid conflicts in case of rerendering
2019-10-15 17:36:02 +02:00
Kolja Markwardt
f089c45115 #958 Cannot center-justify text in nodes
- changed fit() to it() to reactivate test
2019-10-15 16:02:11 +02:00
Kolja Markwardt
90fe015d68 #958 Cannot center-justify text in nodes
- assign text-align style to text node to allow aligning of node text
2019-10-15 16:02:11 +02:00
Kolja Markwardt
96c86fd4b2 #783 Hard to customize font-size for gantt charts
- deselect theme style if font-size is set on the taskText element (e.g. via gantt-config)
2019-10-15 15:59:36 +02:00
Nacho
d921c36cd4 Merge pull request #998
Added missing code snippets for trapezoid nodes in flow chart documentation
2019-10-15 09:59:24 -04:00
Paweł Gajda
4a552069cf Added missing code snippets for trapezoid nodes in flow chart 2019-10-15 15:45:04 +02:00
Nacho
74c171b6d1 Merge pull request #997 from knsv/master 2019-10-15 09:17:46 -04:00
Ashish Jain
1ae1313edd #993 Added mermaid documentation for class diagram-minor fixes 2019-10-15 00:32:21 +02:00
Ashish Jain
5949d01821 #993 Added mermaid documentation for class diagram-minor fixes 2019-10-15 00:05:49 +02:00
Ashish Jain
3cdb0ae4c8 #993 Added mermaid documentation for class diagram 2019-10-14 22:59:26 +02:00
christopherkade
89b6ccf47d #906 Divided flow unit tests 2019-10-14 16:17:43 +02:00
Knut Sveidqvist
047ce2949a #989 Added font styling classes to diagrams lacking then 2019-10-13 19:16:35 +02:00
Knut Sveidqvist
53bdfee057 #989 Font configuration 2019-10-12 16:53:21 +02:00
Knut Sveidqvist
2da55993e0 Test of font-settings for correct image snapshots 2019-10-12 09:16:33 +02:00
Knut Sveidqvist
a258eda035 #945 Setting up stylesheet, classes and colors 2019-10-11 18:12:24 +02:00
Knut Sveidqvist
7c125cf9d6 #945 Moving hardcoded sizes etc to config 2019-10-11 15:39:50 +02:00
Nacho
2af76230f7 Merge pull request #987
Grammar/spelling changes to the "Usage" docs
2019-10-11 09:21:39 -04:00
Knut Sveidqvist
bdb530f831 Adding more info about documentation and moving the contributing file to its proper place 2019-10-11 08:17:47 +02:00
Knut Sveidqvist
7a7c09493c Adding more info about documentation and moving the contributing file to its proper place 2019-10-11 08:17:39 +02:00
Knut Sveidqvist
f3d588eca5 Adding contributing information 2019-10-11 08:10:54 +02:00
Knut Sveidqvist
031c0b7b21 #945 Increasing size, handling forks and joins in multiple directions 2019-10-10 20:55:27 +02:00
Knut Sveidqvist
ce017ecd40 Merge branch 'master' of github.com:knsv/mermaid 2019-10-10 17:57:39 +02:00
Knut Sveidqvist
85e58faa78 #945 White background and forks in composite mode 2019-10-10 17:57:29 +02:00
Steven Engler
808ed11e91 Grammar/spelling changes to the "Usage" docs 2019-10-09 15:43:54 -04:00
Ashish Jain
f8f52c4587 Fix for viewport in classDiagram and stateDiagram renndering 2019-10-09 21:15:17 +02:00
Knut Sveidqvist
54e6e2f66e #945 Some bug fixes and draft docs 2019-10-09 20:05:24 +02:00
Knut Sveidqvist
fe1e09f06b Merge branch 'feature/945_state_diagrams' 2019-10-09 18:16:32 +02:00
Knut Sveidqvist
cd646c0e42 Updated yarn.lockl 2019-10-09 18:16:23 +02:00
Knut Sveidqvist
f180510fbb Merge pull request #983 from knsv/feature/Issue-949_Add_cardinality_support
Feature/issue 949 add cardinality support
2019-10-08 23:06:17 +02:00
Christian Klemm
687e74de9b fixed members order 2019-10-08 22:59:59 +02:00
Knut Sveidqvist
65f91dd051 Merge branch 'master' of github.com:knsv/mermaid 2019-10-08 22:56:56 +02:00
Knut Sveidqvist
a8a4616cab #916 Docs for chaining of links 2019-10-08 22:56:50 +02:00
Ashish Jain
aaac86fd9d #949 Added cypress test case for class diagram cardinality support 2019-10-08 21:46:03 +02:00
Ashish Jain
35ddf9235f #949 Added rendering of cardinality for class diagrams 2019-10-08 21:43:58 +02:00
Knut Sveidqvist
554189908d Merge pull request #970 from mearns/issue-530-hexagon
Add hex shape for flow charts
2019-10-08 21:43:10 +02:00
Ashish Jain
54dbbd154c #949 Added utility function for calculating cardinality position 2019-10-08 21:42:49 +02:00
Knut Sveidqvist
a9224015e0 Merge pull request #964 from volkanunsal/master
Add useMaxWidth to flowRenderer
2019-10-08 21:33:50 +02:00
Eduardas Michelsonas
1cba50266e #755 Linting fixes + merge 2019-10-08 14:25:29 +02:00
edumicse
341456cc25 Merge pull request #981 from knsv/feature/755_handling_br_in_sequence_diagram
Feature/755 handling br in sequence diagram
2019-10-08 14:19:36 +02:00
edumicse
ae7852d9b9 Merge branch 'master' into feature/755_handling_br_in_sequence_diagram 2019-10-08 14:18:55 +02:00
ashishjain0512
4ce523f33b Merge pull request #973 from chris579/feature/963_class_annotations
Class diagram: annotations support
2019-10-08 12:56:49 +02:00
Ashish Jain
6b4a8325ae Merge branch 'feature/963_class_annotations' of https://github.com/chris579/mermaid into develop 2019-10-08 12:49:52 +02:00
Knut Sveidqvist
6d3044bddd Merge pull request #974 from vikyaiyer/Issue-893
added css path to styling in documentation
2019-10-07 10:13:15 +02:00
Alejandro Di Leo
0678f61ce9 Updates node-sass to 4.12 and regenerates lockfiles 2019-10-06 13:15:36 -03:00
Knut Sveidqvist
ebede9b910 #945 Log removal 2019-10-06 16:06:15 +02:00
Knut Sveidqvist
b12791d3e0 #945 Divider lines for concurrency, full width when in a composit state 2019-10-06 15:53:34 +02:00
Knut Sveidqvist
ce0b0fa0c8 #945 Divider lines for concurrency 2019-10-06 15:44:31 +02:00
Knut Sveidqvist
dce09586cd #945 Support for forks and joins 2019-10-06 14:11:17 +02:00
Knut Sveidqvist
4f1186a610 #945 Support for notes, better width and handling of +/- 2019-10-06 11:35:46 +02:00
Knut Sveidqvist
1cb52a602a #945 Support for notes 2019-10-06 10:52:37 +02:00
Knut Sveidqvist
c482083d82 Update README.md 2019-10-06 09:03:56 +02:00
Knut Sveidqvist
d9dda88164 Replaced info about linting 2019-10-06 09:02:07 +02:00
Brian Mearns
c9fe948b90 #530 Finished basic unit tests for flow shapes 2019-10-05 13:48:20 -04:00
Brian Mearns
cc731fe3c4 #530 Pull shape functions out to shorten functions 2019-10-05 09:38:03 -04:00
Christian Klemm
40b7262c19 exchanged class readme image 2019-10-05 12:46:28 +02:00
Christian Klemm
9da61ad562 added some documentation 2019-10-05 12:38:29 +02:00
Knut Sveidqvist
3b731282e3 #945Renabling support for descriptions 2019-10-05 12:15:14 +02:00
Knut Sveidqvist
cfc14ade2a #945 Some more cleanup focusing on stateDb 2019-10-05 10:02:58 +02:00
Knut Sveidqvist
d4306e61c2 #945 Some cleanup 2019-10-05 09:02:20 +02:00
Vignesh Aiyer
3afa6e2350 Update sequenceDiagram.md 2019-10-05 11:15:12 +05:30
Vignesh
8bbb0448dc added css path to styling in documentation 2019-10-05 10:52:23 +05:30
Brian Mearns
dcbcbf40a0 #530 Started adding some tests around how flowchart shapes are rendered in SVG 2019-10-04 22:38:27 -04:00
Brian Mearns
9a0a5ca804 #530 Add some unit tests for flowRenderer.addVertices 2019-10-04 22:03:20 -04:00
Brian Mearns
20b2866631 #530 Further encapsulation of common code 2019-10-04 21:21:00 -04:00
Christian Klemm
92eec664b1 test fix 2019-10-05 00:57:58 +02:00
Christian Klemm
723fe84383 added diagram escaping for e2e tests 2019-10-05 00:39:07 +02:00
Christian Klemm
3ca9347361 test fix 2019-10-05 00:05:47 +02:00
Christian Klemm
704d36a7eb adjusted integration test 2019-10-04 23:58:06 +02:00
Christian Klemm
612df99c34 added tests + alt syntax 2019-10-04 23:49:58 +02:00
Christian Klemm
912e850db4 added grammar 2019-10-04 21:49:02 +02:00
Christian Klemm
96735dd543 Added rendering for annotations 2019-10-04 21:09:49 +02:00
Knut Sveidqvist
65cbfbdb40 #945 Tweaking 2019-10-03 19:54:07 +02:00
Knut Sveidqvist
7865fd4f02 #945 Rendering of composite state in a box 2019-10-03 19:08:15 +02:00
Nacho
801f001098 Merge pull request #972
Removed reference to mermaid.min.css in usage docs #797
2019-10-03 10:18:25 -04:00
Rick Ulrich
7e92257c3c Removed reference to mermaid.min.css in usage docs #797 2019-10-03 09:13:12 -05:00
Nacho
7d4777a8bf Merge pull request #971
Revert "Removed reference to mermaid.min.css in usage docs #797"
2019-10-03 09:35:44 -04:00
Nacho
e7428afb3e Revert "Removed reference to mermaid.min.css in usage docs #797" 2019-10-03 09:35:22 -04:00
Nacho
51b7c90dae Merge pull request #969
Removed reference to mermaid.min.css in usage docs #797
2019-10-03 09:31:59 -04:00
Brian Mearns
c9f84ccae5 #530 Testing Coverage 2019-10-03 06:41:36 -04:00
Brian Mearns
01fd54dd6f #530 Encapsulate some redudant flow shape code 2019-10-02 22:51:12 -04:00
Brian Mearns
e1446ce38a #530 Add unit test for hex nodes 2019-10-02 22:44:56 -04:00
Brian Mearns
1920e9f758 #530 Add hexagon to flow docs 2019-10-02 22:38:41 -04:00
Brian Mearns
550f91aa68 #530 Better shaping of hexagon
The "corner" triangles are a fixed ratio to the height,
so the triangles will always be mathemtically similar.
2019-10-02 22:36:02 -04:00
Brian Mearns
57921e3f52 #530 Add Hex example to index.html 2019-10-02 22:31:41 -04:00
Brian Mearns
b300a4decb #530 Fit hexagon to width and height
The hexagon shape in flow chart now fits
the width and height independently, so it can better fit
large content without taking up too much space.
2019-10-02 22:23:30 -04:00
Brian Mearns
51e902cd36 Added the hex shape to the renderer, and support for it in the flow parser.
Need to work on properly sizing it.
2019-10-02 22:11:02 -04:00
Harrison Ulrich
ea359c0037 Removed reference to mermaid.min.css in usage docs #797 2019-10-02 15:04:58 -05:00
Knut Sveidqvist
f9f8785aef #945 Recursive object from parsing and stateDb 2019-10-02 19:32:13 +02:00
Knut Sveidqvist
0abeaa4dc2 Merge branch 'feature/945_state_diagrams' into develop 2019-10-02 19:17:38 +02:00
Nacho
18f35ac213 Merge pull request #968
Fixes #848
2019-10-02 09:54:34 -04:00
Brian Mearns
9ca077b3dc Add some test coverage for getBranchesAsObjArray 2019-10-01 22:29:07 -04:00
Brian Mearns
351dd3728e #848 - Add Unit Test 2019-10-01 22:03:43 -04:00
Brian Mearns
054901cb79 Fixes #848 - Use more secure PRNG
Math.random() is not cryptogaphically secure, but the crypto-random-string
package provides what is needed with a cryptographically secure pseudo-random
number generator.
2019-10-01 21:29:42 -04:00
Nacho
4f29f7c3a7 Automatically lock/unlock issues on close/reopen 2019-10-01 11:02:26 -04:00
Nacho
f149f090a6 Merge pull request #965
Corrected docs
2019-10-01 08:51:24 -04:00
Nacho
d113364f82 Merge pull request #966
Optimize images
2019-10-01 08:38:02 -04:00
Arnaud ZHENG
d499cce371 remove old files 2019-10-01 10:49:55 +02:00
Arnaud ZHENG
5d7dbd701f remove old files 2019-10-01 10:48:37 +02:00
Arnaud ZHENG
8345134d2a Merge branch 'master' of github.com:knsv/mermaid 2019-10-01 10:47:03 +02:00
Gianfrancø Palumbo
55f9cba0f9 docs: small improvement to flowchart.md 2019-09-30 21:59:10 +03:00
Knut Sveidqvist
94afcfb6f9 #945 Rendering of state descriptions 2019-09-29 15:50:43 +02:00
Volkan Unsal
682faa4f9d Add useMaxWidth to flowRenderer 2019-09-29 09:31:41 -04:00
Knut Sveidqvist
3cffd1e3ed #945 Rendering of labels and new label positioning algorithm 2019-09-28 13:31:10 +02:00
Nacho
0730f73f73 Merge pull request #960
Update gantt.md
2019-09-27 13:21:28 -04:00
lilisha100
dffe20b76c Update gantt.md 2019-09-27 10:15:03 -07:00
lilisha100
e7161fcca6 Update gantt.md 2019-09-27 09:52:22 -07:00
lilisha100
3bf873b99f Update gantt.md 2019-09-27 09:27:53 -07:00
Nacho
f49bae6622 Merge pull request #957 from GDFaber/master
Flowchart parsing issue with CRLF #894
2019-09-27 09:12:19 -04:00
Marc Faber
095233e6cf Flowchart parsing issue with CRLF #894 2019-09-27 01:05:25 +02:00
Nacho
490d42fce1 Merge pull request #956
Created issue template for questions
2019-09-26 11:44:50 -04:00
Nacho
11d2db08fa Created issue template for questions 2019-09-26 11:42:33 -04:00
Knut Sveidqvist
13baa43081 #945 Rendering from diagram data 2019-09-25 21:29:32 +02:00
Knut Sveidqvist
fad76ad534 #945 Rendering of start & end node 2019-09-25 21:01:21 +02:00
Nacho
1c3ddcd120 Merge pull request #954
Create github/action for triage labelling
2019-09-25 11:18:09 -04:00
Nacho
2ccdeec550 Create github/action for triage labelling 2019-09-25 11:14:52 -04:00
Nacho
3164f99b3b Merge pull request #953
Reverted to stalebot instead of github actions/stale
2019-09-25 11:01:23 -04:00
Nacho
1bceae12dd Added config for stalebot 2019-09-25 10:53:08 -04:00
Nacho
b2c60135f5 Deleted github action for stale 2019-09-25 10:52:30 -04:00
Nacho
0dddf3c50c Merge pull request #952
Updated issue templates
2019-09-25 10:06:46 -04:00
Nacho
b4badf6e7f Update issue templates 2019-09-25 09:55:18 -04:00
Nacho
9c69afeddd Merge pull request #951
Corrected typo in mermaidAPI.md
2019-09-24 12:53:16 -04:00
Nacho
e8835429fd Merge branch 'master' into master 2019-09-24 12:47:46 -04:00
0xflotus
029a84159e Update mermaidAPI.md 2019-09-24 18:47:38 +02:00
Knut Sveidqvist
ba01e3778a Tets change to see if it triggers 2019-09-24 09:38:16 +02:00
Nacho
6cfd4e6422 Switching stalebot to github/action (#950)
* Added configuration for github action stale
* Deleted stalebot configuration
2019-09-23 11:29:02 -04:00
Nacho
bb372751f7 Reverted test settings 2019-09-23 10:30:23 -04:00
Nacho
3fdf2c7e32 Updated cron expresion for test 2019-09-23 10:22:19 -04:00
Nacho
9f4ca63603 Deleted stalebot configuration 2019-09-23 10:21:04 -04:00
Nacho
4bdf772130 Added stale pr/issue workflow for test 2019-09-23 10:20:02 -04:00
Nacho
6110640fc2 Merge pull request #940
Use https in githu urls
2019-09-23 09:44:20 -04:00
nothingismagick
6c243488fa revert to http 2019-09-23 12:06:22 +02:00
nothingismagick
4f218435e3 revert to http 2019-09-23 12:05:13 +02:00
nothingismagick
7ca13fd163 revert to http 2019-09-23 12:04:39 +02:00
knsv
2306534248 #945 Handling of dimples state definitions 2019-09-22 03:30:36 -07:00
knsv
2f0248e6d5 #945 Handling of note statements 2019-09-22 02:38:04 -07:00
knsv
3a8564de92 #945 Handling of fork statements 2019-09-21 23:19:03 -07:00
knsv
1aa8b9b804 #945 Handling recursive logn descriptions for states with quotes 2019-09-21 11:31:09 -07:00
knsv
921d5464a1 #945 Handling recursive logn descriptions for states with quotes 2019-09-21 09:12:02 -07:00
knsv
9993b90a20 #945 Handling recursive state statements 2019-09-21 08:54:18 -07:00
knsv
6f054519e7 #945 Handling simple state statements 2019-09-21 08:50:32 -07:00
knsv
51bf4a4c5c #945 Parsing happy case and scale/hide statements 2019-09-21 08:19:55 -07:00
knsv
046b83582d Local docs to use 8.3.1 2019-09-19 15:10:49 -07:00
knsv
be2e467583 Release 8.3.1. Reseting the flow parser between parsings 2019-09-19 15:00:21 -07:00
Knut Sveidqvist
b1d137770c Merge pull request #942 from knsv/bugfix_941
Bugfix 941
2019-09-19 23:19:32 +02:00
knsv
40c7cab1da Merge branch 'master' into HEAD 2019-09-19 13:59:03 -07:00
knsv
f39e120952 #941 Fix for issue with directions iin flowchart 2019-09-19 13:56:41 -07:00
Daniel Thompson-Yvetot
f30f607b0c feat(https): use https in SVGs 2019-09-19 20:53:42 +02:00
Nacho
e40e1da292 Merge pull request #939
Fix accidental paste and code style in readme
2019-09-19 09:00:58 -04:00
Philipp A
1783ef501d Fix accidental paste and code style in readme 2019-09-19 09:45:13 +02:00
knsv
b4ec22ecea Local docs to use 8.3.0 2019-09-18 22:49:33 -07:00
Eduardas Michelsonas
c6efddee87 #755 lint fixes 2019-08-28 20:13:37 +02:00
Eduardas Michelsonas
f6377e6125 #755 2019-08-28 20:09:45 +02:00
Arnaud Zheng
ec5627a44c Merge pull request #1 from arnaud-zg/imgbot
[ImgBot] Optimize images
2019-06-10 13:33:40 +02:00
ImgBotApp
5e52138861 [ImgBot] Optimize images
*Total -- 213.50kb -> 206.22kb (3.41%)

/dist/www/images/logo.png -- 3.29kb -> 1.21kb (63.29%)
/docs/site/images/logo.png -- 3.29kb -> 1.21kb (63.29%)
/docs/img/header.png -- 68.97kb -> 67.93kb (1.5%)
/docs/site/images/header.png -- 68.97kb -> 67.93kb (1.5%)
/dist/www/images/header.png -- 68.97kb -> 67.93kb (1.5%)
2019-06-08 15:55:06 +00:00
151 changed files with 15624 additions and 7107 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"]

12
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: [knsv]
#patreon: # Replace with a single Patreon username
#open_collective: # Replace with a single Open Collective username
#ko_fi: # Replace with a single Ko-fi username
#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
#liberapay: # Replace with a single Liberapay username
#issuehunt: # Replace with a single IssueHunt username
#otechie: # Replace with a single Otechie username
#custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -2,7 +2,7 @@
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
labels: 'Status: Triage, Type: Bug / Error'
assignees: ''
---

View File

@@ -1,10 +0,0 @@
---
name: Custom issue template
about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''
---

View File

@@ -2,7 +2,7 @@
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
labels: 'Status: Triage, Type: Enhancement'
assignees: ''
---

15
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@@ -0,0 +1,15 @@
---
name: Question
about: Get some help from the community.
title: ''
labels: 'Help wanted!, Type: Other'
assignees: ''
---
## Help us help you!
You want an answer. Here are some ways to get it quicker:
* Use a clear and concise title.
* Try to pose a clear and concise question.
* Include as much, or as little, code as necessary.
* Don't be shy to give us some screenshots, if it helps!

3
.github/pr-labeler.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
'Type: Bug / Error': 'bug/*'
'Type: Enhancement': 'feature/*'
'Type: Other': 'other/*'

13
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,13 @@
## :bookmark_tabs: Summary
Brief description about the content of your PR.
Resolves #<your issue id here>
## :straight_ruler: Design Decisions
Describe the way your implementation works or what design decisions you made if applicable.
### :clipboard: Tasks
Make sure you
- [ ] :book: have read the [contribution guidelines](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md)
- [ ] :computer: have added unit/e2e tests (if appropriate)
- [ ] :bookmark: targeted `develop` branch

25
.github/release-drafter.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
name-template: '$NEXT_PATCH_VERSION'
tag-template: '$NEXT_PATCH_VERSION'
categories:
- title: '🚀 Features'
labels:
- 'Type: Enhancement'
- title: '🐛 Bug Fixes'
labels:
- 'Type: Bug / Error'
- title: '🧰 Maintenance'
label: 'Type: Other'
change-template: '- $TITLE (#$NUMBER) @$AUTHOR'
sort-by: title
sort-direction: ascending
branches:
- develop
exclude-labels:
- 'Skip changelog'
no-changes-template: 'This release contains minor changes and bugfixes.'
template: |
# Release Notes
$CHANGES
🎉 **Thanks to all contributors helping with this release!** 🎉

8
.github/stale.yml vendored
View File

@@ -4,11 +4,9 @@ daysUntilStale: 60
daysUntilClose: 14
# Issues with these labels will never be considered stale
exemptLabels:
- Status: Pinned
- Area: Security
- pinned
- Retained
# Label to use when marking an issue as stale
staleLabel: Status: Wontfix
staleLabel: Inactive
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
@@ -18,4 +16,4 @@ markComment: >
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: >
This issue has been been automatically closed due to a lack of activity.
This is done to maintain a clean list of issues that the community is interested in developing.
This is done to maintain a clean list of issues that the community is interested in developing.

64
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,64 @@
name: Build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.x]
steps:
- uses: actions/checkout@v1
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install Yarn
run: npm i yarn --global
- name: Cache Node Modules
uses: actions/cache@v1
with:
path: .cache
key: ${{ runner.OS }}-build-${{ hashFiles('**/yarn.lock') }}
- name: Install Packages
run: |
yarn config set cache-folder $GITHUB_WORKSPACE/.cache/yarn
yarn install --frozen-lockfile
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Run Build
run: yarn build
- name: Upload Build as Artifact
uses: actions/upload-artifact@v1
with:
name: dist
path: dist
- name: Run Unit Tests
run: |
yarn test --coverage
- name: Upload Test Results
uses: coverallsapp/github-action@v1.0.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel: true
# - name: Run E2E Tests
# run: yarn e2e
# env:
# PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
# CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Post Upload Test Results
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true

19
.github/workflows/checks vendored Normal file
View File

@@ -0,0 +1,19 @@
on: [push]
name: Static analysis
jobs:
test:
runs-on: ubuntu-latest
name: check tests
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: testomatio/check-tests@stable
with:
framework: cypress
tests: "./cypress/integration/**/**.spec.js"
token: ${{ secrets.GITHUB_TOKEN }}
has-tests-label: true

14
.github/workflows/issue-triage.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
name: Apply triage label to new issue
on:
issues:
types: [opened]
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: andymckay/labeler@1.0
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
labels: "Status: Triage"

13
.github/workflows/lock-closed-issue.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
name: Lock closed issue
on:
issues:
types: [closed]
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: Dunning-Kruger/lock-issues@v1
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"

13
.github/workflows/pr-labeler.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
name: Apply labels to PR
on:
pull_request:
types: [opened]
jobs:
pr-labeler:
runs-on: ubuntu-latest
steps:
- name: Label PR
uses: TimonVS/pr-labeler-action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

15
.github/workflows/release-draft.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: Draft Release
on:
push:
branches:
- develop
jobs:
draft-release:
runs-on: ubuntu-latest
steps:
- name: Draft Release
uses: toolmantim/release-drafter@v5.2.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -0,0 +1,37 @@
name: Publish release preview package
on:
push:
branches:
- 'release/**'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 10.x
- name: Install Yarn
run: npm i yarn --global
- name: Install Json
run: npm i json --global
- name: Install Packages
run: yarn install --frozen-lockfile
- name: Publish
run: |
PREVIEW_VERSION=$(git rev-list --count --first-parent HEAD)
VERSION=$(echo ${{github.ref}} | tail -c +20)-preview.$PREVIEW_VERSION
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/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

46
.github/workflows/release-publish.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: Publish release
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: fregante/setup-git-token@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 10.x
- name: Install Yarn
run: npm i yarn --global
- name: Install Json
run: npm i json --global
- name: Install Packages
run: yarn install --frozen-lockfile
- name: Prepare release
run: |
VERSION=${GITHUB_REF:10}
echo "Preparing release $VERSION"
git checkout -t origin/release/$VERSION
npm version --no-git-tag-version --allow-same-version $VERSION
git add package.json
git commit -m "Bump version $VERSION"
git checkout -t origin/master
git merge -m "Release $VERSION" --no-ff release/$VERSION
git push --no-verify
- name: Publish
run: |
npm set //registry.npmjs.org/:_authToken $NPM_TOKEN
npm publish
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -0,0 +1,13 @@
name: Unlock reopened issue
on:
issues:
types: [reopened]
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: Dunning-Kruger/unlock-issues@v1
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"

10
.gitignore vendored
View File

@@ -2,6 +2,7 @@
node_modules/
coverage/
.idea/
dist/*.js
dist/*.map
@@ -9,3 +10,12 @@ dist/*.map
yarn-error.log
.npmrc
token
package-lock.json
dist/classTest.html
dist/sequenceTest.html
.vscode/
cypress/platform/current.html

View File

@@ -1,8 +0,0 @@
{
"typescript.format.enable": false,
"typescript.reportStyleChecksAsWarnings": false,
"typescript.validate.enable": false,
"javascript.validate.enable": false,
"editor.formatOnSave": false,
"standard.enable": true
}

98
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,98 @@
# Contributing
So you want to help? That's great!
![Image of happy people jumping with excitement](https://media.giphy.com/media/BlVnrxJgTGsUw/giphy.gif)
Here are a few things to know to get you started on the right path.
## Committing code
We make all changes via pull requests. As we have many pull requests from developers new to mermaid, the current approach is to have *knsv, Knut Sveidqvist* as a main reviewer of changes and merging pull requests. More precisely like this:
* Large changes reviewed by knsv or other developer asked to review by knsv
* Smaller low-risk changes like dependecies, documentation etc can be merged by active collaborators
* documentation (updates to the docs folder is also allowed via direct commits)
To commit code, create a branch, let it start with the type like feature or bug followed by the issue number for reference and some describing text.
One example:
`feature/945_state_diagrams`
Another:
`bug/123_nasty_bug_branch`
## Committing documentation
Less strict here, it is ok to commit directly in the develop branch if you are a collaborator.
## Branching
Going forward we will use a git flow inspired approach to branching. So development is done in develop, to do the development in the develop.
Once development is done we branch a release branch from develop for testing.
Once the release happens we merge the release branch to master and kill the release branch.
This means... **branch off your pull request from develop**
## Content of a pull request
A new feature has been born. Great! But without the steps below it might just ... fade away ...
### **Add unit tests for the parsing part**
This is important so that, if someone else does a change to the grammar that does not know about this great feature, gets notified early on when that change breaks the parser. Another important aspect is that without proper parsing tests refactoring is pretty much impossible.
### **Add e2e tests**
This tests the rendering and visual apearance of the diagram. This ensures that the rendering of that feature in the e2e will be reviewed in the release process going forward. Less chance that it breaks!
To start working with the e2e tests, run `yarn dev` to start the dev server, after that start cypress by running `cypress open` in the mermaid folder. (Make sure you have path to cypress in order, the binary is located in node_modules/.bin).
The rendering tests are very straightforward to create. There is a function imgSnapshotTest. This function takes a diagram in text form, the mermaid options and renders that diagram in cypress.
When running in ci it will take a snapshot of the rendered diagram and compare it with the snapshot from last build and flag for review it if it differs.
This is what a rendering test looks like:
```
it('should render forks and joins', () => {
imgSnapshotTest(
`
stateDiagram
state fork_state &lt;&lt;fork&gt;&gt;
[*] --> fork_state
fork_state --> State2
fork_state --> State3
state join_state &lt;&lt;join&gt;&gt;
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
`,
{ logLevel: 0 }
);
cy.get('svg');
});
```
### **Add documentation for it**
Finally, if it is not in the documentation, no one will know about it and then **no one will use it**. Wouldn't that be sad? With all the effort that was put into the feature?
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://mermaid-js.github.io/mermaid/ once released the updates are commited to https://mermaid-js.github.io/#/
## Last words
Don't get daunted if it is hard in the beginning. We have a great community with only encouraging words. So if you get stuck, ask for help and hints in the slack forum. If you want to show off something good, show it off there.
[Join our slack community if you want closer contact!](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
![Image of superhero wishing you good luck](https://media.giphy.com/media/l49JHz7kJvl6MCj3G/giphy.gif)

355
README.md
View File

@@ -1,94 +1,89 @@
[![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 the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/Mermaid/mermaid)
<!-- <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
# 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> -->
## Special note regarding version 8.2
:trophy: _"The most exciting use of technology"_ - [JS Open Source Awards (2019)](https://osawards.com/javascript/#nominees)
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 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.
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="https://raw.githubusercontent.com/mermaid-js/mermaid/master/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="https://raw.githubusercontent.com/mermaid-js/mermaid/master/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="https://raw.githubusercontent.com/mermaid-js/mermaid/master/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
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class01 &lt;|-- AveryLongClass : Cool
&lt;&lt;interface>> Class01
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
@@ -97,132 +92,84 @@ Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
```
![Class diagram](./img/class.png)
### Git graph - :exclamation: experimental
```
gitGraph:
options
{
"nodeSpacing": 150,
"nodeRadius": 10
class Class10 {
&lt;&lt;service>>
int id
size()
}
end
commit
branch newbranch
checkout newbranch
commit
commit
checkout master
commit
commit
merge newbranch
</pre></td>
<td align="center">
<img src="https://raw.githubusercontent.com/mermaid-js/mermaid/master/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="https://raw.githubusercontent.com/mermaid-js/mermaid/master/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="https://raw.githubusercontent.com/mermaid-js/mermaid/master/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](./img/git.png)
- [Command Line Interface](https://github.com/mermaid-js/mermaid.cli)
- [Live Editor](https://github.com/mermaid-js/mermaid-live-editor)
# 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)
## Installation
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.
### CDN
Detailed information about how to contribute can be found in the [contribution guide](CONTRIBUTING.md)
```
https://unpkg.com/mermaid@<version>/dist/
```
# 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!*
Replace `<version>` with expected version number.
Example: https://unpkg.com/mermaid@7.1.0/dist/
### Node.js
```
yarn add mermaid
```
## 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
## Setup
yarn install
## Build
yarn build:watch
## Lint
yarn lint
We use [JavaScript Standard Style](https://github.com/feross/standard).
We recommend you installing [editor plugins](https://github.com/feross/standard#are-there-text-editor-plugins) 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

@@ -3,9 +3,7 @@ module.exports = {
[
'@babel/preset-env',
{
targets: {
node: 'current'
}
targets: "defaults, ie >= 11, current node"
}
]
]

View File

@@ -26,3 +26,9 @@ export const imgSnapshotTest = (graphStr, options, api) => {
cy.get('svg');
cy.percySnapshot();
};
export const renderGraph = (graphStr, options, api) => {
const url = mermaidUrl(graphStr, options, api);
cy.visit(url);
};

View File

@@ -0,0 +1,100 @@
import { renderGraph } from '../../helpers/util';
/* eslint-env jest */
describe('Configuration', () => {
describe('arrowMarkerAbsolute', () => {
it('should handle default value false of arrowMarkerAbsolute', () => {
renderGraph(
`graph 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]
`,
{ }
);
// Check the marker-end property to make sure it is properly set to
// start with #
cy.get('.edgePath path').first().should('have.attr', 'marker-end')
.should('exist')
.and('include', 'url(#');
});
it('should handle default value false of arrowMarkerAbsolute', () => {
renderGraph(
`graph 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]
`,
{ }
);
// Check the marker-end property to make sure it is properly set to
// start with #
cy.get('.edgePath path').first().should('have.attr', 'marker-end')
.should('exist')
.and('include', 'url(#');
});
it('should handle arrowMarkerAbsolute excplicitly set to false', () => {
renderGraph(
`graph 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]
`,
{
arrowMarkerAbsolute: false
}
);
// Check the marker-end property to make sure it is properly set to
// start with #
cy.get('.edgePath path').first().should('have.attr', 'marker-end')
.should('exist')
.and('include', 'url(#');
});
it('should handle arrowMarkerAbsolute excplicitly set to "false" as false', () => {
renderGraph(
`graph 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]
`,
{
arrowMarkerAbsolute: "false"
}
);
// Check the marker-end property to make sure it is properly set to
// start with #
cy.get('.edgePath path').first().should('have.attr', 'marker-end')
.should('exist')
.and('include', 'url(#');
});
it('should handle arrowMarkerAbsolute set to true', () => {
renderGraph(
`graph 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]
`,
{
arrowMarkerAbsolute: true
}
);
cy.get('.edgePath path').first().should('have.attr', 'marker-end')
.should('exist')
.and('include', 'url(http://localhost');
});
});
});

View File

@@ -16,7 +16,7 @@ describe('Interaction', () => {
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#s1Function')
.find('g[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[id="2URL"]')
.click();
cy.location().should(location => {
@@ -70,7 +70,7 @@ describe('Interaction', () => {
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
});
});
it('should handle a click on a task with a bound function', () => {
it('should handle a click on a task with a bound function without args', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
@@ -78,9 +78,20 @@ describe('Interaction', () => {
.find('rect#cl2')
.click({ force: true });
cy.get('.created-by-gant-click').should('have.text', 'Clicked By Gant');
cy.get('.created-by-gant-click').should('have.text', 'Clicked By Gant cl2');
});
it('should handle a click on a task with a bound function', () => {
it('should handle a click on a task with a bound function with args', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('rect#cl3')
.click({ force: true });
cy.get('.created-by-gant-click').should('have.text', 'Clicked By Gant test1 test2 test3');
});
it('should handle a click on a task with a bound function without args', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
@@ -88,8 +99,19 @@ describe('Interaction', () => {
.find('text#cl2-text')
.click({ force: true });
cy.get('.created-by-gant-click').should('have.text', 'Clicked By Gant');
cy.get('.created-by-gant-click').should('have.text', 'Clicked By Gant cl2');
});
it('should handle a click on a task with a bound function with args ', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('text#cl3-text')
.click({ force: true });
cy.get('.created-by-gant-click').should('have.text', 'Clicked By Gant test1 test2 test3');
});
});
describe('Interaction - security level tight', () => {
@@ -108,7 +130,7 @@ describe('Interaction', () => {
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#s1Function')
.find('g[id="1Function"]')
.click();
cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');
@@ -130,7 +152,7 @@ describe('Interaction', () => {
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#s2URL')
.find('g[id="2URL"]')
.click();
cy.location().should(location => {
@@ -170,7 +192,7 @@ describe('Interaction', () => {
.find('rect#cl2')
.click({ force: true });
cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant');
cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant cl2');
});
it('should handle a click on a task with a bound function', () => {
const url = 'http://localhost:9000/click_security_strict.html';
@@ -180,7 +202,7 @@ describe('Interaction', () => {
.find('text#cl2-text')
.click({ force: true });
cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant');
cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant cl2');
});
});
@@ -200,7 +222,7 @@ describe('Interaction', () => {
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#s1Function')
.find('g[id="1Function"]')
.click();
cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');
@@ -226,7 +248,7 @@ describe('Interaction', () => {
.find('rect#cl2')
.click({ force: true });
cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant');
cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant cl2');
});
it('should handle a click on a task with a bound function', () => {
const url = 'http://localhost:9000/click_security_strict.html';
@@ -236,7 +258,7 @@ describe('Interaction', () => {
.find('text#cl2-text')
.click({ force: true });
cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant');
cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant cl2');
});
});
});

View File

@@ -0,0 +1,16 @@
/* eslint-env jest */
describe('Rerendering', () => {
it('should be able to render and rerender a graph via API', () => {
const url = 'http://localhost:9000/rerender.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('#graph #A').should('have.text', 'XMas');
cy.get('body')
.find('#rerender')
.click({ force: true });
cy.get('#graph #A').should('have.text', 'Saturday');
});
});

View File

@@ -9,8 +9,27 @@ describe('XSS', () => {
const url = mermaidUrl(str,{}, true);
cy.visit(url);
cy.wait(1000).then(()=>{
cy.get('.mermaid').should('exist');
});
cy.get('svg')
cy.percySnapshot()
// cy.percySnapshot()
})
it('should handle xss in tags in non-html mode', () => {
const str = 'eyJjb2RlIjoiXG5ncmFwaCBMUlxuICAgICAgQi0tPkQoPGltZyBvbmVycm9yPWxvY2F0aW9uPWBqYXZhc2NyaXB0XFx1MDAzYXhzc0F0dGFja1xcdTAwMjhkb2N1bWVudC5kb21haW5cXHUwMDI5YCBzcmM9eD4pOyIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0IiwiZmxvd2NoYXJ0Ijp7Imh0bWxMYWJlbHMiOmZhbHNlfX19';
const url = mermaidUrl(str,{
"theme": "default",
"flowchart": {
"htmlMode": false
}
}, true);
cy.visit(url);
// cy.get('svg')
// cy.percySnapshot()
cy.get('.malware').should('not.exist');
})
})

View File

@@ -1,12 +1,148 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util';
describe('Sequencediagram', () => {
it('should render a simple class diagrams', () => {
describe('Class diagram', () => {
it('1: should render a simple class diagram', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
Class12 <|.. Class08
Class11 ..>Class12
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class01 : -int privateChimp
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{logLevel : 1}
);
cy.get('svg');
});
it('2: should render a simple class diagrams with cardinality', () => {
imgSnapshotTest(
`
classDiagram
Class01 "1" <|--|> "*" AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 "1" *-- "*" Class04
Class05 "1" o-- "many" Class06
Class07 "1" .. "*" Class08
Class09 "1" --> "*" C2 : Where am i?
Class09 "*" --* "*" C3
Class09 "1" --|> "1" Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 "1" <--> "*" C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{}
);
cy.get('svg');
});
it('should render a simple class diagram with different visibilities', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class01 : -int privateMethod()
Class01 : +int publicMethod()
Class01 : #int protectedMethod()
Class01 : -int privateChimp
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset
`,
{}
);
cy.get('svg');
});
it('should render multiple class diagrams', () => {
imgSnapshotTest(
[
`
classDiagram
Class01 "1" <|--|> "*" AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 "1" *-- "*" Class04
Class05 "1" o-- "many" Class06
Class07 "1" .. "*" Class08
Class09 "1" --> "*" C2 : Where am i?
Class09 "*" --* "*" C3
Class09 "1" --|> "1" Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 "1" <--> "*" C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
`
classDiagram
Class01 "1" <|--|> "*" AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 "1" *-- "*" Class04
Class05 "1" o-- "many" Class06
Class07 "1" .. "*" Class08
Class09 "1" --> "*" C2 : Where am i?
Class09 "*" --* "*" C3
Class09 "1" --|> "1" Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 "1" <--> "*" C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
],
{}
);
cy.get('svg');
});
it('4: should render a simple class diagram with comments', () => {
imgSnapshotTest(
`
classDiagram
%% this is a comment
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
@@ -19,6 +155,151 @@ describe('Sequencediagram', () => {
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{}
);
cy.get('svg');
});
it('5: should render a simple class diagram with abstract method', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
Class01 : someMethod()*
`,
{}
);
cy.get('svg');
});
it('6: should render a simple class diagram with static method', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
Class01 : someMethod()$
`,
{}
);
cy.get('svg');
});
it('7: should render a simple class diagram with Generic class', () => {
imgSnapshotTest(
`
classDiagram
class Class01~T~
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10~T~ {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{}
);
cy.get('svg');
});
it('8: should render a simple class diagram with Generic class and relations', () => {
imgSnapshotTest(
`
classDiagram
Class01~T~ <|-- AveryLongClass : Cool
Class03~T~ *-- Class04~T~
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10~T~ {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{}
);
cy.get('svg');
});
it('9: should render a simple class diagram with clickable link', () => {
imgSnapshotTest(
`
classDiagram
Class01~T~ <|-- AveryLongClass : Cool
Class03~T~ *-- Class04~T~
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10~T~ {
&lt;&lt;service&gt;&gt;
int id
test()
}
link class01 "google.com" "A Tooltip"
`,
{}
);
cy.get('svg');
});
it('10: should render a simple class diagram with clickable callback', () => {
imgSnapshotTest(
`
classDiagram
Class01~T~ <|-- AveryLongClass : Cool
Class03~T~ *-- Class04~T~
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10~T~ {
&lt;&lt;service&gt;&gt;
int id
test()
}
callback class01 "functionCall" "A Tooltip"
`,
{}
);
cy.get('svg');
});
it('11: should render a simple class diagram with return type on method', () => {
imgSnapshotTest(
`
classDiagram
class Class10~T~ {
int[] id
test(int[] ids) bool
testArray() bool[]
}
`,
{}
);
cy.get('svg');
});
it('12: should render a simple class diagram with generic types', () => {
imgSnapshotTest(
`
classDiagram
class Class10~T~ {
int[] id
List~int~ ids
test(List~int~ ids) List~bool~
testArray() bool[]
}
`,
{}
);

View File

@@ -0,0 +1,21 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util';
describe('State diagram', () => {
it('should render a state with states in it', () => {
imgSnapshotTest(
`
stateDiagram
state PersonalizedCockpit {
Other
state Parent {
C
}
}
`,
{
logLevel: 0,
}
);
});
});

View File

@@ -1,8 +1,8 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util';
describe('Flowcart', () => {
it('should render a simple flowchart', () => {
describe('Flowchart', () => {
it('1: should render a simple flowchart no htmlLabels', () => {
imgSnapshotTest(
`graph TD
A[Christmas] -->|Get money| B(Go shopping)
@@ -11,10 +11,24 @@ describe('Flowcart', () => {
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{}
{ flowchart: { htmlLabels: false } }
);
});
it('should render a simple flowchart with line breaks', () => {
it('2: should render a simple flowchart with htmlLabels', () => {
imgSnapshotTest(
`graph 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]
`,
{ flowchart: { htmlLabels: true } }
);
});
it('3: should render a simple flowchart with line breaks', () => {
imgSnapshotTest(
`
graph TD
@@ -28,7 +42,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
@@ -43,7 +57,7 @@ describe('Flowcart', () => {
);
});
it('should style nodes via a class.', () => {
it('5: should style nodes via a class.', () => {
imgSnapshotTest(
`
graph TD
@@ -59,7 +73,7 @@ describe('Flowcart', () => {
);
});
it('should render a flowchart full of circles', () => {
it('6: should render a flowchart full of circles', () => {
imgSnapshotTest(
`
graph LR
@@ -87,7 +101,8 @@ describe('Flowcart', () => {
{}
);
});
it('should render a flowchart full of icons', () => {
it('7: should render a flowchart full of icons', () => {
imgSnapshotTest(
`
graph TD
@@ -158,7 +173,7 @@ describe('Flowcart', () => {
);
});
it('should render labels with numbers at the start', () => {
it('8: should render labels with numbers at the start', () => {
imgSnapshotTest(
`
graph TB;subgraph "number as labels";1;end;
@@ -166,7 +181,8 @@ describe('Flowcart', () => {
{}
);
});
it('should render subgraphs', () => {
it('9: should render subgraphs', () => {
imgSnapshotTest(
`
graph TB
@@ -178,7 +194,7 @@ describe('Flowcart', () => {
);
});
it('should render subgraphs with a title startign with a digit', () => {
it('10: should render subgraphs with a title starting with a digit', () => {
imgSnapshotTest(
`
graph TB
@@ -190,7 +206,7 @@ describe('Flowcart', () => {
);
});
it('should render styled subgraphs', () => {
it('11: should render styled subgraphs', () => {
imgSnapshotTest(
`
graph TB
@@ -225,7 +241,7 @@ describe('Flowcart', () => {
);
});
it('should render a flowchart with ling sames and class definitoins', () => {
it('12: should render a flowchart with long names and class definitions', () => {
imgSnapshotTest(
`graph LR
sid-B3655226-6C29-4D00-B685-3D5C734DC7E1["
@@ -327,7 +343,7 @@ describe('Flowcart', () => {
);
});
it('should render color of styled nodes', () => {
it('13: should render color of styled nodes', () => {
imgSnapshotTest(
`
graph LR
@@ -344,4 +360,250 @@ describe('Flowcart', () => {
}
);
});
it('14: 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;
class C someclass;
`,
{
listUrl: false,
listId: 'color styling',
logLevel: 0
}
);
});
it('15: should render a simple flowchart with comments', () => {
imgSnapshotTest(
`graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
%% this is a comment
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { htmlLabels: false } }
);
});
it('16: Render Stadium shape', () => {
imgSnapshotTest(
` graph 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;
`,
{ flowchart: { htmlLabels: false } }
);
});
it('17: Render multiline texts', () => {
imgSnapshotTest(
`graph LR
A1[Multi<br>Line] -->|Multi<br>Line| B1(Multi<br>Line)
C1[Multi<br/>Line] -->|Multi<br/>Line| D1(Multi<br/>Line)
E1[Multi<br />Line] -->|Multi<br />Line| F1(Multi<br />Line)
A2[Multi<br>Line] -->|Multi<br>Line| B2(Multi<br>Line)
C2[Multi<br/>Line] -->|Multi<br/>Line| D2(Multi<br/>Line)
E2[Multi<br />Line] -->|Multi<br />Line| F2(Multi<br />Line)
linkStyle 0 stroke:DarkGray,stroke-width:2px
linkStyle 1 stroke:DarkGray,stroke-width:2px
linkStyle 2 stroke:DarkGray,stroke-width:2px
`,
{ flowchart: { htmlLabels: false } }
);
});
it('18: Chaining of nodes', () => {
imgSnapshotTest(
`graph LR
a --> b --> c
`,
{ flowchart: { htmlLabels: false } }
);
});
it('19: Multiple nodes and chaining in one statement', () => {
imgSnapshotTest(
`graph LR
a --> b & c--> d
`,
{ flowchart: { htmlLabels: false } }
);
});
it('20: Multiple nodes and chaining in one statement', () => {
imgSnapshotTest(
`graph TD
A[ h ] -- hello --> B[" test "]:::exClass & C --> D;
classDef exClass background:#bbb,border:1px solid red;
`,
{ flowchart: { htmlLabels: false } }
);
});
it('21: Render cylindrical shape', () => {
imgSnapshotTest(
`graph LR
A[(cylindrical<br />shape<br />test)]
A -->|Get money| B1[(Go shopping 1)]
A -->|Get money| B2[(Go shopping 2)]
A -->|Get money| B3[(Go shopping 3)]
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?)]
B1 --> C
B2 --> C
B3 --> C
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;`,
{ flowchart: { htmlLabels: false } }
);
});
it('22: Render a simple flowchart with nodeSpacing set to 100', () => {
imgSnapshotTest(
`graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
%% this is a comment
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { nodeSpacing: 50 } }
);
});
it('23: Render a simple flowchart with rankSpacing set to 100', () => {
imgSnapshotTest(
`graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
%% this is a comment
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { rankSpacing: '100' } }
);
});
it('24: Keep node label text (if already defined) when a style is applied', () => {
imgSnapshotTest(
`graph LR
A(( )) -->|step 1| B(( ))
B(( )) -->|step 2| C(( ))
C(( )) -->|step 3| D(( ))
linkStyle 1 stroke:greenyellow,stroke-width:2px
style C fill:greenyellow,stroke:green,stroke-width:4px
`,
{ flowchart: { htmlLabels: false } }
);
});
it('25: Handle link click events (link, anchor, mailto, other protocol, script)', () => {
imgSnapshotTest(
`graph TB
TITLE["Link Click Events<br>(click the nodes below)"]
A[link test]
B[anchor test]
C[mailto test]
D[other protocol test]
E[script test]
TITLE --> A & B & C & D & E
click A "https://mermaid-js.github.io/mermaid/#/" "link test"
click B "#link-clicked" "anchor test"
click C "mailto:user@user.user" "mailto test"
click D "notes://do-your-thing/id" "other protocol test"
click E "javascript:alert('test')" "script test"
`,
{ securityLevel: 'loose' }
);
});
it('26: Set text color of nodes and links according to styles when html labels are enabled', () => {
imgSnapshotTest(
`graph LR
A[red<br>text] -->|red<br>text| B(blue<br>text)
C[/red<br/>text/] -->|blue<br/>text| D{blue<br/>text}
E{{default<br />style}} -->|default<br />style| F([default<br />style])
linkStyle default color:Sienna;
linkStyle 0 color:red;
linkStyle 1 stroke:DarkGray,stroke-width:2px,color:#0000ff
style A color:red;
style B color:blue;
style C stroke:#ff0000,fill:#ffcccc,color:#ff0000
style D stroke:#0000ff,fill:#ccccff,color:#0000ff
click B "index.html#link-clicked" "link test"
click D testClick "click test"
`,
{ flowchart: { htmlLabels: true } }
);
});
it('27: Set text color of nodes and links according to styles when html labels are disabled', () => {
imgSnapshotTest(
`graph LR
A[red<br>text] -->|red<br>text| B(blue<br>text)
C[/red<br/>text/] -->|blue<br/>text| D{blue<br/>text}
E{{default<br />style}} -->|default<br />style| F([default<br />style])
linkStyle default color:Sienna;
linkStyle 0 color:red;
linkStyle 1 stroke:DarkGray,stroke-width:2px,color:#0000ff
style A color:red;
style B color:blue;
style C stroke:#ff0000,fill:#ffcccc,color:#ff0000
style D stroke:#0000ff,fill:#ccccff,color:#0000ff
click B "index.html#link-clicked" "link test"
click D testClick "click test"
`,
{ flowchart: { htmlLabels: false } }
);
});
it('30: Possibility to style text color of nodes and subgraphs as well as apply classes to subgraphs', () => {
imgSnapshotTest(
`graph LR
subgraph id1 [title is set]
A-->B
end
subgraph id2 [title]
E
end
B-->C
subgraph id3
C-->D
end
class id3,id2,A redBg;
class id3,A whiteTxt;
classDef redBg fill:#622;
classDef whiteTxt color: white;
`,
{ flowchart: { htmlLabels: false } }
);
});
});

View File

@@ -19,7 +19,7 @@ describe('Sequencediagram', () => {
section Critical tasks
Completed task in the critical line :crit, done, 2014-01-06,24h
Implement parser and jison :crit, done, after des1, 2d
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
@@ -38,4 +38,96 @@ describe('Sequencediagram', () => {
{}
);
});
it('Handle multiline section titles with different line breaks', () => {
imgSnapshotTest(
`
gantt
dateFormat YYYY-MM-DD
axisFormat %d/%m
title GANTT diagram with multiline section titles
excludes weekdays 2014-01-10
section A section<br>multiline
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<br/>multiline
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
section Documentation<br />multiline
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<br />multiline
Describe gantt syntax : after doc1, 3d
Add gantt diagram to demo page : 20h
Add another diagram to demo page : 48h
`,
{}
);
});
it('Multiple dependencies syntax', () => {
imgSnapshotTest(
`
gantt
dateFormat YYYY-MM-DD
axisFormat %d/%m
title Adding GANTT diagram to mermaid
excludes weekdays 2014-01-10
apple :a, 2017-07-20, 1w
banana :crit, b, 2017-07-23, 1d
cherry :active, c, after b a, 1d
`,
{}
);
});
it('should render a gantt chart for issue #1060', () => {
imgSnapshotTest(
`
gantt
excludes weekdays 2017-01-10
title Projects Timeline
section asdf
specs :done, :ps, 2019-05-10, 50d
Plasma :pc, 2019-06-20, 60d
Rollup :or, 2019-08-20, 50d
section CEL
plasma-chamber :done, :pc, 2019-05-20, 60d
Plasma Implementation (Rust) :por, 2019-06-20, 120d
Predicates (Atomic Swap) :pred, 2019-07-20, 60d
section DEX
History zkSNARK :hs, 2019-08-10, 40d
Exit :vs, after hs, 60d
PredicateSpec :ps, 2019-09-1, 20d
PlasmaIntegration :pi, after ps,40d
section Events
ETHBoston :done, :eb, 2019-09-08, 3d
DevCon :active, :dc, 2019-10-08, 3d
section Plasma Calls & updates
OVM :ovm, 2019-07-12, 120d
Plasma call 26 :pc26, 2019-08-21, 1d
Plasma call 27 :pc27, 2019-09-03, 1d
Plasma call 28 :pc28, 2019-09-17, 1d
`,
{}
);
});
});

View File

@@ -2,27 +2,20 @@
import { imgSnapshotTest } from '../../helpers/util.js';
describe('Sequencediagram', () => {
it('should render a simple git graph', () => {
imgSnapshotTest(
`
gitGraph:
options
{
"nodeSpacing": 150,
"nodeRadius": 10
}
end
commit
branch newbranch
checkout newbranch
commit
commit
checkout master
commit
commit
merge newbranch
`,
{}
);
});
// it('should render a simple git graph', () => {
// imgSnapshotTest(
// `
// gitGraph:
// commit
// branch newbranch
// checkout newbranch
// commit
// commit
// checkout master
// commit
// commit
// merge newbranch`,
// { 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

@@ -2,8 +2,8 @@
import { imgSnapshotTest } from '../../helpers/util';
context('Aliasing', () => {
it('should render a simple sequence diagrams', () => {
context('Sequence diagram', () => {
it('should render a simple sequence diagram', () => {
imgSnapshotTest(
`
sequenceDiagram
@@ -32,6 +32,26 @@ context('Aliasing', () => {
{}
);
});
it('should handle different line breaks', () => {
imgSnapshotTest(
`
sequenceDiagram
participant 1 as multiline<br>using #lt;br#gt;
participant 2 as multiline<br/>using #lt;br/#gt;
participant 3 as multiline<br />using #lt;br /#gt;
participant 4 as multiline<br \t/>using #lt;br \t/#gt;
1->>2: multiline<br>using #lt;br#gt;
note right of 2: multiline<br>using #lt;br#gt;
2->>3: multiline<br/>using #lt;br/#gt;
note right of 3: multiline<br/>using #lt;br/#gt;
3->>4: multiline<br />using #lt;br /#gt;
note right of 4: multiline<br />using #lt;br /#gt;
4->>1: multiline<br />using #lt;br /#gt;
note right of 1: multiline<br \t/>using #lt;br \t/#gt;
`,
{}
);
});
context('background rects', () => {
it('should render a single and nested rects', () => {
imgSnapshotTest(
@@ -129,5 +149,38 @@ context('Aliasing', () => {
{}
);
});
it('should render autonumber when configured with such', () => {
imgSnapshotTest(
`
sequenceDiagram
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!
`,
{sequence: { actorMargin: 50, showSequenceNumbers: true }}
);
});
it('should render autonumber when autonumber keyword is used', () => {
imgSnapshotTest(
`
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!
`,
{}
);
});
});
});

View File

@@ -0,0 +1,348 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util';
describe('State diagram', () => {
it('should render a simple state diagrams', () => {
imgSnapshotTest(
`
stateDiagram
[*] --> State1
State1 --> [*]
`,
{ logLevel: 0 }
);
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(
`
stateDiagram
state "A long long name" as long1
state "A" as longlonglongid
`,
{ logLevel: 0 }
);
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(
`
stateDiagram
State1: The state with a note
note right of State1
Important information! You can write
notes.
end note
`,
{ logLevel: 0 }
);
cy.get('svg');
});
it('should render a state with on the left side when so specified', () => {
imgSnapshotTest(
`
stateDiagram
State1: The state with a note with minus - and plus + in it
note left of State1
Important information! You can write
notes with . and in them.
end note
`,
{ logLevel: 0 }
);
cy.get('svg');
});
it('should render a state with a note together with another state', () => {
imgSnapshotTest(
`
stateDiagram
State1: The state with a note +,-
note right of State1
Important information! You can write +,-
notes.
end note
State1 --> State2 : With +,-
note left of State2 : This is the note +,-<br/>
`,
{ logLevel: 0 }
);
cy.get('svg');
});
it('should render a note with multiple lines in it', () => {
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
`,
{}
);
});
it('should handle multiline notes with different line breaks', () => {
imgSnapshotTest(
`
stateDiagram
State1
note right of State1
Line1<br>Line2<br/>Line3<br />Line4<br />Line5
end note
`,
{}
);
});
it('should render a states with descriptions including multi-line descriptions', () => {
imgSnapshotTest(
`
stateDiagram
State1: This a a single line description
State2: This a a multi line description
State2: here comes the multi part
[*] --> State1
State1 --> State2
State2 --> [*]
`,
{ logLevel: 0 }
);
cy.get('svg');
});
it('should render a simple state diagrams', () => {
imgSnapshotTest(
`
stateDiagram
[*] --> State1
State1 --> State2
State1 --> State3
State1 --> [*]
`,
{ logLevel: 0 }
);
cy.get('svg');
});
it('should render a simple state diagrams with labels', () => {
imgSnapshotTest(
`
stateDiagram
[*] --> State1
State1 --> State2 : Transition 1
State1 --> State3 : Transition 2
State1 --> State4 : Transition 3
State1 --> State5 : Transition 4
State2 --> State3 : Transition 5
State1 --> [*]
`,
{ logLevel: 0 }
);
cy.get('svg');
});
it('should render state descriptions', () => {
imgSnapshotTest(
`
stateDiagram
state "Long state description" as XState1
state "Another Long state description" as XState2
XState2 : New line
XState1 --> XState2
`,
{ logLevel: 0 }
);
cy.get('svg');
});
it('should render composit states', () => {
imgSnapshotTest(
`
stateDiagram
[*] --> NotShooting: Pacifist
NotShooting --> A
NotShooting --> B
NotShooting --> C
state NotShooting {
[*] --> Idle: Yet another long long öong öong öong label
Idle --> Configuring : EvConfig
Configuring --> Idle : EvConfig EvConfig EvConfig EvConfig EvConfig
}
`,
{ logLevel: 0 }
);
cy.get('svg');
});
it('should render multiple composit states', () => {
imgSnapshotTest(
`
stateDiagram
[*]-->TV
state TV {
[*] --> Off: Off to start with
On --> Off : Turn off
Off --> On : Turn on
}
TV--> Console
state Console {
[*] --> Off2: Off to start with
On2--> Off2 : Turn off
Off2 --> On2 : Turn on
On2-->Playing
state Playing {
Alive --> Dead
Dead-->Alive
}
}
`,
{ logLevel: 0 }
);
});
it('should render forks in composit states', () => {
imgSnapshotTest(
`
stateDiagram
[*]-->TV
state TV {
state fork_state &lt;&lt;fork&gt;&gt;
[*] --> fork_state
fork_state --> State2
fork_state --> State3
state join_state &lt;&lt;join&gt;&gt;
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
}
`,
{ logLevel: 0 }
);
});
it('should render forks and joins', () => {
imgSnapshotTest(
`
stateDiagram
state fork_state &lt;&lt;fork&gt;&gt;
[*] --> fork_state
fork_state --> State2
fork_state --> State3
state join_state &lt;&lt;join&gt;&gt;
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
`,
{ logLevel: 0 }
);
cy.get('svg');
});
it('should render conurrency states', () => {
imgSnapshotTest(
`
stateDiagram
[*] --> Active
state Active {
[*] --> NumLockOff
NumLockOff --> NumLockOn : EvNumLockPressed
NumLockOn --> NumLockOff : EvNumLockPressed
--
[*] --> CapsLockOff
CapsLockOff --> CapsLockOn : EvCapsLockPressed
CapsLockOn --> CapsLockOff : EvCapsLockPressed
--
[*] --> ScrollLockOff
ScrollLockOff --> ScrollLockOn : EvCapsLockPressed
ScrollLockOn --> ScrollLockOff : EvCapsLockPressed
}
`,
{ logLevel: 0 }
);
cy.get('svg');
});
it('should render a state with states in it', () => {
imgSnapshotTest(
`
stateDiagram
state PilotCockpit {
state Parent {
C
}
}
`,
{
logLevel: 0,
}
);
});
it('Simplest composit state', () => {
imgSnapshotTest(
`
stateDiagram
state Parent {
C
}
`,
{
logLevel: 0,
}
);
});
it('should handle multiple arrows from one node to another', () => {
imgSnapshotTest(
`
stateDiagram
a --> b: Start
a --> b: Stop
`,
{
logLevel: 0,
}
);
});
});

View File

@@ -49,9 +49,11 @@
section Clickable
Visit mermaidjs :active, cl1, 2014-01-07,2014-01-10
Calling a Callback (look at the console log) :cl2, after cl1, 3d
Calling a Callback with args :cl3, after cl1, 3d
click cl1 href "http://localhost:9000/webpackUsage.html"
click cl2 call clickByGantt("test", test, test)
click cl2 call clickByGantt()
click cl3 call clickByGantt("test1", test2, test3)
section Last section
Describe gantt syntax :after doc1, 3d
@@ -69,11 +71,14 @@
document.getElementsByTagName('body')[0].appendChild(div)
}
function clickByGantt(elemName) {
function clickByGantt(arg1, arg2, arg3) {
const div = document.createElement('div')
div.className = 'created-by-gant-click'
div.style = 'padding: 20px; background: green; color: white;'
div.innerText = 'Clicked By Gant'
if (arg1) div.innerText += ' ' + arg1;
if (arg2) div.innerText += ' ' + arg2;
if (arg3) div.innerText += ' ' + arg3;
document.getElementsByTagName('body')[0].appendChild(div)
}

View File

@@ -49,9 +49,11 @@
section Clickable
Visit mermaidjs :active, cl1, 2014-01-07,2014-01-10
Calling a Callback (look at the console log) :cl2, after cl1, 3d
Calling a Callback with args :cl3, after cl1, 3d
click cl1 href "http://localhost:9000/webpackUsage.html"
click cl2 call clickByGantt("test", test, test)
click cl2 call clickByGantt()
click cl3 call clickByGantt("test1", test2, test3)
section Last section
Describe gantt syntax :after doc1, 3d
@@ -69,11 +71,14 @@
document.getElementsByTagName('body')[0].appendChild(div)
}
function clickByGantt(elemName) {
function clickByGantt(arg1, arg2, arg3) {
const div = document.createElement('div')
div.className = 'created-by-gant-click'
div.style = 'padding: 20px; background: green; color: white;'
div.innerText = 'Clicked By Gant'
if (arg1) div.innerText += ' ' + arg1;
if (arg2) div.innerText += ' ' + arg2;
if (arg3) div.innerText += ' ' + arg3;
document.getElementsByTagName('body')[0].appendChild(div)
}

View File

@@ -0,0 +1,51 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
background: white;
font-family: 'Noto Sans SC', sans-serif;
}
h1 { color: white;}
.arrowheadPath {fill: red;}
.edgePath .path {stroke: red;}
</style>
</head>
<body>
<h1>info below</h1>
<div style="display: flex;width: 100%; height: 100%">
<div class="mermaid" style="width: 100%; height: 100%">
sequenceDiagram
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!
</div>
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
// theme: 'dark',
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'linear', "htmlLabels": false },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
fontFamily: '"Noto Sans SC", sans-serif'
});
</script>
</script>
</body>
</html>

View File

@@ -1,11 +1,26 @@
<html>
<head>
<script src="/e2e.js"></script>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<style></style>
<link href="https://fonts.googleapis.com/css?family=Mansalva&display=swap" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* font-family: 'Mansalva', cursive;*/
font-family: 'Mansalva', cursive;
}
/* .mermaid-main-font {
font-family: "trebuchet ms", verdana, arial;
font-family: var(--mermaid-font-family);
} */
/* :root {
--mermaid-font-family: '"trebuchet ms", verdana, arial';
--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive;
--mermaid-font-family: '"Lucida Console", Monaco, monospace';
} */
svg {
border: 2px solid darkred;
}
</style>
</head>
<body>
<script src="./mermaid.js"></script>
@@ -15,6 +30,11 @@
mermaid.initialize({
startOnLoad: false,
useMaxWidth: true,
// "themeCSS": ":root { --mermaid-font-family: \"trebuchet ms\", verdana, arial;}",
// fontFamily: '\"trebuchet ms\", verdana, arial;'
// fontFamily: '"Comic Sans MS", "Comic Sans", cursive'
// fontFamily: '"Mansalva", cursive',
fontFamily: '"Noto Sans SC", sans-serif'
});
</script>
</body>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
</head>
<body>
<div id="graph">
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.init({ startOnLoad: false });
mermaid.mermaidAPI.initialize();
rerender('XMas');
function rerender(text) {
var graphText = `graph TD
A[${text}] -->|Get money| B(Go shopping)`
var graph = mermaid.mermaidAPI.render('id', graphText);
console.log('\x1b[35m%s\x1b[0m', '>> graph', graph)
document.getElementById('graph').innerHTML=graph;
}
</script>
<button id="rerender" onclick="rerender('Saturday')">Rerender</button>
</body>
</html>

View File

@@ -1,50 +1,95 @@
import { Base64 } from 'js-base64'
import mermaid2 from '../../src/mermaid'
import { Base64 } from 'js-base64';
import mermaid2 from '../../src/mermaid';
/**
* ##contentLoaded
* Callback function that is called when page is loaded. This functions fetches configuration for mermaid rendering and
* calls init for rendering the mermaid diagrams on the page.
*/
const contentLoaded = function () {
let pos = document.location.href.indexOf('?graph=')
const contentLoaded = function() {
let pos = document.location.href.indexOf('?graph=');
if (pos > 0) {
pos = pos + 7
const graphBase64 = document.location.href.substr(pos)
const graphObj = JSON.parse(Base64.decode(graphBase64))
pos = pos + 7;
const graphBase64 = document.location.href.substr(pos);
const graphObj = JSON.parse(Base64.decode(graphBase64));
// const graph = 'hello'
console.log(graphObj)
const div = document.createElement('div')
div.id = 'block'
div.className = 'mermaid'
div.innerHTML = graphObj.code
document.getElementsByTagName('body')[0].appendChild(div)
global.mermaid.initialize(graphObj.mermaid)
// console.log('graphObj.mermaid', graphObj.mermaid)
global.mermaid.init()
console.log(graphObj);
if (Array.isArray(graphObj.code)) {
const numCodes = graphObj.code.length;
for (let i = 0; i < numCodes; i++) {
const div = document.createElement('div');
div.id = 'block' + i;
div.className = 'mermaid';
div.innerHTML = graphObj.code[i];
document.getElementsByTagName('body')[0].appendChild(div);
}
} else {
const div = document.createElement('div');
div.id = 'block';
div.className = 'mermaid';
div.innerHTML = graphObj.code;
document.getElementsByTagName('body')[0].appendChild(div);
}
global.mermaid.initialize(graphObj.mermaid);
global.mermaid.init();
}
}
const contentLoadedApi = function () {
let pos = document.location.href.indexOf('?graph=')
};
const contentLoadedApi = function() {
let pos = document.location.href.indexOf('?graph=');
if (pos > 0) {
pos = pos + 7
const graphBase64 = document.location.href.substr(pos)
const graphObj = JSON.parse(Base64.decode(graphBase64))
pos = pos + 7;
const graphBase64 = document.location.href.substr(pos);
const graphObj = JSON.parse(Base64.decode(graphBase64));
// const graph = 'hello'
const div = document.createElement('div')
div.id = 'block'
div.className = 'mermaid'
// div.innerHTML = graphObj.code
document.getElementsByTagName('body')[0].appendChild(div)
global.mermaid.initialize(graphObj.mermaid)
if (Array.isArray(graphObj.code)) {
const numCodes = graphObj.code.length;
const divs = [];
let div;
for (let i = 0; i < numCodes; i++) {
div = document.createElement('div');
div.id = 'block' + i;
div.className = 'mermaid';
// div.innerHTML = graphObj.code
document.getElementsByTagName('body')[0].appendChild(div);
divs[i] = div;
}
mermaid2.render('newid', graphObj.code, (svgCode, bindFunctions) => {
div.innerHTML = svgCode
mermaid2.initialize(graphObj.mermaid);
bindFunctions(div)
}, div)
for (let i = 0; i < numCodes; i++) {
mermaid2.render(
'newid' + i,
graphObj.code[i],
(svgCode, bindFunctions) => {
div.innerHTML = svgCode;
bindFunctions(div);
},
divs[i]
);
}
} else {
const div = document.createElement('div');
div.id = 'block';
div.className = 'mermaid';
// div.innerHTML = graphObj.code
console.warn('graphObj.mermaid', graphObj.mermaid);
document.getElementsByTagName('body')[0].appendChild(div);
mermaid2.initialize(graphObj.mermaid);
mermaid2.render(
'newid',
graphObj.code,
(svgCode, bindFunctions) => {
div.innerHTML = svgCode;
if (bindFunctions) bindFunctions(div);
},
div
);
}
}
}
};
if (typeof document !== 'undefined') {
/*!
@@ -52,15 +97,15 @@ if (typeof document !== 'undefined') {
*/
window.addEventListener(
'load',
function () {
function() {
if (this.location.href.match('xss.html')) {
this.console.log('Using api')
contentLoadedApi()
this.console.log('Using api');
contentLoadedApi();
} else {
this.console.log('Not using api')
contentLoaded()
this.console.log('Not using api');
contentLoaded();
}
},
false
)
);
}

View File

@@ -28,7 +28,10 @@
div.id = 'the-malware'
div.className = 'malware'
div.innerHTML = 'XSS Succeeded'
document.getElementsByTagName('body')[0].appendChild(div)
document.getElementsByTagName('body')[0].appendChild(div);
// const el = document.querySelector('.mermaid');
// el.parentNode.removeChild(el);
throw new Error('XSS Succeded');
}
</script>
</head>

248
dist/index.html vendored
View File

@@ -289,16 +289,100 @@ graph TB
style 456ac9b0d15a8b7f1e71073221059886 fill:#f9f,stroke:#333,stroke-width:4px
</div>
<div class="mermaid">
graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
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;
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;
class C someclass;
</div>
<div class="mermaid">
graph 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="mermaid">
graph LR
A[(cylindrical<br />shape<br />test)]
A -->|Get money| B1[(Go shopping 1)]
A -->|Get money| B2[(Go shopping 2)]
A -->|Get money| B3[(Go shopping 3)]
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?)]
B1 --> C
B2 --> C
B3 --> C
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;
</div>
<div class="mermaid">
graph LR
A1[Multi<br>Line] -->|Multi<br>Line| B1(Multi<br>Line)
C1[Multi<br/>Line] -->|Multi<br/>Line| D1(Multi<br/>Line)
E1[Multi<br />Line] -->|Multi<br />Line| F1(Multi<br />Line)
A2[Multi<br>Line] -->|Multi<br>Line| B2(Multi<br>Line)
C2[Multi<br/>Line] -->|Multi<br/>Line| D2(Multi<br/>Line)
E2[Multi<br />Line] -->|Multi<br />Line| F2(Multi<br />Line)
linkStyle 0 stroke:DarkGray,stroke-width:2px
linkStyle 1 stroke:DarkGray,stroke-width:2px
linkStyle 2 stroke:DarkGray,stroke-width:2px
</div>
<div class="mermaid">
graph LR
A(( )) -->|step 1| B(( ))
B(( )) -->|step 2| C(( ))
C(( )) -->|step 3| D(( ))
linkStyle 1 stroke:greenyellow,stroke-width:2px
style C fill:greenyellow,stroke:green,stroke-width:4px
</div>
<div class="mermaid">
graph TB
TITLE["Link Click Events<br>(click the nodes below)"]
A[link test]
B[anchor test]
C[mailto test]
D[other protocol test]
E[script test]
TITLE --> A & B & C & D & E
click A "https://mermaid-js.github.io/mermaid/#/" "link test"
click B "#link-clicked" "anchor test"
click C "mailto:user@user.user" "mailto test"
click D "notes://do-your-thing/id" "other protocol test"
click E "javascript:alert('test')" "script test"
</div>
<hr/>
<div class="mermaid">
graph LR
A[red<br>text] -->|red<br>text| B(blue<br>text)
C[/red<br/>text/] -->|blue<br/>text| D{blue<br/>text}
E{{default<br />style}} -->|default<br />style| F([default<br />style])
linkStyle default color:Sienna;
linkStyle 0 color:red;
linkStyle 1 stroke:DarkGray,stroke-width:2px,color:#0000ff
style A color:red;
style B color:blue;
style C stroke:#ff0000,fill:#ffcccc,color:#ff0000
style D stroke:#0000ff,fill:#ccccff,color:#0000ff
click B "index.html#link-clicked" "link test"
click D testClick "click test"
</div>
<hr/>
@@ -331,6 +415,21 @@ and
Alice -->> John: Parallel message 2
end
</div>
<div class="mermaid">
sequenceDiagram
participant 1 as multiline<br>using #lt;br#gt;
participant 2 as multiline<br/>using #lt;br/#gt;
participant 3 as multiline<br />using #lt;br /#gt;
participant 4 as multiline<br />using #lt;br /#gt;
1->>2: multiline<br>using #lt;br#gt;
note right of 2: multiline<br>using #lt;br#gt;
2->>3: multiline<br/>using #lt;br/#gt;
note right of 3: multiline<br/>using #lt;br/#gt;
3->>4: multiline<br />using #lt;br /#gt;
note right of 4: multiline<br />using #lt;br /#gt;
4->>1: multiline<br />using #lt;br /#gt;
note right of 1: multiline<br />using #lt;br /#gt;
</div>
<hr/>
@@ -372,6 +471,37 @@ Describe gantt syntax :after doc1, 3d
Add gantt diagram to demo page : 20h
Add another diagram to demo page : 48h
</div>
<div class="mermaid">
gantt
dateFormat YYYY-MM-DD
axisFormat %d/%m
title GANTT diagram with multiline section titles
excludes weekdays 2014-01-10
section A section<br>multiline
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<br/>multiline
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
section Documentation<br />multiline
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<br />multiline
Describe gantt syntax : after doc1, 3d
Add gantt diagram to demo page : 20h
Add another diagram to demo page : 48h
</div>
<hr/>
@@ -399,6 +529,7 @@ merge newbranch
<div class="mermaid">
classDiagram
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 "0" *-- "0..n" Class04
Class05 "1" o-- "many" Class06
Class07 .. Class08
@@ -407,17 +538,95 @@ Class09 "0" --* "1..n" C3
Class09 --|> Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class01 : #size()
Class01 : -int chimp
Class01 : +int gorilla
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
size()
}
</div>
<div class="mermaid">
classDiagram
class Class01~T~
Class01 : #size()
Class01 : -int chimp
Class01 : +int gorilla
class Class10~T~ {
&lt;&lt;service&gt;&gt;
int id
size()
}
</div>
<div class="mermaid">
classDiagram
Class01~T~ <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03~T~ "0" *-- "0..n" Class04
Class05 "1" o-- "many" Class06
Class07~T~ .. Class08
Class09 "many" --> "1" C2 : Where am i?
Class09 "0" --* "1..n" C3
Class09 --|> Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : #size()
Class01 : -int chimp
Class01 : +int gorilla
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
size()
}
</div>
<div class="mermaid">
stateDiagram
State1
</div>
<hr>
<div class="mermaid">
stateDiagram
[*] --> First
state First {
[*] --> second
second --> [*]
}
</div>
<div class="mermaid">
stateDiagram
State1: The state with a note
note right of State1
Important information! You can write
notes.
end note
State1 --> State2
note left of State2 : This is the note to the left.
</div>
<div class="mermaid">
stateDiagram
State1
note right of State1
Line1<br>Line2<br/>Line3<br />Line4<br />Line5
end note
</div>
<h1 id="link-clicked">Anchor for "link-clicked" test</h1>
<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
theme: 'forest',
// themeCSS: '.node rect { fill: red; }',
logLevel: 3,
securityLevel: 'loose',
flowchart: { curve: 'basis' },
gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50 },
@@ -439,5 +648,18 @@ Class08 <--> C2: Cool label
}, 100)
}
</script>
<script>
const testLineEndings = (test, input) => {
try {
mermaid.render(test, input, () => {});
} catch (err) {
console.error("Error in %s:\n\n%s", test, err);
}
};
testLineEndings("CR", "graph LR\rsubgraph CR\rA --> B\rend");
testLineEndings("LF", "graph LR\nsubgraph LF\nA --> B\nend");
testLineEndings("CRLF", "graph LR\r\nsubgraph CRLF\r\nA --> B\r\nend");
</script>
</body>
</html>

View File

@@ -1,15 +1,25 @@
[![Build Status](https://travis-ci.org/knsv/mermaid.svg?branch=master)](https://travis-ci.org/knsv/mermaid)
[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid)
[![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master)
[![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# 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.
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.
* **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 enabled
Closed 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.
@@ -31,7 +41,7 @@ Ever wanted to simplify documentation and avoid heavy tools like Visio when expl
This is why mermaid was born, a simple markdown-like script language for generating charts from text via javascript.
**Mermaid was nomiated and won the JS Open Source Awards (2019) in the catory The most existing 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.**
**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
@@ -160,15 +170,15 @@ https://mermaidjs.github.io
# Request for assistance
Things are piling up and I have hard time keeping up. To remedy this
Things are piling up and I have a 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.
with the future development of 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
* 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.
@@ -190,8 +200,9 @@ Don't hesitate to contact me if you want to get involved.
yarn lint
We use [JavaScript Standard Style](https://github.com/feross/standard).
We recommend you installing [editor plugins](https://github.com/feross/standard#are-there-text-editor-plugins) so you can get real time lint result.
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

View File

@@ -10,10 +10,19 @@
- [Flowchart](flowchart.md)
- [Sequence diagram](sequenceDiagram.md)
- [Class Diagram](classDiagram.md)
- [State Diagram](stateDiagram.md)
- [Gantt](gantt.md)
- [Pie Chart](pie.md)
- Guide
- [Development](development.md)
- [mermaidAPI](mermaidAPI.md)
- [Changelog](CHANGELOG.md)
- [Changelog](CHANGELOG.md)
- I'm a n00b
- [overview](n00b-overview.md)
- [Getting started - easier](n00b-gettingStarted.md)
- [Diagram syntax intro](n00b-syntaxReference.md)
- [Advanced usage](n00b-advanced.md)

627
docs/classDiagram.md Normal file
View File

@@ -0,0 +1,627 @@
# Class diagrams
> "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.
Mermaid can render class diagrams.
```
classDiagram
Animal <|-- Duck
Animal <|-- Fish
Animal <|-- Zebra
Animal : +int age
Animal : +String gender
Animal: +isMammal()
Animal: +mate()
class Duck{
+String beakColor
+swim()
+quack()
}
class Fish{
-int sizeInFeet
-canEat()
}
class Zebra{
+bool is_wild
+run()
}
```
```mermaid
classDiagram
Animal <|-- Duck
Animal <|-- Fish
Animal <|-- Zebra
Animal : +int age
Animal : +String gender
Animal: +isMammal()
Animal: +mate()
class Duck{
+String beakColor
+swim()
+quack()
}
class Fish{
-int sizeInFeet
-canEat()
}
class Zebra{
+bool is_wild
+run()
}
```
## Syntax
### Class
UML provides mechanisms to represent class members, such as attributes and methods, and additional information about them.
A single instance of a class in the diagram contains three compartments:
- The top compartment contains the name of the class. It is printed in bold and centered, and the first letter is capitalized. It may also contain optional annotation text describing the nature of the class.
- The middle compartment contains the attributes of the class. They are left-aligned and the first letter is lowercase.
- The bottom compartment contains the operations the class can execute. They are also left-aligned and the first letter is lowercase.
```
classDiagram
class BankAccount
BankAccount : +String owner
BankAccount : +Bigdecimal balance
BankAccount : +deposit(amount)
BankAccount : +withdrawl(amount)
```
```mermaid
classDiagram
class BankAccount
BankAccount : +String owner
BankAccount : +BigDecimal balance
BankAccount : +deposit(amount)
BankAccount : +withdrawl(amount)
```
## Define a class
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.
```
classDiagram
class Animal
Vehicle <|-- Car
```
```mermaid
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.
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.
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 :
- Associate a member of a class using **:** (colon) followed by member name, useful to define one member at a time. For example:
```
class BankAccount
BankAccount : +String owner
BankAccount : +BigDecimal balance
BankAccount : +deposit(amount)
BankAccount : +withdrawal(amount)
```
``` mermaid
classDiagram
class BankAccount
BankAccount : +String owner
BankAccount : +BigDecimal balance
BankAccount : +deposit(amount)
BankAccount : +withdrawl(amount)
```
- 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 owner
+BigDecimal balance
+deposit(amount) bool
+withdrawl(amount)
}
```
```mermaid
classDiagram
class BankAccount{
+String owner
+BigDecimal balance
+deposit(amount) bool
+withdrawl(amount) int
}
```
#### 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:
```
class BankAccount{
+String owner
+BigDecimal balance
+deposit(amount) bool
+withdrawl(amount) int
}
```
```mermaid
classDiagram
class BankAccount{
+String owner
+BigDecimal balance
+deposit(amount) bool
+withdrawl(amount) int
}
```
#### 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
This can be done as part of either class definition method:
```
classDiagram
class Square~Shape~{
int id
List~int~ position
setPoints(List~int~ points)
getPoints() List~int~
}
Square : -List~string~ messages
Square : +setMessages(List~string~ messages)
Square : +getMessages() List~string~
```
```mermaid
classDiagram
class Square~Shape~{
int id
List~int~ position
setPoints(List~int~ points)
getPoints() List~int~
}
Square : -List~string~ messages
Square : +setMessages(List~string~ messages)
Square : +getMessages() List~string~
```
#### Return Type
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:
- `+` Public
- `-` Private
- `#` Protected
- `~` Package/Internal
>_note_ you can also include additional _classifers_ to a method definition by adding the following notations to the end of the method, i.e.: after the `()`:
> - `*` Abstract e.g.: `someAbstractMethod()*`
> - `$` Static e.g.: `someStaticMethod()$`
## Defining Relationship
A relationship is a general term covering the specific types of logical connections found on class and object diagrams.
```
[classA][Arrow][ClassB]:LabelText
```
There are different types of relations defined for classes under UML which are currently supported:
Type | Description
--- | ---
<\|-- | Inheritance
*-- | Composition
o-- | Aggregation
--> | Association
-- | Link (Solid)
..> | Dependency
..\|> | Realization
.. | Link (Dashed)
```
classDiagram
classA <|-- classB
classC *-- classD
classE o-- classF
classG <-- classH
classI -- classJ
classK <.. classL
classM <|.. classN
classO .. classP
```
```mermaid
classDiagram
classA <|-- classB
classC *-- classD
classE o-- classF
classG <-- classH
classI -- classJ
classK <.. classL
classM <|.. classN
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 :
```
classDiagram
classA --|> classB : Inheritance
classC --* classD : Composition
classE --o classF : Aggregation
classG --> classH : Association
classI -- classJ : Link(Solid)
classK ..> classL : Dependency
classM ..|> classN : Realization
classO .. classP : Link(Dashed)
```
```mermaid
classDiagram
classA --|> classB : Inheritance
classC --* classD : Composition
classE --o classF : Aggregation
classG --> classH : Association
classI -- classJ : Link(Solid)
classK ..> classL : Dependency
classM ..|> classN : Realization
classO .. classP : Link(Dashed)
```
## Labels on Relations
It is possible to add a label text to a relation:
```
[classA][Arrow][ClassB]:LabelText
```
```
classDiagram
classA <|-- classB : implements
classC *-- classD : composition
classE o-- classF : association
```
```mermaid
classDiagram
classA <|-- classB : implements
classE o-- classF : association
```
## 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 notations are placed near the ends of an association.
The different cardinality options are :
- `0..1` Zero or one
- `1` Only 1
- `0..1` Zero or One
- `1..*` One or more
- `*` Many
- `n` n {where n>1}
- `0..n` zeor to n {where n>1}
- `1..n` one to n {where n>1}
Cardinality can be easily defined by placing cardinality text within qoutes `"` before(optional) and after(optional) a given arrow.
```
[classA] "cardinality1" [Arrow] "cardinality2" [ClassB]:LabelText
```
```
classDiagram
Customer "1" --> "*" Ticket
Student "1" --> "1..*" Course
Galaxy --> "many" Star : Contains
```
```mermaid
classDiagram
Customer "1" --> "*" Ticket
Student "1" --> "1..*" Course
Galaxy --> "many" Star : Contains
```
## 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:
- `<<Interface>>` To represent an Interface class
- `<<abstract>>` To represent an abstract class
- `<<Service>>` To represent a service class
- `<<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 :
- In a ***separate line*** after a class is defined. For example:
```
classDiagram
class Shape
<<interface>> Shape
```
```mermaid
classDiagram
class Shape
<<interface>> Shape
Shape : noOfVertices
Shape : draw()
```
- In a ***nested structure*** along with class definition. For example:
```
classDiagram
class Shape{
<<interface>>
noOfVertices
draw()
}
class Color{
<<enumeration>>
RED
BLUE
GREEN
WHITE
BLACK
}
```
```mermaid
classDiagram
class Shape{
<<interface>>
noOfVertices
draw()
}
class Color{
<<enumeration>>
RED
BLUE
GREEN
WHITE
BLACK
}
```
## 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
```
classDiagram
%% This whole line is a comment classDiagram class Shape <<interface>>
class Shape{
<<interface>>
noOfVertices
draw()
}
```
## 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'`.
You would define these actions on a separate line after all classes have been declared.
```
action className "reference" "tooltip"
```
* _action_ is either `link` or `callback`, depending on which type of interaction you want to have called
* _className_ is the id of the node that the action will be associated with
* _reference_ is either the url link, or the function name for callback. (note: callback function will be called with the nodeId as parameter).
* (_optional_) tooltip is a string to be displayed when hovering over element (note: The styles of the tooltip are set by the class .mermaidTooltip.)
### Examples:
*URL Link:*
```
classDiagram
class Shape
link Shape "http://www.github.com" "This is a tooltip for a link"
```
*Callback:*
```
classDiagram
class Shape
callback Shape "callbackFunction" "This is a tooltip for a callback"
```
```
<script>
var callbackFunction = function(){
alert('A callback was triggered');
}
<script>
```
```mermaid
classDiagram
class Class01
class Class02
callback Class01 "callbackFunction" "Callback tooltip"
link Class02 "http://www.github.com" "This is a link"
```
> **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:
```
<body>
<div class="mermaid">
classDiagram
Animal <|-- Duck
Animal <|-- Fish
Animal <|-- Zebra
Animal : +int age
Animal : +String gender
Animal: +isMammal()
Animal: +mate()
class Duck{
+String beakColor
+swim()
+quack()
}
class Fish{
-int sizeInFeet
-canEat()
}
class Zebra{
+bool is_wild
+run()
}
callback Duck callback "Tooltip"
click Zebra "http://www.github.com" "This is a link"
</div>
<script>
var callback = function(){
alert('A callback was triggered');
}
var config = {
startOnLoad:true,
securityLevel:'loose',
};
mermaid.initialize(config);
</script>
</body>
```
## Styling
Styling of the class diagram is done by defining a number of css classes. During rendering these classes are extracted from the file located at src/themes/class.scss
### Styling Classes used
Class | Description
--- | ---
g.classGroup text | Styles for general class text
classGroup .title | Styles for general class title
g.classGroup rect | Styles for class diagram rectangle
g.classGroup line | Styles for class diagram line
.classLabel .box | Styles for class label box
.classLabel .label | Styles for class label text
composition | Styles for componsition arrow head and arrow line
aggregation | Styles for aggregation arrow head and arrow line(dashed or solid)
dependency | Styles for dependency arrow head and arrow line
### Sample stylesheet
```css
body {
background: white;
}
g.classGroup text {
fill: $nodeBorder;
stroke: none;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family);
font-size: 10px;
.title {
font-weight: bolder;
}
}
g.classGroup rect {
fill: $nodeBkg;
stroke: $nodeBorder;
}
g.classGroup line {
stroke: $nodeBorder;
stroke-width: 1;
}
.classLabel .box {
stroke: none;
stroke-width: 0;
fill: $nodeBkg;
opacity: 0.5;
}
.classLabel .label {
fill: $nodeBorder;
font-size: 10px;
}
.relation {
stroke: $nodeBorder;
stroke-width: 1;
fill: none;
}
@mixin composition {
fill: $nodeBorder;
stroke: $nodeBorder;
stroke-width: 1;
}
#compositionStart {
@include composition;
}
#compositionEnd {
@include composition;
}
@mixin aggregation {
fill: $nodeBkg;
stroke: $nodeBorder;
stroke-width: 1;
}
#aggregationStart {
@include aggregation;
}
#aggregationEnd {
@include aggregation;
}
#dependencyStart {
@include composition;
}
#dependencyEnd {
@include composition;
}
#extensionStart {
@include composition;
}
#extensionEnd {
@include composition;
}
```
## Configuration
`Coming soon`

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
```

View File

@@ -4,7 +4,7 @@
This statement declares a new graph and the direction of the graph layout.
This declares a graph oriented from top to bottom.
This declares a graph oriented from top to bottom (`TD` or `TB`).
```
graph TD
@@ -15,7 +15,16 @@ graph TD
Start --> Stop
```
This declares a graph oriented from left to right.
This declares a graph oriented from left to right (`LR`).
```
graph LR
Start --> Stop
```
```mermaid
graph LR
Start --> Stop
```
Possible directions are:
@@ -26,14 +35,6 @@ Possible directions are:
* TD - same as TB
```
graph LR
Start --> Stop
```
```mermaid
graph LR
Start --> Stop
```
## Nodes & shapes
@@ -77,6 +78,28 @@ graph LR
id1(This is the text in the box)
```
### A stadium-shaped node
```
graph LR
id1([This is the text in the box])
```
```mermaid
graph LR
id1([This is the text in the box])
```
### A node in a cylindrical shape
```
graph LR
id1[(Database)]
```
```mermaid
graph LR
id1[(Database)]
```
### A node in the form of a circle
```
@@ -111,14 +134,55 @@ graph LR
id1{This is the text in the box}
```
### A hexagon node
```
graph LR
id1{{This is the text in the box}}
```
```mermaid
graph LR
id1{{This is the text in the box}}
```
### Parallelogram
```
graph TD
id1[/This is the text in the box/]
```
```mermaid
graph TD
id1[/This is the text in the box/]
```
### Parallelogram alt
```
graph TD
id1[\This is the text in the box\]
```
```mermaid
graph TD
id1[\This is the text in the box\]
```
### Trapezoid
```
graph TD
A[/Christmas\]
```
```mermaid
graph TD
A[/Christmas\]
```
### Trapezoid alt
```
graph TD
B[\Go shopping/]
```
```mermaid
graph TD
B[\Go shopping/]
@@ -238,6 +302,50 @@ graph LR
A == text ==> B
```
### Chaining of links
It is possible declare many links in the same line as per below:
```
graph LR
A -- text --> B -- text2 --> C
```
```mermaid
graph LR
A -- text --> B -- text2 --> C
```
It is also possible to declare multiple nodes links in the same line as per below:
```
graph LR
a --> b & c--> d
```
```mermaid
graph LR
a --> b & c--> d
```
You can then describe dependencies in a very expressive way. Like the onliner below:
```
graph TB
A & B--> C & D
```
```mermaid
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 to much and not to little.
This goes for expressive syntaxes as well.
```
graph TB
A --> C
A --> D
B --> C
B --> D
```
## 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:
@@ -349,7 +457,7 @@ Beginners tip, a full example using interactive links in a html context:
click A callback "Tooltip"
click B "http://www.github.com" "This is a link"
</div>
<script>
var callback = function(){
alert('A callback was triggered');
@@ -363,12 +471,22 @@ Beginners tip, a full example using interactive links in a html context:
},
securityLevel:'loose',
};
mermaid.initialize(config);
</script>
</body>
```
### 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
```
graph LR
%% this is a comment A -- text --> B{node}
A -- text --> B -- text2 --> C
```
## Styling and classes
### Styling links
@@ -379,7 +497,7 @@ Instead of ids, the order number of when the link was defined in the graph is us
defined in the linkStyle statement will belong to the fourth link in the graph:
```
linkStyle 3 stroke:#ff3,stroke-width:4px;
linkStyle 3 stroke:#ff3,stroke-width:4px,color:red;
```
@@ -391,13 +509,13 @@ It is possible to apply specific styles such as a thicker border or a different
graph LR
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#ccf,stroke:#f66,stroke-width:2px,stroke-dasharray: 5, 5
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5, 5
```
```mermaid
graph LR
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#ccf,stroke:#f66,stroke-width:2px,stroke-dasharray: 5, 5
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5, 5
```
@@ -425,6 +543,19 @@ It is also possible to attach a class to a list of 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:
```
graph LR
A:::someclass --> B
classDef someclass fill:#f96;
```
```mermaid
graph LR
A:::someclass --> B
classDef someclass fill:#f96;
```
### Css classes

View File

@@ -26,8 +26,6 @@ gantt
Task in sec :2014-01-12 , 12d
another task : 24d
```
## Syntax
```
@@ -89,6 +87,20 @@ gantt
Add another diagram to demo page :48h
```
It is possible to set multiple depenendenies separated by space:
```
gantt
apple :a, 2017-07-20, 1w
banana :crit, b, 2017-07-23, 1d
cherry :active, c, after b a, 1d
```
```
gantt
apple :a, 2017-07-20, 1w
banana :crit, b, 2017-07-23, 1d
cherry :active, c, after b a, 1d
```
### Title
Tbd
@@ -106,7 +118,11 @@ Tbd
### Date format
Tbd
The default date format is YYYY-MM-DD. You can define your ``dateFormat``. For example:
```
dateFormat YYYY MM DD
```
### Diagram definition
@@ -171,6 +187,23 @@ More info in: http://momentjs.com/docs/#/parsing/string-format/
More info in: https://github.com/mbostock/d3/wiki/Time-Formatting
## Comments
Comments can be entered within a gantt chart, 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
```
gantt
title A Gantt Diagram
%% this is a comment
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
```
## Styling
@@ -269,3 +302,48 @@ Param | Descriotion | Default value
--- | --- | ---
mirrorActor|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 unwantewd clipping which is why this config param exists.|1
## Interaction
It is possible to bind a click event to a task, the click can lead to either a javascript callback or to a link which will be opened in the current browser tab. **Note**: This functionality is disabled when using `securityLevel='strict'` and enabled when using `securityLevel='loose'`.
```
click taskId call callback(arguments)
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:
```
<body>
<div class="mermaid">
gantt
dateFormat YYYY-MM-DD
section Clickable
Visit mermaidjs :active, cl1, 2014-01-07, 3d
Print arguments :cl2, after cl1, 3d
Print task :cl3, after cl2, 3d
click cl1 href "https://mermaidjs.github.io/"
click cl2 call printArguments("test1", "test2", test3)
click cl3 call printTask()
</div>
<script>
var printArguments = function(arg1, arg2, arg3) {
alert('printArguments called with arguments: ' + arg1 + ', ' + arg2 + ', ' + arg3);
}
var printTask = function(taskId) {
alert('taskId: ' + taskId);
}
var config = {
startOnLoad:true,
securityLevel:'loose',
};
mermaid.initialize(config);
</script>
</body>
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
docs/img/n00b-firstFlow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@@ -7,8 +7,20 @@
<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/dist/mermaid.min.js"></script> -->
<script src="//localhost:9000/mermaid.js"></script>
<script src="//cdn.jsdelivr.net/npm/mermaid@8.4.7/dist/mermaid.min.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-153180559-1', 'auto');
if(location) {
ga('send', 'pageview', location.hash);
}
</script>
<style>
.markdown-section {
max-width: 1200px;
@@ -43,8 +55,18 @@
var num = 0;
mermaid.initialize({ logLevel:0, startOnLoad: false, themeCSS:'.label { font-family: Source Sans Pro,Helvetica Neue,Arial,sans-serif; }' });
</script>
<script>
window.onhashchange = function(a) {
//code
if(location) {
ga('send', 'pageview', location.hash);
}
}
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script>
<scrpt src="//unpkg.com/docsify/lib/plugins/ga.min.js"></scrpt>
</body>
</html>
<!-- -->

View File

@@ -19,7 +19,7 @@ These are the default options which can be overridden with the initialization ca
<pre>
mermaid.initialize({
flowchart:{
htmlLabels: false
htmlLabels: false
}
});
</pre>
@@ -27,7 +27,7 @@ mermaid.initialize({
**Example 2:**
<pre>
<script>
&lt;script>
var config = {
startOnLoad:true,
flowchart:{
@@ -39,10 +39,10 @@ mermaid.initialize({
securityLevel:'loose',
};
mermaid.initialize(config);
</script>
&lt;/script>
</pre>
A summary of all options and their defaults is found [here](https://github.com/knsv/mermaid/blob/master/docs/mermaidAPI.md#mermaidapi-configuration-defaults). A description of each option follows below.
A summary of all options and their defaults is found [here][2]. A description of each option follows below.
## theme
@@ -63,6 +63,10 @@ theme , the CSS style sheet
"themeCSS": ".node rect { fill: red; }"
</pre>
## fontFamily
**fontFamily** The font to be used for the rendered diagrams. Default value is \\"trebuchet ms\\", verdana, arial;
## logLevel
This option decides the amount of logging to be used.
@@ -101,6 +105,18 @@ Flag for setting whether or not a html tag should be used for rendering labels
on the edges.
**Default value true**.
### nodeSpacing
Defines the spacing between nodes on the same level (meaning horizontal spacing for
TB or BT graphs, and the vertical spacing for LR as well as RL graphs).
**Default value 50**.
### rankSpacing
Defines the spacing between nodes on different levels (meaning vertical spacing for
TB or BT graphs, and the horizontal spacing for LR as well as RL graphs).
**Default value 50**.
### curve
How mermaid renders curves for flowcharts. Possible values are
@@ -259,11 +275,12 @@ mermaidAPI.initialize({
### Parameters
- `id` the id of the element to be rendered
- `txt` the graph definition
- `_txt`
- `cb` callback which is called after rendering is finished with the svg code as inparam.
- `container` 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.
- `txt` the graph definition
##
@@ -271,7 +288,7 @@ mermaidAPI.initialize({
<pre>
<script>
&lt;script>
var config = {
theme:'default',
logLevel:'fatal',
@@ -313,8 +330,9 @@ mermaidAPI.initialize({
}
};
mermaid.initialize(config);
</script>
&lt;/script>
</pre>
[1]: https://github.com/knsv/mermaid/blob/master/docs/mermaidAPI.md#render
[2]: https://github.com/knsv/mermaid/blob/master/docs/mermaidAPI.md#mermaidapi-configuration-defaults

21
docs/n00b-advanced.md Normal file
View File

@@ -0,0 +1,21 @@
# Advanced n00b mermaid (Coming soon..)
## splitting mermaid code from html
A more condensed html code can be achieved by embedding the mermaid code in its own .js file, which is referenced like so:
```
stuff stuff
</div>
</body>
</html>
```
The actual mermaid file could for example look like this:
```
mermaid content...
```
---
## mermaid configuration options
...

154
docs/n00b-gettingStarted.md Normal file
View File

@@ -0,0 +1,154 @@
# A more basic getting started
Writing mermaid code is simple.
But how is the code turned into a diagram in a web page? To do this we need a mermaid renderer.
Thankfully the mermaid renderer is very accessible, in essence it is a javascript.
The requirement is on the part of the web browser. Modern web browsers, such as Firefox, Chrome and Safari, can render mermaid. But Internet Explorer cannot. The web browser also needs access to the online mermaid renderer which it downloads from https://cdn.jsdelivr.net/npm/mermaid
For an easy introduction, here follows three practical examples using:
1. an online mermaid editor
2. a mermaid plugin
3. a generic web server of your choosing
Following either of these examples, you can get started with converting your own mermaid code into web diagrams.
## the mermaid live editor
The quickest way to get started with mermaid is to visit [The mermaid live editor](https://mermaidjs.github.io/mermaid-live-editor).
In the `Code` section one can write or edit raw mermaid code, and instantly `Preview` the rendered result.
This is a great way to get started.
It is also the easiest way to develop diagrams, the code of which can be pasted straight into documentation.
![Flowchart](./img/n00b-liveEditor.png)
The `Mermaid configuration` is for controlling mermaid behaviour. An easy introduction to mermaid configuration is found in the [Advanced usage](n00b-advanced.md) section. A complete configuration reference cataloguing default values is found on the [mermaidAPI](mermaidAPI.md) page.
## mermaid using plugins
Thanks to the growing popularity of mermaid, many plugins already exist which incorporate a mermaid renderer.
One example is the [Atlassian Confluence mermaid plugin](https://marketplace.atlassian.com/apps/1214124/mermaid-plugin-for-confluence?hosting=server&tab=overview)
When the mermaid plugin is installed on a Confluence server, one can insert a mermaid object into any Confluence page.
---
- In a Confluence page, Add Other macros.
![Flowchart](./img/n00b-Confluence1.png)
---
- Search for mermaid.
![Flowchart](./img/n00b-Confluence2.png)
---
- The mermaid object appears. Paste your mermaid code into it.
![Flowchart](./img/n00b-Confluence3.png)
---
- Save the page and the diagram appears.
![Flowchart](./img/n00b-Confluence4.png)
---
## mermaid using any web server (or just a browser)
This example can be used with any common web server. Apache, IIS, nginx, node express [...], you pick your favourite.
We do not need to install anything on the server, apart from a normal file of html to be reached by a web browser (such as Firefox, Chrome, Safari, but not Internet Explorer). So if you want to really simplify things when testing this out, don't use a web server at all but just create the file locally and drag it into your browser window. It is the browser which does all the work of rendering mermaid!
Through the html file, we give the web browser three instructions inside the html code it retrieves:
1. a reference for fetching the online mermaid renderer, the renderer is just a javascript.
2. the mermaid code we want to diagram.
3. the `mermaid.initialize()` command to start the rendering process
All this is done in the html `<body>` section of the web page.
This is what needs to go into the html file:
1. The reference to the mermaid renderer is done in a `<script src>` tag like so:
```
<body>
<script src="https://cdn.jsdelivr.net/npm/mermaid@8.4.0/dist/mermaid.min.js"></script>
</body>
```
2. The embedded mermaid code is similarly placed in a `<div>` tag:
```
<body>
Here is a mermaid diagram:
<div class="mermaid">
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server01]
B --> D[Server02]
</div>
</body>
```
3. When initializing mermaid using `mermaid.initialize()`, mermaid takes all the `<div class="mermaid">` tags it can find in the html body and starts to render them one by one. This is done like so:
```
<body>
<script>mermaid.initialize({startOnLoad:true});</script>
</body>
```
*Finally*
4. Putting the three steps together is as simple as:
```
<html>
<body>
<script src="https://cdn.jsdelivr.net/npm/mermaid@8.4.0/dist/mermaid.min.js"></script>
<script>mermaid.initialize({startOnLoad:true});</script>
Here is one mermaid diagram:
<div class="mermaid">
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server1]
B --> D[Server2]
</div>
And here is another:
<div class="mermaid">
graph TD
A[Client] -->|tcp_123| B(Load Balancer)
B -->|tcp_456| C[Server1]
B -->|tcp_456| D[Server2]
</div>
</body>
</html>
```
Save this to a html file and fetch it with a browser from the web server (or just drag it into your web browser window) and voila!
---
**Three additional comments from Knut Sveidqvist, creator of mermaid:**
- In early versions of mermaid, the `<script src>` tag was invoked in the `<head>` part of the web page. Nowdays we can place it directly in `<body>` as seen above. However, older parts of the documentation frequently reflects the previous way which still works.
- We initialize the mermaid rendering with `mermaid.initialize()` directly in the html code. In principle this could be done through placing `mermaid.initialize()` inside of `mermaid.min.js`. We would then eliminate the need for this explicit line in the html. However, there are use cases where we do want to separate the two steps. Sometimes we want full control over when we start looking for `<div>`tags inside the web page with `mermaid.initialize()`, for example when we think that all `<div>` tags may not have been loaded by the time `mermaid.min.js` runs.
- In the example above, `mermaid.min.js` is called using an absolute path. Even worse, the example includes the mermaid version number which of course will change as time goes by. However, the example makes it easy to understand what is going on - even though it is perhaps doomed in a way we do not want in a production environment. When going from testing mermaid out to getting serious with it, I would suggest one of the following approaches for calling `mermaid.min.js`:
1. If you do not enter a specific version, you automatically get the latest one.
2. If you really need a specific version, hard code it (this is rare but it happens).
3. If you need to know the current mermaid version, replace a mermaid code block with the word `info` and the version will be returned like [this](https://mermaid-js.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiaW5mb1xuXG4iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ==)

27
docs/n00b-overview.md Normal file
View File

@@ -0,0 +1,27 @@
# Overview for n00bs
As a sysadmin I frequently have to document things, including drawing stuff.
Using mermaid, I can type this as a comment in a script:
```
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server01]
B --> D[Server02]
```
And end up with this in the documentation:
![Flowchart](./img/n00b-firstFlow.png)
Most of the stuff I need to visualize can be scripted in a similar way, with a varitety of different symbols and chart types available. Since the diagram source is text based, it can be part of production scripts (and other pieces of code). So less time needs be spent on documenting as a separate task.
Comparing with Visio and similar applications, mermaid is a really fast way to create good visualizations. This is especially apparent when editing a complex visualisation, this could take me hours in a desktop application but takes minutes (or even less if generation has been scripted) with mermaid.
With mermaid I can spend a fraction of the time I normally would spend, and instead automate the diagram generation and end up saving even more time. I love it!
However, a lot of the mermaid documentation is geared to professional frontend developers, presuming a skill set which I simply do not have.
I needed a really basic instruction. And here it is.

View File

@@ -0,0 +1,11 @@
## Diagram syntax reference
Having already [gotten started](n00b-gettingStarted.md), existing diagram syntax documentation was easy enough to follow even for a n00b like me..
- [Flowchart](flowchart.md)
- [Sequence diagram](sequenceDiagram.md)
- [Class Diagram](classDiagram.md)
- [State Diagram](stateDiagram.md)
- [Gantt](gantt.md)
- [Pie Chart](pie.md)

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

@@ -271,11 +271,57 @@ sequenceDiagram
```
## 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
```
sequenceDiagram
Alice->>John: Hello John, how are you?
%% this is a comment
John-->>Alice: Great!
```
## sequenceNumbers
It is possiebl 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:
```
<script>
mermaid.initialize({
sequence: { showSequenceNumbers: true },
});
</script>
```
It can also be be turned on via the diagram code as in the diagram:
```
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!
```
```mermaid
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!
```
## Styling
Styling of the a sequence diagram is done by defining a number of css classes. During rendering these classes are extracted from the
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
@@ -405,5 +451,5 @@ mermaid.sequenceConfig = {
Param | Description | Default value
--- | --- | ---
mirrorActor | 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 unwantewd clipping which is why this config param exists. | 1
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

342
docs/stateDiagram.md Executable file
View File

@@ -0,0 +1,342 @@
# State diagrams
> "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.
```markdown
stateDiagram
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
```
```mermaid
stateDiagram
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
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 is a state description" as s2
```
```mermaid
stateDiagram
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 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, "\-\-\>".
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
```
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
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 --> [*]
```
## 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 composite states in this terminology.
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 {
[*] --> second
second --> [*]
}
```
```mermaid
stateDiagram
[*] --> First
state First {
[*] --> second
second --> [*]
}
```
You can do this in several layers:
```markdown
stateDiagram
[*] --> First
state First {
[*] --> Second
state Second {
[*] --> second
second --> Third
state Third {
[*] --> third
third --> [*]
}
}
}
```
```mermaid
stateDiagram
[*] --> First
state First {
[*] --> Second
state Second {
[*] --> second
second --> Third
state Third {
[*] --> third
third --> [*]
}
}
}
```
You can also define transitions also between composite states:
```markdown
stateDiagram
[*] --> First
First --> Second
First --> Third
state First {
[*] --> fir
fir --> [*]
}
state Second {
[*] --> sec
sec --> [*]
}
state Third {
[*] --> thi
thi --> [*]
}
```
```mermaid
stateDiagram
[*] --> First
First --> Second
First --> Third
state First {
[*] --> fir
fir --> [*]
}
state Second {
[*] --> sec
sec --> [*]
}
state Third {
[*] --> thi
thi --> [*]
}
```
*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
fork_state --> State2
fork_state --> State3
state join_state <<join>>
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
```
```mermaid
stateDiagram
state fork_state <<fork>>
[*] --> fork_state
fork_state --> State2
fork_state --> State3
state join_state <<join>>
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
```
## Notes
Sometimes nothing says it better then a Post-it note. That is also the case in state diagrams.
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
Important information! You can write
notes.
end note
State1 --> State2
note left of State2 : This is the note to the left.
```
```mermaid
stateDiagram
State1: The state with a note
note right of State1
Important information! You can write
notes.
end note
State1 --> State2
note left of State2 : This is the note to the left.
```
## Concurrency
As in plantUml you can specify concurrency using the -- symbol.
```markdown
stateDiagram
[*] --> Active
state Active {
[*] --> NumLockOff
NumLockOff --> NumLockOn : EvNumLockPressed
NumLockOn --> NumLockOff : EvNumLockPressed
--
[*] --> CapsLockOff
CapsLockOff --> CapsLockOn : EvCapsLockPressed
CapsLockOn --> CapsLockOff : EvCapsLockPressed
--
[*] --> ScrollLockOff
ScrollLockOff --> ScrollLockOn : EvCapsLockPressed
ScrollLockOn --> ScrollLockOff : EvCapsLockPressed
}
```
```mermaid
stateDiagram
[*] --> Active
state Active {
[*] --> NumLockOff
NumLockOff --> NumLockOn : EvNumLockPressed
NumLockOn --> NumLockOff : EvNumLockPressed
--
[*] --> CapsLockOff
CapsLockOff --> CapsLockOn : EvCapsLockPressed
CapsLockOn --> CapsLockOff : EvCapsLockPressed
--
[*] --> ScrollLockOff
ScrollLockOff --> ScrollLockOn : EvCapsLockPressed
ScrollLockOn --> ScrollLockOff : EvCapsLockPressed
}
```
## Comments
Comments can be entered within a state diagram chart, 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
```
stateDiagram
[*] --> Still
Still --> [*]
%% this is a comment
Still --> Moving
Moving --> Still %% another comment
Moving --> Crash
Crash --> [*]
```
## 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

View File

@@ -12,7 +12,7 @@ yarn add mermaid
https://unpkg.com/mermaid/
Please note that you can switch versions through the dropdown box on top right.
Please note that you can switch versions through the dropdown box at the top right.
## Simple usage on a web page
@@ -21,8 +21,8 @@ The easiest way to integrate mermaid on a web page requires two elements:
1. Inclusion of the mermaid framework in the html page using a script tag
2. A graph definition on the web page
If these things are in place mermaid listens to the page load event and when fires, when the page has loaded, it will
locate the graphs n the page and transform them to svg files.
If these things are in place mermaid listens to the page load event and when fired (when the page has loaded) it will
locate the graphs on the page and transform them to svg files.
### Include mermaid on your web page:
@@ -32,7 +32,7 @@ locate the graphs n the page and transform them to svg files.
```
Further down on your page mermaid will look for tags with `class="mermaid"`. From these tags mermaid will try to
read the chart definiton which will be replaced with the svg chart.
read the chart definiton and replace it with the svg chart.
### Define a chart like this:
@@ -53,18 +53,18 @@ Would end up like this:
</div>
```
An id is also added to mermaid tags without id.
An id attribute is also added to mermaid tags without one.
### To enable click event and tags in nodes
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.
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.
* **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 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.
⚠️ **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 resposibility for the diagram source security you can set the securityLevel accordingly. By doing this clicks and tags are again allowed.
If your application is taking resposibility for the diagram source security you can set the `securityLevel` accordingly. By doing this clicks and tags are again allowed.
```javascript
mermaidAPI.initialize({
@@ -79,7 +79,6 @@ If your application is taking resposibility for the diagram source security you
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="mermaid.min.css">
</head>
<body>
<div class="mermaid">
@@ -97,7 +96,7 @@ If your application is taking resposibility for the diagram source security you
### Labels out of bounds
If you use dynamically loaded fonts that are loaded through CSS, such as Google fonts, mermaid should wait for the
whole page to have been loaded (dom + assets, particularly the fonts file).
whole page to load (dom + assets, particularly the fonts file).
```javascript
$(document).load(function() {
@@ -113,7 +112,7 @@ $(document).ready(function() {
});
```
Not doing so will most likely result in mermaid rendering graphs that have labels out of bounds. The default integration in mermaid uses the window.load event to start rendering. Also note that when rendering the width of lebale sare calucated of what width it bening meassured at the time.
Not doing so will most likely result in mermaid rendering graphs that have labels out of bounds. The default integration in mermaid uses the window.load event to start rendering.
If your page has other fonts in its body those might be used instead of the mermaid font. Specifying the font in your styling is a workaround for this.
```
@@ -131,7 +130,7 @@ finer-grained control of this behavior, you can call `init` yourself with:
- a configuration object
- some nodes, as
- a node
- an a array-like of nodes
- an array-like of nodes
- or W3C selector that will find your nodes
Example:
@@ -146,7 +145,7 @@ Or with no config object, and a jQuery selection:
mermaid.init(undefined, $("#someId .yetAnotherClass"));
```
> **Warning** This type of integration is deprecated instead the preferred way of handling more complex integration is to us the mermaidAPI instead.
> **Warning** This type of integration is deprecated. Instead the preferred way of handling more complex integration is to use the mermaidAPI instead.
## Usage with webpack
@@ -156,18 +155,17 @@ mermaid fully supports webpack. Here is a [working demo](https://github.com/merm
## API usage
The main idea with the API is to be able to call a render function with graph defintion as a string. The render function
The main idea of the API is to be able to call a render function with the graph defintion as a string. The render function
will render the graph and call a callback with the resulting svg code. With this approach it is up to the site creator to
fetch the graph definition from the site, perhaps from a textarea, render it and place the graph somewhere in the site.
fetch the graph definition from the site (perhaps from a textarea), render it and place the graph somewhere in the site.
To do this, include mermaidAPI on your web website instead of mermaid.js. The example below show an outline of how this
could be used. The example just logs the resulting svg to the javascript console.
The example below show an outline of how this could be used. The example just logs the resulting svg to the javascript console.
```html
<script src="mermaidAPI.js"></script>
<script src="mermaid.js"></script>
<script>
mermaidAPI.initialize({
mermaid.mermaidAPI.initialize({
startOnLoad:false
});
$(function(){
@@ -179,7 +177,7 @@ could be used. The example just logs the resulting svg to the javascript console
};
var graphDefinition = 'graph TB\na-->b';
var graph = mermaidAPI.render('graphDiv', graphDefinition, insertSvg);
var graph = mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg);
});
</script>
```
@@ -211,8 +209,8 @@ mermaidAPI.render(id,txt,insertSvg, element);
1. The graph is generated using the render call.
2. After generation the render function calls the provided callback function, in this case it's called insertSvg.
3. The callback function is called with two parameters, the svg code of the generated graph and a function. This function binds events to the svg **after** it is inserted into the DOM.
4. Insert the svg code into the DOM for presentation
5. Call the binding function that binds the events
4. Insert the svg code into the DOM for presentation.
5. Call the binding function that binds the events.
## Example of a marked renderer
@@ -231,7 +229,7 @@ renderer.code = function (code, language) {
};
```
Another example in coffeescript that also includes the mermaid script tag into the generated markup.
Another example in coffeescript that also includes the mermaid script tag in the generated markup.
```CoffeeScript
marked = require 'marked'
@@ -259,7 +257,7 @@ module.exports = (options) ->
**Error handling**
When the parser encounters invalid syntax the **mermaid.parseError** function is called. It is possible to override this
function in order to handle the error in an application specific way.
function in order to handle the error in an application-specific way.
**Parsing text without rendering**
@@ -296,13 +294,13 @@ setting the options in mermaid.
3. *using the global mermaid_config object* - deprecated
4. Instantiation of the configuration using the **mermaid.init** call
The list above has two ways to many of doing this. Three are deprecated and will eventually be removed. The list of
The list above has two ways too many of doing this. Three are deprecated and will eventually be removed. The list of
configuration objects are described [in the mermaidAPI documentation](mermaidAPI.html).
## Using the `mermaidAPI.initialize`/`mermaid.initialize` call
The future proof way of setting the configuration is by using the initialization call to mermaid or mermaidAPi depending
The future proof way of setting the configuration is by using the initialization call to mermaid or mermaidAPI depending
on what kind of integration you use.
```html
@@ -334,11 +332,11 @@ approach are:
mermaid.startOnLoad = true;
```
> **Warning** This way of setting the configuration is deprecated instead the preferred way of is to use the initialize method. This functionality is only kept for not breaking existing integrations
> **Warning** This way of setting the configuration is deprecated. Instead the preferred way is to use the initialize method. This functionality is only kept for backwards compatibility.
## Using the mermaid_config
Is it possible to set some configuration via the mermaid object. The two parameters that are supported using this
It is possible to set some configuration via the mermaid object. The two parameters that are supported using this
approach are:
* mermaid_config.startOnLoad
@@ -348,7 +346,7 @@ approach are:
mermaid_config.startOnLoad = true;
```
> **Warning** This way of setting the configuration is deprecated instead the preferred way of is to use the initialize method. This functionality is only kept for not breaking existing integrations
> **Warning** This way of setting the configuration is deprecated. Instead the preferred way is to use the initialize method. This functionality is only kept for backwards compatibility.
## Using the mermaid.init call
@@ -362,4 +360,4 @@ approach are:
mermaid_config.startOnLoad = true;
```
> **Warning** This way of setting the configuration is deprecated instead the preferred way of is to use the initialize method. This functionality is only kept for not breaking existing integrations
> **Warning** This way of setting the configuration is deprecated. Instead the preferred way is to use the initialize method. This functionality is only kept for backwards compatibility.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 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: 69 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -1,6 +1,6 @@
{
"name": "mermaid",
"version": "8.3.0",
"version": "8.4.7",
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"main": "dist/mermaid.core.js",
"keywords": [
@@ -24,9 +24,9 @@
"e2e": "start-server-and-test dev http://localhost:9000/ cypress",
"e2e-upd": "yarn lint && jest e2e -u --config e2e/jest.config.js",
"dev": "webpack-dev-server --config webpack.config.e2e.js",
"test": "yarn lint && jest src",
"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": {
@@ -47,46 +47,45 @@
},
"dependencies": {
"@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": "^0.8.4",
"dagre-d3": "^0.6.4",
"graphlib": "^2.1.7",
"he": "^1.2.0",
"lodash": "^4.17.11",
"minify": "^4.1.1",
"moment-mini": "^2.22.1",
"prettier": "^1.18.2",
"scope-css": "^1.2.1"
},
"devDependencies": {
"documentation": "^12.0.1",
"eslint": "^6.3.0",
"eslint-config-prettier": "^6.3.0",
"eslint-plugin-prettier": "^3.1.0",
"@babel/core": "^7.2.2",
"@babel/preset-env": "^7.2.0",
"@babel/preset-env": "^7.8.4",
"@babel/register": "^7.0.0",
"@percy/cypress": "^2.0.1",
"@percy/cypress": "*",
"babel-core": "7.0.0-bridge.0",
"babel-jest": "^23.6.0",
"babel-jest": "^24.9.0",
"babel-loader": "^8.0.4",
"coveralls": "^3.0.2",
"css-loader": "^2.0.1",
"css-to-string-loader": "^0.1.3",
"cypress": "3.4.0",
"cypress": "4.0.1",
"documentation": "^12.0.1",
"eslint": "^6.3.0",
"eslint-config-prettier": "^6.3.0",
"eslint-plugin-prettier": "^3.1.0",
"husky": "^1.2.1",
"identity-obj-proxy": "^3.0.0",
"jest": "^23.6.0",
"jest-environment-puppeteer": "^4.2.0",
"jest-image-snapshot": "^2.8.2",
"jest-puppeteer": "^4.2.0",
"jest": "^24.9.0",
"jison": "^0.4.18",
"moment": "^2.23.0",
"node-sass": "^4.11.0",
"node-sass": "^4.12.0",
"prettier": "^1.18.2",
"puppeteer": "^1.17.0",
"sass-loader": "^7.1.0",
"start-server-and-test": "^1.10.0",
"webpack": "^4.27.1",
"start-server-and-test": "^1.10.6",
"terser-webpack-plugin": "^2.2.2",
"webpack": "^4.41.2",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.4.1",
"webpack-node-externals": "^1.7.2",

View File

@@ -25,3 +25,12 @@ export const setConfig = conf => {
setConf(conf);
};
export const getConfig = () => config;
const configApi = {
setConfig,
getConfig
// get conf() {
// return config;
// }
};
export default configApi;

View File

@@ -1,28 +1,72 @@
import * as d3 from 'd3';
import { logger } from '../../logger';
import { getConfig } from '../../config';
import utils from '../../utils';
const MERMAID_DOM_ID_PREFIX = 'classid-';
const config = getConfig();
let relations = [];
let classes = {};
let classCounter = 0;
let funs = [];
const splitClassNameAndType = function(id) {
let genericType = '';
let className = id;
if (id.indexOf('~') > 0) {
let split = id.split('~');
className = split[0];
genericType = split[1];
}
return { className: className, type: genericType };
};
/**
* Function called by parser when a node definition has been found.
* @param id
* @param text
* @param type
* @param style
* @public
*/
export const addClass = function(id) {
if (typeof classes[id] === 'undefined') {
classes[id] = {
id: id,
methods: [],
members: []
};
let classId = splitClassNameAndType(id);
// Only add class if not exists
if (typeof classes[classId.className] !== 'undefined') return;
classes[classId.className] = {
id: classId.className,
type: classId.type,
cssClasses: [],
methods: [],
members: [],
annotations: [],
domId: MERMAID_DOM_ID_PREFIX + classId.className + '-' + classCounter
};
classCounter++;
};
/**
* Function to lookup domId from id in the graph definition.
* @param id
* @public
*/
export const lookUpDomId = function(id) {
const classKeys = Object.keys(classes);
for (let i = 0; i < classKeys.length; i++) {
if (classes[classKeys[i]].id === id) {
return classes[classKeys[i]].domId;
}
}
};
export const clear = function() {
relations = [];
classes = {};
funs = [];
funs.push(setupToolTips);
};
export const getClass = function(id) {
@@ -40,34 +84,153 @@ export const addRelation = function(relation) {
logger.debug('Adding relation: ' + JSON.stringify(relation));
addClass(relation.id1);
addClass(relation.id2);
relation.id1 = splitClassNameAndType(relation.id1).className;
relation.id2 = splitClassNameAndType(relation.id2).className;
relations.push(relation);
};
/**
* Adds an annotation to the specified class
* Annotations mark special properties of the given type (like 'interface' or 'service')
* @param className The class name
* @param annotation The name of the annotation without any brackets
* @public
*/
export const addAnnotation = function(className, annotation) {
const validatedClassName = splitClassNameAndType(className).className;
classes[validatedClassName].annotations.push(annotation);
};
/**
* Adds a member to the specified class
* @param className The class name
* @param member The full name of the member.
* If the member is enclosed in <<brackets>> it is treated as an annotation
* If the member is ending with a closing bracket ) it is treated as a method
* Otherwise the member will be treated as a normal property
* @public
*/
export const addMember = function(className, member) {
const theClass = classes[className];
const validatedClassName = splitClassNameAndType(className).className;
const theClass = classes[validatedClassName];
if (typeof member === 'string') {
if (member.substr(-1) === ')') {
theClass.methods.push(member);
} else {
theClass.members.push(member);
// Member can contain white spaces, we trim them out
const memberString = member.trim();
if (memberString.startsWith('<<') && memberString.endsWith('>>')) {
// Remove leading and trailing brackets
theClass.annotations.push(memberString.substring(2, memberString.length - 2));
} else if (memberString.indexOf(')') > 0) {
theClass.methods.push(memberString);
} else if (memberString) {
theClass.members.push(memberString);
}
}
};
export const addMembers = function(className, MembersArr) {
if (Array.isArray(MembersArr)) {
MembersArr.forEach(member => addMember(className, member));
export const addMembers = function(className, members) {
if (Array.isArray(members)) {
members.reverse();
members.forEach(member => addMember(className, member));
}
};
export const cleanupLabel = function(label) {
if (label.substring(0, 1) === ':') {
return label.substr(2).trim();
return label.substr(1).trim();
} else {
return label.trim();
}
};
/**
* Called by parser when a special node is found, e.g. a clickable element.
* @param ids Comma separated list of ids
* @param className Class to add
*/
export const setCssClass = function(ids, className) {
ids.split(',').forEach(function(_id) {
let id = _id;
if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (typeof classes[id] !== 'undefined') {
classes[id].cssClasses.push(className);
}
});
};
/**
* Called by parser when a link is found. Adds the URL to the vertex data.
* @param ids Comma separated list of ids
* @param linkStr URL to create a link for
* @param tooltip Tooltip for the clickable element
*/
export const setLink = function(ids, linkStr, tooltip) {
ids.split(',').forEach(function(_id) {
let id = _id;
if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (typeof classes[id] !== 'undefined') {
classes[id].link = utils.formatUrl(linkStr, config);
if (tooltip) {
classes[id].tooltip = utils.sanitize(tooltip, config);
}
}
});
setCssClass(ids, 'clickable');
};
/**
* Called by parser when a click definition is found. Registers an event handler.
* @param ids Comma separated list of ids
* @param functionName Function to be called on click
* @param tooltip Tooltip for the clickable element
*/
export const setClickEvent = function(ids, functionName, tooltip) {
ids.split(',').forEach(function(id) {
setClickFunc(id, functionName, tooltip);
});
setCssClass(ids, 'clickable');
};
const setClickFunc = function(domId, functionName, tooltip) {
let id = domId;
let elemId = lookUpDomId(id);
if (config.securityLevel !== 'loose') {
return;
}
if (typeof functionName === 'undefined') {
return;
}
if (typeof classes[id] !== 'undefined') {
if (tooltip) {
classes[id].tooltip = utils.sanitize(tooltip, config);
}
funs.push(function() {
const elem = document.querySelector(`[id="${elemId}"]`);
if (elem !== null) {
elem.addEventListener(
'click',
function() {
window[functionName](elemId);
},
false
);
}
});
}
};
export const bindFunctions = function(element) {
funs.forEach(function(fun) {
fun(element);
});
};
export const lineType = {
LINE: 0,
DOTTED_LINE: 1
@@ -80,16 +243,66 @@ export const relationType = {
DEPENDENCY: 3
};
const setupToolTips = function(element) {
let tooltipElem = d3.select('.mermaidTooltip');
if ((tooltipElem._groups || tooltipElem)[0][0] === null) {
tooltipElem = d3
.select('body')
.append('div')
.attr('class', 'mermaidTooltip')
.style('opacity', 0);
}
const svg = d3.select(element).select('svg');
const nodes = svg.selectAll('g.node');
nodes
.on('mouseover', function() {
const el = d3.select(this);
const title = el.attr('title');
// Dont try to draw a tooltip if no data is provided
if (title === null) {
return;
}
const rect = this.getBoundingClientRect();
tooltipElem
.transition()
.duration(200)
.style('opacity', '.9');
tooltipElem
.html(el.attr('title'))
.style('left', rect.left + (rect.right - rect.left) / 2 + 'px')
.style('top', rect.top - 14 + document.body.scrollTop + 'px');
el.classed('hover', true);
})
.on('mouseout', function() {
tooltipElem
.transition()
.duration(500)
.style('opacity', 0);
const el = d3.select(this);
el.classed('hover', false);
});
};
funs.push(setupToolTips);
export default {
addClass,
bindFunctions,
clear,
getClass,
getClasses,
addAnnotation,
getRelations,
addRelation,
addMember,
addMembers,
cleanupLabel,
lineType,
relationType
relationType,
setClickEvent,
setCssClass,
setLink,
lookUpDomId
};

View File

@@ -2,13 +2,13 @@
import { parser } from './parser/classDiagram';
import classDb from './classDb';
describe('class diagram, ', function() {
describe('when parsing an info graph it', function() {
beforeEach(function() {
describe('class diagram, ', function () {
describe('when parsing an info graph it', function () {
beforeEach(function () {
parser.yy = classDb;
});
it('should handle relation definitions', function() {
it('should handle relation definitions', function () {
const str =
'classDiagram\n' +
'Class01 <|-- Class02\n' +
@@ -19,7 +19,8 @@ describe('class diagram, ', function() {
parser.parse(str);
});
it('should handle relation definition of different types and directions', function() {
it('should handle relation definition of different types and directions', function () {
const str =
'classDiagram\n' +
'Class11 <|.. Class12\n' +
@@ -31,7 +32,7 @@ describe('class diagram, ', function() {
parser.parse(str);
});
it('should handle cardinality and labels', function() {
it('should handle cardinality and labels', function () {
const str =
'classDiagram\n' +
'Class01 "1" *-- "many" Class02 : contains\n' +
@@ -40,6 +41,90 @@ describe('class diagram, ', function() {
parser.parse(str);
});
it('should handle visibility for methods and members', function() {
const str =
'classDiagram\n' +
'class TestClass\n' +
'TestClass : -int privateMember\n' +
'TestClass : +int publicMember\n' +
'TestClass : #int protectedMember\n' +
'TestClass : -privateMethod()\n' +
'TestClass : +publicMethod()\n' +
'TestClass : #protectedMethod()\n';
parser.parse(str);
});
it('should handle generic class', function() {
const str =
'classDiagram\n' +
'class Car~T~\n' +
'Driver -- Car : drives >\n' +
'Car *-- Wheel : have 4 >\n' +
'Car -- Person : < owns';
parser.parse(str);
});
it('should break when another `{`is encountered before closing the first one while defining generic class with brackets', function() {
const str =
'classDiagram\n' +
'class Dummy_Class~T~ {\n' +
'String data\n' +
' void methods()\n' +
'}\n' +
'\n' +
'class Dummy_Class {\n' +
'class Flight {\n' +
' flightNumber : Integer\n' +
' departureTime : Date\n' +
'}';
let testPased =false;
try{
parser.parse(str);
}catch (error){
console.log(error.name);
testPased = true;
}
expect(testPased).toBe(true);
});
it('should break when EOF is encountered before closing the first `{` while defining generic class with brackets', function() {
const str =
'classDiagram\n' +
'class Dummy_Class~T~ {\n' +
'String data\n' +
' void methods()\n' +
'}\n' +
'\n' +
'class Dummy_Class {\n';
let testPased =false;
try{
parser.parse(str);
}catch (error){
console.log(error.name);
testPased = true;
}
expect(testPased).toBe(true);
});
it('should handle generic class with brackets', function() {
const str =
'classDiagram\n' +
'class Dummy_Class~T~ {\n' +
'String data\n' +
' void methods()\n' +
'}\n' +
'\n' +
'class Flight {\n' +
' flightNumber : Integer\n' +
' departureTime : Date\n' +
'}';
parser.parse(str);
});
it('should handle class definitions', function() {
const str =
'classDiagram\n' +
@@ -51,7 +136,7 @@ describe('class diagram, ', function() {
parser.parse(str);
});
it('should handle method statements', function() {
it('should handle method statements', function () {
const str =
'classDiagram\n' +
'Object <|-- ArrayList\n' +
@@ -61,10 +146,11 @@ describe('class diagram, ', function() {
parser.parse(str);
});
it('should handle parsing of method statements grouped by brackets', 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' +
@@ -77,7 +163,37 @@ describe('class diagram, ', function() {
parser.parse(str);
});
it('should handle parsing of separators', function() {
it('should handle return types on methods', function () {
const str =
'classDiagram\n' +
'Object <|-- ArrayList\n' +
'Object : equals()\n' +
'Object : -Object[] objects\n' +
'Object : +getObjects() Object[]\n' +
'ArrayList : Dummy elementData\n' +
'ArrayList : getDummy() Dummy';
parser.parse(str);
});
it('should handle return types on methods grouped by brackets', function () {
const str =
'classDiagram\n' +
'class Dummy_Class {\n' +
'string data\n' +
'getDummy() Dummy\n' +
'}\n' +
'\n' +
'class Flight {\n' +
' int flightNumber\n' +
' datetime departureTime\n' +
' getDepartureTime() datetime\n' +
'}';
parser.parse(str);
});
it('should handle parsing of separators', function () {
const str =
'classDiagram\n' +
'class Foo1 {\n' +
@@ -109,14 +225,205 @@ describe('class diagram, ', function() {
parser.parse(str);
});
it('should handle a comment', function () {
const str =
'classDiagram\n' +
'class Class1 {\n' +
'%% Comment\n' +
'int : test\n' +
'string : foo\n' +
'test()\n' +
'foo()\n' +
'}';
parser.parse(str);
});
it('should handle comments at the start', function () {
const str =
'%% Comment\n' +
'classDiagram\n' +
'class Class1 {\n' +
'int : test\n' +
'string : foo\n' +
'test()\n' +
'foo()\n' +
'}';
parser.parse(str);
});
it('should handle comments at the end', function () {
const str =
'classDiagram\n' +
'class Class1 {\n' +
'int : test\n' +
'string : foo\n' +
'test()\n' +
'foo()\n' +
'\n}' +
'%% Comment\n';
parser.parse(str);
});
it('should handle comments at the end no trailing newline', function () {
const str =
'classDiagram\n' +
'class Class1 {\n' +
'int : test\n' +
'string : foo\n' +
'test()\n' +
'foo()\n' +
'}\n' +
'%% Comment';
parser.parse(str);
});
it('should handle a comment with multiple line feeds', function () {
const str =
'classDiagram\n\n\n' +
'%% Comment\n\n' +
'class Class1 {\n' +
'int : test\n' +
'string : foo\n' +
'test()\n' +
'foo()\n' +
'}';
parser.parse(str);
});
it('should handle a comment with mermaid class diagram code in them', function () {
const str =
'classDiagram\n' +
'%% Comment Class01 <|-- Class02\n' +
'class Class1 {\n' +
'int : test\n' +
'string : foo\n' +
'test()\n' +
'foo()\n' +
'}';
parser.parse(str);
});
it('should handle a comment inside brackets', function () {
const str =
'classDiagram\n' +
'class Class1 {\n' +
'%% Comment Class01 <|-- Class02\n' +
'int : test\n' +
'string : foo\n' +
'test()\n' +
'foo()\n' +
'}';
parser.parse(str);
});
it('should handle click statement with link', function () {
const str =
'classDiagram\n' +
'class Class1 {\n' +
'%% Comment Class01 <|-- Class02\n' +
'int : test\n' +
'string : foo\n' +
'test()\n' +
'foo()\n' +
'}\n' +
'link Class01 "google.com" ';
parser.parse(str);
});
it('should handle click statement with link and tooltip', function () {
const str =
'classDiagram\n' +
'class Class1 {\n' +
'%% Comment Class01 <|-- Class02\n' +
'int : test\n' +
'string : foo\n' +
'test()\n' +
'foo()\n' +
'}\n' +
'link Class01 "google.com" "A Tooltip" ';
parser.parse(str);
});
it('should handle click statement with callback', function () {
const str =
'classDiagram\n' +
'class Class1 {\n' +
'%% Comment Class01 <|-- Class02\n' +
'int : test\n' +
'string : foo\n' +
'test()\n' +
'foo()\n' +
'}\n' +
'callback Class01 "functionCall" ';
parser.parse(str);
});
it('should handle click statement with callback and tooltip', function () {
const str =
'classDiagram\n' +
'class Class1 {\n' +
'%% Comment Class01 <|-- Class02\n' +
'int : test\n' +
'string : foo\n' +
'test()\n' +
'foo()\n' +
'}\n' +
'callback Class01 "functionCall" "A Tooltip" ';
parser.parse(str);
});
it('should handle dashed relation definition of different types and directions', function () {
const str =
'classDiagram\n' +
'Class11 <|.. Class12\n' +
'Class13 <.. Class14\n' +
'Class15 ..|> Class16\n' +
'Class17 ..> Class18\n' +
'Class19 .. Class20';
parser.parse(str);
});
it('should handle generic types in members', function () {
const str =
'classDiagram\n' +
'class Car~T~\n' +
'Car : -List~Wheel~ wheels\n' +
'Car : +setWheels(List~Wheel~ wheels)\n' +
'Car : +getWheels() List~Wheel~';
parser.parse(str);
});
it('should handle generic types in members in class with brackets', function () {
const str =
'classDiagram\n' +
'class Car {\n' +
'List~Wheel~ wheels\n' +
'setWheels(List~Wheel~ wheels)\n' +
'+getWheels() List~Wheel~\n' +
'}';
parser.parse(str);
});
});
describe('when fetching data from an classDiagram graph it', function() {
beforeEach(function() {
describe('when fetching data from a classDiagram graph it', function () {
beforeEach(function () {
parser.yy = classDb;
parser.yy.clear();
});
it('should handle relation definitions EXTENSION', function() {
it('should handle relation definitions EXTENSION', function () {
const str = 'classDiagram\n' + 'Class01 <|-- Class02';
parser.parse(str);
@@ -129,7 +436,8 @@ describe('class diagram, ', function() {
expect(relations[0].relation.type2).toBe('none');
expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE);
});
it('should handle relation definitions AGGREGATION and dotted line', function() {
it('should handle relation definitions AGGREGATION and dotted line', function () {
const str = 'classDiagram\n' + 'Class01 o.. Class02';
parser.parse(str);
@@ -142,7 +450,8 @@ describe('class diagram, ', function() {
expect(relations[0].relation.type2).toBe('none');
expect(relations[0].relation.lineType).toBe(classDb.lineType.DOTTED_LINE);
});
it('should handle relation definitions COMPOSITION on both sides', function() {
it('should handle relation definitions COMPOSITION on both sides', function () {
const str = 'classDiagram\n' + 'Class01 *--* Class02';
parser.parse(str);
@@ -155,7 +464,8 @@ describe('class diagram, ', function() {
expect(relations[0].relation.type2).toBe(classDb.relationType.COMPOSITION);
expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE);
});
it('should handle relation definitions no types', function() {
it('should handle relation definitions no types', function () {
const str = 'classDiagram\n' + 'Class01 -- Class02';
parser.parse(str);
@@ -168,7 +478,8 @@ describe('class diagram, ', function() {
expect(relations[0].relation.type2).toBe('none');
expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE);
});
it('should handle relation definitions with type only on right side', function() {
it('should handle relation definitions with type only on right side', function () {
const str = 'classDiagram\n' + 'Class01 --|> Class02';
parser.parse(str);
@@ -182,7 +493,7 @@ describe('class diagram, ', function() {
expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE);
});
it('should handle multiple classes and relation definitions', function() {
it('should handle multiple classes and relation definitions', function () {
const str =
'classDiagram\n' +
'Class01 <|-- Class02\n' +
@@ -207,5 +518,154 @@ describe('class diagram, ', function() {
expect(relations[3].relation.type2).toBe('none');
expect(relations[3].relation.lineType).toBe(classDb.lineType.DOTTED_LINE);
});
it('should handle generic class with relation definitions', function () {
const str = 'classDiagram\n' + 'Class01~T~ <|-- Class02';
parser.parse(str);
const relations = parser.yy.getRelations();
expect(parser.yy.getClass('Class01').id).toBe('Class01');
expect(parser.yy.getClass('Class01').type).toBe('T');
expect(parser.yy.getClass('Class02').id).toBe('Class02');
expect(relations[0].relation.type1).toBe(classDb.relationType.EXTENSION);
expect(relations[0].relation.type2).toBe('none');
expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE);
});
it('should handle class annotations', function () {
const str = 'classDiagram\n' + 'class Class1\n' + '<<interface>> Class1';
parser.parse(str);
const testClass = parser.yy.getClass('Class1');
expect(testClass.annotations.length).toBe(1);
expect(testClass.members.length).toBe(0);
expect(testClass.methods.length).toBe(0);
expect(testClass.annotations[0]).toBe('interface');
});
it('should handle class annotations with members and methods', function () {
const str =
'classDiagram\n' +
'class Class1\n' +
'Class1 : int test\n' +
'Class1 : test()\n' +
'<<interface>> Class1';
parser.parse(str);
const testClass = parser.yy.getClass('Class1');
expect(testClass.annotations.length).toBe(1);
expect(testClass.members.length).toBe(1);
expect(testClass.methods.length).toBe(1);
expect(testClass.annotations[0]).toBe('interface');
});
it('should handle class annotations in brackets', function () {
const str = 'classDiagram\n' + 'class Class1 {\n' + '<<interface>>\n' + '}';
parser.parse(str);
const testClass = parser.yy.getClass('Class1');
expect(testClass.annotations.length).toBe(1);
expect(testClass.members.length).toBe(0);
expect(testClass.methods.length).toBe(0);
expect(testClass.annotations[0]).toBe('interface');
});
it('should handle class annotations in brackets with members and methods', function () {
const str =
'classDiagram\n' +
'class Class1 {\n' +
'<<interface>>\n' +
'int : test\n' +
'test()\n' +
'}';
parser.parse(str);
const testClass = parser.yy.getClass('Class1');
expect(testClass.annotations.length).toBe(1);
expect(testClass.members.length).toBe(1);
expect(testClass.methods.length).toBe(1);
expect(testClass.annotations[0]).toBe('interface');
});
it('should add bracket members in right order', function () {
const str =
'classDiagram\n' +
'class Class1 {\n' +
'int : test\n' +
'string : foo\n' +
'test()\n' +
'foo()\n' +
'}';
parser.parse(str);
const testClass = parser.yy.getClass('Class1');
expect(testClass.members.length).toBe(2);
expect(testClass.methods.length).toBe(2);
expect(testClass.members[0]).toBe('int : test');
expect(testClass.members[1]).toBe('string : foo');
expect(testClass.methods[0]).toBe('test()');
expect(testClass.methods[1]).toBe('foo()');
});
it('should handle abstract methods', function () {
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()*';
parser.parse(str);
const testClass = parser.yy.getClass('Class1');
expect(testClass.annotations.length).toBe(0);
expect(testClass.members.length).toBe(0);
expect(testClass.methods.length).toBe(1);
expect(testClass.methods[0]).toBe('someMethod()*');
});
it('should handle static methods', function () {
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()$';
parser.parse(str);
const testClass = parser.yy.getClass('Class1');
expect(testClass.annotations.length).toBe(0);
expect(testClass.members.length).toBe(0);
expect(testClass.methods.length).toBe(1);
expect(testClass.methods[0]).toBe('someMethod()$');
});
it('should associate link and css appropriately', function () {
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'link Class1 "google.com"';
parser.parse(str);
const testClass = parser.yy.getClass('Class1');
expect(testClass.link).toBe('about:blank');//('google.com'); security needs to be set to 'loose' for this to work right
expect(testClass.cssClasses.length).toBe(1);
expect(testClass.cssClasses[0]).toBe('clickable');
});
it('should associate link with tooltip', function () {
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'link Class1 "google.com" "A tooltip"';
parser.parse(str);
const testClass = parser.yy.getClass('Class1');
expect(testClass.link).toBe('about:blank');//('google.com'); security needs to be set to 'loose' for this to work right
expect(testClass.tooltip).toBe('A tooltip');
expect(testClass.cssClasses.length).toBe(1);
expect(testClass.cssClasses[0]).toBe('clickable');
});
it('should associate callback appropriately', function () {
spyOn(classDb, 'setClickEvent');
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'callback Class1 "functionCall"';
parser.parse(str);
expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall', undefined);
});
it('should associate callback with tooltip', function () {
spyOn(classDb, 'setClickEvent');
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'callback Class1 "functionCall" "A tooltip"';
parser.parse(str);
expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall', 'A tooltip');
});
});
});

View File

@@ -1,15 +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 classDb from './classDb';
import classDb, { lookUpDomId } from './classDb';
import { parser } from './parser/classDiagram';
import svgDraw from './svgDraw';
parser.yy = classDb;
const idCache = {};
let idCache = {};
let classCnt = 0;
const conf = {
dividerMargin: 10,
padding: 5,
@@ -134,198 +134,6 @@ const insertMarkers = function(elem) {
.attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z');
};
let edgeCount = 0;
let total = 0;
const drawEdge = function(elem, path, relation) {
const getRelationType = function(type) {
switch (type) {
case classDb.relationType.AGGREGATION:
return 'aggregation';
case classDb.relationType.EXTENSION:
return 'extension';
case classDb.relationType.COMPOSITION:
return 'composition';
case classDb.relationType.DEPENDENCY:
return 'dependency';
}
};
path.points = path.points.filter(p => !Number.isNaN(p.y));
// The data for our line
const lineData = path.points;
// This is the accessor function we talked about above
const lineFunction = d3
.line()
.x(function(d) {
return d.x;
})
.y(function(d) {
return d.y;
})
.curve(d3.curveBasis);
const svgPath = elem
.append('path')
.attr('d', lineFunction(lineData))
.attr('id', 'edge' + edgeCount)
.attr('class', 'relation');
let url = '';
if (conf.arrowMarkerAbsolute) {
url =
window.location.protocol +
'//' +
window.location.host +
window.location.pathname +
window.location.search;
url = url.replace(/\(/g, '\\(');
url = url.replace(/\)/g, '\\)');
}
if (relation.relation.type1 !== 'none') {
svgPath.attr(
'marker-start',
'url(' + url + '#' + getRelationType(relation.relation.type1) + 'Start' + ')'
);
}
if (relation.relation.type2 !== 'none') {
svgPath.attr(
'marker-end',
'url(' + url + '#' + getRelationType(relation.relation.type2) + 'End' + ')'
);
}
let x, y;
const l = path.points.length;
if (l % 2 !== 0 && l > 1) {
const p1 = path.points[Math.floor(l / 2)];
const p2 = path.points[Math.ceil(l / 2)];
x = (p1.x + p2.x) / 2;
y = (p1.y + p2.y) / 2;
} else {
const p = path.points[Math.floor(l / 2)];
x = p.x;
y = p.y;
}
if (typeof relation.title !== 'undefined') {
const g = elem.append('g').attr('class', 'classLabel');
const label = g
.append('text')
.attr('class', 'label')
.attr('x', x)
.attr('y', y)
.attr('fill', 'red')
.attr('text-anchor', 'middle')
.text(relation.title);
window.label = label;
const bounds = label.node().getBBox();
g.insert('rect', ':first-child')
.attr('class', 'box')
.attr('x', bounds.x - conf.padding / 2)
.attr('y', bounds.y - conf.padding / 2)
.attr('width', bounds.width + conf.padding)
.attr('height', bounds.height + conf.padding);
}
edgeCount++;
};
const drawClass = function(elem, classDef) {
logger.info('Rendering class ' + classDef);
const addTspan = function(textEl, txt, isFirst) {
const tSpan = textEl
.append('tspan')
.attr('x', conf.padding)
.text(txt);
if (!isFirst) {
tSpan.attr('dy', conf.textHeight);
}
};
const id = 'classId' + (classCnt % total);
const classInfo = {
id: id,
label: classDef.id,
width: 0,
height: 0
};
const g = elem
.append('g')
.attr('id', id)
.attr('class', 'classGroup');
const title = g
.append('text')
.attr('x', conf.padding)
.attr('y', conf.textHeight + conf.padding)
.text(classDef.id);
const titleHeight = title.node().getBBox().height;
const membersLine = g
.append('line') // text label for the x axis
.attr('x1', 0)
.attr('y1', conf.padding + titleHeight + conf.dividerMargin / 2)
.attr('y2', conf.padding + titleHeight + conf.dividerMargin / 2);
const members = g
.append('text') // text label for the x axis
.attr('x', conf.padding)
.attr('y', titleHeight + conf.dividerMargin + conf.textHeight)
.attr('fill', 'white')
.attr('class', 'classText');
let isFirst = true;
classDef.members.forEach(function(member) {
addTspan(members, member, isFirst);
isFirst = false;
});
const membersBox = members.node().getBBox();
const methodsLine = g
.append('line') // text label for the x axis
.attr('x1', 0)
.attr('y1', conf.padding + titleHeight + conf.dividerMargin + membersBox.height)
.attr('y2', conf.padding + titleHeight + conf.dividerMargin + membersBox.height);
const methods = g
.append('text') // text label for the x axis
.attr('x', conf.padding)
.attr('y', titleHeight + 2 * conf.dividerMargin + membersBox.height + conf.textHeight)
.attr('fill', 'white')
.attr('class', 'classText');
isFirst = true;
classDef.methods.forEach(function(method) {
addTspan(methods, method, isFirst);
isFirst = false;
});
const classBox = g.node().getBBox();
g.insert('rect', ':first-child')
.attr('x', 0)
.attr('y', 0)
.attr('width', classBox.width + 2 * conf.padding)
.attr('height', classBox.height + conf.padding + 0.5 * conf.dividerMargin);
membersLine.attr('x2', classBox.width + 2 * conf.padding);
methodsLine.attr('x2', classBox.width + 2 * conf.padding);
classInfo.width = classBox.width + 2 * conf.padding;
classInfo.height = classBox.height + conf.padding + 0.5 * conf.dividerMargin;
idCache[id] = classInfo;
classCnt++;
return classInfo;
};
export const setConf = function(cnf) {
const keys = Object.keys(cnf);
@@ -333,18 +141,20 @@ export const setConf = function(cnf) {
conf[key] = cnf[key];
});
};
/**
* Draws a flowchart in the tag with id: id based on the graph definition in text.
* @param text
* @param id
*/
export const draw = function(text, id) {
idCache = {};
parser.yy.clear();
parser.parse(text);
logger.info('Rendering diagram ' + text);
/// / Fetch the default direction, use TD if none was found
// Fetch the default direction, use TD if none was found
const diagram = d3.select(`[id='${id}']`);
insertMarkers(diagram);
@@ -365,14 +175,16 @@ export const draw = function(text, id) {
const classes = classDb.getClasses();
const keys = Object.keys(classes);
total = keys.length;
for (let i = 0; i < keys.length; i++) {
const classDef = classes[keys[i]];
const node = drawClass(diagram, classDef);
const node = svgDraw.drawClass(diagram, classDef, conf);
idCache[node.id] = node;
// Add nodes to the graph. The first argument is the node id. The second is
// metadata about the node. In this case we're going to add labels to each of
// our nodes.
g.setNode(node.id, node);
logger.info('Org height: ' + node.height);
}
@@ -381,15 +193,21 @@ export const draw = function(text, id) {
logger.info(
'tjoho' + getGraphId(relation.id1) + getGraphId(relation.id2) + JSON.stringify(relation)
);
g.setEdge(getGraphId(relation.id1), getGraphId(relation.id2), {
relation: relation
});
g.setEdge(
getGraphId(relation.id1),
getGraphId(relation.id2),
{
relation: relation
},
relation.title || 'DEFAULT'
);
});
dagre.layout(g);
g.nodes().forEach(function(v) {
if (typeof v !== 'undefined' && typeof g.node(v) !== 'undefined') {
logger.debug('Node ' + v + ': ' + JSON.stringify(g.node(v)));
d3.select('#' + v).attr(
d3.select('#' + lookUpDomId(v)).attr(
'transform',
'translate(' +
(g.node(v).x - g.node(v).width / 2) +
@@ -399,16 +217,17 @@ export const draw = function(text, id) {
);
}
});
g.edges().forEach(function(e) {
if (typeof e !== 'undefined' && typeof g.edge(e) !== 'undefined') {
logger.debug('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(g.edge(e)));
drawEdge(diagram, g.edge(e), g.edge(e).relation);
svgDraw.drawEdge(diagram, g.edge(e), g.edge(e).relation, conf);
}
});
diagram.attr('height', '100%');
diagram.attr('width', '100%');
diagram.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20));
diagram.attr('height', g.graph().height + 40);
diagram.attr('width', g.graph().width * 1.5 + 20);
diagram.attr('viewBox', '-10 -10 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20));
};
export default {

View File

@@ -6,14 +6,16 @@
/* lexical grammar */
%lex
%x string struct
%x string generic struct
%%
\%\%[^\n]* /* do nothing */
\%\%[^\n]*\n* /* do nothing */
\n+ return 'NEWLINE';
\s+ /* skip whitespace */
"classDiagram" return 'CLASS_DIAGRAM';
[\{] { this.begin("struct"); /*console.log('Starting struct');*/return 'STRUCT_START';}
<struct><<EOF>> return "EOF_IN_STRUCT";
<struct>[\{] return "OPEN_IN_STRUCT";
<struct>\} { /*console.log('Ending struct');*/this.popState(); return 'STRUCT_STOP';}}
<struct>[\n] /* nothing */
<struct>[^\{\}\n]* { /*console.log('lex-member: ' + yytext);*/ return "MEMBER";}
@@ -21,6 +23,14 @@
"class" return 'CLASS';
//"click" return 'CLICK';
"callback" return 'CALLBACK';
"link" return 'LINK';
"<<" return 'ANNOTATION_START';
">>" return 'ANNOTATION_END';
[~] this.begin("generic");
<generic>[~] this.popState();
<generic>[^~]* return "GENERICTYPE";
["] this.begin("string");
<string>["] this.popState();
<string>[^"]* return "STR";
@@ -34,15 +44,15 @@
\s*o return 'AGGREGATION';
\-\- return 'LINE';
\.\. return 'DOTTED_LINE';
":"[^#\n;]+ return 'LABEL';
":"[^\n;]+ return 'LABEL';
\- return 'MINUS';
"." return 'DOT';
\+ return 'PLUS';
\% 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]|
@@ -131,10 +141,11 @@ statements
| statement NEWLINE statements
;
className
: alphaNumToken className { $$=$1+$2; }
| alphaNumToken { $$=$1; }
| alphaNumToken GENERICTYPE className { $$=$1+'~'+$2+$3; }
| alphaNumToken GENERICTYPE { $$=$1+'~'+$2; }
;
statement
@@ -142,6 +153,8 @@ statement
| relationStatement LABEL { $1.title = yy.cleanupLabel($2); yy.addRelation($1); }
| classStatement
| methodStatement
| annotationStatement
| clickStatement
;
classStatement
@@ -149,6 +162,10 @@ classStatement
| CLASS className STRUCT_START members STRUCT_STOP {/*console.log($2,JSON.stringify($4));*/yy.addClass($2);yy.addMembers($2,$4);}
;
annotationStatement
: ANNOTATION_START alphaNumToken ANNOTATION_END className { yy.addAnnotation($4,$2); }
;
members
: MEMBER { $$ = [$1]; }
| MEMBER members { $2.push($1);$$=$2;}
@@ -157,7 +174,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);*/}
;
@@ -187,6 +204,13 @@ lineType
| DOTTED_LINE {$$=yy.lineType.DOTTED_LINE;}
;
clickStatement
: CALLBACK className STR {$$ = $1;yy.setClickEvent($2, $3, undefined);}
| CALLBACK className STR STR {$$ = $1;yy.setClickEvent($2, $3, $4);}
| LINK className STR {$$ = $1;yy.setLink($2, $3, undefined);}
| LINK className STR STR {$$ = $1;yy.setLink($2, $3, $4);}
;
commentToken : textToken | graphCodeTokens ;
textToken : textNoTagsToken | TAGSTART | TAGEND | '==' | '--' | PCT | DEFAULT;

View File

@@ -0,0 +1,413 @@
import * as d3 from 'd3';
import classDb, { lookUpDomId } from './classDb';
import utils from '../../utils';
import { logger } from '../../logger';
let edgeCount = 0;
export const drawEdge = function(elem, path, relation, conf) {
const getRelationType = function(type) {
switch (type) {
case classDb.relationType.AGGREGATION:
return 'aggregation';
case classDb.relationType.EXTENSION:
return 'extension';
case classDb.relationType.COMPOSITION:
return 'composition';
case classDb.relationType.DEPENDENCY:
return 'dependency';
}
};
path.points = path.points.filter(p => !Number.isNaN(p.y));
// The data for our line
const lineData = path.points;
// This is the accessor function we talked about above
const lineFunction = d3
.line()
.x(function(d) {
return d.x;
})
.y(function(d) {
return d.y;
})
.curve(d3.curveBasis);
const svgPath = elem
.append('path')
.attr('d', lineFunction(lineData))
.attr('id', 'edge' + edgeCount)
.attr('class', 'relation');
let url = '';
if (conf.arrowMarkerAbsolute) {
url =
window.location.protocol +
'//' +
window.location.host +
window.location.pathname +
window.location.search;
url = url.replace(/\(/g, '\\(');
url = url.replace(/\)/g, '\\)');
}
if (relation.relation.lineType == 1) {
svgPath.attr('class', 'relation dashed-line');
}
if (relation.relation.type1 !== 'none') {
svgPath.attr(
'marker-start',
'url(' + url + '#' + getRelationType(relation.relation.type1) + 'Start' + ')'
);
}
if (relation.relation.type2 !== 'none') {
svgPath.attr(
'marker-end',
'url(' + url + '#' + getRelationType(relation.relation.type2) + 'End' + ')'
);
}
let x, y;
const l = path.points.length;
// Calculate Label position
let labelPosition = utils.calcLabelPosition(path.points);
x = labelPosition.x;
y = labelPosition.y;
let p1_card_x, p1_card_y;
let p2_card_x, p2_card_y;
if (l % 2 !== 0 && l > 1) {
let cardinality_1_point = utils.calcCardinalityPosition(
relation.relation.type1 !== 'none',
path.points,
path.points[0]
);
let cardinality_2_point = utils.calcCardinalityPosition(
relation.relation.type2 !== 'none',
path.points,
path.points[l - 1]
);
logger.debug('cardinality_1_point ' + JSON.stringify(cardinality_1_point));
logger.debug('cardinality_2_point ' + JSON.stringify(cardinality_2_point));
p1_card_x = cardinality_1_point.x;
p1_card_y = cardinality_1_point.y;
p2_card_x = cardinality_2_point.x;
p2_card_y = cardinality_2_point.y;
}
if (typeof relation.title !== 'undefined') {
const g = elem.append('g').attr('class', 'classLabel');
const label = g
.append('text')
.attr('class', 'label')
.attr('x', x)
.attr('y', y)
.attr('fill', 'red')
.attr('text-anchor', 'middle')
.text(relation.title);
window.label = label;
const bounds = label.node().getBBox();
g.insert('rect', ':first-child')
.attr('class', 'box')
.attr('x', bounds.x - conf.padding / 2)
.attr('y', bounds.y - conf.padding / 2)
.attr('width', bounds.width + conf.padding)
.attr('height', bounds.height + conf.padding);
}
logger.info('Rendering relation ' + JSON.stringify(relation));
if (typeof relation.relationTitle1 !== 'undefined' && relation.relationTitle1 !== 'none') {
const g = elem.append('g').attr('class', 'cardinality');
g.append('text')
.attr('class', 'type1')
.attr('x', p1_card_x)
.attr('y', p1_card_y)
.attr('fill', 'black')
.attr('font-size', '6')
.text(relation.relationTitle1);
}
if (typeof relation.relationTitle2 !== 'undefined' && relation.relationTitle2 !== 'none') {
const g = elem.append('g').attr('class', 'cardinality');
g.append('text')
.attr('class', 'type2')
.attr('x', p2_card_x)
.attr('y', p2_card_y)
.attr('fill', 'black')
.attr('font-size', '6')
.text(relation.relationTitle2);
}
edgeCount++;
};
export const drawClass = function(elem, classDef, conf) {
logger.info('Rendering class ' + classDef);
let cssClassStr = 'classGroup ';
if (classDef.cssClasses.length > 0) {
cssClassStr = cssClassStr + classDef.cssClasses.join(' ');
}
const id = classDef.id;
const classInfo = {
id: id,
label: classDef.id,
width: 0,
height: 0
};
// add class group
const g = elem
.append('g')
.attr('id', lookUpDomId(id))
.attr('class', cssClassStr);
// add title
let title;
if (classDef.link) {
title = g
.append('svg:a')
.attr('xlink:href', classDef.link)
.attr('target', '_blank')
.append('text')
.attr('y', conf.textHeight + conf.padding)
.attr('x', 0);
} else {
title = g
.append('text')
.attr('y', conf.textHeight + conf.padding)
.attr('x', 0);
}
// add annotations
let isFirst = true;
classDef.annotations.forEach(function(member) {
const titleText2 = title.append('tspan').text('«' + member + '»');
if (!isFirst) titleText2.attr('dy', conf.textHeight);
isFirst = false;
});
let classTitleString = classDef.id;
if (classDef.type !== undefined && classDef.type !== '') {
classTitleString += '<' + classDef.type + '>';
}
const classTitle = title
.append('tspan')
.text(classTitleString)
.attr('class', 'title');
// If class has annotations the title needs to have an offset of the text height
if (!isFirst) classTitle.attr('dy', conf.textHeight);
const titleHeight = title.node().getBBox().height;
const membersLine = g
.append('line') // text label for the x axis
.attr('x1', 0)
.attr('y1', conf.padding + titleHeight + conf.dividerMargin / 2)
.attr('y2', conf.padding + titleHeight + conf.dividerMargin / 2);
const members = g
.append('text') // text label for the x axis
.attr('x', conf.padding)
.attr('y', titleHeight + conf.dividerMargin + conf.textHeight)
.attr('fill', 'white')
.attr('class', 'classText');
isFirst = true;
classDef.members.forEach(function(member) {
addTspan(members, member, isFirst, conf);
isFirst = false;
});
const membersBox = members.node().getBBox();
const methodsLine = g
.append('line') // text label for the x axis
.attr('x1', 0)
.attr('y1', conf.padding + titleHeight + conf.dividerMargin + membersBox.height)
.attr('y2', conf.padding + titleHeight + conf.dividerMargin + membersBox.height);
const methods = g
.append('text') // text label for the x axis
.attr('x', conf.padding)
.attr('y', titleHeight + 2 * conf.dividerMargin + membersBox.height + conf.textHeight)
.attr('fill', 'white')
.attr('class', 'classText');
isFirst = true;
classDef.methods.forEach(function(method) {
addTspan(methods, method, isFirst, conf);
isFirst = false;
});
const classBox = g.node().getBBox();
const rect = g
.insert('rect', ':first-child')
.attr('x', 0)
.attr('y', 0)
.attr('width', classBox.width + 2 * conf.padding)
.attr('height', classBox.height + conf.padding + 0.5 * conf.dividerMargin);
const rectWidth = rect.node().getBBox().width;
// Center title
// We subtract the width of each text element from the class box width and divide it by 2
title.node().childNodes.forEach(function(x) {
x.setAttribute('x', (rectWidth - x.getBBox().width) / 2);
});
if (classDef.tooltip) {
title.insert('title').text(classDef.tooltip);
}
membersLine.attr('x2', rectWidth);
methodsLine.attr('x2', rectWidth);
classInfo.width = rectWidth;
classInfo.height = classBox.height + conf.padding + 0.5 * conf.dividerMargin;
return classInfo;
};
export const parseMember = function(text) {
const fieldRegEx = /^(\+|-|~|#)?(\w+)(~\w+~|\[\])?\s+(\w+)$/;
const methodRegEx = /^(\+|-|~|#)?(\w+)\s?\(\s*(\w+(~\w+~|\[\])?\s*(\w+)?)?\s*\)\s?([*|$])?\s?(\w+(~\w+~|\[\])?)?\s*$/;
let fieldMatch = text.match(fieldRegEx);
let methodMatch = text.match(methodRegEx);
if (fieldMatch) {
return buildFieldDisplay(fieldMatch);
} else if (methodMatch) {
return buildMethodDisplay(methodMatch);
} else {
return buildLegacyDisplay(text);
}
};
const buildFieldDisplay = function(parsedText) {
let visibility = parsedText[1] ? parsedText[1].trim() : '';
let fieldType = parsedText[2] ? parsedText[2].trim() : '';
let genericType = parsedText[3] ? parseGenericTypes(parsedText[3]) : '';
let fieldName = parsedText[4] ? parsedText[4].trim() : '';
return {
displayText: visibility + fieldType + genericType + ' ' + fieldName,
cssStyle: ''
};
};
const buildMethodDisplay = function(parsedText) {
let cssStyle = '';
let displayText = parsedText;
let visibility = parsedText[1] ? parsedText[1].trim() : '';
let methodName = parsedText[2] ? parsedText[2].trim() : '';
let parameters = parsedText[3] ? parseGenericTypes(parsedText[3]) : '';
let classifier = parsedText[6] ? parsedText[6].trim() : '';
let returnType = parsedText[7] ? ' : ' + parseGenericTypes(parsedText[7]).trim() : '';
displayText = visibility + methodName + '(' + parameters + ')' + returnType;
cssStyle = parseClassifier(classifier);
let member = {
displayText: displayText,
cssStyle: cssStyle
};
return member;
};
const buildLegacyDisplay = function(text) {
// if for some reason we dont have any match, use old format to parse text
let memberText = '';
let cssStyle = '';
let returnType = '';
let methodStart = text.indexOf('(');
let methodEnd = text.indexOf(')');
if (methodStart > 1 && methodEnd > methodStart && methodEnd <= text.length) {
let parsedText = text.match(/(\+|-|~|#)?(\w+)/);
let visibility = parsedText[1] ? parsedText[1].trim() : '';
let methodName = parsedText[2];
let parameters = text.substring(methodStart + 1, methodEnd);
let classifier = text.substring(methodEnd, methodEnd + 1);
cssStyle = parseClassifier(classifier);
memberText = visibility + methodName + '(' + parseGenericTypes(parameters.trim()) + ')';
if (methodEnd < memberText.length) {
returnType = text.substring(methodEnd + 2).trim();
if (returnType !== '') {
returnType = ' : ' + parseGenericTypes(returnType);
}
}
} else {
// finally - if all else fails, just send the text back as written (other than parsing for generic types)
memberText = parseGenericTypes(text);
}
let member = {
displayText: memberText + returnType,
cssStyle: cssStyle
};
return member;
};
const addTspan = function(textEl, txt, isFirst, conf) {
let member = parseMember(txt);
const tSpan = textEl
.append('tspan')
.attr('x', conf.padding)
.text(member.displayText);
if (member.cssStyle !== '') {
tSpan.attr('style', member.cssStyle);
}
if (!isFirst) {
tSpan.attr('dy', conf.textHeight);
}
};
const parseGenericTypes = function(text) {
let cleanedText = text;
if (text.indexOf('~') != -1) {
cleanedText = cleanedText.replace('~', '<');
cleanedText = cleanedText.replace('~', '>');
return parseGenericTypes(cleanedText);
} else {
return cleanedText;
}
};
const parseClassifier = function(classifier) {
switch (classifier) {
case '*':
return 'font-style:italic;';
case '$':
return 'text-decoration:underline;';
default:
return '';
}
};
export default {
drawClass,
drawEdge,
parseMember
};

View File

@@ -0,0 +1,152 @@
/* eslint-env jasmine */
import svgDraw from './svgDraw';
describe('class member Renderer, ', function () {
describe('when parsing text to build method display string', function () {
it('should handle simple method declaration', function () {
const str = 'foo()';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('foo()');
expect(actual.cssStyle).toBe('');
});
it('should handle public visibility', function () {
const str = '+foo()';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('+foo()');
expect(actual.cssStyle).toBe('');
});
it('should handle private visibility', function () {
const str = '-foo()';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('-foo()');
expect(actual.cssStyle).toBe('');
});
it('should handle protected visibility', function () {
const str = '#foo()';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('#foo()');
expect(actual.cssStyle).toBe('');
});
it('should handle package/internal visibility', function () {
const str = '~foo()';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('~foo()');
expect(actual.cssStyle).toBe('');
});
it('should ignore unknown character for visibility', function () {
const str = '!foo()';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('foo()');
expect(actual.cssStyle).toBe('');
});
it('should handle abstract classifier', function () {
const str = 'foo()*';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('foo()');
expect(actual.cssStyle).toBe('font-style:italic;');
});
it('should handle static classifier', function () {
const str = 'foo()$';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('foo()');
expect(actual.cssStyle).toBe('text-decoration:underline;');
});
it('should ignore unknown character for classifier', function () {
const str = 'foo()!';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('foo()');
expect(actual.cssStyle).toBe('');
});
it('should handle simple method declaration with parameters', function () {
const str = 'foo(int id)';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('foo(int id)');
expect(actual.cssStyle).toBe('');
});
it('should handle simple method declaration with single item in parameters', function () {
const str = 'foo(id)';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('foo(id)');
expect(actual.cssStyle).toBe('');
});
it('should handle simple method declaration with single item in parameters with extra spaces', function () {
const str = ' foo ( id) ';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('foo(id)');
expect(actual.cssStyle).toBe('');
});
it('should handle method declaration with return value', function () {
const str = 'foo(id) int';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('foo(id) : int');
expect(actual.cssStyle).toBe('');
});
it('should handle method declaration with generic return value', function () {
const str = 'foo(id) List~int~';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('foo(id) : List<int>');
expect(actual.cssStyle).toBe('');
});
it('should handle method declaration with generic parameter', function () {
const str = 'foo(List~int~)';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('foo(List<int>)');
expect(actual.cssStyle).toBe('');
});
it('should handle method declaration with all possible markup', function () {
const str = '+foo ( List~int~ ids )* List~Item~';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('+foo(List<int> ids) : List<Item>');
expect(actual.cssStyle).toBe('font-style:italic;');
});
});
describe('when parsing text to build field display string', function () {
it('should handle simple field declaration', function () {
const str = 'int[] ids';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('int[] ids');
expect(actual.cssStyle).toBe('');
});
it('should handle field declaration with generic type', function () {
const str = 'List~int~ ids';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('List<int> ids');
expect(actual.cssStyle).toBe('');
});
});
});

View File

@@ -0,0 +1,261 @@
import dagreD3 from 'dagre-d3';
function question(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const s = (w + h) * 0.9;
const points = [
{ x: s / 2, y: 0 },
{ x: s, y: -s / 2 },
{ x: s / 2, y: -s },
{ x: 0, y: -s / 2 }
];
const shapeSvg = insertPolygonShape(parent, s, s, points);
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
}
function hexagon(parent, bbox, node) {
const f = 4;
const h = bbox.height;
const m = h / f;
const w = bbox.width + 2 * m;
const points = [
{ x: m, y: 0 },
{ x: w - m, y: 0 },
{ x: w, y: -h / 2 },
{ x: w - m, y: -h },
{ x: m, y: -h },
{ x: 0, y: -h / 2 }
];
const shapeSvg = insertPolygonShape(parent, w, h, points);
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
}
function rect_left_inv_arrow(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const points = [
{ x: -h / 2, y: 0 },
{ x: w, y: 0 },
{ x: w, y: -h },
{ x: -h / 2, y: -h },
{ x: 0, y: -h / 2 }
];
const shapeSvg = insertPolygonShape(parent, w, h, points);
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
}
function lean_right(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const points = [
{ x: (-2 * h) / 6, y: 0 },
{ x: w - h / 6, y: 0 },
{ x: w + (2 * h) / 6, y: -h },
{ x: h / 6, y: -h }
];
const shapeSvg = insertPolygonShape(parent, w, h, points);
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
}
function lean_left(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const points = [
{ x: (2 * h) / 6, y: 0 },
{ x: w + h / 6, y: 0 },
{ x: w - (2 * h) / 6, y: -h },
{ x: -h / 6, y: -h }
];
const shapeSvg = insertPolygonShape(parent, w, h, points);
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
}
function trapezoid(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const points = [
{ x: (-2 * h) / 6, y: 0 },
{ x: w + (2 * h) / 6, y: 0 },
{ x: w - h / 6, y: -h },
{ x: h / 6, y: -h }
];
const shapeSvg = insertPolygonShape(parent, w, h, points);
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
}
function inv_trapezoid(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const points = [
{ x: h / 6, y: 0 },
{ x: w - h / 6, y: 0 },
{ x: w + (2 * h) / 6, y: -h },
{ x: (-2 * h) / 6, y: -h }
];
const shapeSvg = insertPolygonShape(parent, w, h, points);
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
}
function rect_right_inv_arrow(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const points = [
{ x: 0, y: 0 },
{ x: w + h / 2, y: 0 },
{ x: w, y: -h / 2 },
{ x: w + h / 2, y: -h },
{ x: 0, y: -h }
];
const shapeSvg = insertPolygonShape(parent, w, h, points);
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
}
function stadium(parent, bbox, node) {
const h = bbox.height;
const w = bbox.width + h / 4;
const shapeSvg = parent
.insert('rect', ':first-child')
.attr('rx', h / 2)
.attr('ry', h / 2)
.attr('x', -w / 2)
.attr('y', -h / 2)
.attr('width', w)
.attr('height', h);
node.intersect = function(point) {
return dagreD3.intersect.rect(node, point);
};
return shapeSvg;
}
function cylinder(parent, bbox, node) {
const w = bbox.width;
const rx = w / 2;
const ry = rx / (2.5 + w / 50);
const h = bbox.height + ry;
const shape =
'M 0,' +
ry +
' a ' +
rx +
',' +
ry +
' 0,0,0 ' +
w +
' 0 a ' +
rx +
',' +
ry +
' 0,0,0 ' +
-w +
' 0 l 0,' +
h +
' a ' +
rx +
',' +
ry +
' 0,0,0 ' +
w +
' 0 l 0,' +
-h;
const shapeSvg = parent
.attr('label-offset-y', ry)
.insert('path', ':first-child')
.attr('d', shape)
.attr('transform', 'translate(' + -w / 2 + ',' + -(h / 2 + ry) + ')');
node.intersect = function(point) {
const pos = dagreD3.intersect.rect(node, point);
const x = pos.x - node.x;
if (
rx != 0 &&
(Math.abs(x) < node.width / 2 ||
(Math.abs(x) == node.width / 2 && Math.abs(pos.y - node.y) > node.height / 2 - ry))
) {
// ellipsis equation: x*x / a*a + y*y / b*b = 1
// solve for y to get adjustion value for pos.y
let y = ry * ry * (1 - (x * x) / (rx * rx));
if (y != 0) y = Math.sqrt(y);
y = ry - y;
if (point.y - node.y > 0) y = -y;
pos.y += y;
}
return pos;
};
return shapeSvg;
}
export function addToRender(render) {
render.shapes().question = question;
render.shapes().hexagon = hexagon;
render.shapes().stadium = stadium;
render.shapes().cylinder = cylinder;
// Add custom shape for box with inverted arrow on left side
render.shapes().rect_left_inv_arrow = rect_left_inv_arrow;
// Add custom shape for box with inverted arrow on left side
render.shapes().lean_right = lean_right;
// Add custom shape for box with inverted arrow on left side
render.shapes().lean_left = lean_left;
// Add custom shape for box with inverted arrow on left side
render.shapes().trapezoid = trapezoid;
// Add custom shape for box with inverted arrow on left side
render.shapes().inv_trapezoid = inv_trapezoid;
// Add custom shape for box with inverted arrow on right side
render.shapes().rect_right_inv_arrow = rect_right_inv_arrow;
}
function insertPolygonShape(parent, w, h, points) {
return parent
.insert('polygon', ':first-child')
.attr(
'points',
points
.map(function(d) {
return d.x + ',' + d.y;
})
.join(' ')
)
.attr('transform', 'translate(' + -w / 2 + ',' + h / 2 + ')');
}
export default {
addToRender
};

View File

@@ -0,0 +1,131 @@
import { addToRender } from './flowChartShapes';
describe('flowchart shapes', function() {
// rect-based shapes
[
['stadium', useWidth, useHeight]
].forEach(function([shapeType, getW, getH]) {
it(`should add a ${shapeType} shape that renders a properly positioned rect element`, function() {
const mockRender = MockRender();
const mockSvg = MockSvg();
addToRender(mockRender);
[[100, 100], [123, 45], [71, 300]].forEach(function([width, height]) {
const shape = mockRender.shapes()[shapeType](mockSvg, { width, height }, {});
const w = width + height / 4;
const h = height;
const dx = -getW(w, h) / 2;
const dy = -getH(w, h) / 2;
expect(shape.__tag).toEqual('rect');
expect(shape.__attrs).toHaveProperty('x', dx);
expect(shape.__attrs).toHaveProperty('y', dy);
});
});
});
// path-based shapes
[
['cylinder', useWidth, useHeight]
].forEach(function([shapeType, getW, getH]) {
it(`should add a ${shapeType} shape that renders a properly positioned path element`, function() {
const mockRender = MockRender();
const mockSvg = MockSvg();
addToRender(mockRender);
[[100, 100], [123, 45], [71, 300]].forEach(function([width, height]) {
const shape = mockRender.shapes()[shapeType](mockSvg, { width, height }, {});
expect(shape.__tag).toEqual('path');
expect(shape.__attrs).toHaveProperty('d');
});
});
});
// polygon-based shapes
[
[
'question',
4,
function(w, h) {
return (w + h) * 0.9;
},
function(w, h) {
return (w + h) * 0.9;
}
],
[
'hexagon',
6,
function(w, h) {
return w + h / 2;
},
useHeight
],
['rect_left_inv_arrow', 5, useWidth, useHeight],
['rect_right_inv_arrow', 5, useWidth, useHeight],
['lean_right', 4, useWidth, useHeight],
['lean_left', 4, useWidth, useHeight],
['trapezoid', 4, useWidth, useHeight],
['inv_trapezoid', 4, useWidth, useHeight]
].forEach(function([shapeType, expectedPointCount, getW, getH]) {
it(`should add a ${shapeType} shape that renders a properly translated polygon element`, function() {
const mockRender = MockRender();
const mockSvg = MockSvg();
addToRender(mockRender);
[[100, 100], [123, 45], [71, 300]].forEach(function([width, height]) {
const shape = mockRender.shapes()[shapeType](mockSvg, { width, height }, {});
const dx = -getW(width, height) / 2;
const dy = getH(width, height) / 2;
const points = shape.__attrs.points.split(' ');
expect(shape.__tag).toEqual('polygon');
expect(shape.__attrs).toHaveProperty('transform', `translate(${dx},${dy})`);
expect(points).toHaveLength(expectedPointCount);
});
});
});
});
function MockRender() {
const shapes = {};
return {
shapes() {
return shapes;
}
};
}
function MockSvg(tag, ...args) {
const children = [];
const attributes = {};
return {
get __args() {
return args;
},
get __tag() {
return tag;
},
get __children() {
return children;
},
get __attrs() {
return attributes;
},
insert: function(tag, ...args) {
const child = MockSvg(tag, ...args);
children.push(child);
return child;
},
attr(name, value) {
this.__attrs[name] = value;
return this;
}
};
}
function useWidth(w, h) {
return w;
}
function useHeight(w, h) {
return h;
}

View File

@@ -1,9 +1,11 @@
import * as d3 from 'd3';
import { sanitizeUrl } from '@braintree/sanitize-url';
import { logger } from '../../logger';
import utils from '../../utils';
import { getConfig } from '../../config';
// const MERMAID_DOM_ID_PREFIX = 'mermaid-dom-id-';
const MERMAID_DOM_ID_PREFIX = '';
const config = getConfig();
let vertices = {};
let edges = [];
@@ -17,19 +19,6 @@ let direction;
// Functions to be run after graph rendering
let funs = [];
const sanitize = text => {
let txt = text;
if (config.securityLevel !== 'loose') {
txt = txt.replace(/<br>/g, '#br#');
txt = txt.replace(/<br\S*?\/>/g, '#br#');
txt = txt.replace(/</g, '&lt;').replace(/>/g, '&gt;');
txt = txt.replace(/=/g, '&equals;');
txt = txt.replace(/#br#/g, '<br/>');
}
return txt;
};
/**
* Function called by parser when a node definition has been found
* @param id
@@ -48,22 +37,22 @@ 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: [] };
}
if (typeof text !== 'undefined') {
txt = sanitize(text.trim());
txt = utils.sanitize(text.trim(), config);
// strip quotes if string starts and exnds with a quote
// strip quotes if string starts and ends with a quote
if (txt[0] === '"' && txt[txt.length - 1] === '"') {
txt = txt.substring(1, txt.length - 1);
}
vertices[id].text = txt;
} else {
if (!vertices[id].text) {
if (typeof vertices[id].text === 'undefined') {
vertices[id].text = _id;
}
}
@@ -93,18 +82,18 @@ export const addVertex = function(_id, text, type, style, classes) {
* @param type
* @param linktext
*/
export const addLink = function(_start, _end, type, linktext) {
export const addSingleLink = 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: '' };
linktext = type.text;
if (typeof linktext !== 'undefined') {
edge.text = sanitize(linktext.trim());
edge.text = utils.sanitize(linktext.trim(), config);
// strip quotes if string starts and exnds with a quote
if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') {
@@ -118,6 +107,14 @@ export const addLink = function(_start, _end, type, linktext) {
}
edges.push(edge);
};
export const addLink = function(_start, _end, type, linktext) {
let i, j;
for (i = 0; i < _start.length; i++) {
for (j = 0; j < _end.length; j++) {
addSingleLink(_start[i], _end[j], type, linktext);
}
}
};
/**
* Updates a link's line interpolation algorithm
@@ -154,12 +151,17 @@ export const updateLink = function(positions, style) {
export const addClass = function(id, style) {
if (typeof classes[id] === 'undefined') {
classes[id] = { id: id, styles: [] };
classes[id] = { id: id, styles: [], textStyles: [] };
}
if (typeof style !== 'undefined') {
if (style !== null) {
style.forEach(function(s) {
if (s.match('color')) {
const newStyle1 = s.replace('fill', 'bgFill');
const newStyle2 = newStyle1.replace('color', 'fill');
classes[id].textStyles.push(newStyle2);
}
classes[id].styles.push(s);
});
}
@@ -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);
}
@@ -208,14 +210,14 @@ export const setClass = function(ids, className) {
const setTooltip = function(ids, tooltip) {
ids.split(',').forEach(function(id) {
if (typeof tooltip !== 'undefined') {
tooltips[id] = sanitize(tooltip);
tooltips[id] = utils.sanitize(tooltip, config);
}
});
};
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,13 +249,9 @@ 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, '')
} else {
vertices[id].link = linkStr;
}
vertices[id].link = utils.formatUrl(linkStr, config);
}
});
setTooltip(ids, tooltip);
@@ -283,7 +281,7 @@ export const bindFunctions = function(element) {
});
};
export const getDirection = function() {
return direction;
return direction.trim();
};
/**
* Retrieval function for fetching the found nodes after parsing has completed.
@@ -380,7 +378,7 @@ export const defaultStyle = function() {
* Clears the internal graph db so that a new graph can be parsed.
*/
export const addSubGraph = function(_id, list, _title) {
let id = _id;
let id = _id.trim();
let title = _title;
if (_id === _title && _title.match(/\s/)) {
id = undefined;
@@ -395,7 +393,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,13 +404,13 @@ 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);
title = utils.sanitize(title, config);
subCount = subCount + 1;
const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [] };
subGraphs.push(subGraph);
@@ -492,6 +490,130 @@ export const firstGraph = () => {
return false;
};
const destructStartLink = _str => {
const str = _str.trim();
switch (str) {
case '<--':
return { type: 'arrow', stroke: 'normal' };
case 'x--':
return { type: 'arrow_cross', stroke: 'normal' };
case 'o--':
return { type: 'arrow_circle', stroke: 'normal' };
case '<-.':
return { type: 'arrow', stroke: 'dotted' };
case 'x-.':
return { type: 'arrow_cross', stroke: 'dotted' };
case 'o-.':
return { type: 'arrow_circle', stroke: 'dotted' };
case '<==':
return { type: 'arrow', stroke: 'thick' };
case 'x==':
return { type: 'arrow_cross', stroke: 'thick' };
case 'o==':
return { type: 'arrow_circle', stroke: 'thick' };
case '--':
return { type: 'arrow_open', stroke: 'normal' };
case '==':
return { type: 'arrow_open', stroke: 'thick' };
case '-.':
return { type: 'arrow_open', stroke: 'dotted' };
}
};
const destructEndLink = _str => {
const str = _str.trim();
switch (str) {
case '--x':
return { type: 'arrow_cross', stroke: 'normal' };
case '-->':
return { type: 'arrow', stroke: 'normal' };
case '<-->':
return { type: 'double_arrow_point', stroke: 'normal' };
case 'x--x':
return { type: 'double_arrow_cross', stroke: 'normal' };
case 'o--o':
return { type: 'double_arrow_circle', stroke: 'normal' };
case 'o.-o':
return { type: 'double_arrow_circle', stroke: 'dotted' };
case '<==>':
return { type: 'double_arrow_point', stroke: 'thick' };
case 'o==o':
return { type: 'double_arrow_circle', stroke: 'thick' };
case 'x==x':
return { type: 'double_arrow_cross', stroke: 'thick' };
case 'x.-x':
return { type: 'double_arrow_cross', stroke: 'dotted' };
case 'x-.-x':
return { type: 'double_arrow_cross', stroke: 'dotted' };
case '<.->':
return { type: 'double_arrow_point', stroke: 'dotted' };
case '<-.->':
return { type: 'double_arrow_point', stroke: 'dotted' };
case 'o-.-o':
return { type: 'double_arrow_circle', stroke: 'dotted' };
case '--o':
return { type: 'arrow_circle', stroke: 'normal' };
case '---':
return { type: 'arrow_open', stroke: 'normal' };
case '-.-x':
return { type: 'arrow_cross', stroke: 'dotted' };
case '-.->':
return { type: 'arrow', stroke: 'dotted' };
case '-.-o':
return { type: 'arrow_circle', stroke: 'dotted' };
case '-.-':
return { type: 'arrow_open', stroke: 'dotted' };
case '.-x':
return { type: 'arrow_cross', stroke: 'dotted' };
case '.->':
return { type: 'arrow', stroke: 'dotted' };
case '.-o':
return { type: 'arrow_circle', stroke: 'dotted' };
case '.-':
return { type: 'arrow_open', stroke: 'dotted' };
case '==x':
return { type: 'arrow_cross', stroke: 'thick' };
case '==>':
return { type: 'arrow', stroke: 'thick' };
case '==o':
return { type: 'arrow_circle', stroke: 'thick' };
case '===':
return { type: 'arrow_open', stroke: 'thick' };
}
};
const destructLink = (_str, _startStr) => {
const info = destructEndLink(_str);
let startInfo;
if (_startStr) {
startInfo = destructStartLink(_startStr);
if (startInfo.stroke !== info.stroke) {
return { type: 'INVALID', stroke: 'INVALID' };
}
if (startInfo.type === 'arrow_open') {
// -- xyz --> - take arrow type form ending
startInfo.type = info.type;
} else {
// x-- xyz --> - not supported
if (startInfo.type !== info.type) return { type: 'INVALID', stroke: 'INVALID' };
startInfo.type = 'double_' + startInfo.type;
}
if (startInfo.type === 'double_arrow') {
startInfo.type = 'double_arrow_point';
}
return startInfo;
}
return info;
};
export default {
addVertex,
addLink,
@@ -514,6 +636,7 @@ export default {
getDepthFirstPos,
indexNodes,
getSubGraphs,
destructLink,
lex: {
firstGraph
}

View File

@@ -1,13 +1,15 @@
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';
import dagreD3 from 'dagre-d3';
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
import { logger } from '../../logger';
import { interpolateToCurve } from '../../utils';
import { interpolateToCurve, getStylesFromArray } from '../../utils';
import flowChartShapes from './flowChartShapes';
const conf = {};
export const setConf = function(cnf) {
@@ -26,24 +28,6 @@ export const addVertices = function(vert, g, svgId) {
const svg = d3.select(`[id="${svgId}"]`);
const keys = Object.keys(vert);
const styleFromStyleArr = function(styleStr, arr, { label }) {
if (!label) {
// Create a compound style definition from the style definitions found for the node in the graph definition
for (let i = 0; i < arr.length; i++) {
if (typeof arr[i] !== 'undefined') {
styleStr = styleStr + arr[i] + ';';
}
}
} else {
for (let i = 0; i < arr.length; i++) {
if (typeof arr[i] !== 'undefined') {
if (arr[i].match('^color:')) styleStr = styleStr + arr[i] + ';';
}
}
}
return styleStr;
};
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
keys.forEach(function(id) {
const vertex = vert[id];
@@ -57,15 +41,7 @@ export const addVertices = function(vert, g, svgId) {
classStr = vertex.classes.join(' ');
}
/**
* Variable for storing the extracted style for the vertex
* @type {string}
*/
let style = '';
// Create a compound style definition from the style definitions found for the node in the graph definition
style = styleFromStyleArr(style, vertex.styles, { label: false });
let labelStyle = '';
labelStyle = styleFromStyleArr(labelStyle, vertex.styles, { label: true });
const styles = getStylesFromArray(vertex.styles);
// Use vertex id as text in the box if no text is provided by the graph definition
let vertexText = vertex.text !== undefined ? vertex.text : vertex.id;
@@ -84,8 +60,9 @@ export const addVertices = function(vert, g, svgId) {
vertexNode.parentNode.removeChild(vertexNode);
} else {
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:'));
const rows = vertexText.split(/<br[/]{0,1}>/);
const rows = vertexText.split(/<br\s*\/?>/gi);
for (let j = 0; j < rows.length; j++) {
const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
@@ -98,15 +75,6 @@ export const addVertices = function(vert, g, svgId) {
vertexNode = svgLabel;
}
// If the node has a link, we wrap it in a SVG link
if (vertex.link) {
const link = document.createElementNS('http://www.w3.org/2000/svg', 'a');
link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertex.link);
link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener');
link.appendChild(vertexNode);
vertexNode = link;
}
let radious = 0;
let _shape = '';
// Set the shape based parameters
@@ -121,6 +89,9 @@ export const addVertices = function(vert, g, svgId) {
case 'diamond':
_shape = 'question';
break;
case 'hexagon':
_shape = 'hexagon';
break;
case 'odd':
_shape = 'rect_left_inv_arrow';
break;
@@ -145,6 +116,12 @@ export const addVertices = function(vert, g, svgId) {
case 'ellipse':
_shape = 'ellipse';
break;
case 'stadium':
_shape = 'stadium';
break;
case 'cylinder':
_shape = 'cylinder';
break;
case 'group':
_shape = 'rect';
break;
@@ -154,13 +131,13 @@ export const addVertices = function(vert, g, svgId) {
// Add the node
g.setNode(vertex.id, {
labelType: 'svg',
labelStyle: labelStyle,
labelStyle: styles.labelStyle,
shape: _shape,
label: vertexNode,
rx: radious,
ry: radious,
class: classStr,
style: style,
style: styles.style,
id: vertex.id
});
});
@@ -175,8 +152,12 @@ export const addEdges = function(edges, g) {
let cnt = 0;
let defaultStyle;
let defaultLabelStyle;
if (typeof edges.defaultStyle !== 'undefined') {
defaultStyle = edges.defaultStyle.toString().replace(/,/g, ';');
const defaultStyles = getStylesFromArray(edges.defaultStyle);
defaultStyle = defaultStyles.style;
defaultLabelStyle = defaultStyles.labelStyle;
}
edges.forEach(function(edge) {
@@ -191,10 +172,12 @@ export const addEdges = function(edges, g) {
}
let style = '';
let labelStyle = '';
if (typeof edge.style !== 'undefined') {
edge.style.forEach(function(s) {
style = style + s + ';';
});
const styles = getStylesFromArray(edge.style);
style = styles.style;
labelStyle = styles.labelStyle;
} else {
switch (edge.stroke) {
case 'normal':
@@ -202,16 +185,21 @@ export const addEdges = function(edges, g) {
if (typeof defaultStyle !== 'undefined') {
style = defaultStyle;
}
if (typeof defaultLabelStyle !== 'undefined') {
labelStyle = defaultLabelStyle;
}
break;
case 'dotted':
style = 'stroke: #333; fill:none;stroke-width:2px;stroke-dasharray:3;';
style = 'fill:none;stroke-width:2px;stroke-dasharray:3;';
break;
case 'thick':
style = 'stroke: #333; stroke-width: 3.5px;fill:none';
style = ' stroke-width: 3.5px;fill:none';
break;
}
}
edgeData.style = style;
edgeData.labelStyle = labelStyle;
if (typeof edge.interpolate !== 'undefined') {
edgeData.curve = interpolateToCurve(edge.interpolate, d3.curveLinear);
@@ -227,18 +215,20 @@ export const addEdges = function(edges, g) {
}
} else {
edgeData.arrowheadStyle = 'fill: #333';
if (typeof edge.style === 'undefined') {
edgeData.labelpos = 'c';
if (getConfig().flowchart.htmlLabels) {
edgeData.labelType = 'html';
edgeData.label = '<span class="edgeLabel">' + edge.text + '</span>';
} else {
edgeData.labelType = 'text';
edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none';
edgeData.label = edge.text.replace(/<br>/g, '\n');
}
edgeData.labelpos = 'c';
if (getConfig().flowchart.htmlLabels) {
edgeData.labelType = 'html';
edgeData.label = '<span class="edgeLabel">' + edge.text + '</span>';
} else {
edgeData.label = edge.text.replace(/<br>/g, '\n');
edgeData.labelType = 'text';
edgeData.label = edge.text.replace(/<br\s*\/?>/gi, '\n');
if (typeof edge.style === 'undefined') {
edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none';
}
edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:');
}
}
// Add the edge to the graph
@@ -285,6 +275,10 @@ export const draw = function(text, id) {
dir = 'TD';
}
const conf = getConfig().flowchart;
const nodeSpacing = conf.nodeSpacing || 50;
const rankSpacing = conf.rankSpacing || 50;
// Create the input mermaid.graph
const g = new graphlib.Graph({
multigraph: true,
@@ -292,8 +286,10 @@ export const draw = function(text, id) {
})
.setGraph({
rankdir: dir,
marginx: 20,
marginy: 20
nodesep: nodeSpacing,
ranksep: rankSpacing,
marginx: 8,
marginy: 8
})
.setDefaultEdgeLabel(function() {
return {};
@@ -328,199 +324,8 @@ export const draw = function(text, id) {
const Render = dagreD3.render;
const render = new Render();
// Add custom shape for rhombus type of boc (decision)
render.shapes().question = function(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const s = (w + h) * 0.9;
const points = [
{ x: s / 2, y: 0 },
{ x: s, y: -s / 2 },
{ x: s / 2, y: -s },
{ x: 0, y: -s / 2 }
];
const shapeSvg = parent
.insert('polygon', ':first-child')
.attr(
'points',
points
.map(function(d) {
return d.x + ',' + d.y;
})
.join(' ')
)
.attr('rx', 5)
.attr('ry', 5)
.attr('transform', 'translate(' + -s / 2 + ',' + (s * 2) / 4 + ')');
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
};
// Add custom shape for box with inverted arrow on left side
render.shapes().rect_left_inv_arrow = function(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const points = [
{ x: -h / 2, y: 0 },
{ x: w, y: 0 },
{ x: w, y: -h },
{ x: -h / 2, y: -h },
{ x: 0, y: -h / 2 }
];
const shapeSvg = parent
.insert('polygon', ':first-child')
.attr(
'points',
points
.map(function(d) {
return d.x + ',' + d.y;
})
.join(' ')
)
.attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')');
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
};
// Add custom shape for box with inverted arrow on left side
render.shapes().lean_right = function(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const points = [
{ x: (-2 * h) / 6, y: 0 },
{ x: w - h / 6, y: 0 },
{ x: w + (2 * h) / 6, y: -h },
{ x: h / 6, y: -h }
];
const shapeSvg = parent
.insert('polygon', ':first-child')
.attr(
'points',
points
.map(function(d) {
return d.x + ',' + d.y;
})
.join(' ')
)
.attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')');
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
};
// Add custom shape for box with inverted arrow on left side
render.shapes().lean_left = function(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const points = [
{ x: (2 * h) / 6, y: 0 },
{ x: w + h / 6, y: 0 },
{ x: w - (2 * h) / 6, y: -h },
{ x: -h / 6, y: -h }
];
const shapeSvg = parent
.insert('polygon', ':first-child')
.attr(
'points',
points
.map(function(d) {
return d.x + ',' + d.y;
})
.join(' ')
)
.attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')');
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
};
// Add custom shape for box with inverted arrow on left side
render.shapes().trapezoid = function(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const points = [
{ x: (-2 * h) / 6, y: 0 },
{ x: w + (2 * h) / 6, y: 0 },
{ x: w - h / 6, y: -h },
{ x: h / 6, y: -h }
];
const shapeSvg = parent
.insert('polygon', ':first-child')
.attr(
'points',
points
.map(function(d) {
return d.x + ',' + d.y;
})
.join(' ')
)
.attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')');
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
};
// Add custom shape for box with inverted arrow on left side
render.shapes().inv_trapezoid = function(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const points = [
{ x: h / 6, y: 0 },
{ x: w - h / 6, y: 0 },
{ x: w + (2 * h) / 6, y: -h },
{ x: (-2 * h) / 6, y: -h }
];
const shapeSvg = parent
.insert('polygon', ':first-child')
.attr(
'points',
points
.map(function(d) {
return d.x + ',' + d.y;
})
.join(' ')
)
.attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')');
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
};
// Add custom shape for box with inverted arrow on right side
render.shapes().rect_right_inv_arrow = function(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
const points = [
{ x: 0, y: 0 },
{ x: w + h / 2, y: 0 },
{ x: w, y: -h / 2 },
{ x: w + h / 2, y: -h },
{ x: 0, y: -h }
];
const shapeSvg = parent
.insert('polygon', ':first-child')
.attr(
'points',
points
.map(function(d) {
return d.x + ',' + d.y;
})
.join(' ')
)
.attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')');
node.intersect = function(point) {
return dagreD3.intersect.polygon(node, points, point);
};
return shapeSvg;
};
// Add custom shapes
flowChartShapes.addToRender(render);
// Add our custom arrow - an empty arrowhead
render.arrows().none = function normal(parent, id, edge, type) {
@@ -540,7 +345,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)
@@ -572,12 +377,26 @@ export const draw = function(text, id) {
});
const padding = 8;
const width = g.maxX - g.minX + padding * 2;
const height = g.maxY - g.minY + padding * 2;
svg.attr('width', '100%');
svg.attr('style', `max-width: ${width}px;`);
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;`);
} else {
svg.attr('height', height);
svg.attr('width', width);
}
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 - g._label.marginx}, ${padding - svgBounds.y})`);
// Index nodes
flowDb.indexNodes('subGraph' + i);
@@ -587,8 +406,8 @@ export const draw = function(text, id) {
subG = subGraphs[i];
if (subG.title !== 'undefined') {
const clusterRects = document.querySelectorAll('#' + id + ' #' + subG.id + ' rect');
const clusterEl = document.querySelectorAll('#' + id + ' #' + subG.id);
const clusterRects = document.querySelectorAll('#' + id + ' [id="' + subG.id + '"] rect');
const clusterEl = document.querySelectorAll('#' + id + ' [id="' + subG.id + '"]');
const xPos = clusterRects[0].x.baseVal.value;
const yPos = clusterRects[0].y.baseVal.value;
@@ -597,12 +416,16 @@ export const draw = function(text, id) {
const te = cluster.select('.label');
te.attr('transform', `translate(${xPos + width / 2}, ${yPos + 14})`);
te.attr('id', id + 'Text');
for (let j = 0; j < subG.classes.length; j++) {
clusterEl[0].classList.add(subG.classes[j]);
}
}
}
// Add label rects for non html labels
if (!getConfig().flowchart.htmlLabels) {
const labels = document.querySelectorAll('#' + id + ' .edgeLabel .label');
if (!conf.htmlLabels) {
const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label');
for (let k = 0; k < labels.length; k++) {
const label = labels[k];
@@ -619,6 +442,40 @@ export const draw = function(text, id) {
label.insertBefore(rect, label.firstChild);
}
}
// If node has a link, wrap it in an anchor SVG object.
const keys = Object.keys(vert);
keys.forEach(function(key) {
const vertex = vert[key];
if (vertex.link) {
const node = d3.select('#' + id + ' [id="' + key + '"]');
if (node) {
const link = document.createElementNS('http://www.w3.org/2000/svg', 'a');
link.setAttributeNS('http://www.w3.org/2000/svg', 'class', vertex.classes.join(' '));
link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertex.link);
link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener');
const linkNode = node.insert(function() {
return link;
}, ':first-child');
const shape = node.select('.label-container');
if (shape) {
linkNode.append(function() {
return shape.node();
});
}
const label = node.select('.label');
if (label) {
linkNode.append(function() {
return label.node();
});
}
}
}
});
};
export default {

View File

@@ -0,0 +1,188 @@
import { addVertices, addEdges } from './flowRenderer';
import { setConfig } from '../../config';
setConfig({
flowchart: {
htmlLabels: false
}
});
describe('the flowchart renderer', function() {
describe('when adding vertices to a graph', function() {
[
['round', 'rect', 5],
['square', 'rect'],
['diamond', 'question'],
['hexagon', 'hexagon'],
['odd', 'rect_left_inv_arrow'],
['lean_right', 'lean_right'],
['lean_left', 'lean_left'],
['trapezoid', 'trapezoid'],
['inv_trapezoid', 'inv_trapezoid'],
['odd_right', 'rect_left_inv_arrow'],
['circle', 'circle'],
['ellipse', 'ellipse'],
['stadium', 'stadium'],
['cylinder', 'cylinder'],
['group', 'rect']
].forEach(function([type, expectedShape, expectedRadios = 0]) {
it(`should add the correct shaped node to the graph for vertex type ${type}`, function() {
const addedNodes = [];
const mockG = {
setNode: function(id, object) {
addedNodes.push([id, object]);
}
};
addVertices(
{
v1: {
type,
id: 'my-node-id',
classes: [],
styles: [],
text: 'my vertex text'
}
},
mockG,
'svg-id'
);
expect(addedNodes).toHaveLength(1);
expect(addedNodes[0][0]).toEqual('my-node-id');
expect(addedNodes[0][1]).toHaveProperty('id', 'my-node-id');
expect(addedNodes[0][1]).toHaveProperty('labelType', 'svg');
expect(addedNodes[0][1]).toHaveProperty('shape', expectedShape);
expect(addedNodes[0][1]).toHaveProperty('rx', expectedRadios);
expect(addedNodes[0][1]).toHaveProperty('ry', expectedRadios);
});
});
[
'Multi<br>Line',
'Multi<br/>Line',
'Multi<br />Line',
'Multi<br\t/>Line'
].forEach(function(labelText) {
it('should handle multiline texts with different line breaks', function() {
const addedNodes = [];
const mockG = {
setNode: function(id, object) {
addedNodes.push([id, object]);
}
};
addVertices(
{
v1: {
type: 'rect',
id: 'my-node-id',
classes: [],
styles: [],
text: 'Multi<br>Line'
}
},
mockG,
'svg-id'
);
expect(addedNodes).toHaveLength(1);
expect(addedNodes[0][0]).toEqual('my-node-id');
expect(addedNodes[0][1]).toHaveProperty('id', 'my-node-id');
expect(addedNodes[0][1]).toHaveProperty('labelType', 'svg');
expect(addedNodes[0][1].label).toBeDefined();
expect(addedNodes[0][1].label).toBeDefined(); // <text> node
expect(addedNodes[0][1].label.firstChild.innerHTML).toEqual('Multi'); // <tspan> node, line 1
expect(addedNodes[0][1].label.lastChild.innerHTML).toEqual('Line'); // <tspan> node, line 2
});
});
[
[['fill:#fff'], 'fill:#fff;', ''],
[['color:#ccc'], '', 'color:#ccc;'],
[['fill:#fff', 'color:#ccc'], 'fill:#fff;', 'color:#ccc;'],
[['fill:#fff', 'color:#ccc', 'text-align:center'], 'fill:#fff;', 'color:#ccc;text-align:center;']
].forEach(function([style, expectedStyle, expectedLabelStyle]) {
it(`should add the styles to style and/or labelStyle for style ${style}`, function() {
const addedNodes = [];
const mockG = {
setNode: function(id, object) {
addedNodes.push([id, object]);
}
};
addVertices(
{
v1: {
type: 'rect',
id: 'my-node-id',
classes: [],
styles: style,
text: 'my vertex text'
}
},
mockG,
'svg-id'
);
expect(addedNodes).toHaveLength(1);
expect(addedNodes[0][0]).toEqual('my-node-id');
expect(addedNodes[0][1]).toHaveProperty('id', 'my-node-id');
expect(addedNodes[0][1]).toHaveProperty('labelType', 'svg');
expect(addedNodes[0][1]).toHaveProperty('style', expectedStyle);
expect(addedNodes[0][1]).toHaveProperty('labelStyle', expectedLabelStyle);
});
});
});
describe('when adding edges to a graph', function() {
it('should handle multiline texts and set centered label position', function() {
const addedEdges = [];
const mockG = {
setEdge: function(s, e, data, c) {
addedEdges.push(data);
}
};
addEdges(
[
{ text: 'Multi<br>Line' },
{ text: 'Multi<br/>Line' },
{ text: 'Multi<br />Line' },
{ text: 'Multi<br\t/>Line' },
{ style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi<br>Line' },
{ style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi<br/>Line' },
{ style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi<br />Line' },
{ style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi<br\t/>Line' }
],
mockG,
'svg-id'
);
addedEdges.forEach(function(edge) {
expect(edge).toHaveProperty('label', 'Multi\nLine');
expect(edge).toHaveProperty('labelpos', 'c');
});
});
[
[['stroke:DarkGray'], 'stroke:DarkGray;', ''],
[['color:red'], '', 'fill:red;'],
[['stroke:DarkGray', 'color:red'], 'stroke:DarkGray;', 'fill:red;'],
[['stroke:DarkGray', 'color:red', 'stroke-width:2px'], 'stroke:DarkGray;stroke-width:2px;', 'fill:red;']
].forEach(function([style, expectedStyle, expectedLabelStyle]) {
it(`should add the styles to style and/or labelStyle for style ${style}`, function() {
const addedEdges = [];
const mockG = {
setEdge: function(s, e, data, c) {
addedEdges.push(data);
}
};
addEdges(
[
{ style: style, text: 'styling' }
],
mockG,
'svg-id'
);
expect(addedEdges).toHaveLength(1);
expect(addedEdges[0]).toHaveProperty('style', expectedStyle);
expect(addedEdges[0]).toHaveProperty('labelStyle', expectedLabelStyle);
});
});
});
});

View File

@@ -0,0 +1,245 @@
import flowDb from '../flowDb';
import flow from './flow';
import { setConfig } from '../../../config';
setConfig({
securityLevel: 'strict'
});
describe('[Arrows] when parsing', () => {
beforeEach(function() {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});
it('should handle a nodes and edges', function() {
const res = flow.parser.parse('graph TD;\nA-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it("should handle angle bracket ' > ' as direction LR", function() {
const res = flow.parser.parse('graph >;A-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const direction = flow.parser.yy.getDirection();
expect(direction).toBe('LR');
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it("should handle angle bracket ' < ' as direction RL", function() {
const res = flow.parser.parse('graph <;A-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const direction = flow.parser.yy.getDirection();
expect(direction).toBe('RL');
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it("should handle caret ' ^ ' as direction BT", function() {
const res = flow.parser.parse('graph ^;A-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const direction = flow.parser.yy.getDirection();
expect(direction).toBe('BT');
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it("should handle lower-case 'v' as direction TB", function() {
const res = flow.parser.parse('graph v;A-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const direction = flow.parser.yy.getDirection();
expect(direction).toBe('TB');
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it('should handle a nodes and edges and a space between link and node', function() {
const res = flow.parser.parse('graph TD;A --> B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it('should handle a nodes and edges, a space between link and node and each line ending without semicolon', function() {
const res = flow.parser.parse('graph TD\nA --> B\n style e red');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it('should handle statements ending without semicolon', function() {
const res = flow.parser.parse('graph TD\nA-->B\nB-->C');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(2);
expect(edges[1].start).toBe('B');
expect(edges[1].end).toBe('C');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
describe('it should multi directional arrows', function() {
describe('point', function() {
it('should handle double edged nodes and edges', function() {
const res = flow.parser.parse('graph TD;\nA<-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('');
});
it('should handle double edged nodes with text', function() {
const res = flow.parser.parse('graph TD;\nA<-- text -->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].text).toBe('text');
});
it('should handle double edged nodes and edges on thick arrows', function() {
const res = flow.parser.parse('graph TD;\nA<==>B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].text).toBe('');
});
it('should handle double edged nodes with text on thick arrows', function() {
const res = flow.parser.parse('graph TD;\nA<== text ==>B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].text).toBe('text');
});
it('should handle double edged nodes and edges on dotted arrows', function() {
const res = flow.parser.parse('graph TD;\nA<-.->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].text).toBe('');
});
it('should handle double edged nodes with text on dotted arrows', function() {
const res = flow.parser.parse('graph TD;\nA<-. text .->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].text).toBe('text');
});
});
});
});

View File

@@ -0,0 +1,151 @@
import flowDb from '../flowDb';
import flow from './flow';
import { setConfig } from '../../../config';
setConfig({
securityLevel: 'strict'
});
describe('[Comments] when parsing', () => {
beforeEach(function() {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});
it('should handle comments', function() {
const res = flow.parser.parse('graph TD;\n%% Comment\n A-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it('should handle comments at the start', function() {
const res = flow.parser.parse('%% Comment\ngraph TD;\n A-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it('should handle comments at the end', function() {
const res = flow.parser.parse('graph TD;\n A-->B\n %% Comment at the end\n');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it('should handle comments at the end no trailing newline', function() {
const res = flow.parser.parse('graph TD;\n A-->B\n%% Commento');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it('should handle comments at the end many trailing newlines', function() {
const res = flow.parser.parse('graph TD;\n A-->B\n%% Commento\n\n\n');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it('should handle no trailing newlines', function() {
const res = flow.parser.parse('graph TD;\n A-->B');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it('should handle many trailing newlines', function() {
const res = flow.parser.parse('graph TD;\n A-->B\n\n');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it('should handle a comment with blank rows in-between', function() {
const res = flow.parser.parse('graph TD;\n\n\n %% Comment\n A-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
it('should handle a comment with mermaid flowchart code in them', function() {
const res = flow.parser.parse(
'graph TD;\n\n\n %% Test od>Odd shape]-->|Two line<br>edge comment|ro;\n A-->B;'
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
});
});

View File

@@ -0,0 +1,253 @@
import flowDb from '../flowDb';
import flow from './flow';
import { setConfig } from '../../../config';
setConfig({
securityLevel: 'strict'
});
describe('[Edges] when parsing', () => {
beforeEach(function() {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});
it('should handle open ended edges', function() {
const res = flow.parser.parse('graph TD;A---B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_open');
});
it('should handle cross ended edges', function() {
const res = flow.parser.parse('graph TD;A--xB;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
});
it('should handle open ended edges', function() {
const res = flow.parser.parse('graph TD;A--oB;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_circle');
});
describe('cross', function() {
it('should handle double edged nodes and edges', function() {
const res = flow.parser.parse('graph TD;\nA x--x B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_cross');
expect(edges[0].text).toBe('');
});
it('should handle double edged nodes with text', function() {
const res = flow.parser.parse('graph TD;\nA x-- text --x B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_cross');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].text).toBe('text');
});
it('should handle double edged nodes and edges on thick arrows', function() {
const res = flow.parser.parse('graph TD;\nA x==x B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_cross');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].text).toBe('');
});
it('should handle double edged nodes with text on thick arrows XYZ1', function() {
const res = flow.parser.parse('graph TD;\nA x== text ==x B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_cross');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].text).toBe('text');
});
it('should handle double edged nodes and edges on dotted arrows', function() {
const res = flow.parser.parse('graph TD;\nA x-.-x B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_cross');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].text).toBe('');
});
it('should handle double edged nodes with text on dotted arrows', function() {
const res = flow.parser.parse('graph TD;\nA x-. text .-x B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_cross');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].text).toBe('text');
});
});
describe('circle', function() {
it('should handle double edged nodes and edges', function() {
const res = flow.parser.parse('graph TD;\nA o--o B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_circle');
expect(edges[0].text).toBe('');
});
it('should handle double edged nodes with text', function() {
const res = flow.parser.parse('graph TD;\nA o-- text --o B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_circle');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].text).toBe('text');
});
it('should handle double edged nodes and edges on thick arrows', function() {
const res = flow.parser.parse('graph TD;\nA o==o B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_circle');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].text).toBe('');
});
it('should handle double edged nodes with text on thick arrows', function() {
const res = flow.parser.parse('graph TD;\nA o== text ==o B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_circle');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].text).toBe('text');
});
it('should handle double edged nodes and edges on dotted arrows', function() {
const res = flow.parser.parse('graph TD;\nA o-.-o B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_circle');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].text).toBe('');
});
it('should handle double edged nodes with text on dotted arrows', function() {
const res = flow.parser.parse('graph TD;\nA o-. text .-o B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_circle');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].text).toBe('text');
});
});
it('should handle multiple edges', function() {
const res = flow.parser.parse(
'graph TD;A---|This is the 123 s text|B;\nA---|This is the second edge|B;'
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(2);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].text).toBe('This is the 123 s text');
expect(edges[1].start).toBe('A');
expect(edges[1].end).toBe('B');
expect(edges[1].text).toBe('This is the second edge');
});
});

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More