mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-13 12:29:42 +02:00
Fixed test cases for sequence diagrams
Updated config to match a conversation knut and i had about the relationship between global, site, and integrator configuration (Will update docs) Renamed wrapEnabled to wrap Poor man's caching for calculateTextDimensions, wrapLabel, and breakString (actually makes a huge difference)
This commit is contained in:
@@ -144,7 +144,7 @@ context('Sequence diagram', () => {
|
|||||||
it('should wrap (directive) long actor descriptions', () => {
|
it('should wrap (directive) long actor descriptions', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
%%{init: {'config': {'wrapEnabled': true }}}%%
|
%%{init: {'config': {'wrap': true }}}%%
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
participant A as Extremely utterly long line of longness which had preivously overflown the actor box as it is much longer than what it should be
|
participant A as Extremely utterly long line of longness which had preivously overflown the actor box as it is much longer than what it should be
|
||||||
A->>Bob: Hola
|
A->>Bob: Hola
|
||||||
@@ -326,7 +326,7 @@ context('Sequence diagram', () => {
|
|||||||
it('should render a single and nested opt with long test wrapping', () => {
|
it('should render a single and nested opt with long test wrapping', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
%%{init: { 'config': { 'wrapEnabled': true } } }%%
|
%%{init: { 'config': { 'wrap': true } } }%%
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
participant A
|
participant A
|
||||||
participant B
|
participant B
|
||||||
@@ -482,7 +482,7 @@ context('Sequence diagram', () => {
|
|||||||
it('should render with wrapping enabled', () => {
|
it('should render with wrapping enabled', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
%%{init: { 'config': { 'wrapEnabled': true }}}%%
|
%%{init: { 'config': { 'wrap': true }}}%%
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
participant A as Alice, the talkative one
|
participant A as Alice, the talkative one
|
||||||
A->>John: Hello John, how are you today? I'm feeling quite verbose today.
|
A->>John: Hello John, how are you today? I'm feeling quite verbose today.
|
||||||
@@ -495,7 +495,7 @@ context('Sequence diagram', () => {
|
|||||||
});
|
});
|
||||||
it('should render with an init directive', () => {
|
it('should render with an init directive', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`%%{init: { "theme": "dark", 'config': { "fontFamily": "Menlo", "fontSize": 18, "fontWeight": 400, "wrapEnabled": true }}}%%
|
`%%{init: { "theme": "dark", 'config': { "fontFamily": "Menlo", "fontSize": 18, "fontWeight": 400, "wrap": true }}}%%
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
|
Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
|
||||||
Note left of Alice: Bob thinks
|
Note left of Alice: Bob thinks
|
||||||
@@ -520,11 +520,10 @@ context('Sequence diagram', () => {
|
|||||||
it('should overide config with directive settings', () => {
|
it('should overide config with directive settings', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
%%{init: { "config": { "mirrorActors": false }}}%%
|
%%{init: { "config": { "mirrorActors": false, "wrap": true }}}%%
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
%%{config: { "mirrorActors": false} }%%
|
|
||||||
Alice->>Bob: I'm short
|
Alice->>Bob: I'm short
|
||||||
note left of Alice: config set to mirrorActors: true<br/>directive set to mirrorActors: false
|
note left of Alice: config: mirrorActors=true<br/>directive: mirrorActors=false
|
||||||
Bob->>Alice: Short as well
|
Bob->>Alice: Short as well
|
||||||
`,
|
`,
|
||||||
{ logLevel:0, sequence: { mirrorActors: true, noteFontSize: 18, noteFontFamily: 'Arial' } }
|
{ logLevel:0, sequence: { mirrorActors: true, noteFontSize: 18, noteFontFamily: 'Arial' } }
|
||||||
|
@@ -11,429 +11,6 @@ It is is then up to the user of the API to make use of the svg, either insert it
|
|||||||
|
|
||||||
In addition to the render function, a number of behavioral configuration options are available.
|
In addition to the render function, a number of behavioral configuration options are available.
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
These are the default options which can be overridden with the initialization call like so:
|
|
||||||
**Example 1:**
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
mermaid.initialize({
|
|
||||||
flowchart:{
|
|
||||||
htmlLabels: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
**Example 2:**
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
<script>
|
|
||||||
var config = {
|
|
||||||
startOnLoad:true,
|
|
||||||
flowchart:{
|
|
||||||
useMaxWidth:true,
|
|
||||||
htmlLabels:true,
|
|
||||||
curve:'cardinal',
|
|
||||||
},
|
|
||||||
|
|
||||||
securityLevel:'loose',
|
|
||||||
};
|
|
||||||
mermaid.initialize(config);
|
|
||||||
</script>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
A summary of all options and their defaults is found [here][2]. A description of each option follows below.
|
|
||||||
|
|
||||||
## theme
|
|
||||||
|
|
||||||
theme , the CSS style sheet
|
|
||||||
|
|
||||||
**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; }"
|
|
||||||
</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.
|
|
||||||
|
|
||||||
- debug: 1
|
|
||||||
- info: 2
|
|
||||||
- warn: 3
|
|
||||||
- error: 4
|
|
||||||
- fatal: (**default**) 5
|
|
||||||
|
|
||||||
## securityLevel
|
|
||||||
|
|
||||||
Sets the level of trust to be used on the parsed diagrams.
|
|
||||||
|
|
||||||
- **strict**: (**default**) tags in text are encoded, click functionality is disabeled
|
|
||||||
- **loose**: tags in text are allowed, click functionality is enabled
|
|
||||||
|
|
||||||
## startOnLoad
|
|
||||||
|
|
||||||
This options controls whether or mermaid starts when the page loads
|
|
||||||
**Default value true**.
|
|
||||||
|
|
||||||
## arrowMarkerAbsolute
|
|
||||||
|
|
||||||
This options controls whether or arrow markers in html code will be absolute paths or
|
|
||||||
an anchor, #. This matters if you are using base tag settings.
|
|
||||||
**Default value false**.
|
|
||||||
|
|
||||||
## flowchart
|
|
||||||
|
|
||||||
The object containing configurations specific for flowcharts
|
|
||||||
|
|
||||||
### htmlLabels
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
- basis
|
|
||||||
- linear **default**
|
|
||||||
- cardinal
|
|
||||||
|
|
||||||
## sequence
|
|
||||||
|
|
||||||
The object containing configurations specific for sequence diagrams
|
|
||||||
|
|
||||||
### diagramMarginX
|
|
||||||
|
|
||||||
margin to the right and left of the sequence diagram.
|
|
||||||
**Default value 50**.
|
|
||||||
|
|
||||||
### diagramMarginY
|
|
||||||
|
|
||||||
margin to the over and under the sequence diagram.
|
|
||||||
**Default value 10**.
|
|
||||||
|
|
||||||
### actorMargin
|
|
||||||
|
|
||||||
Margin between actors.
|
|
||||||
**Default value 50**.
|
|
||||||
|
|
||||||
### width
|
|
||||||
|
|
||||||
Width of actor boxes
|
|
||||||
**Default value 150**.
|
|
||||||
|
|
||||||
### height
|
|
||||||
|
|
||||||
Height of actor boxes
|
|
||||||
**Default value 65**.
|
|
||||||
|
|
||||||
### boxMargin
|
|
||||||
|
|
||||||
Margin around loop boxes
|
|
||||||
**Default value 10**.
|
|
||||||
|
|
||||||
### boxTextMargin
|
|
||||||
|
|
||||||
margin around the text in loop/alt/opt boxes
|
|
||||||
**Default value 5**.
|
|
||||||
|
|
||||||
### noteMargin
|
|
||||||
|
|
||||||
margin around notes.
|
|
||||||
**Default value 10**.
|
|
||||||
|
|
||||||
### messageMargin
|
|
||||||
|
|
||||||
Space between messages.
|
|
||||||
**Default value 35**.
|
|
||||||
|
|
||||||
### messageAlign
|
|
||||||
|
|
||||||
Multiline message alignment. Possible values are:
|
|
||||||
|
|
||||||
- left
|
|
||||||
- center **default**
|
|
||||||
- right
|
|
||||||
|
|
||||||
### mirrorActors
|
|
||||||
|
|
||||||
mirror actors under diagram.
|
|
||||||
**Default value true**.
|
|
||||||
|
|
||||||
### bottomMarginAdj
|
|
||||||
|
|
||||||
Depending on css styling this might need adjustment.
|
|
||||||
Prolongs the edge of the diagram downwards.
|
|
||||||
**Default value 1**.
|
|
||||||
|
|
||||||
### useMaxWidth
|
|
||||||
|
|
||||||
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**.
|
|
||||||
|
|
||||||
### rightAngles
|
|
||||||
|
|
||||||
This will display arrows that start and begin at the same node as right angles, rather than a curve
|
|
||||||
**Default value false**.
|
|
||||||
|
|
||||||
### showSequenceNumbers
|
|
||||||
|
|
||||||
This will show the node numbers
|
|
||||||
**Default value false**.
|
|
||||||
|
|
||||||
### actorFontSize
|
|
||||||
|
|
||||||
This sets the font size of the actor's description
|
|
||||||
**Default value 14**.
|
|
||||||
|
|
||||||
### actorFontFamily
|
|
||||||
|
|
||||||
This sets the font family of the actor's description
|
|
||||||
**Default value "Open-Sans", "sans-serif"**.
|
|
||||||
|
|
||||||
### actorFontWeight
|
|
||||||
|
|
||||||
This sets the font weight of the actor's description
|
|
||||||
\*\*Default value 400.
|
|
||||||
|
|
||||||
### noteFontSize
|
|
||||||
|
|
||||||
This sets the font size of actor-attached notes.
|
|
||||||
**Default value 14**.
|
|
||||||
|
|
||||||
### noteFontFamily
|
|
||||||
|
|
||||||
This sets the font family of actor-attached notes.
|
|
||||||
**Default value "trebuchet ms", verdana, arial**.
|
|
||||||
|
|
||||||
### noteFontWeight
|
|
||||||
|
|
||||||
This sets the font weight of the note's description
|
|
||||||
\*\*Default value 400.
|
|
||||||
|
|
||||||
### noteAlign
|
|
||||||
|
|
||||||
This sets the text alignment of actor-attached notes.
|
|
||||||
**Default value center**.
|
|
||||||
|
|
||||||
### messageFontSize
|
|
||||||
|
|
||||||
This sets the font size of actor messages.
|
|
||||||
**Default value 16**.
|
|
||||||
|
|
||||||
### messageFontFamily
|
|
||||||
|
|
||||||
This sets the font family of actor messages.
|
|
||||||
**Default value "trebuchet ms", verdana, arial**.
|
|
||||||
|
|
||||||
### messageFontWeight
|
|
||||||
|
|
||||||
This sets the font weight of the message's description
|
|
||||||
\*\*Default value 400.
|
|
||||||
|
|
||||||
### wrapEnabled
|
|
||||||
|
|
||||||
This sets the auto-wrap state for the diagram
|
|
||||||
\*\*Default value false.
|
|
||||||
|
|
||||||
### wrapPadding
|
|
||||||
|
|
||||||
This sets the auto-wrap padding for the diagram (sides only)
|
|
||||||
\*\*Default value 15.
|
|
||||||
|
|
||||||
## gantt
|
|
||||||
|
|
||||||
The object containing configurations specific for gantt diagrams\*
|
|
||||||
|
|
||||||
### titleTopMargin
|
|
||||||
|
|
||||||
Margin top for the text over the gantt diagram
|
|
||||||
**Default value 25**.
|
|
||||||
|
|
||||||
### barHeight
|
|
||||||
|
|
||||||
The height of the bars in the graph
|
|
||||||
**Default value 20**.
|
|
||||||
|
|
||||||
### barGap
|
|
||||||
|
|
||||||
The margin between the different activities in the gantt diagram.
|
|
||||||
**Default value 4**.
|
|
||||||
|
|
||||||
### topPadding
|
|
||||||
|
|
||||||
Margin between title and gantt diagram and between axis and gantt diagram.
|
|
||||||
**Default value 50**.
|
|
||||||
|
|
||||||
### leftPadding
|
|
||||||
|
|
||||||
The space allocated for the section name to the left of the activities.
|
|
||||||
**Default value 75**.
|
|
||||||
|
|
||||||
### gridLineStartPadding
|
|
||||||
|
|
||||||
Vertical starting position of the grid lines.
|
|
||||||
**Default value 35**.
|
|
||||||
|
|
||||||
### fontSize
|
|
||||||
|
|
||||||
Font size ...
|
|
||||||
**Default value 11**.
|
|
||||||
|
|
||||||
### fontFamily
|
|
||||||
|
|
||||||
font family ...
|
|
||||||
**Default value '"Open-Sans", "sans-serif"'**.
|
|
||||||
|
|
||||||
### numberSectionStyles
|
|
||||||
|
|
||||||
The number of alternating section styles.
|
|
||||||
**Default value 4**.
|
|
||||||
|
|
||||||
### axisFormat
|
|
||||||
|
|
||||||
Datetime format of the axis. This might need adjustment to match your locale and preferences
|
|
||||||
**Default value '%Y-%m-%d'**.
|
|
||||||
|
|
||||||
## journey
|
|
||||||
|
|
||||||
The object containing configurations specific for sequence diagrams
|
|
||||||
|
|
||||||
### diagramMarginX
|
|
||||||
|
|
||||||
margin to the right and left of the sequence diagram.
|
|
||||||
**Default value 50**.
|
|
||||||
|
|
||||||
### diagramMarginY
|
|
||||||
|
|
||||||
margin to the over and under the sequence diagram.
|
|
||||||
**Default value 10**.
|
|
||||||
|
|
||||||
### actorMargin
|
|
||||||
|
|
||||||
Margin between actors.
|
|
||||||
**Default value 50**.
|
|
||||||
|
|
||||||
### width
|
|
||||||
|
|
||||||
Width of actor boxes
|
|
||||||
**Default value 150**.
|
|
||||||
|
|
||||||
### height
|
|
||||||
|
|
||||||
Height of actor boxes
|
|
||||||
**Default value 65**.
|
|
||||||
|
|
||||||
### boxMargin
|
|
||||||
|
|
||||||
Margin around loop boxes
|
|
||||||
**Default value 10**.
|
|
||||||
|
|
||||||
### boxTextMargin
|
|
||||||
|
|
||||||
margin around the text in loop/alt/opt boxes
|
|
||||||
**Default value 5**.
|
|
||||||
|
|
||||||
### noteMargin
|
|
||||||
|
|
||||||
margin around notes.
|
|
||||||
**Default value 10**.
|
|
||||||
|
|
||||||
### messageMargin
|
|
||||||
|
|
||||||
Space between messages.
|
|
||||||
**Default value 35**.
|
|
||||||
|
|
||||||
### messageAlign
|
|
||||||
|
|
||||||
Multiline message alignment. Possible values are:
|
|
||||||
|
|
||||||
- left
|
|
||||||
- center **default**
|
|
||||||
- right
|
|
||||||
|
|
||||||
### bottomMarginAdj
|
|
||||||
|
|
||||||
Depending on css styling this might need adjustment.
|
|
||||||
Prolongs the edge of the diagram downwards.
|
|
||||||
**Default value 1**.
|
|
||||||
|
|
||||||
### useMaxWidth
|
|
||||||
|
|
||||||
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**.
|
|
||||||
|
|
||||||
### rightAngles
|
|
||||||
|
|
||||||
This will display arrows that start and begin at the same node as right angles, rather than a curve
|
|
||||||
**Default value false**.
|
|
||||||
|
|
||||||
## er
|
|
||||||
|
|
||||||
The object containing configurations specific for entity relationship diagrams
|
|
||||||
|
|
||||||
### diagramPadding
|
|
||||||
|
|
||||||
The amount of padding around the diagram as a whole so that embedded diagrams have margins, expressed in pixels
|
|
||||||
|
|
||||||
### layoutDirection
|
|
||||||
|
|
||||||
Directional bias for layout of entities. Can be either 'TB', 'BT', 'LR', or 'RL',
|
|
||||||
where T = top, B = bottom, L = left, and R = right.
|
|
||||||
|
|
||||||
### minEntityWidth
|
|
||||||
|
|
||||||
The mimimum width of an entity box, expressed in pixels
|
|
||||||
|
|
||||||
### minEntityHeight
|
|
||||||
|
|
||||||
The minimum height of an entity box, expressed in pixels
|
|
||||||
|
|
||||||
### entityPadding
|
|
||||||
|
|
||||||
The minimum internal padding between the text in an entity box and the enclosing box borders, expressed in pixels
|
|
||||||
|
|
||||||
### stroke
|
|
||||||
|
|
||||||
Stroke color of box edges and lines
|
|
||||||
|
|
||||||
### fill
|
|
||||||
|
|
||||||
Fill color of entity boxes
|
|
||||||
|
|
||||||
### fontSize
|
|
||||||
|
|
||||||
Font size (expressed as an integer representing a number of pixels)
|
|
||||||
|
|
||||||
## render
|
## render
|
||||||
|
|
||||||
Function that renders an svg with a graph from a chart definition. Usage example below.
|
Function that renders an svg with a graph from a chart definition. Usage example below.
|
||||||
@@ -513,5 +90,3 @@ mermaidAPI.initialize({
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
[1]: https://github.com/knsv/mermaid/blob/master/docs/mermaidAPI.md#render
|
[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
|
|
||||||
|
633
src/config.js
633
src/config.js
@@ -1,19 +1,632 @@
|
|||||||
import { assignWithDepth } from './utils';
|
import { assignWithDepth } from './utils';
|
||||||
const config = {};
|
import { logger } from './logger';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are the default options which can be overridden with the initialization call like so:
|
||||||
|
* **Example 1:**
|
||||||
|
* <pre>
|
||||||
|
* mermaid.initialize({
|
||||||
|
* flowchart:{
|
||||||
|
* htmlLabels: false
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* **Example 2:**
|
||||||
|
* <pre>
|
||||||
|
* <script>
|
||||||
|
* var currentConfig = {
|
||||||
|
* startOnLoad:true,
|
||||||
|
* flowchart:{
|
||||||
|
* useMaxWidth:true,
|
||||||
|
* htmlLabels:true,
|
||||||
|
* curve:'cardinal',
|
||||||
|
* },
|
||||||
|
*
|
||||||
|
* securityLevel:'loose',
|
||||||
|
* };
|
||||||
|
* mermaid.initialize(currentConfig);
|
||||||
|
* </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.
|
||||||
|
*
|
||||||
|
* @name Configuration
|
||||||
|
*/
|
||||||
|
const config = {
|
||||||
|
/** theme , the CSS style sheet
|
||||||
|
*
|
||||||
|
* **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; }"
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
theme: 'default',
|
||||||
|
themeCSS: undefined,
|
||||||
|
/* **maxTextSize** - The maximum allowed size of the users text diamgram */
|
||||||
|
maxTextSize: 50000,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **fontFamily** The font to be used for the rendered diagrams. Default value is \"trebuchet ms\", verdana, arial;
|
||||||
|
*/
|
||||||
|
fontFamily: '"trebuchet ms", verdana, arial;',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This option decides the amount of logging to be used.
|
||||||
|
* * debug: 1
|
||||||
|
* * info: 2
|
||||||
|
* * warn: 3
|
||||||
|
* * error: 4
|
||||||
|
* * fatal: (**default**) 5
|
||||||
|
*/
|
||||||
|
logLevel: 5,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the level of trust to be used on the parsed diagrams.
|
||||||
|
* * **strict**: (**default**) tags in text are encoded, click functionality is disabeled
|
||||||
|
* * **loose**: tags in text are allowed, click functionality is enabled
|
||||||
|
*/
|
||||||
|
securityLevel: 'strict',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This options controls whether or mermaid starts when the page loads
|
||||||
|
* **Default value true**.
|
||||||
|
*/
|
||||||
|
startOnLoad: true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This options controls whether or arrow markers in html code will be absolute paths or
|
||||||
|
* an anchor, #. This matters if you are using base tag settings.
|
||||||
|
* **Default value false**.
|
||||||
|
*/
|
||||||
|
arrowMarkerAbsolute: false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This option controls which currentConfig keys are considered _secure_ and can only be changed via
|
||||||
|
* call to mermaidAPI.initialize. Calls to mermaidAPI.reinitialize cannot make changes to
|
||||||
|
* the `secure` keys in the current currentConfig. This prevents malicious graph directives from
|
||||||
|
* overriding a site's default security.
|
||||||
|
*/
|
||||||
|
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object containing configurations specific for flowcharts
|
||||||
|
*/
|
||||||
|
flowchart: {
|
||||||
|
/**
|
||||||
|
* Flag for setting whether or not a html tag should be used for rendering labels
|
||||||
|
* on the edges.
|
||||||
|
* **Default value true**.
|
||||||
|
*/
|
||||||
|
htmlLabels: true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How mermaid renders curves for flowcharts. Possible values are
|
||||||
|
* * basis
|
||||||
|
* * linear **default**
|
||||||
|
* * cardinal
|
||||||
|
*/
|
||||||
|
curve: 'linear',
|
||||||
|
// Only used in new experimental rendering
|
||||||
|
// repreesents the padding between the labels and the shape
|
||||||
|
padding: 15
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object containing configurations specific for sequence diagrams
|
||||||
|
*/
|
||||||
|
sequence: {
|
||||||
|
/**
|
||||||
|
* 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',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mirror actors under diagram.
|
||||||
|
* **Default value true**.
|
||||||
|
*/
|
||||||
|
mirrorActors: true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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,
|
||||||
|
/**
|
||||||
|
* This will show the node numbers
|
||||||
|
* **Default value false**.
|
||||||
|
*/
|
||||||
|
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"',
|
||||||
|
/**
|
||||||
|
* This sets the font weight of the actor's description
|
||||||
|
* **Default value 400.
|
||||||
|
*/
|
||||||
|
actorFontWeight: 400,
|
||||||
|
/**
|
||||||
|
* 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',
|
||||||
|
/**
|
||||||
|
* This sets the font weight of the note's description
|
||||||
|
* **Default value 400.
|
||||||
|
*/
|
||||||
|
noteFontWeight: 400,
|
||||||
|
/**
|
||||||
|
* 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**.
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
wrap: false,
|
||||||
|
/**
|
||||||
|
* This sets the auto-wrap padding for the diagram (sides only)
|
||||||
|
* **Default value 15.
|
||||||
|
*/
|
||||||
|
wrapPadding: 15,
|
||||||
|
/**
|
||||||
|
* This sets the width of the loop-box (loop, alt, opt, par)
|
||||||
|
* **Default value 50.
|
||||||
|
*/
|
||||||
|
labelBoxWidth: 50,
|
||||||
|
/**
|
||||||
|
* This sets the height of the loop-box (loop, alt, opt, par)
|
||||||
|
* **Default value 20.
|
||||||
|
*/
|
||||||
|
labelBoxHeight: 20,
|
||||||
|
messageFont: () => {
|
||||||
|
return {
|
||||||
|
fontFamily: config.messageFontFamily,
|
||||||
|
fontSize: config.messageFontSize,
|
||||||
|
fontWeight: config.messageFontWeight
|
||||||
|
};
|
||||||
|
},
|
||||||
|
noteFont: () => {
|
||||||
|
return {
|
||||||
|
fontFamily: config.noteFontFamily,
|
||||||
|
fontSize: config.noteFontSize,
|
||||||
|
fontWeight: config.noteFontWeight
|
||||||
|
};
|
||||||
|
},
|
||||||
|
actorFont: () => {
|
||||||
|
return {
|
||||||
|
fontFamily: config.actorFontFamily,
|
||||||
|
fontSize: config.actorFontSize,
|
||||||
|
fontWeight: config.actorFontWeight
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object containing configurations specific for gantt diagrams*
|
||||||
|
*/
|
||||||
|
gantt: {
|
||||||
|
/**
|
||||||
|
* Margin top for the text over the gantt diagram
|
||||||
|
* **Default value 25**.
|
||||||
|
*/
|
||||||
|
titleTopMargin: 25,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The height of the bars in the graph
|
||||||
|
* **Default value 20**.
|
||||||
|
*/
|
||||||
|
barHeight: 20,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The margin between the different activities in the gantt diagram.
|
||||||
|
* **Default value 4**.
|
||||||
|
*/
|
||||||
|
barGap: 4,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Margin between title and gantt diagram and between axis and gantt diagram.
|
||||||
|
* **Default value 50**.
|
||||||
|
*/
|
||||||
|
topPadding: 50,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The space allocated for the section name to the left of the activities.
|
||||||
|
* **Default value 75**.
|
||||||
|
*/
|
||||||
|
leftPadding: 75,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vertical starting position of the grid lines.
|
||||||
|
* **Default value 35**.
|
||||||
|
*/
|
||||||
|
gridLineStartPadding: 35,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Font size ...
|
||||||
|
* **Default value 11**.
|
||||||
|
*/
|
||||||
|
fontSize: 11,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* font family ...
|
||||||
|
* **Default value '"Open-Sans", "sans-serif"'**.
|
||||||
|
*/
|
||||||
|
fontFamily: '"Open-Sans", "sans-serif"',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of alternating section styles.
|
||||||
|
* **Default value 4**.
|
||||||
|
*/
|
||||||
|
numberSectionStyles: 4,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Datetime format of the axis. This might need adjustment to match your locale and preferences
|
||||||
|
* **Default value '%Y-%m-%d'**.
|
||||||
|
*/
|
||||||
|
axisFormat: '%Y-%m-%d'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
},
|
||||||
|
class: {
|
||||||
|
arrowMarkerAbsolute: false
|
||||||
|
},
|
||||||
|
git: {
|
||||||
|
arrowMarkerAbsolute: false
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
dividerMargin: 10,
|
||||||
|
sizeUnit: 5,
|
||||||
|
padding: 8,
|
||||||
|
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
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object containing configurations specific for entity relationship diagrams
|
||||||
|
*/
|
||||||
|
er: {
|
||||||
|
/**
|
||||||
|
* The amount of padding around the diagram as a whole so that embedded diagrams have margins, expressed in pixels
|
||||||
|
*/
|
||||||
|
diagramPadding: 20,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directional bias for layout of entities. Can be either 'TB', 'BT', 'LR', or 'RL',
|
||||||
|
* where T = top, B = bottom, L = left, and R = right.
|
||||||
|
*/
|
||||||
|
layoutDirection: 'TB',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mimimum width of an entity box, expressed in pixels
|
||||||
|
*/
|
||||||
|
minEntityWidth: 100,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum height of an entity box, expressed in pixels
|
||||||
|
*/
|
||||||
|
minEntityHeight: 75,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum internal padding between the text in an entity box and the enclosing box borders, expressed in pixels
|
||||||
|
*/
|
||||||
|
entityPadding: 15,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stroke color of box edges and lines
|
||||||
|
*/
|
||||||
|
stroke: 'gray',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill color of entity boxes
|
||||||
|
*/
|
||||||
|
fill: 'honeydew',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Font size (expressed as an integer representing a number of pixels)
|
||||||
|
*/
|
||||||
|
fontSize: 12
|
||||||
|
}
|
||||||
|
};
|
||||||
|
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||||
|
config.git.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||||
|
export const defaultConfig = Object.freeze(config);
|
||||||
|
|
||||||
|
const siteConfig = assignWithDepth({}, defaultConfig);
|
||||||
|
const currentConfig = assignWithDepth({}, defaultConfig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the siteConfig. The siteConfig is a protected configuration for repeat use. Calls to reset() will reset
|
||||||
|
* the currentConfig to siteConfig. Calls to reset(configApi.defaultConfig) will reset siteConfig and currentConfig
|
||||||
|
* to the defaultConfig
|
||||||
|
* Note: currentConfig is set in this function
|
||||||
|
* @param conf - the base currentConfig to use as siteConfig
|
||||||
|
* @returns {*} - the siteConfig
|
||||||
|
*/
|
||||||
|
export const setSiteConfig = conf => {
|
||||||
|
assignWithDepth(currentConfig, conf, { clobber: true });
|
||||||
|
assignWithDepth(siteConfig, conf);
|
||||||
|
return getSiteConfig();
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Obtains the current siteConfig base configuration
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export const getSiteConfig = () => {
|
||||||
|
return assignWithDepth({}, siteConfig);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Sets the currentConfig. The param conf is sanitized based on the siteConfig.secure keys. Any
|
||||||
|
* values found in conf with key found in siteConfig.secure will be replaced with the corresponding
|
||||||
|
* siteConfig value.
|
||||||
|
* @param conf - the potential currentConfig
|
||||||
|
* @returns {*} - the currentConfig merged with the sanitized conf
|
||||||
|
*/
|
||||||
export const setConfig = conf => {
|
export const setConfig = conf => {
|
||||||
assignWithDepth(config, conf);
|
sanitize(conf);
|
||||||
|
assignWithDepth(currentConfig, conf);
|
||||||
|
return getConfig();
|
||||||
};
|
};
|
||||||
export const getConfig = () => config;
|
/**
|
||||||
|
* Obtains the currentConfig
|
||||||
export const reset = conf => {
|
* @returns {*} - the currentConfig
|
||||||
Object.keys(config).forEach(key => delete config[key]);
|
*/
|
||||||
assignWithDepth(config, conf, { clobber: true });
|
export const getConfig = () => {
|
||||||
|
return assignWithDepth({}, currentConfig);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Ensures options parameter does not attempt to override siteConfig secure keys
|
||||||
|
* Note: modifies options in-place
|
||||||
|
* @param options - the potential setConfig parameter
|
||||||
|
*/
|
||||||
|
export const sanitize = options => {
|
||||||
|
Object.keys(siteConfig.secure).forEach(key => {
|
||||||
|
if (typeof options[siteConfig.secure[key]] !== 'undefined') {
|
||||||
|
// DO NOT attempt to print options[siteConfig.secure[key]] within `${}` as a malicious script
|
||||||
|
// can exploit the logger's attempt to stringify the value and execute arbitrary code
|
||||||
|
logger.warn(
|
||||||
|
`Denied attempt to modify a secure key ${siteConfig.secure[key]}`,
|
||||||
|
options[siteConfig.secure[key]]
|
||||||
|
);
|
||||||
|
delete options[siteConfig.secure[key]];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Resets this currentConfig to conf
|
||||||
|
* @param conf - the base currentConfig to reset to (default: current siteConfig )
|
||||||
|
*/
|
||||||
|
export const reset = (conf = getSiteConfig()) => {
|
||||||
|
Object.keys(siteConfig).forEach(key => delete siteConfig[key]);
|
||||||
|
Object.keys(currentConfig).forEach(key => delete currentConfig[key]);
|
||||||
|
assignWithDepth(siteConfig, conf, { clobber: true });
|
||||||
|
assignWithDepth(currentConfig, conf, { clobber: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
const configApi = {
|
const configApi = Object.freeze({
|
||||||
|
sanitize,
|
||||||
|
setSiteConfig,
|
||||||
|
getSiteConfig,
|
||||||
setConfig,
|
setConfig,
|
||||||
getConfig,
|
getConfig,
|
||||||
reset
|
reset,
|
||||||
};
|
defaultConfig
|
||||||
|
});
|
||||||
export default configApi;
|
export default configApi;
|
||||||
|
52
src/config.spec.js
Normal file
52
src/config.spec.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/* eslint-env jasmine */
|
||||||
|
import configApi from './config';
|
||||||
|
|
||||||
|
describe('when working with site config', function() {
|
||||||
|
beforeEach(() => {
|
||||||
|
configApi.reset(configApi.defaultConfig);
|
||||||
|
});
|
||||||
|
it('should set site config and config properly', function() {
|
||||||
|
let config_0 = { foo: 'bar', bar: 0 };
|
||||||
|
configApi.setSiteConfig(config_0);
|
||||||
|
let config_1 = configApi.getSiteConfig();
|
||||||
|
let config_2 = configApi.getConfig();
|
||||||
|
expect(config_1.foo).toEqual(config_0.foo);
|
||||||
|
expect(config_1.bar).toEqual(config_0.bar);
|
||||||
|
expect(config_1).toEqual(config_2);
|
||||||
|
});
|
||||||
|
it('should set config and respect secure keys', function() {
|
||||||
|
let config_0 = { foo: 'bar', bar: 0, secure: [...configApi.defaultConfig.secure, 'bar'] };
|
||||||
|
configApi.setSiteConfig(config_0);
|
||||||
|
let config_1 = { foo: 'baf', bar: 'foo'};
|
||||||
|
configApi.setConfig(config_1);
|
||||||
|
let config_2 = configApi.getConfig();
|
||||||
|
expect(config_2.foo).toEqual(config_1.foo);
|
||||||
|
expect(config_2.bar).toEqual(0); // Should be siteConfig.bar
|
||||||
|
});
|
||||||
|
it('should set reset config properly', function() {
|
||||||
|
let config_0 = { foo: 'bar', bar: 0};
|
||||||
|
configApi.setSiteConfig(config_0);
|
||||||
|
let config_1 = { foo: 'baf'};
|
||||||
|
configApi.setConfig(config_1);
|
||||||
|
let config_2 = configApi.getConfig();
|
||||||
|
expect(config_2.foo).toEqual(config_1.foo);
|
||||||
|
configApi.reset();
|
||||||
|
let config_3 = configApi.getConfig();
|
||||||
|
expect(config_3.foo).toEqual(config_0.foo);
|
||||||
|
let config_4 = configApi.getSiteConfig();
|
||||||
|
expect(config_4.foo).toEqual(config_0.foo);
|
||||||
|
});
|
||||||
|
it('should set global reset config properly', function() {
|
||||||
|
let config_0 = { foo: 'bar', bar: 0};
|
||||||
|
configApi.setSiteConfig(config_0);
|
||||||
|
let config_1 = configApi.getSiteConfig();
|
||||||
|
expect(config_1.foo).toEqual(config_0.foo);
|
||||||
|
let config_2 = configApi.getConfig();
|
||||||
|
expect(config_2.foo).toEqual(config_0.foo);
|
||||||
|
configApi.reset(configApi.defaultConfig);
|
||||||
|
let config_3 = configApi.getSiteConfig();
|
||||||
|
expect(config_3.foo).toBeUndefined();
|
||||||
|
let config_4 = configApi.getConfig();
|
||||||
|
expect(config_4.foo).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
@@ -230,7 +230,7 @@ argDirective
|
|||||||
;
|
;
|
||||||
|
|
||||||
closeDirective
|
closeDirective
|
||||||
: close_directive { yy.parseDirective('}%%', 'close_directive'); }
|
: close_directive { yy.parseDirective('}%%', 'close_directive', 'sequence'); }
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { logger } from '../../logger';
|
|
||||||
import mermaidAPI from '../../mermaidAPI';
|
import mermaidAPI from '../../mermaidAPI';
|
||||||
|
import configApi from '../../config';
|
||||||
|
|
||||||
let prevActor = undefined;
|
let prevActor = undefined;
|
||||||
let actors = {};
|
let actors = {};
|
||||||
@@ -9,63 +9,9 @@ let title = '';
|
|||||||
let titleWrapped = false;
|
let titleWrapped = false;
|
||||||
let sequenceNumbersEnabled = false;
|
let sequenceNumbersEnabled = false;
|
||||||
let wrapEnabled = false;
|
let wrapEnabled = false;
|
||||||
let currentDirective = {};
|
|
||||||
|
|
||||||
export const parseDirective = function(statement, context) {
|
export const parseDirective = function(statement, context, type) {
|
||||||
try {
|
mermaidAPI.parseDirective(statement, context, type);
|
||||||
if (statement !== undefined) {
|
|
||||||
statement = statement.trim();
|
|
||||||
switch (context) {
|
|
||||||
case 'open_directive':
|
|
||||||
currentDirective = {};
|
|
||||||
break;
|
|
||||||
case 'type_directive':
|
|
||||||
currentDirective.type = statement.toLowerCase();
|
|
||||||
break;
|
|
||||||
case 'arg_directive':
|
|
||||||
currentDirective.args = JSON.parse(statement);
|
|
||||||
break;
|
|
||||||
case 'close_directive':
|
|
||||||
handleDirective(currentDirective);
|
|
||||||
currentDirective = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
logger.error(
|
|
||||||
`Error while rendering sequenceDiagram directive: ${statement} jison context: ${context}`
|
|
||||||
);
|
|
||||||
logger.error(error.message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDirective = function(directive) {
|
|
||||||
logger.debug(`Directive type=${directive.type} with args:`, directive.args);
|
|
||||||
switch (directive.type) {
|
|
||||||
case 'init':
|
|
||||||
case 'initialize':
|
|
||||||
['config'].forEach(prop => {
|
|
||||||
if (typeof directive.args[prop] !== 'undefined') {
|
|
||||||
directive.args.sequence = directive.args[prop];
|
|
||||||
delete directive.args[prop];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
mermaidAPI.initialize(directive.args);
|
|
||||||
break;
|
|
||||||
case 'wrap':
|
|
||||||
case 'nowrap':
|
|
||||||
wrapEnabled = directive.type === 'wrap';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
logger.warn(
|
|
||||||
`Unhandled directive: source: '%%{${directive.type}: ${JSON.stringify(
|
|
||||||
directive.args ? directive.args : {}
|
|
||||||
)}}%%`,
|
|
||||||
directive
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addActor = function(id, name, description) {
|
export const addActor = function(id, name, description) {
|
||||||
@@ -126,22 +72,8 @@ export const addSignal = function(
|
|||||||
message = { text: undefined, wrap: undefined },
|
message = { text: undefined, wrap: undefined },
|
||||||
messageType
|
messageType
|
||||||
) {
|
) {
|
||||||
logger.debug(
|
|
||||||
'Adding message from=' +
|
|
||||||
idFrom +
|
|
||||||
' to=' +
|
|
||||||
idTo +
|
|
||||||
' message=' +
|
|
||||||
message.text +
|
|
||||||
' wrap=' +
|
|
||||||
message.wrap +
|
|
||||||
' type=' +
|
|
||||||
messageType
|
|
||||||
);
|
|
||||||
|
|
||||||
if (messageType === LINETYPE.ACTIVE_END) {
|
if (messageType === LINETYPE.ACTIVE_END) {
|
||||||
const cnt = activationCount(idFrom.actor);
|
const cnt = activationCount(idFrom.actor);
|
||||||
logger.debug('Adding message from=', messages, cnt);
|
|
||||||
if (cnt < 1) {
|
if (cnt < 1) {
|
||||||
// Bail out as there is an activation signal from an inactive participant
|
// Bail out as there is an activation signal from an inactive participant
|
||||||
let error = new Error('Trying to inactivate an inactive participant (' + idFrom.actor + ')');
|
let error = new Error('Trying to inactivate an inactive participant (' + idFrom.actor + ')');
|
||||||
@@ -356,6 +288,7 @@ export default {
|
|||||||
getActorKeys,
|
getActorKeys,
|
||||||
getTitle,
|
getTitle,
|
||||||
parseDirective,
|
parseDirective,
|
||||||
|
getConfig: () => configApi.getConfig().sequence,
|
||||||
getTitleWrapped,
|
getTitleWrapped,
|
||||||
clear,
|
clear,
|
||||||
parseMessage,
|
parseMessage,
|
||||||
|
@@ -23,7 +23,7 @@ Alice->Bob:Hello Bob, how are you?
|
|||||||
Note right of Bob: Bob thinks
|
Note right of Bob: Bob thinks
|
||||||
Bob-->Alice: I am good thanks!`;
|
Bob-->Alice: I am good thanks!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
actors.Bob.description = 'Bob';
|
actors.Bob.description = 'Bob';
|
||||||
@@ -41,7 +41,7 @@ Alice->Bob:Hello Bob, how are you?
|
|||||||
Note right of Bob: Bob thinks
|
Note right of Bob: Bob thinks
|
||||||
Bob-->Alice: I am good thanks!`;
|
Bob-->Alice: I am good thanks!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
expect(parser.yy.showSequenceNumbers()).toBe(false);
|
expect(parser.yy.showSequenceNumbers()).toBe(false);
|
||||||
});
|
});
|
||||||
it('it should show sequence numbers when autonumber is enabled', function() {
|
it('it should show sequence numbers when autonumber is enabled', function() {
|
||||||
@@ -52,7 +52,7 @@ Alice->Bob:Hello Bob, how are you?
|
|||||||
Note right of Bob: Bob thinks
|
Note right of Bob: Bob thinks
|
||||||
Bob-->Alice: I am good thanks!`;
|
Bob-->Alice: I am good thanks!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
expect(parser.yy.showSequenceNumbers()).toBe(true);
|
expect(parser.yy.showSequenceNumbers()).toBe(true);
|
||||||
});
|
});
|
||||||
it('it should handle a sequenceDiagram definition with a title', function() {
|
it('it should handle a sequenceDiagram definition with a title', function() {
|
||||||
@@ -63,7 +63,7 @@ Alice->Bob:Hello Bob, how are you?
|
|||||||
Note right of Bob: Bob thinks
|
Note right of Bob: Bob thinks
|
||||||
Bob-->Alice: I am good thanks!`;
|
Bob-->Alice: I am good thanks!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
actors.Bob.description = 'Bob';
|
actors.Bob.description = 'Bob';
|
||||||
@@ -82,7 +82,7 @@ sequenceDiagram
|
|||||||
Alice->Bob:Hello Bob, how are - you?
|
Alice->Bob:Hello Bob, how are - you?
|
||||||
Bob-->Alice: I am good thanks!`;
|
Bob-->Alice: I am good thanks!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
actors.Bob.description = 'Bob';
|
actors.Bob.description = 'Bob';
|
||||||
@@ -101,7 +101,7 @@ participant B as Bob
|
|||||||
A->B:Hello Bob, how are you?
|
A->B:Hello Bob, how are you?
|
||||||
B-->A: I am good thanks!`;
|
B-->A: I am good thanks!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(Object.keys(actors)).toEqual(['A', 'B']);
|
expect(Object.keys(actors)).toEqual(['A', 'B']);
|
||||||
@@ -118,7 +118,7 @@ B-->A: I am good thanks!`;
|
|||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
Alice-xBob:Hello Bob, how are you?`;
|
Alice-xBob:Hello Bob, how are you?`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
expect(actors.Bob.description).toBe('Bob');
|
expect(actors.Bob.description).toBe('Bob');
|
||||||
@@ -133,7 +133,7 @@ Alice-xBob:Hello Bob, how are you?`;
|
|||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
Alice--xBob:Hello Bob, how are you?`;
|
Alice--xBob:Hello Bob, how are you?`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
expect(actors.Bob.description).toBe('Bob');
|
expect(actors.Bob.description).toBe('Bob');
|
||||||
@@ -148,7 +148,7 @@ Alice--xBob:Hello Bob, how are you?`;
|
|||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
Alice->>Bob:Hello Bob, how are you?`;
|
Alice->>Bob:Hello Bob, how are you?`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
expect(actors.Bob.description).toBe('Bob');
|
expect(actors.Bob.description).toBe('Bob');
|
||||||
@@ -161,7 +161,7 @@ Alice->>Bob:Hello Bob, how are you?`;
|
|||||||
it('it should handle in arrow messages', function() {
|
it('it should handle in arrow messages', function() {
|
||||||
const str = 'sequenceDiagram\n' + 'Alice-->>Bob:Hello Bob, how are you?';
|
const str = 'sequenceDiagram\n' + 'Alice-->>Bob:Hello Bob, how are you?';
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
expect(actors.Bob.description).toBe('Bob');
|
expect(actors.Bob.description).toBe('Bob');
|
||||||
@@ -179,7 +179,7 @@ activate Bob
|
|||||||
Bob-->>Alice:Hello Alice, I'm fine and you?
|
Bob-->>Alice:Hello Alice, I'm fine and you?
|
||||||
deactivate Bob`;
|
deactivate Bob`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
expect(actors.Bob.description).toBe('Bob');
|
expect(actors.Bob.description).toBe('Bob');
|
||||||
@@ -200,7 +200,7 @@ deactivate Bob`;
|
|||||||
Alice-->>+Bob:Hello Bob, how are you?
|
Alice-->>+Bob:Hello Bob, how are you?
|
||||||
Bob-->>- Alice:Hello Alice, I'm fine and you?`;
|
Bob-->>- Alice:Hello Alice, I'm fine and you?`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
expect(actors.Bob.description).toBe('Bob');
|
expect(actors.Bob.description).toBe('Bob');
|
||||||
@@ -223,7 +223,7 @@ deactivate Bob`;
|
|||||||
Bob-->>- Alice:Hello Alice, please meet Carol?
|
Bob-->>- Alice:Hello Alice, please meet Carol?
|
||||||
Carol->>- Bob:Oh Bob, I'm so happy to be here!`;
|
Carol->>- Bob:Oh Bob, I'm so happy to be here!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
expect(actors.Bob.description).toBe('Bob');
|
expect(actors.Bob.description).toBe('Bob');
|
||||||
@@ -261,7 +261,7 @@ deactivate Bob`;
|
|||||||
|
|
||||||
let error = false;
|
let error = false;
|
||||||
try {
|
try {
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e.hash);
|
console.log(e.hash);
|
||||||
error = true;
|
error = true;
|
||||||
@@ -277,7 +277,7 @@ deactivate Bob`;
|
|||||||
Note right of Bob: Bob thinks
|
Note right of Bob: Bob thinks
|
||||||
Bob-->Alice: I am good thanks!`;
|
Bob-->Alice: I am good thanks!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
actors.Bob.description = 'Bob';
|
actors.Bob.description = 'Bob';
|
||||||
@@ -298,7 +298,7 @@ deactivate Bob`;
|
|||||||
Bob-->Alice: I am good thanks!
|
Bob-->Alice: I am good thanks!
|
||||||
`;
|
`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
actors.Bob.description = 'Bob';
|
actors.Bob.description = 'Bob';
|
||||||
@@ -313,7 +313,7 @@ deactivate Bob`;
|
|||||||
const str = `
|
const str = `
|
||||||
sequenceDiagram;Alice->Bob: Hello Bob, how are you?;Note right of Bob: Bob thinks;Bob-->Alice: I am good thanks!;`;
|
sequenceDiagram;Alice->Bob: Hello Bob, how are you?;Note right of Bob: Bob thinks;Bob-->Alice: I am good thanks!;`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
actors.Bob.description = 'Bob';
|
actors.Bob.description = 'Bob';
|
||||||
@@ -333,7 +333,7 @@ sequenceDiagram
|
|||||||
Note right of Bob: Bob thinks
|
Note right of Bob: Bob thinks
|
||||||
Bob-->Alice: I am good thanks!`;
|
Bob-->Alice: I am good thanks!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
actors.Bob.description = 'Bob';
|
actors.Bob.description = 'Bob';
|
||||||
@@ -353,7 +353,7 @@ sequenceDiagram
|
|||||||
Note right of Bob: Bob thinks
|
Note right of Bob: Bob thinks
|
||||||
Bob-->Alice: I am good thanks!`;
|
Bob-->Alice: I am good thanks!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
actors.Bob.description = 'Bob';
|
actors.Bob.description = 'Bob';
|
||||||
@@ -378,7 +378,7 @@ Note right of John: Rational thoughts<br/>prevail...
|
|||||||
John->Bob: How about you?
|
John->Bob: How about you?
|
||||||
Bob-->John: Jolly good!`;
|
Bob-->John: Jolly good!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
actors.Bob.description = 'Bob';
|
actors.Bob.description = 'Bob';
|
||||||
@@ -406,7 +406,7 @@ note right of 4: multiline<br />text
|
|||||||
note right of 1: multiline<br \t/>text
|
note right of 1: multiline<br \t/>text
|
||||||
`;
|
`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors['1'].description).toBe('multiline<br>text');
|
expect(actors['1'].description).toBe('multiline<br>text');
|
||||||
@@ -431,7 +431,7 @@ Alice->Bob: Hello Bob, how are you?
|
|||||||
Note over Bob: Bob thinks
|
Note over Bob: Bob thinks
|
||||||
`;
|
`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const messages = parser.yy.getMessages();
|
const messages = parser.yy.getMessages();
|
||||||
expect(messages[1].from).toBe('Bob');
|
expect(messages[1].from).toBe('Bob');
|
||||||
@@ -445,7 +445,7 @@ Note over Alice,Bob: confusion
|
|||||||
Note over Bob,Alice: resolution
|
Note over Bob,Alice: resolution
|
||||||
`;
|
`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const messages = parser.yy.getMessages();
|
const messages = parser.yy.getMessages();
|
||||||
expect(messages[1].from).toBe('Alice');
|
expect(messages[1].from).toBe('Alice');
|
||||||
@@ -465,7 +465,7 @@ loop Multiple happy responses
|
|||||||
Bob-->Alice: I am good thanks!
|
Bob-->Alice: I am good thanks!
|
||||||
end`;
|
end`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
actors.Bob.description = 'Bob';
|
actors.Bob.description = 'Bob';
|
||||||
@@ -487,7 +487,7 @@ end`;
|
|||||||
end
|
end
|
||||||
`;
|
`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
actors.Bob.description = 'Bob';
|
actors.Bob.description = 'Bob';
|
||||||
@@ -512,7 +512,7 @@ end`;
|
|||||||
Bob-->Alice: I am good thanks
|
Bob-->Alice: I am good thanks
|
||||||
end
|
end
|
||||||
`;
|
`;
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
actors.Bob.description = 'Bob';
|
actors.Bob.description = 'Bob';
|
||||||
@@ -539,7 +539,7 @@ opt Perhaps a happy response
|
|||||||
Bob-->Alice: I am good thanks!
|
Bob-->Alice: I am good thanks!
|
||||||
end`;
|
end`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
actors.Bob.description = 'Bob';
|
actors.Bob.description = 'Bob';
|
||||||
@@ -564,7 +564,7 @@ else isSick
|
|||||||
Bob-->Alice: Feel sick...
|
Bob-->Alice: Feel sick...
|
||||||
end`;
|
end`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
|
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
@@ -591,7 +591,7 @@ Bob-->Alice: Feel sick...
|
|||||||
else default
|
else default
|
||||||
Bob-->Alice: :-)
|
Bob-->Alice: :-)
|
||||||
end`;
|
end`;
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const messages = parser.yy.getMessages();
|
const messages = parser.yy.getMessages();
|
||||||
expect(messages.length).toBe(9);
|
expect(messages.length).toBe(9);
|
||||||
expect(messages[1].from).toBe('Bob');
|
expect(messages[1].from).toBe('Bob');
|
||||||
@@ -617,7 +617,7 @@ Alice->>Bob: What do you think about it?
|
|||||||
Bob-->>Alice: It's good!
|
Bob-->>Alice: It's good!
|
||||||
end`;
|
end`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
|
|
||||||
expect(actors.Alice.description).toBe('Alice');
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
@@ -633,7 +633,7 @@ end`;
|
|||||||
it('it should handle special characters in signals', function() {
|
it('it should handle special characters in signals', function() {
|
||||||
const str = 'sequenceDiagram\n' + 'Alice->Bob: -:<>,;# comment';
|
const str = 'sequenceDiagram\n' + 'Alice->Bob: -:<>,;# comment';
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const messages = parser.yy.getMessages();
|
const messages = parser.yy.getMessages();
|
||||||
expect(messages[0].message).toBe('-:<>,');
|
expect(messages[0].message).toBe('-:<>,');
|
||||||
@@ -644,7 +644,7 @@ sequenceDiagram
|
|||||||
Alice->Bob: Hello Bob, how are you?
|
Alice->Bob: Hello Bob, how are you?
|
||||||
Note right of Bob: -:<>,;# comment`;
|
Note right of Bob: -:<>,;# comment`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const messages = parser.yy.getMessages();
|
const messages = parser.yy.getMessages();
|
||||||
expect(messages[1].message).toBe('-:<>,');
|
expect(messages[1].message).toBe('-:<>,');
|
||||||
@@ -657,7 +657,7 @@ loop -:<>,;# comment
|
|||||||
Bob-->Alice: I am good thanks!
|
Bob-->Alice: I am good thanks!
|
||||||
end`;
|
end`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const messages = parser.yy.getMessages();
|
const messages = parser.yy.getMessages();
|
||||||
expect(messages[1].message).toBe('-:<>,');
|
expect(messages[1].message).toBe('-:<>,');
|
||||||
@@ -670,7 +670,7 @@ opt -:<>,;# comment
|
|||||||
Bob-->Alice: I am good thanks!
|
Bob-->Alice: I am good thanks!
|
||||||
end`;
|
end`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const messages = parser.yy.getMessages();
|
const messages = parser.yy.getMessages();
|
||||||
expect(messages[1].message).toBe('-:<>,');
|
expect(messages[1].message).toBe('-:<>,');
|
||||||
@@ -685,7 +685,7 @@ else ,<>:-#; comment
|
|||||||
Bob-->Alice: I am good thanks!
|
Bob-->Alice: I am good thanks!
|
||||||
end`;
|
end`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const messages = parser.yy.getMessages();
|
const messages = parser.yy.getMessages();
|
||||||
expect(messages[1].message).toBe('-:<>,');
|
expect(messages[1].message).toBe('-:<>,');
|
||||||
@@ -701,7 +701,7 @@ and ,<>:-#; comment
|
|||||||
Bob-->Alice: I am good thanks!
|
Bob-->Alice: I am good thanks!
|
||||||
end`;
|
end`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const messages = parser.yy.getMessages();
|
const messages = parser.yy.getMessages();
|
||||||
expect(messages[1].message).toBe('-:<>,');
|
expect(messages[1].message).toBe('-:<>,');
|
||||||
@@ -715,7 +715,7 @@ loop
|
|||||||
Bob-->Alice: I am good thanks!
|
Bob-->Alice: I am good thanks!
|
||||||
end`;
|
end`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const messages = parser.yy.getMessages();
|
const messages = parser.yy.getMessages();
|
||||||
expect(messages[1].message).toBe('');
|
expect(messages[1].message).toBe('');
|
||||||
@@ -729,7 +729,7 @@ opt # comment
|
|||||||
Bob-->Alice: I am good thanks!
|
Bob-->Alice: I am good thanks!
|
||||||
end`;
|
end`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const messages = parser.yy.getMessages();
|
const messages = parser.yy.getMessages();
|
||||||
expect(messages[1].message).toBe('');
|
expect(messages[1].message).toBe('');
|
||||||
@@ -744,7 +744,7 @@ else # comment
|
|||||||
Bob-->Alice: I am good thanks!
|
Bob-->Alice: I am good thanks!
|
||||||
end`;
|
end`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const messages = parser.yy.getMessages();
|
const messages = parser.yy.getMessages();
|
||||||
expect(messages[1].message).toBe('');
|
expect(messages[1].message).toBe('');
|
||||||
@@ -761,7 +761,7 @@ and # comment
|
|||||||
Bob-->Alice: I am good thanks!
|
Bob-->Alice: I am good thanks!
|
||||||
end`;
|
end`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const messages = parser.yy.getMessages();
|
const messages = parser.yy.getMessages();
|
||||||
expect(messages[1].message).toBe('');
|
expect(messages[1].message).toBe('');
|
||||||
@@ -772,12 +772,8 @@ end`;
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('when checking the bounds in a sequenceDiagram', function() {
|
describe('when checking the bounds in a sequenceDiagram', function() {
|
||||||
let conf;
|
beforeAll(() => {
|
||||||
beforeEach(function() {
|
let conf = {
|
||||||
mermaidAPI.reset();
|
|
||||||
parser.yy = sequenceDb;
|
|
||||||
parser.yy.clear();
|
|
||||||
conf = {
|
|
||||||
diagramMarginX: 50,
|
diagramMarginX: 50,
|
||||||
diagramMarginY: 10,
|
diagramMarginY: 10,
|
||||||
actorMargin: 50,
|
actorMargin: 50,
|
||||||
@@ -791,13 +787,21 @@ describe('when checking the bounds in a sequenceDiagram', function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
mermaidAPI.initialize({ sequence: conf });
|
mermaidAPI.initialize({ sequence: conf });
|
||||||
|
});
|
||||||
|
|
||||||
|
let conf;
|
||||||
|
beforeEach(function() {
|
||||||
|
mermaidAPI.reset();
|
||||||
|
parser.yy = sequenceDb;
|
||||||
|
parser.yy.clear();
|
||||||
renderer.bounds.init();
|
renderer.bounds.init();
|
||||||
|
conf = parser.yy.getConfig();
|
||||||
});
|
});
|
||||||
it('it should handle a simple bound call', function() {
|
it('it should handle a simple bound call', function() {
|
||||||
|
|
||||||
renderer.bounds.insert(100, 100, 200, 200);
|
renderer.bounds.insert(100, 100, 200, 200);
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(100);
|
expect(bounds.startx).toBe(100);
|
||||||
expect(bounds.starty).toBe(100);
|
expect(bounds.starty).toBe(100);
|
||||||
expect(bounds.stopx).toBe(200);
|
expect(bounds.stopx).toBe(200);
|
||||||
@@ -808,7 +812,7 @@ describe('when checking the bounds in a sequenceDiagram', function() {
|
|||||||
renderer.bounds.insert(100, 100, 200, 200);
|
renderer.bounds.insert(100, 100, 200, 200);
|
||||||
renderer.bounds.insert(25, 50, 300, 400);
|
renderer.bounds.insert(25, 50, 300, 400);
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(25);
|
expect(bounds.startx).toBe(25);
|
||||||
expect(bounds.starty).toBe(50);
|
expect(bounds.starty).toBe(50);
|
||||||
expect(bounds.stopx).toBe(300);
|
expect(bounds.stopx).toBe(300);
|
||||||
@@ -820,7 +824,7 @@ describe('when checking the bounds in a sequenceDiagram', function() {
|
|||||||
renderer.bounds.insert(25, 50, 300, 400);
|
renderer.bounds.insert(25, 50, 300, 400);
|
||||||
renderer.bounds.insert(125, 150, 150, 200);
|
renderer.bounds.insert(125, 150, 150, 200);
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(25);
|
expect(bounds.startx).toBe(25);
|
||||||
expect(bounds.starty).toBe(50);
|
expect(bounds.starty).toBe(50);
|
||||||
expect(bounds.stopx).toBe(300);
|
expect(bounds.stopx).toBe(300);
|
||||||
@@ -841,7 +845,7 @@ describe('when checking the bounds in a sequenceDiagram', function() {
|
|||||||
expect(loop.stopy).toBe(200 + conf.boxMargin);
|
expect(loop.stopy).toBe(200 + conf.boxMargin);
|
||||||
|
|
||||||
// Check bounds of first loop
|
// Check bounds of first loop
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds } = renderer.bounds.getBounds();
|
||||||
|
|
||||||
expect(bounds.startx).toBe(25);
|
expect(bounds.startx).toBe(25);
|
||||||
expect(bounds.starty).toBe(50);
|
expect(bounds.starty).toBe(50);
|
||||||
@@ -873,7 +877,7 @@ describe('when checking the bounds in a sequenceDiagram', function() {
|
|||||||
expect(loop.stopy).toBe(300 + 2 * conf.boxMargin);
|
expect(loop.stopy).toBe(300 + 2 * conf.boxMargin);
|
||||||
|
|
||||||
// Check bounds of first loop
|
// Check bounds of first loop
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds } = renderer.bounds.getBounds();
|
||||||
|
|
||||||
expect(bounds.startx).toBe(100);
|
expect(bounds.startx).toBe(100);
|
||||||
expect(bounds.starty).toBe(100);
|
expect(bounds.starty).toBe(100);
|
||||||
@@ -895,7 +899,7 @@ describe('when checking the bounds in a sequenceDiagram', function() {
|
|||||||
expect(loop.stopy).toBe(300 + conf.boxMargin);
|
expect(loop.stopy).toBe(300 + conf.boxMargin);
|
||||||
|
|
||||||
// Check bounds after the loop
|
// Check bounds after the loop
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds } = renderer.bounds.getBounds();
|
||||||
|
|
||||||
expect(bounds.startx).toBe(loop.startx);
|
expect(bounds.startx).toBe(loop.startx);
|
||||||
expect(bounds.starty).toBe(loop.starty);
|
expect(bounds.starty).toBe(loop.starty);
|
||||||
@@ -905,13 +909,8 @@ describe('when checking the bounds in a sequenceDiagram', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('when rendering a sequenceDiagram', function() {
|
describe('when rendering a sequenceDiagram', function() {
|
||||||
let conf;
|
beforeAll(() => {
|
||||||
beforeEach(function() {
|
let conf = {
|
||||||
mermaidAPI.reset();
|
|
||||||
parser.yy = sequenceDb;
|
|
||||||
parser.yy.clear();
|
|
||||||
|
|
||||||
conf = {
|
|
||||||
diagramMarginX: 50,
|
diagramMarginX: 50,
|
||||||
diagramMarginY: 10,
|
diagramMarginY: 10,
|
||||||
actorMargin: 50,
|
actorMargin: 50,
|
||||||
@@ -922,10 +921,17 @@ describe('when rendering a sequenceDiagram', function() {
|
|||||||
messageMargin: 40,
|
messageMargin: 40,
|
||||||
boxTextMargin: 15,
|
boxTextMargin: 15,
|
||||||
noteMargin: 25,
|
noteMargin: 25,
|
||||||
wrapEnabled: false,
|
wrap: false,
|
||||||
mirrorActors: false
|
mirrorActors: false
|
||||||
};
|
};
|
||||||
mermaidAPI.initialize({ sequence: conf });
|
mermaidAPI.initialize({ sequence: conf });
|
||||||
|
});
|
||||||
|
let conf;
|
||||||
|
beforeEach(function() {
|
||||||
|
mermaidAPI.reset();
|
||||||
|
parser.yy = sequenceDb;
|
||||||
|
parser.yy.clear();
|
||||||
|
conf = parser.yy.getConfig();
|
||||||
renderer.bounds.init();
|
renderer.bounds.init();
|
||||||
});
|
});
|
||||||
['tspan', 'fo', 'old', undefined].forEach(function(textPlacement) {
|
['tspan', 'fo', 'old', undefined].forEach(function(textPlacement) {
|
||||||
@@ -935,12 +941,12 @@ it should handle one actor, when textPlacement is ${textPlacement}`, function()
|
|||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
participant Alice`;
|
participant Alice`;
|
||||||
|
|
||||||
mermaidAPI.initialize(addConf(conf, 'textPlacement', textPlacement));
|
mermaidAPI.reinitialize({sequence: { textPlacement: textPlacement}});
|
||||||
renderer.bounds.init();
|
mermaidAPI.parse(str);
|
||||||
parser.parse(str);
|
// renderer.setConf(mermaidAPI.getConfig().sequence);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
expect(bounds.stopx).toBe(conf.width);
|
expect(bounds.stopx).toBe(conf.width);
|
||||||
@@ -955,7 +961,7 @@ participant Alice
|
|||||||
participant Alice
|
participant Alice
|
||||||
`;
|
`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
|
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
expect(Object.keys(actors)).toEqual(['Alice']);
|
expect(Object.keys(actors)).toEqual(['Alice']);
|
||||||
@@ -967,15 +973,16 @@ participant Alice
|
|||||||
Note over Alice: Alice thinks
|
Note over Alice: Alice thinks
|
||||||
`;
|
`;
|
||||||
|
|
||||||
parser.parse(str);
|
expect(mermaidAPI.getConfig().sequence.mirrorActors).toBeFalsy();
|
||||||
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
expect(bounds.stopx).toBe(conf.width);
|
expect(bounds.stopx).toBe(conf.width);
|
||||||
// 10 comes from mock of text height
|
// 10 comes from mock of text height
|
||||||
expect(bounds.stopy).toBe(conf.height + conf.boxMargin + 2 * conf.noteMargin + 10);
|
expect(bounds.stopy).toBe(models.lastNote().stopy);
|
||||||
});
|
});
|
||||||
it('it should handle one actor and a note to the left', function() {
|
it('it should handle one actor and a note to the left', function() {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -983,15 +990,15 @@ sequenceDiagram
|
|||||||
participant Alice
|
participant Alice
|
||||||
Note left of Alice: Alice thinks`;
|
Note left of Alice: Alice thinks`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2);
|
expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
expect(bounds.stopx).toBe(conf.width);
|
expect(bounds.stopx).toBe(conf.width);
|
||||||
// 10 comes from mock of text height
|
// 10 comes from mock of text height
|
||||||
expect(bounds.stopy).toBe(conf.height + conf.boxMargin + 2 * conf.noteMargin + 10);
|
expect(bounds.stopy).toBe(models.lastNote().stopy);
|
||||||
});
|
});
|
||||||
it('it should handle one actor and a note to the right', function() {
|
it('it should handle one actor and a note to the right', function() {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -999,29 +1006,29 @@ sequenceDiagram
|
|||||||
participant Alice
|
participant Alice
|
||||||
Note right of Alice: Alice thinks`;
|
Note right of Alice: Alice thinks`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
expect(bounds.stopx).toBe(conf.width / 2 + conf.actorMargin / 2 + conf.width);
|
expect(bounds.stopx).toBe(conf.width / 2 + conf.actorMargin / 2 + conf.width);
|
||||||
// 10 comes from mock of text height
|
// 10 comes from mock of text height
|
||||||
expect(bounds.stopy).toBe(conf.height + conf.boxMargin + 2 * conf.noteMargin + 10);
|
expect(bounds.stopy).toBe(models.lastNote().stopy);
|
||||||
});
|
});
|
||||||
it('it should handle two actors', function() {
|
it('it should handle two actors', function() {
|
||||||
const str = `
|
const str = `
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
Alice->Bob: Hello Bob, how are you?`;
|
Alice->Bob: Hello Bob, how are you?`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||||
expect(bounds.stopy).toBe(conf.messageMargin + conf.height);
|
expect(bounds.stopy).toBe(models.lastMessage().stopy);
|
||||||
});
|
});
|
||||||
it('it should handle two actors with init directive', function() {
|
it('it should handle two actors with init directive', function() {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -1029,16 +1036,16 @@ Alice->Bob: Hello Bob, how are you?`;
|
|||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
Alice->Bob: Hello Bob, how are you?`;
|
Alice->Bob: Hello Bob, how are you?`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
const mermaid = mermaidAPI.getConfig();
|
const mermaid = mermaidAPI.getConfig();
|
||||||
expect(mermaid.logLevel).toBe(0);
|
expect(mermaid.logLevel).toBe(0);
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||||
expect(bounds.stopy).toBe(conf.height + conf.messageMargin + (conf.mirrorActors ? 2 * conf.boxMargin + conf.height : 0));
|
expect(bounds.stopy).toBe(models.lastMessage().stopy);
|
||||||
});
|
});
|
||||||
it('it should handle two actors with init directive with multiline directive', function() {
|
it('it should handle two actors with init directive with multiline directive', function() {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -1049,17 +1056,17 @@ wrap
|
|||||||
}%%
|
}%%
|
||||||
Alice->Bob: Hello Bob, how are you?`;
|
Alice->Bob: Hello Bob, how are you?`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const msgs = parser.yy.getMessages();
|
const msgs = parser.yy.getMessages();
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
const mermaid = mermaidAPI.getConfig();
|
const mermaid = mermaidAPI.getConfig();
|
||||||
expect(mermaid.logLevel).toBe(0);
|
expect(mermaid.logLevel).toBe(0);
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||||
expect(bounds.stopy).toBe(conf.messageMargin + conf.height);
|
expect(bounds.stopy).toBe(models.lastMessage().stopy);
|
||||||
expect(msgs.every(v => v.wrap)).toBe(true);
|
expect(msgs.every(v => v.wrap)).toBe(true);
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -1070,17 +1077,15 @@ Alice->Bob: Hello Bob, how are you?
|
|||||||
Note over Alice,Bob: Looks
|
Note over Alice,Bob: Looks
|
||||||
Note over Bob,Alice: Looks back
|
Note over Bob,Alice: Looks back
|
||||||
`;
|
`;
|
||||||
|
mermaidAPI.initialize({logLevel:0})
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||||
expect(bounds.stopy).toBe(
|
expect(bounds.stopy).toBe(models.lastNote().stopy);
|
||||||
conf.height + conf.messageMargin + 2 * (conf.boxMargin + 2 * conf.noteMargin + 10)
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
it('it should draw two actors and two messages', function() {
|
it('it should draw two actors and two messages', function() {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -1088,14 +1093,14 @@ sequenceDiagram
|
|||||||
Alice->Bob: Hello Bob, how are you?
|
Alice->Bob: Hello Bob, how are you?
|
||||||
Bob->Alice: Fine!`;
|
Bob->Alice: Fine!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
expect(bounds.stopx).toBe(0 + conf.width * 2 + conf.actorMargin);
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||||
expect(bounds.stopy).toBe(0 + 2 * conf.messageMargin + conf.height);
|
expect(bounds.stopy).toBe(models.lastMessage().stopy);
|
||||||
});
|
});
|
||||||
it('it should draw two actors notes to the right', function() {
|
it('it should draw two actors notes to the right', function() {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -1104,19 +1109,17 @@ Alice->Bob: Hello Bob, how are you?
|
|||||||
Note right of Bob: Bob thinks
|
Note right of Bob: Bob thinks
|
||||||
Bob->Alice: Fine!`;
|
Bob->Alice: Fine!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
|
|
||||||
const expStopX = conf.actorMargin + conf.width + conf.width / 2 + conf.noteMargin + conf.width;
|
const expStopX = conf.actorMargin + conf.width + conf.width / 2 + conf.noteMargin + conf.width;
|
||||||
|
|
||||||
expect(bounds.stopx).toBe(expStopX);
|
expect(bounds.stopx).toBe(expStopX);
|
||||||
expect(bounds.stopy).toBe(
|
expect(bounds.stopy).toBe(models.lastMessage().stopy);
|
||||||
2 * conf.messageMargin + conf.height + conf.boxMargin + 10 + 2 * conf.noteMargin
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
it('it should draw two actors notes to the left', function() {
|
it('it should draw two actors notes to the left', function() {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -1125,17 +1128,15 @@ Alice->Bob: Hello Bob, how are you?
|
|||||||
Note left of Alice: Bob thinks
|
Note left of Alice: Bob thinks
|
||||||
Bob->Alice: Fine!`;
|
Bob->Alice: Fine!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2);
|
expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
|
|
||||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||||
expect(bounds.stopy).toBe(
|
expect(bounds.stopy).toBe(models.lastMessage().stopy);
|
||||||
2 * conf.messageMargin + conf.height + conf.boxMargin + 10 + 2 * conf.noteMargin
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
it('it should draw two actors notes to the left with text wrapped (inline)', function() {
|
it('it should draw two actors notes to the left with text wrapped (inline)', function() {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -1144,19 +1145,17 @@ Alice->>Bob:wrap: Hello Bob, how are you? If you are not available right now, I
|
|||||||
Note left of Alice: Bob thinks
|
Note left of Alice: Bob thinks
|
||||||
Bob->>Alice: Fine!`;
|
Bob->>Alice: Fine!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
const msgs = parser.yy.getMessages();
|
const msgs = parser.yy.getMessages();
|
||||||
expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2);
|
expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
expect(msgs[0].wrap).toBe(true);
|
expect(msgs[0].wrap).toBe(true);
|
||||||
|
|
||||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||||
expect(bounds.stopy).toBe(
|
expect(bounds.stopy).toBe(models.lastMessage().stopy);
|
||||||
2 * conf.messageMargin + conf.height + conf.boxMargin + 10 + 2 * conf.noteMargin
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
it('it should draw two actors notes to the left with text wrapped (directive)', function() {
|
it('it should draw two actors notes to the left with text wrapped (directive)', function() {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -1167,10 +1166,10 @@ Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can l
|
|||||||
Note left of Alice: Bob thinks
|
Note left of Alice: Bob thinks
|
||||||
Bob->>Alice: Fine!`;
|
Bob->>Alice: Fine!`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
const msgs = parser.yy.getMessages();
|
const msgs = parser.yy.getMessages();
|
||||||
const mermaid = mermaidAPI.getConfig();
|
const mermaid = mermaidAPI.getConfig();
|
||||||
expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2);
|
expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2);
|
||||||
@@ -1179,9 +1178,7 @@ Bob->>Alice: Fine!`;
|
|||||||
expect(msgs.every(v => v.wrap)).toBe(true);
|
expect(msgs.every(v => v.wrap)).toBe(true);
|
||||||
|
|
||||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||||
expect(bounds.stopy).toBe(
|
expect(bounds.stopy).toBe(models.lastMessage().stopy);
|
||||||
2 * conf.messageMargin + conf.height + conf.boxMargin + 10 + 2 * conf.noteMargin
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
it('it should draw two actors notes to the left with text wrapped and the init directive sets the theme to dark', function() {
|
it('it should draw two actors notes to the left with text wrapped and the init directive sets the theme to dark', function() {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -1191,10 +1188,11 @@ sequenceDiagram
|
|||||||
Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
|
Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
|
||||||
Note left of Alice: Bob thinks
|
Note left of Alice: Bob thinks
|
||||||
Bob->>Alice: Fine!`;
|
Bob->>Alice: Fine!`;
|
||||||
parser.parse(str);
|
|
||||||
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
const msgs = parser.yy.getMessages();
|
const msgs = parser.yy.getMessages();
|
||||||
const mermaid = mermaidAPI.getConfig();
|
const mermaid = mermaidAPI.getConfig();
|
||||||
expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2);
|
expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2);
|
||||||
@@ -1203,22 +1201,19 @@ Bob->>Alice: Fine!`;
|
|||||||
expect(msgs.every(v => v.wrap)).toBe(true);
|
expect(msgs.every(v => v.wrap)).toBe(true);
|
||||||
|
|
||||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||||
expect(bounds.stopy).toBe(
|
expect(bounds.stopy).toBe(models.lastMessage().stopy);
|
||||||
2 * conf.messageMargin + conf.height + conf.boxMargin + 10 + 2 * conf.noteMargin
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
it('it should draw two actors, notes to the left with text wrapped and the init directive sets the theme to dark and fontFamily to Menlo, fontSize to 18, and fontWeight to 800', function() {
|
it('it should draw two actors, notes to the left with text wrapped and the init directive sets the theme to dark and fontFamily to Menlo, fontSize to 18, and fontWeight to 800', function() {
|
||||||
const str = `
|
const str = `
|
||||||
%%{init: { "theme": "dark", 'config': { "fontFamily": "Menlo", "fontSize": 18, "fontWeight": 400, "wrapEnabled": true }}}%%
|
%%{init: { "theme": "dark", 'config': { "fontFamily": "Menlo", "fontSize": 18, "fontWeight": 400, "wrap": true }}}%%
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
|
Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
|
||||||
Note left of Alice: Bob thinks
|
Note left of Alice: Bob thinks
|
||||||
Bob->>Alice: Fine!`;
|
Bob->>Alice: Fine!`;
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
// renderer.setConf(mermaidAPI.getConfig().sequence);
|
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
const msgs = parser.yy.getMessages();
|
const msgs = parser.yy.getMessages();
|
||||||
const mermaid = mermaidAPI.getConfig();
|
const mermaid = mermaidAPI.getConfig();
|
||||||
expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2);
|
expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2);
|
||||||
@@ -1230,9 +1225,7 @@ Bob->>Alice: Fine!`;
|
|||||||
expect(msgs.every(v => v.wrap)).toBe(true);
|
expect(msgs.every(v => v.wrap)).toBe(true);
|
||||||
|
|
||||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||||
expect(bounds.stopy).toBe(
|
expect(bounds.stopy).toBe(models.lastMessage().stopy);
|
||||||
2 * conf.messageMargin + conf.height + conf.boxMargin + 10 + 2 * conf.noteMargin
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
it('it should draw two loops', function() {
|
it('it should draw two loops', function() {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -1241,17 +1234,15 @@ Alice->Bob: Hello Bob, how are you?
|
|||||||
loop Cheers
|
loop Cheers
|
||||||
Bob->Alice: Fine!
|
Bob->Alice: Fine!
|
||||||
end`;
|
end`;
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
|
|
||||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||||
expect(bounds.stopy).toBe(
|
expect(bounds.stopy).toBe(models.lastLoop().stopy);
|
||||||
2 * conf.messageMargin + conf.height + 3 * conf.boxMargin + conf.boxTextMargin
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
it('it should draw background rect', function() {
|
it('it should draw background rect', function() {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -1261,26 +1252,21 @@ end`;
|
|||||||
Bob->Alice: I feel surrounded by darkness
|
Bob->Alice: I feel surrounded by darkness
|
||||||
end
|
end
|
||||||
`;
|
`;
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
|
|
||||||
expect(bounds.stopx).toBe(0 + conf.width * 2 + conf.actorMargin);
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||||
expect(bounds.stopy).toBe(0 + 2 * conf.messageMargin + conf.height + 3 * conf.boxMargin);
|
expect(bounds.stopy).toBe(models.lastLoop().stopy);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('when rendering a sequenceDiagram with actor mirror activated', function() {
|
describe('when rendering a sequenceDiagram with actor mirror activated', function() {
|
||||||
let conf;
|
beforeAll(() => {
|
||||||
beforeEach(function() {
|
let conf = {
|
||||||
mermaidAPI.reset();
|
|
||||||
parser.yy = sequenceDb;
|
|
||||||
parser.yy.clear();
|
|
||||||
|
|
||||||
conf = {
|
|
||||||
diagramMarginX: 50,
|
diagramMarginX: 50,
|
||||||
diagramMarginY: 10,
|
diagramMarginY: 10,
|
||||||
actorMargin: 50,
|
actorMargin: 50,
|
||||||
@@ -1296,7 +1282,16 @@ describe('when rendering a sequenceDiagram with actor mirror activated', functio
|
|||||||
// Prolongs the edge of the diagram downwards
|
// Prolongs the edge of the diagram downwards
|
||||||
bottomMarginAdj: 1
|
bottomMarginAdj: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
mermaidAPI.initialize({ sequence: conf });
|
mermaidAPI.initialize({ sequence: conf });
|
||||||
|
});
|
||||||
|
|
||||||
|
let conf;
|
||||||
|
beforeEach(function() {
|
||||||
|
mermaidAPI.reset();
|
||||||
|
parser.yy = sequenceDb;
|
||||||
|
parser.yy.clear();
|
||||||
|
conf = parser.yy.getConfig();
|
||||||
renderer.bounds.init();
|
renderer.bounds.init();
|
||||||
});
|
});
|
||||||
['tspan', 'fo', 'old', undefined].forEach(function(textPlacement) {
|
['tspan', 'fo', 'old', undefined].forEach(function(textPlacement) {
|
||||||
@@ -1306,31 +1301,26 @@ describe('when rendering a sequenceDiagram with actor mirror activated', functio
|
|||||||
const str = `
|
const str = `
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
participant Alice`;
|
participant Alice`;
|
||||||
|
renderer.bounds.init();
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
expect(bounds.stopx).toBe(conf.width);
|
expect(bounds.stopx).toBe(conf.width);
|
||||||
expect(bounds.stopy).toBe(2 * conf.height + 2 * conf.boxMargin);
|
expect(bounds.stopy).toBe(models.lastActor().y + models.lastActor().height);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when rendering a sequenceDiagram with directives', function() {
|
describe('when rendering a sequenceDiagram with directives', function() {
|
||||||
let conf;
|
beforeAll(function() {
|
||||||
beforeEach(function() {
|
let conf = {
|
||||||
mermaidAPI.reset();
|
|
||||||
parser.yy = sequenceDb;
|
|
||||||
parser.yy.clear();
|
|
||||||
conf = {
|
|
||||||
diagramMarginX: 50,
|
diagramMarginX: 50,
|
||||||
diagramMarginY: 10,
|
diagramMarginY: 10,
|
||||||
actorMargin: 50,
|
actorMargin: 50,
|
||||||
width: 150,
|
width: 150,
|
||||||
// Height of actor boxes
|
|
||||||
height: 65,
|
height: 65,
|
||||||
boxMargin: 10,
|
boxMargin: 10,
|
||||||
messageMargin: 40,
|
messageMargin: 40,
|
||||||
@@ -1338,6 +1328,14 @@ describe('when rendering a sequenceDiagram with directives', function() {
|
|||||||
noteMargin: 25
|
noteMargin: 25
|
||||||
};
|
};
|
||||||
mermaidAPI.initialize({ sequence: conf });
|
mermaidAPI.initialize({ sequence: conf });
|
||||||
|
});
|
||||||
|
|
||||||
|
let conf;
|
||||||
|
beforeEach(function() {
|
||||||
|
mermaidAPI.reset();
|
||||||
|
parser.yy = sequenceDb;
|
||||||
|
parser.yy.clear();
|
||||||
|
conf = parser.yy.getConfig();
|
||||||
renderer.bounds.init();
|
renderer.bounds.init();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1349,17 +1347,18 @@ sequenceDiagram
|
|||||||
participant Alice
|
participant Alice
|
||||||
`;
|
`;
|
||||||
|
|
||||||
parser.parse(str);
|
renderer.bounds.init();
|
||||||
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
const mermaid = mermaidAPI.getConfig();
|
const mermaid = mermaidAPI.getConfig();
|
||||||
expect(mermaid.theme).toBe('dark');
|
expect(mermaid.theme).toBe('dark');
|
||||||
expect(mermaid.logLevel).toBe(1);
|
expect(mermaid.logLevel).toBe(1);
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
expect(bounds.stopy).toBe(2 * conf.height + 2 * conf.boxMargin);
|
expect(bounds.stopy).toBe(models.lastActor().y + models.lastActor().height);
|
||||||
});
|
});
|
||||||
it('it should handle one actor, when logLevel is 3', function() {
|
it('it should handle one actor, when logLevel is 3', function() {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -1368,15 +1367,15 @@ sequenceDiagram
|
|||||||
participant Alice
|
participant Alice
|
||||||
`;
|
`;
|
||||||
|
|
||||||
parser.parse(str);
|
mermaidAPI.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
const bounds = renderer.bounds.getBounds();
|
const { bounds, models } = renderer.bounds.getBounds();
|
||||||
const mermaid = mermaidAPI.getConfig();
|
const mermaid = mermaidAPI.getConfig();
|
||||||
expect(mermaid.logLevel).toBe(3);
|
expect(mermaid.logLevel).toBe(3);
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.startx).toBe(0);
|
expect(bounds.startx).toBe(0);
|
||||||
expect(bounds.starty).toBe(0);
|
expect(bounds.starty).toBe(0);
|
||||||
expect(bounds.stopy).toBe(2 * conf.height + 2 * conf.boxMargin);
|
expect(bounds.stopy).toBe(models.lastActor().y + models.lastActor().height);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -8,79 +8,7 @@ import utils, { assignWithDepth } from '../../utils';
|
|||||||
|
|
||||||
parser.yy = sequenceDb;
|
parser.yy = sequenceDb;
|
||||||
|
|
||||||
const conf = {
|
const conf = {};
|
||||||
diagramMarginX: 50,
|
|
||||||
diagramMarginY: 30,
|
|
||||||
// Margin between actors
|
|
||||||
actorMargin: 50,
|
|
||||||
// Width of actor boxes
|
|
||||||
width: 150,
|
|
||||||
// Height of actor boxes
|
|
||||||
height: 65,
|
|
||||||
actorFontSize: 14,
|
|
||||||
actorFontFamily: '"Open-Sans", "sans-serif"',
|
|
||||||
// 400 = normal
|
|
||||||
actorFontWeight: 400,
|
|
||||||
// Note font settings
|
|
||||||
noteFontSize: 14,
|
|
||||||
noteFontFamily: '"trebuchet ms", verdana, arial',
|
|
||||||
noteFontWeight: 400,
|
|
||||||
noteAlign: 'center',
|
|
||||||
// Message font settings
|
|
||||||
messageFontSize: 16,
|
|
||||||
messageFontFamily: '"trebuchet ms", verdana, arial',
|
|
||||||
messageFontWeight: 400,
|
|
||||||
// Margin around loop boxes
|
|
||||||
boxMargin: 10,
|
|
||||||
boxTextMargin: 5,
|
|
||||||
noteMargin: 10,
|
|
||||||
// Space between messages
|
|
||||||
messageMargin: 35,
|
|
||||||
// Multiline message alignment
|
|
||||||
messageAlign: 'center',
|
|
||||||
// mirror actors under diagram
|
|
||||||
mirrorActors: false,
|
|
||||||
// Depending on css styling this might need adjustment
|
|
||||||
// Prolongs the edge of the diagram downwards
|
|
||||||
bottomMarginAdj: 1,
|
|
||||||
|
|
||||||
// width of activation box
|
|
||||||
activationWidth: 10,
|
|
||||||
labelBoxWidth: 50,
|
|
||||||
labelBoxHeight: 20,
|
|
||||||
|
|
||||||
// text placement as: tspan | fo | old only text as before
|
|
||||||
textPlacement: 'tspan',
|
|
||||||
|
|
||||||
showSequenceNumbers: false,
|
|
||||||
|
|
||||||
// wrap text
|
|
||||||
wrapEnabled: false,
|
|
||||||
// padding for wrapped text
|
|
||||||
wrapPadding: 15,
|
|
||||||
|
|
||||||
messageFont: () => {
|
|
||||||
return {
|
|
||||||
fontFamily: conf.messageFontFamily,
|
|
||||||
fontSize: conf.messageFontSize,
|
|
||||||
fontWeight: conf.messageFontWeight
|
|
||||||
};
|
|
||||||
},
|
|
||||||
noteFont: () => {
|
|
||||||
return {
|
|
||||||
fontFamily: conf.noteFontFamily,
|
|
||||||
fontSize: conf.noteFontSize,
|
|
||||||
fontWeight: conf.noteFontWeight
|
|
||||||
};
|
|
||||||
},
|
|
||||||
actorFont: () => {
|
|
||||||
return {
|
|
||||||
fontFamily: conf.actorFontFamily,
|
|
||||||
fontSize: conf.actorFontSize,
|
|
||||||
fontWeight: conf.actorFontWeight
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const bounds = {
|
export const bounds = {
|
||||||
data: {
|
data: {
|
||||||
@@ -90,10 +18,57 @@ export const bounds = {
|
|||||||
stopy: undefined
|
stopy: undefined
|
||||||
},
|
},
|
||||||
verticalPos: 0,
|
verticalPos: 0,
|
||||||
|
|
||||||
sequenceItems: [],
|
sequenceItems: [],
|
||||||
activations: [],
|
activations: [],
|
||||||
models: {
|
models: {
|
||||||
|
getHeight: function() {
|
||||||
|
return (
|
||||||
|
Math.max.apply(
|
||||||
|
null,
|
||||||
|
this.actors.length === 0 ? [0] : this.actors.map(actor => actor.height || 0)
|
||||||
|
) +
|
||||||
|
(this.loops.length === 0
|
||||||
|
? 0
|
||||||
|
: this.loops.map(it => it.height || 0).reduce((acc, h) => acc + h)) +
|
||||||
|
(this.messages.length === 0
|
||||||
|
? 0
|
||||||
|
: this.messages.map(it => it.height || 0).reduce((acc, h) => acc + h)) +
|
||||||
|
(this.notes.length === 0
|
||||||
|
? 0
|
||||||
|
: this.notes.map(it => it.height || 0).reduce((acc, h) => acc + h))
|
||||||
|
);
|
||||||
|
},
|
||||||
|
clear: function() {
|
||||||
|
this.actors = [];
|
||||||
|
this.loops = [];
|
||||||
|
this.messages = [];
|
||||||
|
this.notes = [];
|
||||||
|
},
|
||||||
|
addActor: function(actorModel) {
|
||||||
|
this.actors.push(actorModel);
|
||||||
|
},
|
||||||
|
addLoop: function(loopModel) {
|
||||||
|
this.loops.push(loopModel);
|
||||||
|
},
|
||||||
|
addMessage: function(msgModel) {
|
||||||
|
this.messages.push(msgModel);
|
||||||
|
},
|
||||||
|
addNote: function(noteModel) {
|
||||||
|
this.notes.push(noteModel);
|
||||||
|
},
|
||||||
|
lastActor: function() {
|
||||||
|
return this.actors[this.actors.length - 1];
|
||||||
|
},
|
||||||
|
lastLoop: function() {
|
||||||
|
return this.loops[this.loops.length - 1];
|
||||||
|
},
|
||||||
|
lastMessage: function() {
|
||||||
|
return this.messages[this.messages.length - 1];
|
||||||
|
},
|
||||||
|
lastNote: function() {
|
||||||
|
return this.notes[this.notes.length - 1];
|
||||||
|
},
|
||||||
|
actors: [],
|
||||||
loops: [],
|
loops: [],
|
||||||
messages: [],
|
messages: [],
|
||||||
notes: []
|
notes: []
|
||||||
@@ -101,11 +76,7 @@ export const bounds = {
|
|||||||
init: function() {
|
init: function() {
|
||||||
this.sequenceItems = [];
|
this.sequenceItems = [];
|
||||||
this.activations = [];
|
this.activations = [];
|
||||||
this.models = {
|
this.models.clear();
|
||||||
loops: [],
|
|
||||||
messages: [],
|
|
||||||
notes: []
|
|
||||||
};
|
|
||||||
this.data = {
|
this.data = {
|
||||||
startx: undefined,
|
startx: undefined,
|
||||||
stopx: undefined,
|
stopx: undefined,
|
||||||
@@ -113,6 +84,7 @@ export const bounds = {
|
|||||||
stopy: undefined
|
stopy: undefined
|
||||||
};
|
};
|
||||||
this.verticalPos = 0;
|
this.verticalPos = 0;
|
||||||
|
setConf(parser.yy.getConfig());
|
||||||
},
|
},
|
||||||
updateVal: function(obj, key, val, fun) {
|
updateVal: function(obj, key, val, fun) {
|
||||||
if (typeof obj[key] === 'undefined') {
|
if (typeof obj[key] === 'undefined') {
|
||||||
@@ -219,7 +191,7 @@ export const bounds = {
|
|||||||
return this.verticalPos;
|
return this.verticalPos;
|
||||||
},
|
},
|
||||||
getBounds: function() {
|
getBounds: function() {
|
||||||
return this.data;
|
return { bounds: this.data, models: this.models };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -229,17 +201,20 @@ export const bounds = {
|
|||||||
* @param noteModel:{x: number, y: number, message: string, width: number} - startx: x axis start position, verticalPos: y axis position, messsage: the message to be shown, width: Set this with a custom width to override the default configured width.
|
* @param noteModel:{x: number, y: number, message: string, width: number} - startx: x axis start position, verticalPos: y axis position, messsage: the message to be shown, width: Set this with a custom width to override the default configured width.
|
||||||
*/
|
*/
|
||||||
const drawNote = function(elem, noteModel) {
|
const drawNote = function(elem, noteModel) {
|
||||||
|
bounds.bumpVerticalPos(conf.boxMargin);
|
||||||
|
noteModel.height = conf.boxMargin;
|
||||||
|
noteModel.starty = bounds.getVerticalPos();
|
||||||
const rect = svgDraw.getNoteRect();
|
const rect = svgDraw.getNoteRect();
|
||||||
rect.x = noteModel.x;
|
rect.x = noteModel.startx;
|
||||||
rect.y = noteModel.y;
|
rect.y = noteModel.starty;
|
||||||
rect.width = noteModel.width || conf.width;
|
rect.width = noteModel.width || conf.width;
|
||||||
rect.class = 'note';
|
rect.class = 'note';
|
||||||
|
|
||||||
let g = elem.append('g');
|
let g = elem.append('g');
|
||||||
const rectElem = svgDraw.drawRect(g, rect);
|
const rectElem = svgDraw.drawRect(g, rect);
|
||||||
const textObj = svgDraw.getTextObj();
|
const textObj = svgDraw.getTextObj();
|
||||||
textObj.x = noteModel.x;
|
textObj.x = noteModel.startx;
|
||||||
textObj.y = noteModel.y;
|
textObj.y = noteModel.starty;
|
||||||
textObj.width = rect.width;
|
textObj.width = rect.width;
|
||||||
textObj.dy = '1em';
|
textObj.dy = '1em';
|
||||||
textObj.text = noteModel.message;
|
textObj.text = noteModel.message;
|
||||||
@@ -258,12 +233,13 @@ const drawNote = function(elem, noteModel) {
|
|||||||
textElem.map(te => (te._groups || te)[0][0].getBBox().height).reduce((acc, curr) => acc + curr)
|
textElem.map(te => (te._groups || te)[0][0].getBBox().height).reduce((acc, curr) => acc + curr)
|
||||||
);
|
);
|
||||||
|
|
||||||
noteModel.height = textHeight + 2 * conf.noteMargin;
|
rectElem.attr('height', textHeight + 2 * conf.noteMargin);
|
||||||
|
noteModel.height += textHeight + 2 * conf.noteMargin;
|
||||||
bounds.insert(noteModel.x, noteModel.y, noteModel.x + rect.width, noteModel.y + noteModel.height);
|
bounds.bumpVerticalPos(textHeight + 2 * conf.noteMargin);
|
||||||
|
noteModel.stopy = noteModel.starty + textHeight + 2 * conf.noteMargin;
|
||||||
rectElem.attr('height', noteModel.height);
|
noteModel.stopx = noteModel.startx + rect.width;
|
||||||
bounds.bumpVerticalPos(noteModel.height);
|
bounds.insert(noteModel.startx, noteModel.starty, noteModel.stopx, noteModel.stopy);
|
||||||
|
bounds.models.addNote(noteModel);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -272,10 +248,13 @@ const drawNote = function(elem, noteModel) {
|
|||||||
* @param msgModel - the model containing fields describing a message
|
* @param msgModel - the model containing fields describing a message
|
||||||
*/
|
*/
|
||||||
const drawMessage = function(g, msgModel) {
|
const drawMessage = function(g, msgModel) {
|
||||||
|
bounds.bumpVerticalPos(conf.messageMargin);
|
||||||
|
msgModel.height += conf.messageMargin;
|
||||||
|
msgModel.starty = bounds.getVerticalPos();
|
||||||
const { startx, stopx, starty: verticalPos, message, type, sequenceIndex, wrap } = msgModel;
|
const { startx, stopx, starty: verticalPos, message, type, sequenceIndex, wrap } = msgModel;
|
||||||
const textObj = svgDraw.getTextObj();
|
const textObj = svgDraw.getTextObj();
|
||||||
textObj.x = startx;
|
textObj.x = startx;
|
||||||
textObj.y = verticalPos - (conf.messageFontSize + 7);
|
textObj.y = verticalPos;
|
||||||
textObj.width = stopx - startx;
|
textObj.width = stopx - startx;
|
||||||
textObj.class = 'messageText';
|
textObj.class = 'messageText';
|
||||||
textObj.dy = '1em';
|
textObj.dy = '1em';
|
||||||
@@ -290,20 +269,18 @@ const drawMessage = function(g, msgModel) {
|
|||||||
textObj.wrap = wrap;
|
textObj.wrap = wrap;
|
||||||
|
|
||||||
let textElem = drawText(g, textObj);
|
let textElem = drawText(g, textObj);
|
||||||
|
const lineHeight = (textElem[0]._groups || textElem[0])[0][0].getBBox().height;
|
||||||
|
textElem.forEach(te => te.attr('y', verticalPos - 7 - lineHeight / 2));
|
||||||
|
|
||||||
const lines = message.split(common.lineBreakRegex).length - 1 > 0 ? 1 : 0;
|
const lines = message.split(common.lineBreakRegex).length - 1;
|
||||||
|
|
||||||
let totalOffset = Math.round(
|
let totalOffset = Math.round(lineHeight + lines * lineHeight);
|
||||||
textElem.map(te => (te._groups || te)[0][0].getBBox().height).reduce((acc, curr) => acc + curr)
|
|
||||||
);
|
|
||||||
|
|
||||||
let textWidth = Math.max.apply(
|
let textWidth = Math.max.apply(
|
||||||
null,
|
null,
|
||||||
textElem.map(te => (te._groups || te)[0][0].getBBox().width)
|
textElem.map(te => (te._groups || te)[0][0].getBBox().width)
|
||||||
);
|
);
|
||||||
|
|
||||||
bounds.bumpVerticalPos(totalOffset - lines * conf.messageFontSize);
|
|
||||||
|
|
||||||
let line;
|
let line;
|
||||||
if (startx === stopx) {
|
if (startx === stopx) {
|
||||||
if (conf.rightAngles) {
|
if (conf.rightAngles) {
|
||||||
@@ -342,25 +319,32 @@ const drawMessage = function(g, msgModel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bounds.bumpVerticalPos(30);
|
bounds.bumpVerticalPos(30);
|
||||||
|
msgModel.height += 30;
|
||||||
const dx = Math.max(textWidth / 2, 100);
|
const dx = Math.max(textWidth / 2, 100);
|
||||||
bounds.insert(
|
bounds.insert(
|
||||||
startx - dx,
|
startx - dx,
|
||||||
bounds.getVerticalPos() - 10 + totalOffset,
|
bounds.getVerticalPos() - 10 + totalOffset,
|
||||||
stopx + dx,
|
stopx + dx,
|
||||||
bounds.getVerticalPos() + totalOffset
|
bounds.getVerticalPos() + 30 + totalOffset
|
||||||
);
|
);
|
||||||
|
bounds.bumpVerticalPos(10);
|
||||||
|
msgModel.height += 10;
|
||||||
} else {
|
} else {
|
||||||
line = g.append('line');
|
line = g.append('line');
|
||||||
line.attr('x1', startx);
|
line.attr('x1', startx);
|
||||||
line.attr('y1', verticalPos + totalOffset);
|
line.attr('y1', verticalPos + totalOffset);
|
||||||
line.attr('x2', stopx);
|
line.attr('x2', stopx);
|
||||||
line.attr('y2', verticalPos + totalOffset);
|
line.attr('y2', verticalPos + totalOffset);
|
||||||
|
bounds.bumpVerticalPos(10);
|
||||||
|
msgModel.height += 10;
|
||||||
bounds.insert(
|
bounds.insert(
|
||||||
startx,
|
startx,
|
||||||
bounds.getVerticalPos() - 10 + totalOffset,
|
bounds.getVerticalPos() - 10 + totalOffset,
|
||||||
stopx,
|
stopx,
|
||||||
bounds.getVerticalPos() + totalOffset
|
bounds.getVerticalPos() + totalOffset
|
||||||
);
|
);
|
||||||
|
msgModel.height += 10;
|
||||||
|
bounds.bumpVerticalPos(10);
|
||||||
}
|
}
|
||||||
// Make an SVG Container
|
// Make an SVG Container
|
||||||
// Draw the line
|
// Draw the line
|
||||||
@@ -411,6 +395,9 @@ const drawMessage = function(g, msgModel) {
|
|||||||
.attr('class', 'sequenceNumber')
|
.attr('class', 'sequenceNumber')
|
||||||
.text(sequenceIndex);
|
.text(sequenceIndex);
|
||||||
}
|
}
|
||||||
|
msgModel.stopy = msgModel.starty + msgModel.height;
|
||||||
|
bounds.insert(msgModel.fromBounds, msgModel.starty, msgModel.toBounds, msgModel.stopy);
|
||||||
|
logger.debug(`mm.h:${msgModel.height} vs c.h:${msgModel.stopy - msgModel.starty}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const drawActors = function(diagram, actors, actorKeys, verticalPos) {
|
export const drawActors = function(diagram, actors, actorKeys, verticalPos) {
|
||||||
@@ -435,6 +422,7 @@ export const drawActors = function(diagram, actors, actorKeys, verticalPos) {
|
|||||||
|
|
||||||
prevWidth += actor.width;
|
prevWidth += actor.width;
|
||||||
prevMargin += actor.margin;
|
prevMargin += actor.margin;
|
||||||
|
bounds.models.addActor(actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a margin between the actor boxes and the first arrow
|
// Add a margin between the actor boxes and the first arrow
|
||||||
@@ -461,7 +449,7 @@ const actorActivations = function(actor) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const actorFlowVerticaBounds = function(actor, actors) {
|
const activationBounds = function(actor, actors) {
|
||||||
// handle multiple stacked activations for same actor
|
// handle multiple stacked activations for same actor
|
||||||
const actorObj = actors[actor];
|
const actorObj = actors[actor];
|
||||||
const activations = actorActivations(actor);
|
const activations = actorActivations(actor);
|
||||||
@@ -498,7 +486,7 @@ function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoop
|
|||||||
*/
|
*/
|
||||||
export const draw = function(text, id) {
|
export const draw = function(text, id) {
|
||||||
parser.yy.clear();
|
parser.yy.clear();
|
||||||
parser.yy.setWrap(conf.wrapEnabled);
|
parser.yy.setWrap(conf.wrap);
|
||||||
parser.parse(text + '\n');
|
parser.parse(text + '\n');
|
||||||
|
|
||||||
bounds.init();
|
bounds.init();
|
||||||
@@ -545,11 +533,8 @@ export const draw = function(text, id) {
|
|||||||
|
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
case parser.yy.LINETYPE.NOTE:
|
case parser.yy.LINETYPE.NOTE:
|
||||||
bounds.bumpVerticalPos(conf.boxMargin);
|
|
||||||
noteModel = msg.noteModel;
|
noteModel = msg.noteModel;
|
||||||
noteModel.y = bounds.getVerticalPos();
|
|
||||||
drawNote(diagram, noteModel);
|
drawNote(diagram, noteModel);
|
||||||
bounds.models.notes.push(noteModel);
|
|
||||||
break;
|
break;
|
||||||
case parser.yy.LINETYPE.ACTIVE_START:
|
case parser.yy.LINETYPE.ACTIVE_START:
|
||||||
bounds.newActivation(msg, diagram, actors);
|
bounds.newActivation(msg, diagram, actors);
|
||||||
@@ -568,9 +553,9 @@ export const draw = function(text, id) {
|
|||||||
break;
|
break;
|
||||||
case parser.yy.LINETYPE.LOOP_END:
|
case parser.yy.LINETYPE.LOOP_END:
|
||||||
loopModel = bounds.endLoop();
|
loopModel = bounds.endLoop();
|
||||||
svgDraw.drawLoop(diagram, loopModel, 'loop', conf);
|
svgDraw.drawLoop(diagram, loopModel, 'loop', conf, bounds);
|
||||||
bounds.models.loops.push(loopModel);
|
|
||||||
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
|
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
|
||||||
|
bounds.models.addLoop(loopModel);
|
||||||
break;
|
break;
|
||||||
case parser.yy.LINETYPE.RECT_START:
|
case parser.yy.LINETYPE.RECT_START:
|
||||||
adjustLoopHeightForWrap(loopWidths, msg, conf.boxMargin, conf.boxMargin, message =>
|
adjustLoopHeightForWrap(loopWidths, msg, conf.boxMargin, conf.boxMargin, message =>
|
||||||
@@ -580,7 +565,7 @@ export const draw = function(text, id) {
|
|||||||
case parser.yy.LINETYPE.RECT_END:
|
case parser.yy.LINETYPE.RECT_END:
|
||||||
loopModel = bounds.endLoop();
|
loopModel = bounds.endLoop();
|
||||||
svgDraw.drawBackgroundRect(diagram, loopModel);
|
svgDraw.drawBackgroundRect(diagram, loopModel);
|
||||||
bounds.models.loops.push(loopModel);
|
bounds.models.addLoop(loopModel);
|
||||||
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
|
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
|
||||||
break;
|
break;
|
||||||
case parser.yy.LINETYPE.OPT_START:
|
case parser.yy.LINETYPE.OPT_START:
|
||||||
@@ -595,8 +580,8 @@ export const draw = function(text, id) {
|
|||||||
case parser.yy.LINETYPE.OPT_END:
|
case parser.yy.LINETYPE.OPT_END:
|
||||||
loopModel = bounds.endLoop();
|
loopModel = bounds.endLoop();
|
||||||
svgDraw.drawLoop(diagram, loopModel, 'opt', conf);
|
svgDraw.drawLoop(diagram, loopModel, 'opt', conf);
|
||||||
bounds.models.loops.push(loopModel);
|
|
||||||
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
|
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
|
||||||
|
bounds.models.addLoop(loopModel);
|
||||||
break;
|
break;
|
||||||
case parser.yy.LINETYPE.ALT_START:
|
case parser.yy.LINETYPE.ALT_START:
|
||||||
adjustLoopHeightForWrap(
|
adjustLoopHeightForWrap(
|
||||||
@@ -619,8 +604,8 @@ export const draw = function(text, id) {
|
|||||||
case parser.yy.LINETYPE.ALT_END:
|
case parser.yy.LINETYPE.ALT_END:
|
||||||
loopModel = bounds.endLoop();
|
loopModel = bounds.endLoop();
|
||||||
svgDraw.drawLoop(diagram, loopModel, 'alt', conf);
|
svgDraw.drawLoop(diagram, loopModel, 'alt', conf);
|
||||||
bounds.models.loops.push(loopModel);
|
|
||||||
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
|
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
|
||||||
|
bounds.models.addLoop(loopModel);
|
||||||
break;
|
break;
|
||||||
case parser.yy.LINETYPE.PAR_START:
|
case parser.yy.LINETYPE.PAR_START:
|
||||||
adjustLoopHeightForWrap(
|
adjustLoopHeightForWrap(
|
||||||
@@ -643,19 +628,16 @@ export const draw = function(text, id) {
|
|||||||
case parser.yy.LINETYPE.PAR_END:
|
case parser.yy.LINETYPE.PAR_END:
|
||||||
loopModel = bounds.endLoop();
|
loopModel = bounds.endLoop();
|
||||||
svgDraw.drawLoop(diagram, loopModel, 'par', conf);
|
svgDraw.drawLoop(diagram, loopModel, 'par', conf);
|
||||||
bounds.models.loops.push(loopModel);
|
|
||||||
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
|
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
|
||||||
|
bounds.models.addLoop(loopModel);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
try {
|
try {
|
||||||
// lastMsg = msg
|
// lastMsg = msg
|
||||||
bounds.bumpVerticalPos(conf.messageMargin);
|
|
||||||
msgModel = msg.msgModel;
|
msgModel = msg.msgModel;
|
||||||
msgModel.starty = bounds.getVerticalPos();
|
|
||||||
msgModel.sequenceIndex = sequenceIndex;
|
msgModel.sequenceIndex = sequenceIndex;
|
||||||
drawMessage(diagram, msgModel);
|
drawMessage(diagram, msgModel);
|
||||||
bounds.models.messages.push(msgModel);
|
bounds.models.addMessage(msgModel);
|
||||||
bounds.insert(msgModel.fromBounds, msgModel.starty, msgModel.toBounds, msgModel.starty);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('error while drawing message', e);
|
logger.error('error while drawing message', e);
|
||||||
}
|
}
|
||||||
@@ -681,7 +663,7 @@ export const draw = function(text, id) {
|
|||||||
drawActors(diagram, actors, actorKeys, bounds.getVerticalPos());
|
drawActors(diagram, actors, actorKeys, bounds.getVerticalPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
const box = bounds.getBounds();
|
const { bounds: box } = bounds.getBounds();
|
||||||
|
|
||||||
// Adjust line height of actor lines now that the height of the diagram is known
|
// Adjust line height of actor lines now that the height of the diagram is known
|
||||||
logger.debug('For line height fix Querying: #' + id + ' .actor-line');
|
logger.debug('For line height fix Querying: #' + id + ' .actor-line');
|
||||||
@@ -724,7 +706,7 @@ export const draw = function(text, id) {
|
|||||||
' ' +
|
' ' +
|
||||||
(height + extraVertForTitle)
|
(height + extraVertForTitle)
|
||||||
);
|
);
|
||||||
logger.debug('bounds', bounds);
|
logger.debug(`models: ${JSON.stringify(bounds.models, null, 2)}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -879,13 +861,16 @@ const buildNoteModel = function(msg, actors) {
|
|||||||
shouldWrap ? utils.wrapLabel(msg.message, conf.width, conf.noteFont()) : msg.message,
|
shouldWrap ? utils.wrapLabel(msg.message, conf.width, conf.noteFont()) : msg.message,
|
||||||
conf.noteFont()
|
conf.noteFont()
|
||||||
);
|
);
|
||||||
|
logger.debug(`TD:[${textDimensions.width},${textDimensions.height}]`);
|
||||||
let noteModel = {
|
let noteModel = {
|
||||||
width: shouldWrap
|
width: shouldWrap
|
||||||
? conf.width
|
? conf.width
|
||||||
: Math.max(conf.width, textDimensions.width + 2 * conf.noteMargin),
|
: Math.max(conf.width, textDimensions.width + 2 * conf.noteMargin),
|
||||||
height: 0,
|
height: 0,
|
||||||
x: actors[msg.from].x,
|
startx: actors[msg.from].x,
|
||||||
y: 0,
|
stopx: 0,
|
||||||
|
starty: 0,
|
||||||
|
stopy: 0,
|
||||||
message: msg.message
|
message: msg.message
|
||||||
};
|
};
|
||||||
if (msg.placement === parser.yy.PLACEMENT.RIGHTOF) {
|
if (msg.placement === parser.yy.PLACEMENT.RIGHTOF) {
|
||||||
@@ -895,7 +880,7 @@ const buildNoteModel = function(msg, actors) {
|
|||||||
actors[msg.from].width / 2 + actors[msg.to].width / 2,
|
actors[msg.from].width / 2 + actors[msg.to].width / 2,
|
||||||
textDimensions.width + 2 * conf.noteMargin
|
textDimensions.width + 2 * conf.noteMargin
|
||||||
);
|
);
|
||||||
noteModel.x = startx + (actors[msg.from].width + conf.actorMargin) / 2;
|
noteModel.startx = startx + (actors[msg.from].width + conf.actorMargin) / 2;
|
||||||
} else if (msg.placement === parser.yy.PLACEMENT.LEFTOF) {
|
} else if (msg.placement === parser.yy.PLACEMENT.LEFTOF) {
|
||||||
noteModel.width = shouldWrap
|
noteModel.width = shouldWrap
|
||||||
? Math.max(conf.width, textDimensions.width + 2 * conf.noteMargin)
|
? Math.max(conf.width, textDimensions.width + 2 * conf.noteMargin)
|
||||||
@@ -903,7 +888,7 @@ const buildNoteModel = function(msg, actors) {
|
|||||||
actors[msg.from].width / 2 + actors[msg.to].width / 2,
|
actors[msg.from].width / 2 + actors[msg.to].width / 2,
|
||||||
textDimensions.width + 2 * conf.noteMargin
|
textDimensions.width + 2 * conf.noteMargin
|
||||||
);
|
);
|
||||||
noteModel.x = startx - noteModel.width + (actors[msg.from].width - conf.actorMargin) / 2;
|
noteModel.startx = startx - noteModel.width + (actors[msg.from].width - conf.actorMargin) / 2;
|
||||||
} else if (msg.to === msg.from) {
|
} else if (msg.to === msg.from) {
|
||||||
textDimensions = utils.calculateTextDimensions(
|
textDimensions = utils.calculateTextDimensions(
|
||||||
shouldWrap
|
shouldWrap
|
||||||
@@ -914,12 +899,12 @@ const buildNoteModel = function(msg, actors) {
|
|||||||
noteModel.width = shouldWrap
|
noteModel.width = shouldWrap
|
||||||
? Math.max(conf.width, actors[msg.to].width)
|
? Math.max(conf.width, actors[msg.to].width)
|
||||||
: Math.max(actors[msg.to].width, conf.width, textDimensions.width + 2 * conf.noteMargin);
|
: Math.max(actors[msg.to].width, conf.width, textDimensions.width + 2 * conf.noteMargin);
|
||||||
noteModel.x = startx + (actors[msg.to].width - noteModel.width) / 2;
|
noteModel.startx = startx + (actors[msg.to].width - noteModel.width) / 2;
|
||||||
} else {
|
} else {
|
||||||
noteModel.width =
|
noteModel.width =
|
||||||
Math.abs(startx + actors[msg.from].width / 2 - (stopx + actors[msg.to].width / 2)) +
|
Math.abs(startx + actors[msg.from].width / 2 - (stopx + actors[msg.to].width / 2)) +
|
||||||
conf.actorMargin;
|
conf.actorMargin;
|
||||||
noteModel.x =
|
noteModel.startx =
|
||||||
startx < stopx
|
startx < stopx
|
||||||
? startx + actors[msg.from].width / 2 - conf.actorMargin / 2
|
? startx + actors[msg.from].width / 2 - conf.actorMargin / 2
|
||||||
: stopx + actors[msg.to].width / 2 - conf.actorMargin / 2;
|
: stopx + actors[msg.to].width / 2 - conf.actorMargin / 2;
|
||||||
@@ -951,8 +936,8 @@ const buildMessageModel = function(msg, actors) {
|
|||||||
if (!process) {
|
if (!process) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const fromBounds = actorFlowVerticaBounds(msg.from, actors);
|
const fromBounds = activationBounds(msg.from, actors);
|
||||||
const toBounds = actorFlowVerticaBounds(msg.to, actors);
|
const toBounds = activationBounds(msg.to, actors);
|
||||||
const fromIdx = fromBounds[0] <= toBounds[0] ? 1 : 0;
|
const fromIdx = fromBounds[0] <= toBounds[0] ? 1 : 0;
|
||||||
const toIdx = fromBounds[0] < toBounds[0] ? 0 : 1;
|
const toIdx = fromBounds[0] < toBounds[0] ? 0 : 1;
|
||||||
const allBounds = fromBounds.concat(toBounds);
|
const allBounds = fromBounds.concat(toBounds);
|
||||||
@@ -985,7 +970,7 @@ const calculateLoopBounds = function(messages, actors) {
|
|||||||
let current, noteModel, msgModel;
|
let current, noteModel, msgModel;
|
||||||
|
|
||||||
messages.forEach(function(msg) {
|
messages.forEach(function(msg) {
|
||||||
msg.id = utils.generateId();
|
msg.id = utils.random({ length: 10 });
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
case parser.yy.LINETYPE.LOOP_START:
|
case parser.yy.LINETYPE.LOOP_START:
|
||||||
case parser.yy.LINETYPE.ALT_START:
|
case parser.yy.LINETYPE.ALT_START:
|
||||||
@@ -1046,8 +1031,8 @@ const calculateLoopBounds = function(messages, actors) {
|
|||||||
let depth = 0;
|
let depth = 0;
|
||||||
stack.forEach(stk => {
|
stack.forEach(stk => {
|
||||||
current = stk;
|
current = stk;
|
||||||
current.from = Math.min(current.from, noteModel.x);
|
current.from = Math.min(current.from, noteModel.startx);
|
||||||
current.to = Math.max(current.to, noteModel.x + noteModel.width);
|
current.to = Math.max(current.to, noteModel.startx + noteModel.width);
|
||||||
current.width =
|
current.width =
|
||||||
Math.max(current.width, Math.abs(current.from - current.to)) -
|
Math.max(current.width, Math.abs(current.from - current.to)) -
|
||||||
50 -
|
50 -
|
||||||
|
@@ -251,11 +251,11 @@ export const drawActivation = function(elem, bounds, verticalPos, conf, actorAct
|
|||||||
/**
|
/**
|
||||||
* Draws a loop in the diagram
|
* Draws a loop in the diagram
|
||||||
* @param elem - elemenet to append the loop to.
|
* @param elem - elemenet to append the loop to.
|
||||||
* @param bounds - bounds of the given loop.
|
* @param loopModel - loopModel of the given loop.
|
||||||
* @param labelText - Text within the loop.
|
* @param labelText - Text within the loop.
|
||||||
* @param conf
|
* @param conf - diagrom configuration
|
||||||
*/
|
*/
|
||||||
export const drawLoop = function(elem, bounds, labelText, conf) {
|
export const drawLoop = function(elem, loopModel, labelText, conf) {
|
||||||
const g = elem.append('g');
|
const g = elem.append('g');
|
||||||
const drawLoopLine = function(startx, starty, stopx, stopy) {
|
const drawLoopLine = function(startx, starty, stopx, stopy) {
|
||||||
return g
|
return g
|
||||||
@@ -266,20 +266,23 @@ export const drawLoop = function(elem, bounds, labelText, conf) {
|
|||||||
.attr('y2', stopy)
|
.attr('y2', stopy)
|
||||||
.attr('class', 'loopLine');
|
.attr('class', 'loopLine');
|
||||||
};
|
};
|
||||||
drawLoopLine(bounds.startx, bounds.starty, bounds.stopx, bounds.starty);
|
drawLoopLine(loopModel.startx, loopModel.starty, loopModel.stopx, loopModel.starty);
|
||||||
drawLoopLine(bounds.stopx, bounds.starty, bounds.stopx, bounds.stopy);
|
drawLoopLine(loopModel.stopx, loopModel.starty, loopModel.stopx, loopModel.stopy);
|
||||||
drawLoopLine(bounds.startx, bounds.stopy, bounds.stopx, bounds.stopy);
|
drawLoopLine(loopModel.startx, loopModel.stopy, loopModel.stopx, loopModel.stopy);
|
||||||
drawLoopLine(bounds.startx, bounds.starty, bounds.startx, bounds.stopy);
|
drawLoopLine(loopModel.startx, loopModel.starty, loopModel.startx, loopModel.stopy);
|
||||||
if (typeof bounds.sections !== 'undefined') {
|
if (typeof loopModel.sections !== 'undefined') {
|
||||||
bounds.sections.forEach(function(item) {
|
loopModel.sections.forEach(function(item) {
|
||||||
drawLoopLine(bounds.startx, item.y, bounds.stopx, item.y).style('stroke-dasharray', '3, 3');
|
drawLoopLine(loopModel.startx, item.y, loopModel.stopx, item.y).style(
|
||||||
|
'stroke-dasharray',
|
||||||
|
'3, 3'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let txt = getTextObj();
|
let txt = getTextObj();
|
||||||
txt.text = labelText;
|
txt.text = labelText;
|
||||||
txt.x = bounds.startx;
|
txt.x = loopModel.startx;
|
||||||
txt.y = bounds.starty;
|
txt.y = loopModel.starty;
|
||||||
const msgFont = conf.messageFont();
|
const msgFont = conf.messageFont();
|
||||||
txt.fontFamily = msgFont.fontFamily;
|
txt.fontFamily = msgFont.fontFamily;
|
||||||
txt.fontSize = msgFont.fontSize;
|
txt.fontSize = msgFont.fontSize;
|
||||||
@@ -294,9 +297,9 @@ export const drawLoop = function(elem, bounds, labelText, conf) {
|
|||||||
|
|
||||||
drawLabel(g, txt);
|
drawLabel(g, txt);
|
||||||
txt = getTextObj();
|
txt = getTextObj();
|
||||||
txt.text = bounds.title;
|
txt.text = loopModel.title;
|
||||||
txt.x = bounds.startx + conf.labelBoxWidth / 2 + (bounds.stopx - bounds.startx) / 2;
|
txt.x = loopModel.startx + conf.labelBoxWidth / 2 + (loopModel.stopx - loopModel.startx) / 2;
|
||||||
txt.y = bounds.starty + conf.boxMargin + conf.boxTextMargin;
|
txt.y = loopModel.starty + conf.boxMargin + conf.boxTextMargin;
|
||||||
txt.anchor = 'middle';
|
txt.anchor = 'middle';
|
||||||
txt.class = 'loopText';
|
txt.class = 'loopText';
|
||||||
txt.fontFamily = msgFont.fontFamily;
|
txt.fontFamily = msgFont.fontFamily;
|
||||||
@@ -306,12 +309,12 @@ export const drawLoop = function(elem, bounds, labelText, conf) {
|
|||||||
|
|
||||||
let textElem = drawText(g, txt);
|
let textElem = drawText(g, txt);
|
||||||
|
|
||||||
if (typeof bounds.sectionTitles !== 'undefined') {
|
if (typeof loopModel.sectionTitles !== 'undefined') {
|
||||||
bounds.sectionTitles.forEach(function(item, idx) {
|
loopModel.sectionTitles.forEach(function(item, idx) {
|
||||||
if (item.message) {
|
if (item.message) {
|
||||||
txt.text = item.message;
|
txt.text = item.message;
|
||||||
txt.x = bounds.startx + (bounds.stopx - bounds.startx) / 2;
|
txt.x = loopModel.startx + (loopModel.stopx - loopModel.startx) / 2;
|
||||||
txt.y = bounds.sections[idx].y + conf.boxMargin + conf.boxTextMargin;
|
txt.y = loopModel.sections[idx].y + conf.boxMargin + conf.boxTextMargin;
|
||||||
txt.class = 'loopText';
|
txt.class = 'loopText';
|
||||||
txt.anchor = 'middle';
|
txt.anchor = 'middle';
|
||||||
txt.valign = 'middle';
|
txt.valign = 'middle';
|
||||||
@@ -319,20 +322,19 @@ export const drawLoop = function(elem, bounds, labelText, conf) {
|
|||||||
txt.fontFamily = msgFont.fontFamily;
|
txt.fontFamily = msgFont.fontFamily;
|
||||||
txt.fontSize = msgFont.fontSize;
|
txt.fontSize = msgFont.fontSize;
|
||||||
txt.fontWeight = msgFont.fontWeight;
|
txt.fontWeight = msgFont.fontWeight;
|
||||||
txt.wrap = bounds.wrap;
|
txt.wrap = loopModel.wrap;
|
||||||
textElem = drawText(g, txt);
|
textElem = drawText(g, txt);
|
||||||
let sectionHeight = Math.round(
|
let sectionHeight = Math.round(
|
||||||
textElem
|
textElem
|
||||||
.map(te => (te._groups || te)[0][0].getBBox().height)
|
.map(te => (te._groups || te)[0][0].getBBox().height)
|
||||||
.reduce((acc, curr) => acc + curr)
|
.reduce((acc, curr) => acc + curr)
|
||||||
);
|
);
|
||||||
bounds.sections[idx].height += sectionHeight - (conf.boxMargin + conf.boxTextMargin);
|
loopModel.sections[idx].height += sectionHeight - (conf.boxMargin + conf.boxTextMargin);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bounds.height = Math.round(bounds.stopy - bounds.starty);
|
loopModel.height = Math.round(loopModel.stopy - loopModel.starty);
|
||||||
|
|
||||||
return g;
|
return g;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -71,11 +71,11 @@ const init = function() {
|
|||||||
logger.debug('Start On Load before: ' + mermaid.startOnLoad);
|
logger.debug('Start On Load before: ' + mermaid.startOnLoad);
|
||||||
if (typeof mermaid.startOnLoad !== 'undefined') {
|
if (typeof mermaid.startOnLoad !== 'undefined') {
|
||||||
logger.debug('Start On Load inner: ' + mermaid.startOnLoad);
|
logger.debug('Start On Load inner: ' + mermaid.startOnLoad);
|
||||||
mermaidAPI.setConfig({ startOnLoad: mermaid.startOnLoad });
|
mermaidAPI.initialize({ startOnLoad: mermaid.startOnLoad });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof mermaid.ganttConfig !== 'undefined') {
|
if (typeof mermaid.ganttConfig !== 'undefined') {
|
||||||
mermaidAPI.setConfig({ gantt: mermaid.ganttConfig });
|
mermaidAPI.initialize({ gantt: mermaid.ganttConfig });
|
||||||
}
|
}
|
||||||
|
|
||||||
let txt;
|
let txt;
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
import { select } from 'd3';
|
import { select } from 'd3';
|
||||||
import scope from 'scope-css';
|
import scope from 'scope-css';
|
||||||
import pkg from '../package.json';
|
import pkg from '../package.json';
|
||||||
import { setConfig, getConfig } from './config';
|
import { setConfig, getConfig, setSiteConfig, getSiteConfig } from './config';
|
||||||
import { logger, setLogLevel } from './logger';
|
import { logger, setLogLevel } from './logger';
|
||||||
import utils, { assignWithDepth } from './utils';
|
import utils, { assignWithDepth } from './utils';
|
||||||
import flowRenderer from './diagrams/flowchart/flowRenderer';
|
import flowRenderer from './diagrams/flowchart/flowRenderer';
|
||||||
@@ -56,529 +56,11 @@ for (const themeName of ['default', 'forest', 'dark', 'neutral']) {
|
|||||||
themes[themeName] = require(`./themes/${themeName}/index.scss`);
|
themes[themeName] = require(`./themes/${themeName}/index.scss`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* These are the default options which can be overridden with the initialization call like so:
|
|
||||||
* **Example 1:**
|
|
||||||
* <pre>
|
|
||||||
* mermaid.initialize({
|
|
||||||
* flowchart:{
|
|
||||||
* htmlLabels: false
|
|
||||||
* }
|
|
||||||
* });
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* **Example 2:**
|
|
||||||
* <pre>
|
|
||||||
* <script>
|
|
||||||
* var config = {
|
|
||||||
* startOnLoad:true,
|
|
||||||
* flowchart:{
|
|
||||||
* useMaxWidth:true,
|
|
||||||
* htmlLabels:true,
|
|
||||||
* curve:'cardinal',
|
|
||||||
* },
|
|
||||||
*
|
|
||||||
* securityLevel:'loose',
|
|
||||||
* };
|
|
||||||
* mermaid.initialize(config);
|
|
||||||
* </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.
|
|
||||||
*
|
|
||||||
* @name Configuration
|
|
||||||
*/
|
|
||||||
const config = {
|
|
||||||
/** theme , the CSS style sheet
|
|
||||||
*
|
|
||||||
* **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; }"
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
theme: 'default',
|
|
||||||
themeCSS: undefined,
|
|
||||||
/* **maxTextSize** - The maximum allowed size of the users text diamgram */
|
|
||||||
maxTextSize: 50000,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* **fontFamily** The font to be used for the rendered diagrams. Default value is \"trebuchet ms\", verdana, arial;
|
|
||||||
*/
|
|
||||||
fontFamily: '"trebuchet ms", verdana, arial;',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This option decides the amount of logging to be used.
|
|
||||||
* * debug: 1
|
|
||||||
* * info: 2
|
|
||||||
* * warn: 3
|
|
||||||
* * error: 4
|
|
||||||
* * fatal: (**default**) 5
|
|
||||||
*/
|
|
||||||
logLevel: 5,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the level of trust to be used on the parsed diagrams.
|
|
||||||
* * **strict**: (**default**) tags in text are encoded, click functionality is disabeled
|
|
||||||
* * **loose**: tags in text are allowed, click functionality is enabled
|
|
||||||
*/
|
|
||||||
securityLevel: 'strict',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This options controls whether or mermaid starts when the page loads
|
|
||||||
* **Default value true**.
|
|
||||||
*/
|
|
||||||
startOnLoad: true,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This options controls whether or arrow markers in html code will be absolute paths or
|
|
||||||
* an anchor, #. This matters if you are using base tag settings.
|
|
||||||
* **Default value false**.
|
|
||||||
*/
|
|
||||||
arrowMarkerAbsolute: false,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The object containing configurations specific for flowcharts
|
|
||||||
*/
|
|
||||||
flowchart: {
|
|
||||||
/**
|
|
||||||
* Flag for setting whether or not a html tag should be used for rendering labels
|
|
||||||
* on the edges.
|
|
||||||
* **Default value true**.
|
|
||||||
*/
|
|
||||||
htmlLabels: true,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* How mermaid renders curves for flowcharts. Possible values are
|
|
||||||
* * basis
|
|
||||||
* * linear **default**
|
|
||||||
* * cardinal
|
|
||||||
*/
|
|
||||||
curve: 'linear',
|
|
||||||
// Only used in new experimental rendering
|
|
||||||
// repreesents the padding between the labels and the shape
|
|
||||||
padding: 15
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The object containing configurations specific for sequence diagrams
|
|
||||||
*/
|
|
||||||
sequence: {
|
|
||||||
/**
|
|
||||||
* 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',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mirror actors under diagram.
|
|
||||||
* **Default value true**.
|
|
||||||
*/
|
|
||||||
mirrorActors: true,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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,
|
|
||||||
/**
|
|
||||||
* This will show the node numbers
|
|
||||||
* **Default value false**.
|
|
||||||
*/
|
|
||||||
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"',
|
|
||||||
/**
|
|
||||||
* This sets the font weight of the actor's description
|
|
||||||
* **Default value 400.
|
|
||||||
*/
|
|
||||||
actorFontWeight: 400,
|
|
||||||
/**
|
|
||||||
* 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',
|
|
||||||
/**
|
|
||||||
* This sets the font weight of the note's description
|
|
||||||
* **Default value 400.
|
|
||||||
*/
|
|
||||||
noteFontWeight: 400,
|
|
||||||
/**
|
|
||||||
* 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**.
|
|
||||||
*/
|
|
||||||
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,
|
|
||||||
/**
|
|
||||||
* This sets the width of the loop-box (loop, alt, opt, par)
|
|
||||||
* **Default value 50.
|
|
||||||
*/
|
|
||||||
labelBoxWidth: 50,
|
|
||||||
/**
|
|
||||||
* This sets the height of the loop-box (loop, alt, opt, par)
|
|
||||||
* **Default value 20.
|
|
||||||
*/
|
|
||||||
labelBoxHeight: 20
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The object containing configurations specific for gantt diagrams*
|
|
||||||
*/
|
|
||||||
gantt: {
|
|
||||||
/**
|
|
||||||
* Margin top for the text over the gantt diagram
|
|
||||||
* **Default value 25**.
|
|
||||||
*/
|
|
||||||
titleTopMargin: 25,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The height of the bars in the graph
|
|
||||||
* **Default value 20**.
|
|
||||||
*/
|
|
||||||
barHeight: 20,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The margin between the different activities in the gantt diagram.
|
|
||||||
* **Default value 4**.
|
|
||||||
*/
|
|
||||||
barGap: 4,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Margin between title and gantt diagram and between axis and gantt diagram.
|
|
||||||
* **Default value 50**.
|
|
||||||
*/
|
|
||||||
topPadding: 50,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The space allocated for the section name to the left of the activities.
|
|
||||||
* **Default value 75**.
|
|
||||||
*/
|
|
||||||
leftPadding: 75,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vertical starting position of the grid lines.
|
|
||||||
* **Default value 35**.
|
|
||||||
*/
|
|
||||||
gridLineStartPadding: 35,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Font size ...
|
|
||||||
* **Default value 11**.
|
|
||||||
*/
|
|
||||||
fontSize: 11,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* font family ...
|
|
||||||
* **Default value '"Open-Sans", "sans-serif"'**.
|
|
||||||
*/
|
|
||||||
fontFamily: '"Open-Sans", "sans-serif"',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of alternating section styles.
|
|
||||||
* **Default value 4**.
|
|
||||||
*/
|
|
||||||
numberSectionStyles: 4,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Datetime format of the axis. This might need adjustment to match your locale and preferences
|
|
||||||
* **Default value '%Y-%m-%d'**.
|
|
||||||
*/
|
|
||||||
axisFormat: '%Y-%m-%d'
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
},
|
|
||||||
class: {},
|
|
||||||
git: {},
|
|
||||||
state: {
|
|
||||||
dividerMargin: 10,
|
|
||||||
sizeUnit: 5,
|
|
||||||
padding: 8,
|
|
||||||
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
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The object containing configurations specific for entity relationship diagrams
|
|
||||||
*/
|
|
||||||
er: {
|
|
||||||
/**
|
|
||||||
* The amount of padding around the diagram as a whole so that embedded diagrams have margins, expressed in pixels
|
|
||||||
*/
|
|
||||||
diagramPadding: 20,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Directional bias for layout of entities. Can be either 'TB', 'BT', 'LR', or 'RL',
|
|
||||||
* where T = top, B = bottom, L = left, and R = right.
|
|
||||||
*/
|
|
||||||
layoutDirection: 'TB',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The mimimum width of an entity box, expressed in pixels
|
|
||||||
*/
|
|
||||||
minEntityWidth: 100,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The minimum height of an entity box, expressed in pixels
|
|
||||||
*/
|
|
||||||
minEntityHeight: 75,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The minimum internal padding between the text in an entity box and the enclosing box borders, expressed in pixels
|
|
||||||
*/
|
|
||||||
entityPadding: 15,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stroke color of box edges and lines
|
|
||||||
*/
|
|
||||||
stroke: 'gray',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fill color of entity boxes
|
|
||||||
*/
|
|
||||||
fill: 'honeydew',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Font size (expressed as an integer representing a number of pixels)
|
|
||||||
*/
|
|
||||||
fontSize: 12
|
|
||||||
}
|
|
||||||
};
|
|
||||||
export const defaultConfig = Object.freeze(assignWithDepth({}, config));
|
|
||||||
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
|
||||||
config.git.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
|
||||||
|
|
||||||
setLogLevel(config.logLevel);
|
|
||||||
configApi.reset(config);
|
|
||||||
|
|
||||||
function parse(text) {
|
function parse(text) {
|
||||||
const graphInit = utils.detectInit(text);
|
const graphInit = utils.detectInit(text);
|
||||||
if (graphInit) {
|
if (graphInit) {
|
||||||
initialize(graphInit);
|
reinitialize(graphInit);
|
||||||
logger.debug('Init ', graphInit);
|
logger.debug('reinit ', graphInit);
|
||||||
}
|
}
|
||||||
const graphType = utils.detectType(text);
|
const graphType = utils.detectType(text);
|
||||||
let parser;
|
let parser;
|
||||||
@@ -640,7 +122,7 @@ function parse(text) {
|
|||||||
parser.parser.yy = journeyDb;
|
parser.parser.yy = journeyDb;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
parser.parser.yy.graphType = graphType;
|
||||||
parser.parser.yy.parseError = (str, hash) => {
|
parser.parser.yy.parseError = (str, hash) => {
|
||||||
const error = { str, hash };
|
const error = { str, hash };
|
||||||
throw error;
|
throw error;
|
||||||
@@ -722,7 +204,7 @@ const render = function(id, _txt, cb, container) {
|
|||||||
}
|
}
|
||||||
const graphInit = utils.detectInit(txt);
|
const graphInit = utils.detectInit(txt);
|
||||||
if (graphInit) {
|
if (graphInit) {
|
||||||
initialize(graphInit);
|
reinitialize(graphInit);
|
||||||
assignWithDepth(cnf, getConfig());
|
assignWithDepth(cnf, getConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -942,6 +424,79 @@ const render = function(id, _txt, cb, container) {
|
|||||||
return svgCode;
|
return svgCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let currentDirective = {};
|
||||||
|
|
||||||
|
const parseDirective = function(statement, context, type) {
|
||||||
|
try {
|
||||||
|
if (statement !== undefined) {
|
||||||
|
statement = statement.trim();
|
||||||
|
switch (context) {
|
||||||
|
case 'open_directive':
|
||||||
|
currentDirective = {};
|
||||||
|
break;
|
||||||
|
case 'type_directive':
|
||||||
|
currentDirective.type = statement.toLowerCase();
|
||||||
|
break;
|
||||||
|
case 'arg_directive':
|
||||||
|
currentDirective.args = JSON.parse(statement);
|
||||||
|
break;
|
||||||
|
case 'close_directive':
|
||||||
|
handleDirective(currentDirective, type);
|
||||||
|
currentDirective = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(
|
||||||
|
`Error while rendering sequenceDiagram directive: ${statement} jison context: ${context}`
|
||||||
|
);
|
||||||
|
logger.error(error.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDirective = function(directive, type) {
|
||||||
|
logger.debug(`Directive type=${directive.type} with args:`, directive.args);
|
||||||
|
switch (directive.type) {
|
||||||
|
case 'init':
|
||||||
|
case 'initialize': {
|
||||||
|
['config'].forEach(prop => {
|
||||||
|
if (typeof directive.args[prop] !== 'undefined') {
|
||||||
|
if (type === 'flowchart-v2') {
|
||||||
|
type = 'flowchart';
|
||||||
|
}
|
||||||
|
directive.args[type] = directive.args[prop];
|
||||||
|
delete directive.args[prop];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
reinitialize(directive.args);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'wrap':
|
||||||
|
case 'nowrap':
|
||||||
|
directive.args = { config: { wrap: directive.type === 'wrap' } };
|
||||||
|
['config'].forEach(prop => {
|
||||||
|
if (typeof directive.args[prop] !== 'undefined') {
|
||||||
|
if (type === 'flowchart-v2') {
|
||||||
|
type = 'flowchart';
|
||||||
|
}
|
||||||
|
directive.args[type] = directive.args[prop];
|
||||||
|
delete directive.args[prop];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
reinitialize(directive.args);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.warn(
|
||||||
|
`Unhandled directive: source: '%%{${directive.type}: ${JSON.stringify(
|
||||||
|
directive.args ? directive.args : {}
|
||||||
|
)}}%%`,
|
||||||
|
directive
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function updateRendererConfigs(conf) {
|
function updateRendererConfigs(conf) {
|
||||||
gitGraphRenderer.setConf(conf.git);
|
gitGraphRenderer.setConf(conf.git);
|
||||||
flowRenderer.setConf(conf.flowchart);
|
flowRenderer.setConf(conf.flowchart);
|
||||||
@@ -961,14 +516,20 @@ function updateRendererConfigs(conf) {
|
|||||||
errorRenderer.setConf(conf.class);
|
errorRenderer.setConf(conf.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
function initialize(options) {
|
function reinitialize(options) {
|
||||||
console.log(`mermaidAPI.initialize: v${pkg.version}`);
|
console.log(`mermaidAPI.reinitialize: v${pkg.version}`, options);
|
||||||
// Set default options
|
// Set default options
|
||||||
if (typeof options === 'object') {
|
const config = typeof options === 'object' ? setConfig(options) : getSiteConfig();
|
||||||
assignWithDepth(config, options);
|
updateRendererConfigs(config);
|
||||||
updateRendererConfigs(config);
|
setLogLevel(config.logLevel);
|
||||||
}
|
logger.debug('mermaidAPI.reinitialize: ', config);
|
||||||
setConfig(config);
|
}
|
||||||
|
|
||||||
|
function initialize(options) {
|
||||||
|
// console.log(`mermaidAPI.initialize: v${pkg.version}`);
|
||||||
|
// Set default options
|
||||||
|
const config = typeof options === 'object' ? setSiteConfig(options) : getSiteConfig();
|
||||||
|
updateRendererConfigs(config);
|
||||||
setLogLevel(config.logLevel);
|
setLogLevel(config.logLevel);
|
||||||
logger.debug('mermaidAPI.initialize: ', config);
|
logger.debug('mermaidAPI.initialize: ', config);
|
||||||
}
|
}
|
||||||
@@ -977,22 +538,30 @@ function initialize(options) {
|
|||||||
// console.warn('get config')
|
// console.warn('get config')
|
||||||
// return config
|
// return config
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const mermaidAPI = Object.freeze({
|
const mermaidAPI = Object.freeze({
|
||||||
render,
|
render,
|
||||||
parse,
|
parse,
|
||||||
|
parseDirective,
|
||||||
initialize,
|
initialize,
|
||||||
|
reinitialize,
|
||||||
getConfig,
|
getConfig,
|
||||||
setConfig,
|
getSiteConfig,
|
||||||
reset: () => {
|
reset: () => {
|
||||||
// console.warn('reset');
|
// console.warn('reset');
|
||||||
configApi.reset(defaultConfig);
|
configApi.reset();
|
||||||
assignWithDepth(config, defaultConfig, { clobber: true });
|
const siteConfig = getSiteConfig();
|
||||||
updateRendererConfigs(config);
|
updateRendererConfigs(siteConfig);
|
||||||
},
|
},
|
||||||
defaultConfig
|
globalReset: () => {
|
||||||
|
configApi.reset(configApi.defaultConfig);
|
||||||
|
updateRendererConfigs(getConfig());
|
||||||
|
},
|
||||||
|
defaultConfig: configApi.defaultConfig
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setLogLevel(getConfig().logLevel);
|
||||||
|
configApi.reset(getConfig());
|
||||||
|
|
||||||
export default mermaidAPI;
|
export default mermaidAPI;
|
||||||
/**
|
/**
|
||||||
* ## mermaidAPI configuration defaults
|
* ## mermaidAPI configuration defaults
|
||||||
|
@@ -6,7 +6,7 @@ describe('when using mermaidAPI and ', function() {
|
|||||||
describe('doing initialize ', function() {
|
describe('doing initialize ', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
document.body.innerHTML = '';
|
document.body.innerHTML = '';
|
||||||
mermaidAPI.reset();
|
mermaidAPI.globalReset();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should copy a literal into the configuration', function() {
|
it('should copy a literal into the configuration', function() {
|
||||||
@@ -30,11 +30,9 @@ describe('when using mermaidAPI and ', function() {
|
|||||||
mermaidAPI.initialize({ testObject: object });
|
mermaidAPI.initialize({ testObject: object });
|
||||||
let config = mermaidAPI.getConfig();
|
let config = mermaidAPI.getConfig();
|
||||||
|
|
||||||
console.log('1:', config);
|
|
||||||
expect(config.testObject.test1).toBe(1);
|
expect(config.testObject.test1).toBe(1);
|
||||||
mermaidAPI.initialize({ testObject: { test3: true } });
|
mermaidAPI.initialize({ testObject: { test3: true } });
|
||||||
config = mermaidAPI.getConfig();
|
config = mermaidAPI.getConfig();
|
||||||
console.log(config);
|
|
||||||
|
|
||||||
expect(config.testObject.test1).toBe(1);
|
expect(config.testObject.test1).toBe(1);
|
||||||
expect(config.testObject.test2).toBe(false);
|
expect(config.testObject.test2).toBe(false);
|
||||||
@@ -42,13 +40,50 @@ describe('when using mermaidAPI and ', function() {
|
|||||||
});
|
});
|
||||||
it('should reset mermaid config to global defaults', function() {
|
it('should reset mermaid config to global defaults', function() {
|
||||||
let config = {
|
let config = {
|
||||||
logLevel: 0
|
logLevel: 0,
|
||||||
|
securityLevel: 'loose'
|
||||||
};
|
};
|
||||||
mermaidAPI.initialize(config);
|
mermaidAPI.initialize(config);
|
||||||
expect(mermaidAPI.getConfig().logLevel).toBe(0);
|
expect(mermaidAPI.getConfig().logLevel).toBe(0);
|
||||||
mermaidAPI.reset();
|
expect(mermaidAPI.getConfig().securityLevel).toBe('loose');
|
||||||
|
mermaidAPI.globalReset();
|
||||||
expect(mermaidAPI.getConfig()).toEqual(mermaidAPI.defaultConfig);
|
expect(mermaidAPI.getConfig()).toEqual(mermaidAPI.defaultConfig);
|
||||||
});
|
});
|
||||||
|
it('should reset mermaid config to site defaults', function() {
|
||||||
|
let config = {
|
||||||
|
logLevel: 0
|
||||||
|
};
|
||||||
|
mermaidAPI.initialize(config);
|
||||||
|
const siteConfig = mermaidAPI.getSiteConfig();
|
||||||
|
expect(mermaidAPI.getConfig().logLevel).toBe(0);
|
||||||
|
config.logLevel = 3;
|
||||||
|
config.securityLevel = 'loose';
|
||||||
|
mermaidAPI.reinitialize(config);
|
||||||
|
expect(mermaidAPI.getConfig().logLevel).toBe(3);
|
||||||
|
expect(mermaidAPI.getConfig().securityLevel).toBe('strict');
|
||||||
|
mermaidAPI.reset();
|
||||||
|
expect(mermaidAPI.getSiteConfig()).toEqual(siteConfig)
|
||||||
|
expect(mermaidAPI.getConfig()).toEqual(siteConfig);
|
||||||
|
});
|
||||||
|
it('should prevent changes to site defaults (sneaky)', function() {
|
||||||
|
let config = {
|
||||||
|
logLevel: 0
|
||||||
|
};
|
||||||
|
mermaidAPI.initialize(config);
|
||||||
|
const siteConfig = mermaidAPI.getSiteConfig();
|
||||||
|
expect(mermaidAPI.getConfig().logLevel).toBe(0);
|
||||||
|
config.secure = {
|
||||||
|
toString: function() {
|
||||||
|
mermaidAPI.initialize({ securityLevel: 'loose' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mermaidAPI.reinitialize(config);
|
||||||
|
expect(mermaidAPI.getConfig().secure).toEqual(mermaidAPI.getSiteConfig().secure);
|
||||||
|
expect(mermaidAPI.getConfig().securityLevel).toBe('strict');
|
||||||
|
mermaidAPI.reset();
|
||||||
|
expect(mermaidAPI.getSiteConfig()).toEqual(siteConfig)
|
||||||
|
expect(mermaidAPI.getConfig()).toEqual(siteConfig);
|
||||||
|
});
|
||||||
it('should prevent clobbering global defaults (direct)', function() {
|
it('should prevent clobbering global defaults (direct)', function() {
|
||||||
let config = assignWithDepth({}, mermaidAPI.defaultConfig);
|
let config = assignWithDepth({}, mermaidAPI.defaultConfig);
|
||||||
assignWithDepth(config, { logLevel: 0 });
|
assignWithDepth(config, { logLevel: 0 });
|
||||||
@@ -65,7 +100,7 @@ describe('when using mermaidAPI and ', function() {
|
|||||||
it('should prevent changes to global defaults (direct)', function() {
|
it('should prevent changes to global defaults (direct)', function() {
|
||||||
let error = { message: '' };
|
let error = { message: '' };
|
||||||
try {
|
try {
|
||||||
mermaidAPI.defaultConfig.logLevel = 0;
|
mermaidAPI.defaultConfig['logLevel'] = 0;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
error = e;
|
error = e;
|
||||||
}
|
}
|
||||||
|
34
src/utils.js
34
src/utils.js
@@ -15,6 +15,7 @@ import {
|
|||||||
import { logger } from './logger';
|
import { logger } from './logger';
|
||||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||||
import common from './diagrams/common/common';
|
import common from './diagrams/common/common';
|
||||||
|
import cryptoRandomString from 'crypto-random-string';
|
||||||
|
|
||||||
// Effectively an enum of the supported curve types, accessible by name
|
// Effectively an enum of the supported curve types, accessible by name
|
||||||
const d3CurveTypes = {
|
const d3CurveTypes = {
|
||||||
@@ -396,6 +397,10 @@ export const generateId = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const random = options => {
|
||||||
|
return cryptoRandomString(options);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function assignWithDepth
|
* @function assignWithDepth
|
||||||
* Extends the functionality of {@link ObjectConstructor.assign} with the ability to merge arbitrary-depth objects
|
* Extends the functionality of {@link ObjectConstructor.assign} with the ability to merge arbitrary-depth objects
|
||||||
@@ -442,7 +447,7 @@ export const assignWithDepth = function(dst, src, config) {
|
|||||||
(dst[key] === undefined || typeof dst[key] === 'object')
|
(dst[key] === undefined || typeof dst[key] === 'object')
|
||||||
) {
|
) {
|
||||||
if (dst[key] === undefined) {
|
if (dst[key] === undefined) {
|
||||||
dst[key] = {};
|
dst[key] = Array.isArray(src[key]) ? [] : {};
|
||||||
}
|
}
|
||||||
dst[key] = assignWithDepth(dst[key], src[key], { depth: depth - 1, clobber });
|
dst[key] = assignWithDepth(dst[key], src[key], { depth: depth - 1, clobber });
|
||||||
} else if (clobber || (typeof dst[key] !== 'object' && typeof src[key] !== 'object')) {
|
} else if (clobber || (typeof dst[key] !== 'object' && typeof src[key] !== 'object')) {
|
||||||
@@ -501,6 +506,10 @@ export const wrapLabel = (label, maxWidth, config) => {
|
|||||||
{ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', margin: 0, joinWith: '<br/>' },
|
{ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', margin: 0, joinWith: '<br/>' },
|
||||||
config
|
config
|
||||||
);
|
);
|
||||||
|
const cacheKey = `${label}-${maxWidth}-${JSON.stringify(config)}`;
|
||||||
|
if (wrapLabel[cacheKey]) {
|
||||||
|
return wrapLabel[cacheKey];
|
||||||
|
}
|
||||||
if (common.lineBreakRegex.test(label)) {
|
if (common.lineBreakRegex.test(label)) {
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
@@ -526,11 +535,17 @@ export const wrapLabel = (label, maxWidth, config) => {
|
|||||||
completedLines.push(nextLine);
|
completedLines.push(nextLine);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return completedLines.filter(line => line !== '').join(config.joinWith);
|
const result = completedLines.filter(line => line !== '').join(config.joinWith);
|
||||||
|
wrapLabel[cacheKey] = result;
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
const breakString = (word, maxWidth, hyphenCharacter = '-', config) => {
|
const breakString = (word, maxWidth, hyphenCharacter = '-', config) => {
|
||||||
config = Object.assign({ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', margin: 0 }, config);
|
config = Object.assign({ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', margin: 0 }, config);
|
||||||
|
const cacheKey = `${word}-${maxWidth}-${hyphenCharacter}-${JSON.stringify(config)}`;
|
||||||
|
if (breakString[cacheKey]) {
|
||||||
|
return breakString[cacheKey];
|
||||||
|
}
|
||||||
const characters = word.split('');
|
const characters = word.split('');
|
||||||
const lines = [];
|
const lines = [];
|
||||||
let currentLine = '';
|
let currentLine = '';
|
||||||
@@ -547,7 +562,9 @@ const breakString = (word, maxWidth, hyphenCharacter = '-', config) => {
|
|||||||
currentLine = nextLine;
|
currentLine = nextLine;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return { hyphenatedStrings: lines, remainingWord: currentLine };
|
const result = { hyphenatedStrings: lines, remainingWord: currentLine };
|
||||||
|
breakString[cacheKey] = result;
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -598,7 +615,11 @@ export const calculateTextDimensions = function(text, config) {
|
|||||||
);
|
);
|
||||||
const { fontSize, fontFamily, fontWeight } = config;
|
const { fontSize, fontFamily, fontWeight } = config;
|
||||||
if (!text) {
|
if (!text) {
|
||||||
return 0;
|
return { width: 0, height: 0 };
|
||||||
|
}
|
||||||
|
const cacheKey = `${text}-${JSON.stringify(config)}`;
|
||||||
|
if (calculateTextDimensions[cacheKey]) {
|
||||||
|
return calculateTextDimensions[cacheKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can't really know if the user supplied font family will render on the user agent;
|
// We can't really know if the user supplied font family will render on the user agent;
|
||||||
@@ -638,7 +659,9 @@ export const calculateTextDimensions = function(text, config) {
|
|||||||
g.remove();
|
g.remove();
|
||||||
|
|
||||||
// Adds some padding, so the text won't sit exactly within the actor's borders
|
// Adds some padding, so the text won't sit exactly within the actor's borders
|
||||||
return { width: Math.round(maxWidth), height: Math.round(height) };
|
const result = { width: Math.round(maxWidth), height: Math.round(height) };
|
||||||
|
calculateTextDimensions[cacheKey] = result;
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -657,5 +680,6 @@ export default {
|
|||||||
formatUrl,
|
formatUrl,
|
||||||
getStylesFromArray,
|
getStylesFromArray,
|
||||||
generateId,
|
generateId,
|
||||||
|
random,
|
||||||
runFunc
|
runFunc
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user