2015-07-17 23:13:40 +02:00
/ * *
2019-09-11 20:03:22 +02:00
* This is the api to be used when optionally handling the integration with the web page , instead of using the default integration provided by mermaid . js .
*
* The core of this api is the [ * * render * * ] ( https : //github.com/knsv/mermaid/blob/master/docs/mermaidAPI.md#render) function which, given a graph
* definition as text , renders the graph / diagram and returns an svg element for the graph .
*
* It is is then up to the user of the API to make use of the svg , either insert it somewhere in the page or do something completely different .
*
* In addition to the render function , a number of behavioral configuration options are available .
2015-07-17 23:13:40 +02:00
*
2019-07-14 06:07:27 -07:00
* @ name mermaidAPI
2019-09-12 12:59:13 -07:00
* /
2020-05-11 07:10:04 +01:00
import { select } from 'd3' ;
2019-09-12 12:59:13 -07:00
import scope from 'scope-css' ;
import pkg from '../package.json' ;
import { setConfig , getConfig } from './config' ;
import { logger , setLogLevel } from './logger' ;
2020-06-17 18:12:01 -04:00
import utils , { assignWithDepth } from './utils' ;
2019-09-12 12:59:13 -07:00
import flowRenderer from './diagrams/flowchart/flowRenderer' ;
2020-03-08 09:49:41 +01:00
import flowRendererV2 from './diagrams/flowchart/flowRenderer-v2' ;
2019-09-12 12:59:13 -07:00
import flowParser from './diagrams/flowchart/parser/flow' ;
import flowDb from './diagrams/flowchart/flowDb' ;
import sequenceRenderer from './diagrams/sequence/sequenceRenderer' ;
import sequenceParser from './diagrams/sequence/parser/sequenceDiagram' ;
import sequenceDb from './diagrams/sequence/sequenceDb' ;
import ganttRenderer from './diagrams/gantt/ganttRenderer' ;
import ganttParser from './diagrams/gantt/parser/gantt' ;
import ganttDb from './diagrams/gantt/ganttDb' ;
import classRenderer from './diagrams/class/classRenderer' ;
import classParser from './diagrams/class/parser/classDiagram' ;
import classDb from './diagrams/class/classDb' ;
2019-09-25 21:01:21 +02:00
import stateRenderer from './diagrams/state/stateRenderer' ;
2020-03-22 21:45:14 +01:00
import stateRendererV2 from './diagrams/state/stateRenderer-v2' ;
2019-09-25 21:01:21 +02:00
import stateParser from './diagrams/state/parser/stateDiagram' ;
import stateDb from './diagrams/state/stateDb' ;
2019-09-12 12:59:13 -07:00
import gitGraphRenderer from './diagrams/git/gitGraphRenderer' ;
import gitGraphParser from './diagrams/git/parser/gitGraph' ;
import gitGraphAst from './diagrams/git/gitGraphAst' ;
import infoRenderer from './diagrams/info/infoRenderer' ;
2020-06-06 12:42:35 +02:00
import errorRenderer from './errorRenderer' ;
2019-09-12 12:59:13 -07:00
import infoParser from './diagrams/info/parser/info' ;
import infoDb from './diagrams/info/infoDb' ;
import pieRenderer from './diagrams/pie/pieRenderer' ;
import pieParser from './diagrams/pie/parser/pie' ;
import pieDb from './diagrams/pie/pieDb' ;
2020-03-03 21:44:18 +00:00
import erDb from './diagrams/er/erDb' ;
import erParser from './diagrams/er/parser/erDiagram' ;
import erRenderer from './diagrams/er/erRenderer' ;
2020-04-04 17:50:02 +01:00
import journeyParser from './diagrams/user-journey/parser/journey' ;
import journeyDb from './diagrams/user-journey/journeyDb' ;
import journeyRenderer from './diagrams/user-journey/journeyRenderer' ;
2019-09-12 12:59:13 -07:00
const themes = { } ;
2018-03-13 14:31:56 +08:00
for ( const themeName of [ 'default' , 'forest' , 'dark' , 'neutral' ] ) {
2019-09-12 12:59:13 -07:00
themes [ themeName ] = require ( ` ./themes/ ${ themeName } /index.scss ` ) ;
2017-09-12 22:54:50 +08:00
}
2017-09-12 22:06:19 +08:00
2015-06-20 20:58:58 +02:00
/ * *
2019-09-11 20:03:22 +02:00
* These are the default options which can be overridden with the initialization call like so :
* * * Example 1 : * *
* < pre >
2015-07-17 23:13:40 +02:00
* mermaid . initialize ( {
* flowchart : {
2020-01-12 14:38:57 +01:00
* htmlLabels : false
2015-07-17 23:13:40 +02:00
* }
* } ) ;
2019-09-11 20:03:22 +02:00
* < / p r e >
*
* * * Example 2 : * *
* < pre >
2020-01-12 14:38:57 +01:00
* & lt ; script >
2019-09-11 20:03:22 +02:00
* var config = {
* startOnLoad : true ,
* flowchart : {
* useMaxWidth : true ,
* htmlLabels : true ,
* curve : 'cardinal' ,
* } ,
*
* securityLevel : 'loose' ,
* } ;
* mermaid . initialize ( config ) ;
2020-01-12 14:38:57 +01:00
* & lt ; / s c r i p t >
2019-09-11 20:03:22 +02:00
* < / p r e >
* 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.
*
2019-07-14 06:07:27 -07:00
* @ name Configuration
2015-06-20 20:58:58 +02:00
* /
2017-09-14 19:40:38 +08:00
const config = {
2018-12-18 13:32:36 +08:00
/ * * t h e m e , t h e C S S s t y l e s h e e t
2019-09-12 12:59:13 -07:00
*
* * * theme * * - Choose one of the built - in themes :
* * default
* * forest
* * dark
* * neutral .
* To disable any pre - defined mermaid theme , use "null" .
*
* * * themeCSS * * - Use your own CSS . This overrides * * theme * * .
* < pre >
* "theme" : "forest" ,
* "themeCSS" : ".node rect { fill: red; }"
* < / p r e >
* /
2018-03-15 21:22:49 +08:00
theme : 'default' ,
2018-03-15 21:47:53 +08:00
themeCSS : undefined ,
2020-01-25 13:35:11 +01:00
/* **maxTextSize** - The maximum allowed size of the users text diamgram */
maxTextSize : 50000 ,
2019-10-13 19:16:35 +02:00
2019-10-12 16:53:21 +02:00
/ * *
* * * fontFamily * * The font to be used for the rendered diagrams . Default value is \ "trebuchet ms\" , verdana , arial ;
* /
fontFamily : '"trebuchet ms", verdana, arial;' ,
2017-09-12 22:54:50 +08:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* This option decides the amount of logging to be used .
2017-04-16 23:24:47 +08:00
* * debug : 1
* * info : 2
* * warn : 3
* * error : 4
2019-07-14 06:07:27 -07:00
* * fatal : ( * * default * * ) 5
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
logLevel : 5 ,
2015-07-17 23:13:40 +02:00
2019-07-13 22:50:53 -07:00
/ * *
2019-07-14 06:07:27 -07:00
* Sets the level of trust to be used on the parsed diagrams .
2019-09-11 20:03:22 +02:00
* * * * strict * * : ( * * default * * ) tags in text are encoded , click functionality is disabeled
* * * * loose * * : tags in text are allowed , click functionality is enabled
2019-07-13 22:50:53 -07:00
* /
2019-07-14 06:07:27 -07:00
securityLevel : 'strict' ,
2019-07-13 22:50:53 -07:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* This options controls whether or mermaid starts when the page loads
* * * Default value true * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
startOnLoad : true ,
2015-09-26 12:09:47 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* This options controls whether or arrow markers in html code will be absolute paths or
2017-04-16 23:24:47 +08:00
* an anchor , # . This matters if you are using base tag settings .
2019-07-14 06:07:27 -07:00
* * * Default value false * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
arrowMarkerAbsolute : false ,
2015-11-21 11:51:15 +01:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* The object containing configurations specific for flowcharts
2017-04-16 23:24:47 +08:00
* /
flowchart : {
2015-09-26 12:09:47 +02:00
/ * *
2019-07-14 06:07:27 -07:00
* Flag for setting whether or not a html tag should be used for rendering labels
* on the edges .
* * * Default value true * * .
2015-09-26 12:09:47 +02:00
* /
2017-04-11 22:14:25 +08:00
htmlLabels : true ,
2018-03-17 23:05:14 +08:00
2020-01-12 14:09:24 +01:00
/ * *
* 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 * * .
* /
nodeSpacing : 50 ,
/ * *
* 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 * * .
* /
rankSpacing : 50 ,
2019-07-14 06:07:27 -07:00
/ * *
2019-09-11 20:03:22 +02:00
* How mermaid renders curves for flowcharts . Possible values are
* * basis
* * linear * * default * *
* * cardinal
2019-07-14 06:07:27 -07:00
* /
2020-03-08 09:49:41 +01:00
curve : 'linear' ,
// Only used in new experimental rendering
// repreesents the padding between the labels and the shape
padding : 15
2017-04-11 22:14:25 +08:00
} ,
2015-07-17 23:13:40 +02:00
2017-04-16 23:24:47 +08:00
/ * *
* The object containing configurations specific for sequence diagrams
* /
2018-03-12 21:16:22 +08:00
sequence : {
2017-04-16 23:24:47 +08:00
/ * *
2019-09-11 20:03:22 +02:00
* margin to the right and left of the sequence diagram .
2019-07-14 06:07:27 -07:00
* * * Default value 50 * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
diagramMarginX : 50 ,
2015-07-17 23:13:40 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* margin to the over and under the sequence diagram .
* * * Default value 10 * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
diagramMarginY : 10 ,
2015-07-17 23:13:40 +02:00
2015-09-26 12:09:47 +02:00
/ * *
2019-07-14 06:07:27 -07:00
* Margin between actors .
* * * Default value 50 * * .
2015-09-26 12:09:47 +02:00
* /
2017-04-11 22:14:25 +08:00
actorMargin : 50 ,
2015-07-17 23:13:40 +02:00
2015-09-26 12:09:47 +02:00
/ * *
2019-07-14 06:07:27 -07:00
* Width of actor boxes
* * * Default value 150 * * .
2015-09-26 12:09:47 +02:00
* /
2017-04-11 22:14:25 +08:00
width : 150 ,
2015-07-17 23:13:40 +02:00
2015-09-26 12:09:47 +02:00
/ * *
2019-07-14 06:07:27 -07:00
* Height of actor boxes
* * * Default value 65 * * .
2015-09-26 12:09:47 +02:00
* /
2017-04-11 22:14:25 +08:00
height : 65 ,
2015-07-17 23:13:40 +02:00
2015-09-26 12:09:47 +02:00
/ * *
2019-07-14 06:07:27 -07:00
* Margin around loop boxes
* * * Default value 10 * * .
2015-09-26 12:09:47 +02:00
* /
2017-04-11 22:14:25 +08:00
boxMargin : 10 ,
2015-07-17 23:13:40 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* margin around the text in loop / alt / opt boxes
* * * Default value 5 * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
boxTextMargin : 5 ,
2015-05-30 17:20:24 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* margin around notes .
* * * Default value 10 * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
noteMargin : 10 ,
2015-07-17 23:13:40 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* Space between messages .
* * * Default value 35 * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
messageMargin : 35 ,
2015-07-17 23:13:40 +02:00
2020-03-24 22:14:19 +01:00
/ * *
* Multiline message alignment . Possible values are :
* * left
* * center * * default * *
* * right
* /
messageAlign : 'center' ,
2015-09-26 12:09:47 +02:00
/ * *
2019-07-14 06:07:27 -07:00
* mirror actors under diagram .
* * * Default value true * * .
2015-09-26 12:09:47 +02:00
* /
2017-04-11 22:14:25 +08:00
mirrorActors : true ,
2015-07-17 23:13:40 +02:00
2015-09-26 12:09:47 +02:00
/ * *
2019-07-14 06:07:27 -07:00
* Depending on css styling this might need adjustment .
* Prolongs the edge of the diagram downwards .
* * * Default value 1 * * .
2015-09-26 12:09:47 +02:00
* /
2017-04-11 22:14:25 +08:00
bottomMarginAdj : 1 ,
2015-07-17 23:13:40 +02:00
2015-09-26 12:09:47 +02:00
/ * *
2019-07-14 06:07:27 -07:00
* when this flag is set the height and width is set to 100 % and is then scaling with the
* available space if not the absolute space required is used .
* * * Default value true * * .
2015-09-26 12:09:47 +02:00
* /
2018-08-17 10:56:15 -04:00
useMaxWidth : true ,
/ * *
2019-07-14 06:07:27 -07:00
* This will display arrows that start and begin at the same node as right angles , rather than a curve
* * * Default value false * * .
2018-08-17 10:56:15 -04:00
* /
2019-06-30 16:14:59 +02:00
rightAngles : false ,
2018-08-16 13:44:59 -04:00
/ * *
2019-07-14 06:07:27 -07:00
* This will show the node numbers
* * * Default value false * * .
2018-08-16 13:44:59 -04:00
* /
2020-04-23 07:37:32 +03:00
showSequenceNumbers : false ,
/ * *
* This sets the font size of the actor ' s description
* * * Default value 14 * * .
* /
actorFontSize : 14 ,
/ * *
* This sets the font family of the actor ' s description
* * * Default value "Open-Sans" , "sans-serif" * * .
* /
actorFontFamily : '"Open-Sans", "sans-serif"' ,
2020-06-08 14:48:03 -04:00
/ * *
* This sets the font weight of the actor ' s description
* * * Default value 400.
* /
actorFontWeight : 400 ,
2020-04-23 07:37:32 +03:00
/ * *
* This sets the font size of actor - attached notes .
* * * Default value 14 * * .
* /
noteFontSize : 14 ,
/ * *
* This sets the font family of actor - attached notes .
* * * Default value "trebuchet ms" , verdana , arial * * .
* /
noteFontFamily : '"trebuchet ms", verdana, arial' ,
2020-06-08 14:48:03 -04:00
/ * *
* This sets the font weight of the note ' s description
* * * Default value 400.
* /
noteFontWeight : 400 ,
2020-04-23 07:37:32 +03:00
/ * *
* This sets the text alignment of actor - attached notes .
* * * Default value center * * .
* /
noteAlign : 'center' ,
/ * *
* This sets the font size of actor messages .
* * * Default value 16 * * .
* /
messageFontSize : 16 ,
/ * *
* This sets the font family of actor messages .
* * * Default value "trebuchet ms" , verdana , arial * * .
* /
2020-06-08 14:48:03 -04:00
messageFontFamily : '"trebuchet ms", verdana, arial' ,
/ * *
* This sets the font weight of the message ' s description
* * * Default value 400.
* /
messageFontWeight : 400 ,
/ * *
* This sets the auto - wrap state for the diagram
* * * Default value false .
* /
wrapEnabled : false ,
/ * *
* This sets the auto - wrap padding for the diagram ( sides only )
* * * Default value 15.
* /
wrapPadding : 15
2017-04-11 22:14:25 +08:00
} ,
2015-07-17 23:13:40 +02:00
2019-07-14 06:07:27 -07:00
/ * *
2017-04-16 23:24:47 +08:00
* The object containing configurations specific for gantt diagrams *
* /
2017-04-11 22:14:25 +08:00
gantt : {
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* Margin top for the text over the gantt diagram
* * * Default value 25 * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
titleTopMargin : 25 ,
2015-07-17 23:13:40 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* The height of the bars in the graph
* * * Default value 20 * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
barHeight : 20 ,
2015-07-17 23:13:40 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* The margin between the different activities in the gantt diagram .
* * * Default value 4 * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
barGap : 4 ,
2015-07-17 23:13:40 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* Margin between title and gantt diagram and between axis and gantt diagram .
* * * Default value 50 * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
topPadding : 50 ,
2015-07-17 23:13:40 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* The space allocated for the section name to the left of the activities .
* * * Default value 75 * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
leftPadding : 75 ,
2015-07-17 23:13:40 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* Vertical starting position of the grid lines .
* * * Default value 35 * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
gridLineStartPadding : 35 ,
2015-07-17 23:13:40 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* Font size ...
* * * Default value 11 * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
fontSize : 11 ,
2015-07-17 23:13:40 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* font family ...
* * * Default value '"Open-Sans", "sans-serif"' * * .
2017-04-16 23:24:47 +08:00
* /
2017-04-11 22:14:25 +08:00
fontFamily : '"Open-Sans", "sans-serif"' ,
2015-07-17 23:13:40 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-07-14 06:07:27 -07:00
* The number of alternating section styles .
* * * Default value 4 * * .
2017-04-16 23:24:47 +08:00
* /
2018-03-13 21:17:32 +08:00
numberSectionStyles : 4 ,
2015-07-17 23:13:40 +02:00
2017-04-16 23:24:47 +08:00
/ * *
2019-09-11 20:03:22 +02:00
* Datetime format of the axis . This might need adjustment to match your locale and preferences
2019-07-14 06:07:27 -07:00
* * * Default value '%Y-%m-%d' * * .
2018-03-12 21:33:02 +08:00
* /
axisFormat : '%Y-%m-%d'
2017-04-11 22:14:25 +08:00
} ,
2020-04-04 17:50:02 +01:00
/ * *
* The object containing configurations specific for sequence diagrams
* /
journey : {
/ * *
* margin to the right and left of the sequence diagram .
* * * Default value 50 * * .
* /
diagramMarginX : 50 ,
/ * *
* margin to the over and under the sequence diagram .
* * * Default value 10 * * .
* /
diagramMarginY : 10 ,
/ * *
* Margin between actors .
* * * Default value 50 * * .
* /
actorMargin : 50 ,
/ * *
* Width of actor boxes
* * * Default value 150 * * .
* /
width : 150 ,
/ * *
* Height of actor boxes
* * * Default value 65 * * .
* /
height : 65 ,
/ * *
* Margin around loop boxes
* * * Default value 10 * * .
* /
boxMargin : 10 ,
/ * *
* margin around the text in loop / alt / opt boxes
* * * Default value 5 * * .
* /
boxTextMargin : 5 ,
/ * *
* margin around notes .
* * * Default value 10 * * .
* /
noteMargin : 10 ,
/ * *
* Space between messages .
* * * Default value 35 * * .
* /
messageMargin : 35 ,
/ * *
* Multiline message alignment . Possible values are :
* * left
* * center * * default * *
* * right
* /
messageAlign : 'center' ,
/ * *
* Depending on css styling this might need adjustment .
* Prolongs the edge of the diagram downwards .
* * * Default value 1 * * .
* /
bottomMarginAdj : 1 ,
/ * *
* when this flag is set the height and width is set to 100 % and is then scaling with the
* available space if not the absolute space required is used .
* * * Default value true * * .
* /
useMaxWidth : true ,
/ * *
* This will display arrows that start and begin at the same node as right angles , rather than a curve
* * * Default value false * * .
* /
rightAngles : false
} ,
2018-03-12 21:16:22 +08:00
class : { } ,
2019-10-11 15:39:50 +02:00
git : { } ,
state : {
dividerMargin : 10 ,
sizeUnit : 5 ,
2019-10-27 16:58:32 +01:00
padding : 8 ,
2019-10-11 15:39:50 +02:00
textHeight : 10 ,
titleShift : - 15 ,
noteMargin : 10 ,
forkWidth : 70 ,
forkHeight : 7 ,
// Used
miniPadding : 2 ,
// Font size factor, this is used to guess the width of the edges labels before rendering by dagre
// layout. This might need updating if/when switching font
fontSizeFactor : 5.02 ,
fontSize : 24 ,
labelHeight : 16 ,
edgeLengthFactor : '20' ,
compositTitleSize : 35 ,
radius : 5
2020-03-03 21:44:18 +00:00
} ,
/ * *
* The object containing configurations specific for entity relationship diagrams
* /
er : {
2020-03-29 08:42:20 +01:00
/ * *
* The amount of padding around the diagram as a whole so that embedded diagrams have margins , expressed in pixels
* /
diagramPadding : 20 ,
2020-03-17 09:25:16 +00:00
/ * *
2020-03-17 09:48:32 +00:00
* Directional bias for layout of entities . Can be either 'TB' , 'BT' , 'LR' , or 'RL' ,
* where T = top , B = bottom , L = left , and R = right .
2020-03-17 09:25:16 +00:00
* /
layoutDirection : 'TB' ,
2020-03-03 21:44:18 +00:00
/ * *
2020-03-29 08:42:20 +01:00
* The mimimum width of an entity box , expressed in pixels
2020-03-03 21:44:18 +00:00
* /
minEntityWidth : 100 ,
/ * *
2020-03-29 08:42:20 +01:00
* The minimum height of an entity box , expressed in pixels
2020-03-03 21:44:18 +00:00
* /
minEntityHeight : 75 ,
/ * *
2020-03-29 08:42:20 +01:00
* The minimum internal padding between the text in an entity box and the enclosing box borders , expressed in pixels
2020-03-03 21:44:18 +00:00
* /
entityPadding : 15 ,
/ * *
* Stroke color of box edges and lines
* /
2020-03-10 13:48:53 +00:00
stroke : 'gray' ,
2020-03-03 21:44:18 +00:00
/ * *
* Fill color of entity boxes
* /
fill : 'honeydew' ,
2020-03-11 22:17:11 +00:00
/ * *
2020-04-30 15:55:14 +01:00
* Font size ( expressed as an integer representing a number of pixels )
2020-03-11 22:17:11 +00:00
* /
2020-04-30 15:55:14 +01:00
fontSize : 12
2019-10-11 15:39:50 +02:00
}
2019-09-12 12:59:13 -07:00
} ;
2020-06-15 08:03:13 +02:00
config . class . arrowMarkerAbsolute = config . arrowMarkerAbsolute ;
config . git . arrowMarkerAbsolute = config . arrowMarkerAbsolute ;
2017-04-11 22:14:25 +08:00
2019-09-12 12:59:13 -07:00
setLogLevel ( config . logLevel ) ;
setConfig ( config ) ;
2015-10-04 19:30:53 +02:00
2019-09-12 12:59:13 -07:00
function parse ( text ) {
2020-06-11 15:31:59 -04:00
const graphInit = utils . detectInit ( text ) ;
if ( graphInit ) {
2020-06-17 18:12:01 -04:00
initialize ( graphInit ) ;
2020-06-11 15:31:59 -04:00
logger . debug ( 'Init ' , graphInit ) ;
}
2019-09-12 12:59:13 -07:00
const graphType = utils . detectType ( text ) ;
let parser ;
2017-04-11 22:14:25 +08:00
2019-09-12 12:59:13 -07:00
logger . debug ( 'Type ' + graphType ) ;
2017-04-11 22:14:25 +08:00
switch ( graphType ) {
2018-03-12 21:16:22 +08:00
case 'git' :
2019-09-12 12:59:13 -07:00
parser = gitGraphParser ;
parser . parser . yy = gitGraphAst ;
break ;
2018-03-12 21:06:49 +08:00
case 'flowchart' :
2019-09-19 15:00:21 -07:00
flowDb . clear ( ) ;
2019-09-12 12:59:13 -07:00
parser = flowParser ;
parser . parser . yy = flowDb ;
break ;
2020-03-04 20:35:59 +01:00
case 'flowchart-v2' :
flowDb . clear ( ) ;
2020-05-16 19:58:22 +02:00
parser = flowParser ;
2020-03-04 20:35:59 +01:00
parser . parser . yy = flowDb ;
break ;
2018-03-12 21:16:22 +08:00
case 'sequence' :
2019-09-12 12:59:13 -07:00
parser = sequenceParser ;
parser . parser . yy = sequenceDb ;
break ;
2017-04-11 22:14:25 +08:00
case 'gantt' :
2019-09-12 12:59:13 -07:00
parser = ganttParser ;
parser . parser . yy = ganttDb ;
break ;
2018-03-12 21:16:22 +08:00
case 'class' :
2019-09-12 12:59:13 -07:00
parser = classParser ;
parser . parser . yy = classDb ;
break ;
2019-09-25 21:01:21 +02:00
case 'state' :
parser = stateParser ;
parser . parser . yy = stateDb ;
break ;
2020-03-22 21:45:14 +01:00
case 'stateDiagram' :
parser = stateParser ;
parser . parser . yy = stateDb ;
break ;
2019-06-15 14:29:26 +02:00
case 'info' :
2019-09-12 12:59:13 -07:00
logger . debug ( 'info info info' ) ;
parser = infoParser ;
parser . parser . yy = infoDb ;
break ;
2019-09-11 21:20:28 +02:00
case 'pie' :
2019-09-12 12:59:13 -07:00
logger . debug ( 'pie' ) ;
parser = pieParser ;
parser . parser . yy = pieDb ;
break ;
2020-03-03 21:44:18 +00:00
case 'er' :
logger . debug ( 'er' ) ;
parser = erParser ;
parser . parser . yy = erDb ;
break ;
2020-04-04 17:50:02 +01:00
case 'journey' :
logger . debug ( 'Journey' ) ;
parser = journeyParser ;
parser . parser . yy = journeyDb ;
break ;
2017-04-11 22:14:25 +08:00
}
2017-09-10 10:10:36 +08:00
parser . parser . yy . parseError = ( str , hash ) => {
2019-09-12 12:59:13 -07:00
const error = { str , hash } ;
throw error ;
} ;
2017-09-10 00:29:22 +08:00
2019-09-12 12:59:13 -07:00
parser . parse ( text ) ;
2017-04-11 22:14:25 +08:00
}
2015-05-26 20:59:23 +02:00
2019-09-12 12:59:13 -07:00
export const encodeEntities = function ( text ) {
let txt = text ;
2017-04-11 22:14:25 +08:00
2019-09-12 12:59:13 -07:00
txt = txt . replace ( /style.*:\S*#.*;/g , function ( s ) {
const innerTxt = s . substring ( 0 , s . length - 1 ) ;
return innerTxt ;
} ) ;
txt = txt . replace ( /classDef.*:\S*#.*;/g , function ( s ) {
const innerTxt = s . substring ( 0 , s . length - 1 ) ;
return innerTxt ;
} ) ;
2017-04-11 22:14:25 +08:00
2019-09-12 12:59:13 -07:00
txt = txt . replace ( /#\w+;/g , function ( s ) {
const innerTxt = s . substring ( 1 , s . length - 1 ) ;
2017-04-11 22:14:25 +08:00
2019-09-12 12:59:13 -07:00
const isInt = /^\+?\d+$/ . test ( innerTxt ) ;
2017-04-11 22:14:25 +08:00
if ( isInt ) {
2019-09-12 12:59:13 -07:00
return 'fl°°' + innerTxt + '¶ß' ;
2017-04-11 22:14:25 +08:00
} else {
2019-09-12 12:59:13 -07:00
return 'fl°' + innerTxt + '¶ß' ;
2017-04-11 22:14:25 +08:00
}
2019-09-12 12:59:13 -07:00
} ) ;
return txt ;
} ;
export const decodeEntities = function ( text ) {
let txt = text ;
txt = txt . replace ( /fl°°/g , function ( ) {
return '&#' ;
} ) ;
txt = txt . replace ( /fl°/g , function ( ) {
return '&' ;
} ) ;
txt = txt . replace ( /¶ß/g , function ( ) {
return ';' ;
} ) ;
return txt ;
} ;
2015-07-15 11:39:46 +02:00
/ * *
2015-07-17 23:13:40 +02:00
* Function that renders an svg with a graph from a chart definition . Usage example below .
*
2019-07-14 06:07:27 -07:00
* ` ` ` js
2015-07-17 23:13:40 +02:00
* mermaidAPI . initialize ( {
* startOnLoad : true
* } ) ;
* $ ( function ( ) {
2017-09-14 19:40:38 +08:00
* const graphDefinition = 'graph TB\na-->b' ;
* const cb = function ( svgGraph ) {
2015-07-17 23:13:40 +02:00
* console . log ( svgGraph ) ;
* } ;
* mermaidAPI . render ( 'id1' , graphDefinition , cb ) ;
* } ) ;
* ` ` `
* @ param id the id of the element to be rendered
2020-06-17 18:12:01 -04:00
* @ param _txt the graph definition
2015-07-17 23:13:40 +02:00
* @ param cb callback which is called after rendering is finished with the svg code as inparam .
* @ param 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 .
2015-07-15 11:39:46 +02:00
* /
2020-01-25 13:35:11 +01:00
const render = function ( id , _txt , cb , container ) {
2020-06-15 08:03:13 +02:00
const cnf = getConfig ( ) ;
2020-06-15 22:26:11 +02:00
console . warn ( cnf ) ;
2020-01-25 13:35:11 +01:00
// Check the maximum allowed text size
let txt = _txt ;
2020-06-15 08:03:13 +02:00
if ( _txt . length > cnf . maxTextSize ) {
2020-01-25 13:35:11 +01:00
txt = 'graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa' ;
}
2020-06-17 18:12:01 -04:00
const graphInit = utils . detectInit ( txt ) ;
if ( graphInit ) {
initialize ( graphInit ) ;
assignWithDepth ( cnf , getConfig ( ) ) ;
}
2020-01-25 13:35:11 +01:00
2017-04-11 22:14:25 +08:00
if ( typeof container !== 'undefined' ) {
2019-09-12 12:59:13 -07:00
container . innerHTML = '' ;
2016-12-14 12:41:12 +01:00
2020-05-11 07:10:04 +01:00
select ( container )
2019-09-12 12:59:13 -07:00
. append ( 'div' )
2017-04-16 23:24:47 +08:00
. attr ( 'id' , 'd' + id )
2020-06-15 08:03:13 +02:00
. attr ( 'style' , 'font-family: ' + cnf . fontFamily )
2017-04-16 23:24:47 +08:00
. append ( 'svg' )
. attr ( 'id' , id )
. attr ( 'width' , '100%' )
. attr ( 'xmlns' , 'http://www.w3.org/2000/svg' )
2019-09-12 12:59:13 -07:00
. append ( 'g' ) ;
2017-04-11 22:14:25 +08:00
} else {
2019-10-15 08:02:41 +02:00
const existingSvg = document . getElementById ( id ) ;
if ( existingSvg ) {
existingSvg . remove ( ) ;
}
2019-09-12 12:59:13 -07:00
const element = document . querySelector ( '#' + 'd' + id ) ;
2017-04-11 22:14:25 +08:00
if ( element ) {
2019-09-12 12:59:13 -07:00
element . innerHTML = '' ;
2015-06-16 10:40:08 +02:00
}
2016-12-14 12:41:12 +01:00
2020-05-11 07:10:04 +01:00
select ( 'body' )
2019-09-12 12:59:13 -07:00
. append ( 'div' )
2017-04-16 23:24:47 +08:00
. attr ( 'id' , 'd' + id )
. append ( 'svg' )
. attr ( 'id' , id )
. attr ( 'width' , '100%' )
. attr ( 'xmlns' , 'http://www.w3.org/2000/svg' )
2019-09-12 12:59:13 -07:00
. append ( 'g' ) ;
2017-04-11 22:14:25 +08:00
}
2019-09-12 12:59:13 -07:00
window . txt = txt ;
txt = encodeEntities ( txt ) ;
2017-04-11 22:14:25 +08:00
2020-05-11 07:10:04 +01:00
const element = select ( '#d' + id ) . node ( ) ;
2019-09-12 12:59:13 -07:00
const graphType = utils . detectType ( txt ) ;
2017-04-11 22:14:25 +08:00
2017-09-12 22:06:19 +08:00
// insert inline style into svg
2019-09-12 12:59:13 -07:00
const svg = element . firstChild ;
const firstChild = svg . firstChild ;
2018-03-11 23:47:45 +08:00
2018-03-15 21:47:53 +08:00
// pre-defined theme
2020-06-15 08:03:13 +02:00
let style = themes [ cnf . theme ] ;
2018-03-15 22:44:00 +08:00
if ( style === undefined ) {
2019-09-12 12:59:13 -07:00
style = '' ;
2018-03-15 22:44:00 +08:00
}
2018-03-15 21:47:53 +08:00
// user provided theme CSS
2020-06-15 08:03:13 +02:00
if ( cnf . themeCSS !== undefined ) {
style += ` \n ${ cnf . themeCSS } ` ;
2018-03-15 21:47:53 +08:00
}
2019-10-12 16:53:21 +02:00
// user provided theme CSS
2020-06-15 08:03:13 +02:00
if ( cnf . fontFamily !== undefined ) {
style += ` \n :root { --mermaid-font-family: ${ cnf . fontFamily } } ` ;
2019-10-12 16:53:21 +02:00
}
// user provided theme CSS
2020-06-15 08:03:13 +02:00
if ( cnf . altFontFamily !== undefined ) {
style += ` \n :root { --mermaid-alt-font-family: ${ cnf . altFontFamily } } ` ;
2019-10-12 16:53:21 +02:00
}
2018-03-15 21:47:53 +08:00
2018-03-14 21:36:10 +08:00
// classDef
2020-05-06 18:51:12 +02:00
if ( graphType === 'flowchart' || graphType === 'flowchart-v2' ) {
2019-09-12 12:59:13 -07:00
const classes = flowRenderer . getClasses ( txt ) ;
2018-03-14 21:36:10 +08:00
for ( const className in classes ) {
2019-09-12 12:59:13 -07:00
style += ` \n . ${ className } > * { ${ classes [ className ] . styles . join (
' !important; '
) } ! important ; } ` ;
2020-02-05 19:39:50 +01:00
if ( classes [ className ] . textStyles ) {
style += ` \n . ${ className } tspan { ${ classes [ className ] . textStyles . join (
' !important; '
) } ! important ; } ` ;
}
2018-03-14 21:36:10 +08:00
}
}
2019-09-12 12:59:13 -07:00
const style1 = document . createElement ( 'style' ) ;
style1 . innerHTML = scope ( style , ` # ${ id } ` ) ;
svg . insertBefore ( style1 , firstChild ) ;
2018-03-11 23:47:45 +08:00
2019-09-12 12:59:13 -07:00
const style2 = document . createElement ( 'style' ) ;
const cs = window . getComputedStyle ( svg ) ;
2018-03-11 23:47:45 +08:00
style2 . innerHTML = ` # ${ id } {
color : $ { cs . color } ;
font : $ { cs . font } ;
2019-09-12 12:59:13 -07:00
} ` ;
svg . insertBefore ( style2 , firstChild ) ;
2017-09-12 22:06:19 +08:00
2020-06-06 12:42:35 +02:00
try {
switch ( graphType ) {
case 'git' :
2020-06-15 21:55:20 +02:00
cnf . flowchart . arrowMarkerAbsolute = cnf . arrowMarkerAbsolute ;
gitGraphRenderer . setConf ( cnf . git ) ;
2020-06-06 12:42:35 +02:00
gitGraphRenderer . draw ( txt , id , false ) ;
break ;
case 'flowchart' :
2020-06-15 21:55:20 +02:00
cnf . flowchart . arrowMarkerAbsolute = cnf . arrowMarkerAbsolute ;
flowRenderer . setConf ( cnf . flowchart ) ;
2020-06-06 12:42:35 +02:00
flowRenderer . draw ( txt , id , false ) ;
break ;
case 'flowchart-v2' :
2020-06-15 21:55:20 +02:00
cnf . flowchart . arrowMarkerAbsolute = cnf . arrowMarkerAbsolute ;
flowRendererV2 . setConf ( cnf . flowchart ) ;
2020-06-06 12:42:35 +02:00
flowRendererV2 . draw ( txt , id , false ) ;
break ;
case 'sequence' :
2020-06-15 21:55:20 +02:00
cnf . sequence . arrowMarkerAbsolute = cnf . arrowMarkerAbsolute ;
if ( cnf . sequenceDiagram ) {
2020-06-06 12:42:35 +02:00
// backwards compatibility
2020-06-15 21:55:20 +02:00
sequenceRenderer . setConf ( Object . assign ( cnf . sequence , cnf . sequenceDiagram ) ) ;
2020-06-06 12:42:35 +02:00
console . error (
'`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.'
) ;
} else {
2020-06-15 21:55:20 +02:00
sequenceRenderer . setConf ( cnf . sequence ) ;
2020-06-06 12:42:35 +02:00
}
sequenceRenderer . draw ( txt , id ) ;
break ;
case 'gantt' :
2020-06-15 21:55:20 +02:00
cnf . gantt . arrowMarkerAbsolute = cnf . arrowMarkerAbsolute ;
ganttRenderer . setConf ( cnf . gantt ) ;
2020-06-06 12:42:35 +02:00
ganttRenderer . draw ( txt , id ) ;
break ;
case 'class' :
2020-06-15 21:55:20 +02:00
cnf . class . arrowMarkerAbsolute = cnf . arrowMarkerAbsolute ;
2020-06-15 08:03:13 +02:00
classRenderer . setConf ( cnf . class ) ;
2020-06-06 12:42:35 +02:00
classRenderer . draw ( txt , id ) ;
break ;
case 'state' :
2020-06-15 21:55:20 +02:00
cnf . class . arrowMarkerAbsolute = cnf . arrowMarkerAbsolute ;
stateRenderer . setConf ( cnf . state ) ;
2020-06-06 12:42:35 +02:00
stateRenderer . draw ( txt , id ) ;
break ;
case 'stateDiagram' :
2020-06-15 21:55:20 +02:00
cnf . class . arrowMarkerAbsolute = cnf . arrowMarkerAbsolute ;
stateRendererV2 . setConf ( cnf . state ) ;
2020-06-06 12:42:35 +02:00
stateRendererV2 . draw ( txt , id ) ;
break ;
case 'info' :
2020-06-15 21:55:20 +02:00
cnf . class . arrowMarkerAbsolute = cnf . arrowMarkerAbsolute ;
infoRenderer . setConf ( cnf . class ) ;
2020-06-06 12:42:35 +02:00
infoRenderer . draw ( txt , id , pkg . version ) ;
break ;
case 'pie' :
2020-06-15 21:55:20 +02:00
cnf . class . arrowMarkerAbsolute = cnf . arrowMarkerAbsolute ;
pieRenderer . setConf ( cnf . class ) ;
2020-06-06 12:42:35 +02:00
pieRenderer . draw ( txt , id , pkg . version ) ;
break ;
case 'er' :
2020-06-15 21:55:20 +02:00
erRenderer . setConf ( cnf . er ) ;
2020-06-06 12:42:35 +02:00
erRenderer . draw ( txt , id , pkg . version ) ;
break ;
case 'journey' :
2020-06-15 21:55:20 +02:00
journeyRenderer . setConf ( cnf . journey ) ;
2020-06-06 12:42:35 +02:00
journeyRenderer . draw ( txt , id , pkg . version ) ;
break ;
}
} catch ( e ) {
2020-06-15 21:55:20 +02:00
// errorRenderer.setConf(cnf.class);
2020-06-06 12:42:35 +02:00
errorRenderer . draw ( id , pkg . version ) ;
2020-06-06 12:53:19 +02:00
throw e ;
2018-03-21 21:29:12 +08:00
}
2020-05-11 07:10:04 +01:00
select ( ` [id=" ${ id } "] ` )
2019-09-12 12:59:13 -07:00
. selectAll ( 'foreignobject > *' )
. attr ( 'xmlns' , 'http://www.w3.org/1999/xhtml' ) ;
2017-04-11 22:14:25 +08:00
2020-06-15 21:55:20 +02:00
// if (cnf.arrowMarkerAbsolute) {
2019-11-20 19:14:32 +01:00
// url =
// window.location.protocol +
// '//' +
// window.location.host +
// window.location.pathname +
// window.location.search;
// url = url.replace(/\(/g, '\\(');
// url = url.replace(/\)/g, '\\)');
// }
2015-05-26 20:59:23 +02:00
2017-04-16 23:24:47 +08:00
// Fix for when the base tag is used
2020-05-11 07:10:04 +01:00
let svgCode = select ( '#d' + id ) . node ( ) . innerHTML ;
2020-06-15 21:55:20 +02:00
logger . debug ( 'cnf.arrowMarkerAbsolute' , cnf . arrowMarkerAbsolute ) ;
if ( ! cnf . arrowMarkerAbsolute || cnf . arrowMarkerAbsolute === 'false' ) {
2019-11-20 19:14:32 +01:00
svgCode = svgCode . replace ( /marker-end="url\(.*?#/g , 'marker-end="url(#' , 'g' ) ;
2019-11-20 19:06:46 +01:00
}
2015-10-04 21:18:05 +02:00
2019-09-12 12:59:13 -07:00
svgCode = decodeEntities ( svgCode ) ;
2015-10-04 21:18:05 +02:00
2017-04-11 22:14:25 +08:00
if ( typeof cb !== 'undefined' ) {
2019-08-14 18:33:10 +02:00
switch ( graphType ) {
2019-08-11 03:26:44 -07:00
case 'flowchart' :
2020-05-06 18:51:12 +02:00
case 'flowchart-v2' :
2019-09-12 12:59:13 -07:00
cb ( svgCode , flowDb . bindFunctions ) ;
break ;
2019-08-11 03:26:44 -07:00
case 'gantt' :
2019-09-12 12:59:13 -07:00
cb ( svgCode , ganttDb . bindFunctions ) ;
break ;
2020-01-02 11:04:37 -08:00
case 'class' :
cb ( svgCode , classDb . bindFunctions ) ;
break ;
2019-08-14 18:33:10 +02:00
default :
2019-09-12 12:59:13 -07:00
cb ( svgCode ) ;
2019-08-11 03:26:44 -07:00
}
2017-04-11 22:14:25 +08:00
} else {
2019-09-12 12:59:13 -07:00
logger . debug ( 'CB = undefined!' ) ;
2017-04-11 22:14:25 +08:00
}
2015-06-16 10:40:08 +02:00
2020-05-11 07:10:04 +01:00
const node = select ( '#d' + id ) . node ( ) ;
2017-04-11 22:14:25 +08:00
if ( node !== null && typeof node . remove === 'function' ) {
2020-05-11 07:10:04 +01:00
select ( '#d' + id )
2019-09-12 12:59:13 -07:00
. node ( )
. remove ( ) ;
2017-04-11 22:14:25 +08:00
}
2015-11-15 15:06:24 +01:00
2019-09-12 12:59:13 -07:00
return svgCode ;
} ;
2015-05-26 20:59:23 +02:00
2020-06-15 01:11:56 +02:00
let firstInit = true ;
2020-06-08 14:48:03 -04:00
function initialize ( options ) {
2020-06-15 22:26:11 +02:00
console . log ( 'mermaidAPI.initialize' ) ;
2020-06-14 22:50:45 +02:00
// Set default options
if ( typeof options === 'object' ) {
2020-06-15 01:11:56 +02:00
if ( firstInit ) {
firstInit = false ;
setConfig ( config ) ;
}
setConfig ( options ) ;
2017-04-11 22:14:25 +08:00
}
2020-06-17 18:12:01 -04:00
assignWithDepth ( config , getConfig ( ) ) ;
console . warn ( ` Initializing mermaidAPI: v ${ pkg . version } theme: ${ config . theme } ` ) ;
2020-06-15 01:11:56 +02:00
setLogLevel ( getConfig ( ) . logLevel ) ;
2017-04-11 22:14:25 +08:00
}
2017-09-10 10:45:38 +08:00
2019-07-21 02:09:22 -07:00
// function getConfig () {
// console.warn('get config')
// return config
// }
2017-04-11 22:14:25 +08:00
2017-09-10 10:45:38 +08:00
const mermaidAPI = {
2018-03-11 22:23:26 +08:00
render ,
2017-09-10 10:45:38 +08:00
parse ,
initialize ,
2020-06-15 01:11:56 +02:00
getConfig ,
2020-06-15 21:55:20 +02:00
setConfig ,
2020-06-15 01:11:56 +02:00
reset : ( ) => {
2020-06-15 21:55:20 +02:00
// console.warn('reset');
2020-06-15 01:11:56 +02:00
firstInit = true ;
}
2019-09-12 12:59:13 -07:00
} ;
2017-09-10 10:45:38 +08:00
2019-09-12 12:59:13 -07:00
export default mermaidAPI ;
2019-09-11 20:03:22 +02:00
/ * *
* # # mermaidAPI configuration defaults
* < pre >
*
2019-11-07 23:15:53 +01:00
* & lt ; script >
2019-09-11 20:03:22 +02:00
* var config = {
* theme : 'default' ,
* logLevel : 'fatal' ,
* securityLevel : 'strict' ,
* startOnLoad : true ,
* arrowMarkerAbsolute : false ,
*
* flowchart : {
2019-09-18 13:05:08 +02:00
* htmlLabels : true ,
2019-09-11 20:03:22 +02:00
* curve : 'linear' ,
* } ,
* sequence : {
* diagramMarginX : 50 ,
* diagramMarginY : 10 ,
* actorMargin : 50 ,
* width : 150 ,
* height : 65 ,
* boxMargin : 10 ,
* boxTextMargin : 5 ,
* noteMargin : 10 ,
* messageMargin : 35 ,
2020-03-24 22:14:19 +01:00
* messageAlign : 'center' ,
2019-09-11 20:03:22 +02:00
* mirrorActors : true ,
* bottomMarginAdj : 1 ,
* useMaxWidth : true ,
* rightAngles : false ,
* showSequenceNumbers : false ,
* } ,
* gantt : {
* titleTopMargin : 25 ,
* barHeight : 20 ,
* barGap : 4 ,
* topPadding : 50 ,
* leftPadding : 75 ,
* gridLineStartPadding : 35 ,
* fontSize : 11 ,
* fontFamily : '"Open-Sans", "sans-serif"' ,
* numberSectionStyles : 4 ,
* axisFormat : '%Y-%m-%d' ,
* }
* } ;
* mermaid . initialize ( config ) ;
2019-11-07 23:15:53 +01:00
* & lt ; / s c r i p t >
2019-09-11 20:03:22 +02:00
* < / p r e >
* /