Merge branch 'develop' of https://github.com/mermaid-js/mermaid into mermaid-js-develop

This commit is contained in:
Chris Moran 2020-06-14 11:40:15 -04:00
commit 6309dd1350
No known key found for this signature in database
GPG Key ID: FBD13F2A0E1B9152
23 changed files with 1057 additions and 2138 deletions

View File

@ -71,9 +71,9 @@ describe('Class diagram', () => {
classDiagram
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class01 : -int privateMethod()
Class01 : +int publicMethod()
Class01 : #int protectedMethod()
Class01 : -privateMethod()
Class01 : +publicMethod()
Class01 : #protectedMethod()
Class01 : -int privateChimp
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset

View File

@ -20,223 +20,40 @@
</head>
<body>
<h1>info below</h1>
<div class="mermaid" style="width: 100%; height: 20%;">
flowchart LR
user1[fa:fa-user User 1] -- edit -> folder
</div>
<div class="mermaid2" style="width: 50%; height: 20%;">
flowchart LR
A{{A}}-- apa -->B{{B}};
click A callback "Tooltip"
click B "http://www.github.com" "This is a link"
</div>
<div class="mermaid2" style="width: 50%; height: 20%;">
graph LR
A{{A}}--apa-->B{{B}};
</div>
<div class="mermaid2" style="width: 50%; height: 20%;">
stateDiagram-v2
[*]-->TV
state TV {
state fork_state &lt;&lt;fork&gt;&gt;
[*] --> fork_state
fork_state --> State2
fork_state --> State3
state join_state &lt;&lt;join&gt;&gt;
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
}
</div>
<div class="mermaid2" style="width: 100%; height: 100%;">
stateDiagram-v2
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
</div>
<div class="mermaid2" style="width: 100%; height: 100%;">
stateDiagram-v2
[*] --> First
First --> Third
First --> sec
state First {
[*] --> fir
fir --> [*]
}
state Second {
[*] --> sec
sec --> [*]
}
state Third {
[*] --> thi
thi --> [*]
}
thi --> sec
</div>
<div class="mermaid2" style="width: 100%; height: 100%;">
flowchart TD
subgraph A
a
end
subgraph B
b
end
subgraph C
subgraph D
d
end
end
A -- oAo --o B
A --> C
</div>
<div class="mermaid2" style="width: 100%; height: 100%;">
flowchart TD
subgraph A
a
end
subgraph B
b
end
c-->A
c-->B
</div>
<div class="mermaid2" style="width: 100%; height: 100%;">
stateDiagram-v2
[*] --> First
First --> Second
First --> Third
state First {
[*] --> fir
fir --> [*]
}
state Second {
[*] --> sec
sec --> [*]
}
state Third {
[*] --> thi
thi --> [*]
}
</div>
<div class="mermaid2" style="width: 100%; height: 100%;">
stateDiagram-v2
[*]-->TV
state TV {
[*] --> Off: Off to start with
On --> Off : Turn off
Off --> On : Turn on
}
TV--> Console
state Console {
[*] --> Off2: Off to start with
On2--> Off2 : Turn off
Off2 --> On2 : Turn on
On2-->Playing
state Playing {
Alive --> Dead
Dead-->Alive
}
}
<div class="mermaid" style="width: 50%; height: 20%;">
flowchart TB
subgraph 1
A --> B;
A -.-> C;
A ==> D;
A ==> E;
B <--> F
C <--> F
D <--> F
E <--> F
end
subgraph 2
A2 --x B2;
A2 -.-x C2;
A2 ==x D2;
A2 ==x E2;
B2 x--x F2
C2 x--x F2
D2 x--x F2
E2 x--x F2
end
subgraph 3
A3 --o B3;
A3 -.-o C3;
A3 ==o D3;
A3 ==o E3;
B3 o--o F3
C3 o--o F3
D3 o--o F3
E3 o--o F3
end
</div>
<div style="display: flex;flex-direction:column;width: 100%; height: 100%">
<div class="mermaid2" style="width: 100%; height: 100%;">
stateDiagram-v2
state apa {
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
}
</div>
<div class="mermaid2" style="width: 100%; height: 100%">
flowchart TB
a --> b
subgraph id1 [Test]
a --apa--> c
b
c-->b
b-->H
end
G-->H
G-->id1
id1 --> I
I --> G
</div>
<div class="mermaid2" style="width: 100%; height: 100%">
flowchart RL
a --> b
subgraph id1 [Test]
a --apa--> c
b
c-->b
b-->H
end
G-->H
G-->id1
id1 --> I
I --> G
</div>
<div class="mermaid2" style="width: 100%; height: 100%">
flowchart RL
subgraph id1 [Test]
a
end
b-->id1
</div>
<div class="mermaid2" style="width: 100%; height: 100%">
flowchart RL
subgraph id1 [Test1]
a
end
subgraph id2 [Test2]
b
end
a --> id2
a --> b
b-->id1
id1 --> id2
</div>
new:
<div class="mermaid2" style="width: 100%; height: 100%">
flowchart LR
a <--> b
b o--o c
c x--x d
a21([In the box]) --> b2
b2((b2)) --o c2
c2(c2) --x d2 --> id1{{This is the text in the box}} --> A[(cylindrical<br />shape<br />test)]
</div>
old:
<div class="mermaid2" style="width: 100%; height: 100%">
graph LR
a((a)) --> b --> id1{{This is the text in the box}}
A[(cylindrical<br />shape<br />test)]
</div>
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {

1157
dist/mermaid.core.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1436
dist/mermaid.js vendored

File diff suppressed because one or more lines are too long

2
dist/mermaid.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -33,7 +33,7 @@ Closed issues:
⚠️ **Note** : This changes the default behaviour of mermaid so that after upgrade to 8.2, if the securityLevel is not configured, tags in flowcharts are encoded as tags and clicking is prohibited.
If your application is taking resposibility for the diagram source security you can set the securityLevel accordingly. By doing this clicks and tags are again allowed.
If your application is taking responsibility for the diagram source security you can set the securityLevel accordingly. By doing this clicks and tags are again allowed.
```javascript
mermaidAPI.initialize({

View File

@ -3,15 +3,15 @@
> A Gantt chart is a type of bar chart, first developed by Karol Adamiecki in 1896, and independently by Henry Gantt in the 1910s, that illustrates a project schedule and the amount of time it would take for any one project to finish. Gantt charts illustrate number of days between the start and finish dates of the terminal elements and summary elements of a project.
## A note to users
Gannt Charts will record each scheduled task as one continuous bar that extends from the left to the right. The x axis represents time and the y records the different tasks and the order in which they are to be completed.
Gantt Charts will record each scheduled task as one continuous bar that extends from the left to the right. The x axis represents time and the y records the different tasks and the order in which they are to be completed.
It is important to remember that when a date, day or collection of dates specific to a task are "excluded", the Gannt Chart will accomodate those changes by extending an equal number of day, towards the right, not by creating a gap inside the task.
As shown here ![](https://github.com/NeilCuzon/mermaid/blob/develop/docs/img/Gantt-excluded-days-within.png)
It is important to remember that when a date, day, or collection of dates specific to a task are "excluded", the Gantt Chart will accomodate those changes by extending an equal number of day, towards the right, not by creating a gap inside the task.
As shown here ![](https://raw.githubusercontent.com/NeilCuzon/mermaid/develop/docs/img/Gantt-excluded-days-within.png)
However, if the excluded date/s is between two tasks that are set to start consecutively, the excluded dates will be skipped graphically and left blank, and the following task will begin after the end of the excluded date/s.
As shown here ![](https://github.com/NeilCuzon/mermaid/blob/develop/docs/img/Gantt-long-weekend-look.png)
However, if the excluded dates are between two tasks that are set to start consecutively, the excluded dates will be skipped graphically and left blank, and the following task will begin after the end of the excluded dates.
As shown here ![](https://raw.githubusercontent.com/NeilCuzon/mermaid/develop/docs/img/Gantt-long-weekend-look.png)
A Gantt chart is useful for tracking the amount of time it would take before a project is finished, but it can also be used to graphically represent "non-working days, with a few tweaks.
A Gantt chart is useful for tracking the amount of time it would take before a project is finished, but it can also be used to graphically represent "non-working days", with a few tweaks.
Mermaid can render Gantt diagrams as SVG, PNG or a MarkDown link that can be pasted into docs.
@ -117,12 +117,14 @@ It is possible to set multiple depenendenies separated by space:
### Title
Tbd
The `title` is an *optional* string to be displayed at the top of the Gantt chart to describe the chart as a whole.
## Sections statements
### Section statements
Tbd
You can divide the chart into various sections, for example to separate different parts of a project like development and documentation.
To do so, start a line with the `section` keyword and give it a name. (Note that unlike with the [title for the entire chart](#title), this name is *required*.
## Setting dates
@ -293,6 +295,19 @@ noteText | Styles for the text on in the note boxes.
}
```
## Today marker
You can style or hide the marker for the current date. To style it, add a value for the `todayMarker` key.
```
todayMarker stroke-width:5px,stroke:#0f0,opacity:0.5
```
To hide the marker, set `todayMarker` to `off`.
```
todayMarker off
```
## Configuration

View File

@ -112,6 +112,8 @@ Required edgeData for proper rendering:
| label | overlap between label and labelText? |
| labelPos | |
| labelType | overlap between label and labelText? |
| thickness | Sets the thinkess of the edge. Can be ['normal', 'thick'] |
| pattern | Sets the pattern of the edge. Can be ['solid', 'dotted', 'dashed'] |
# Markers

View File

@ -191,11 +191,35 @@ export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph)
})
.curve(curveBasis);
// Contruct stroke classes based on properties
let strokeClasses;
switch (edge.thickness) {
case 'normal':
strokeClasses = 'edge-thickness-normal';
break;
case 'thick':
strokeClasses = 'edge-thickness-thick';
break;
default:
strokeClasses = '';
}
switch (edge.pattern) {
case 'solid':
strokeClasses += ' edge-pattern-solid';
break;
case 'dotted':
strokeClasses += ' edge-pattern-dotted';
break;
case 'dashed':
strokeClasses += ' edge-pattern-dashed';
break;
}
const svgPath = elem
.append('path')
.attr('d', lineFunction(lineData))
.attr('id', edge.id)
.attr('class', 'transition' + (edge.classes ? ' ' + edge.classes : ''));
.attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : ''));
// DEBUG code, adds a red circle at each edge coordinate
// edge.points.forEach(point => {

View File

@ -17,7 +17,7 @@ const extension = (elem, type, id) => {
.append('defs')
.append('marker')
.attr('id', type + '-extensionStart')
.attr('class', 'extension ' + type)
.attr('class', 'marker extension ' + type)
.attr('refX', 0)
.attr('refY', 7)
.attr('markerWidth', 190)
@ -30,7 +30,7 @@ const extension = (elem, type, id) => {
.append('defs')
.append('marker')
.attr('id', type + '-extensionEnd ' + type)
.attr('class', 'extension ' + type)
.attr('class', 'marker extension ' + type)
.attr('refX', 19)
.attr('refY', 7)
.attr('markerWidth', 20)
@ -45,7 +45,7 @@ const composition = (elem, type) => {
.append('defs')
.append('marker')
.attr('id', type + '-compositionStart')
.attr('class', 'extension ' + type)
.attr('class', 'marker extension ' + type)
.attr('refX', 0)
.attr('refY', 7)
.attr('markerWidth', 190)
@ -58,7 +58,7 @@ const composition = (elem, type) => {
.append('defs')
.append('marker')
.attr('id', type + '-compositionEnd')
.attr('class', 'extension ' + type)
.attr('class', 'marker extension ' + type)
.attr('refX', 19)
.attr('refY', 7)
.attr('markerWidth', 20)
@ -72,7 +72,7 @@ const aggregation = (elem, type) => {
.append('defs')
.append('marker')
.attr('id', type + '-aggregationStart')
.attr('class', 'extension ' + type)
.attr('class', 'marker extension ' + type)
.attr('refX', 0)
.attr('refY', 7)
.attr('markerWidth', 190)
@ -85,7 +85,7 @@ const aggregation = (elem, type) => {
.append('defs')
.append('marker')
.attr('id', type + '-aggregationEnd')
.attr('class', type)
.attr('class', 'marker ' + type)
.attr('refX', 19)
.attr('refY', 7)
.attr('markerWidth', 20)
@ -99,7 +99,7 @@ const dependency = (elem, type) => {
.append('defs')
.append('marker')
.attr('id', type + '-dependencyStart')
.attr('class', 'extension ' + type)
.attr('class', 'marker extension ' + type)
.attr('refX', 0)
.attr('refY', 7)
.attr('markerWidth', 190)
@ -112,7 +112,7 @@ const dependency = (elem, type) => {
.append('defs')
.append('marker')
.attr('id', type + '-dependencyEnd')
.attr('class', type)
.attr('class', 'marker ' + type)
.attr('refX', 19)
.attr('refY', 7)
.attr('markerWidth', 20)
@ -125,13 +125,13 @@ const point = (elem, type) => {
elem
.append('marker')
.attr('id', type + '-pointEnd')
.attr('class', type)
.attr('class', 'marker ' + type)
.attr('viewBox', '0 0 10 10')
.attr('refX', 10)
.attr('refX', 9)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 8)
.attr('markerHeight', 8)
.attr('markerUnits', 'userSpaceOnUse')
.attr('markerWidth', 12)
.attr('markerHeight', 12)
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 0 0 L 10 5 L 0 10 z')
@ -141,13 +141,13 @@ const point = (elem, type) => {
elem
.append('marker')
.attr('id', type + '-pointStart')
.attr('class', type)
.attr('class', 'marker ' + type)
.attr('viewBox', '0 0 10 10')
.attr('refX', 0)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 8)
.attr('markerHeight', 8)
.attr('markerUnits', 'userSpaceOnUse')
.attr('markerWidth', 12)
.attr('markerHeight', 12)
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 0 5 L 10 10 L 10 0 z')
@ -159,13 +159,13 @@ const circle = (elem, type) => {
elem
.append('marker')
.attr('id', type + '-circleEnd')
.attr('class', type)
.attr('class', 'marker ' + type)
.attr('viewBox', '0 0 10 10')
.attr('refX', 11)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 7)
.attr('markerHeight', 7)
.attr('markerUnits', 'userSpaceOnUse')
.attr('markerWidth', 11)
.attr('markerHeight', 11)
.attr('orient', 'auto')
.append('circle')
.attr('cx', '5')
@ -178,13 +178,13 @@ const circle = (elem, type) => {
elem
.append('marker')
.attr('id', type + '-circleStart')
.attr('class', type)
.attr('class', 'marker ' + type)
.attr('viewBox', '0 0 10 10')
.attr('refX', -1)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 7)
.attr('markerHeight', 7)
.attr('markerUnits', 'userSpaceOnUse')
.attr('markerWidth', 11)
.attr('markerHeight', 11)
.attr('orient', 'auto')
.append('circle')
.attr('cx', '5')
@ -198,16 +198,16 @@ const cross = (elem, type) => {
elem
.append('marker')
.attr('id', type + '-crossEnd')
.attr('class', type)
.attr('class', 'marker cross ' + type)
.attr('viewBox', '0 0 11 11')
.attr('refX', 12)
.attr('refY', 5.2)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 7)
.attr('markerHeight', 7)
.attr('markerUnits', 'userSpaceOnUse')
.attr('markerWidth', 11)
.attr('markerHeight', 11)
.attr('orient', 'auto')
.append('path')
.attr('stroke', 'black')
// .attr('stroke', 'black')
.attr('d', 'M 1,1 l 9,9 M 10,1 l -9,9')
.attr('class', 'arrowMarkerPath')
.style('stroke-width', 2)
@ -216,16 +216,16 @@ const cross = (elem, type) => {
elem
.append('marker')
.attr('id', type + '-crossStart')
.attr('class', type)
.attr('class', 'marker cross ' + type)
.attr('viewBox', '0 0 11 11')
.attr('refX', -1)
.attr('refY', 5.2)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 7)
.attr('markerHeight', 7)
.attr('markerUnits', 'userSpaceOnUse')
.attr('markerWidth', 11)
.attr('markerHeight', 11)
.attr('orient', 'auto')
.append('path')
.attr('stroke', 'black')
// .attr('stroke', 'black')
.attr('d', 'M 1,1 l 9,9 M 10,1 l -9,9')
.attr('class', 'arrowMarkerPath')
.style('stroke-width', 2)

View File

@ -217,7 +217,7 @@ const setClickFunc = function(domId, functionName, tooltip) {
elem.addEventListener(
'click',
function() {
window[functionName](elemId);
utils.runFunc(functionName, elemId);
},
false
);
@ -272,8 +272,8 @@ const setupToolTips = function(element) {
.style('opacity', '.9');
tooltipElem
.html(el.attr('title'))
.style('left', rect.left + (rect.right - rect.left) / 2 + 'px')
.style('top', rect.top - 14 + document.body.scrollTop + 'px');
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
.style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px');
el.classed('hover', true);
})
.on('mouseout', function() {

View File

@ -10,15 +10,15 @@
%%
\%\%[^\n]*\n* /* do nothing */
\n+ return 'NEWLINE';
\n+ return 'NEWLINE';
\s+ /* skip whitespace */
"classDiagram" return 'CLASS_DIAGRAM';
[\{] { this.begin("struct"); /*console.log('Starting struct');*/return 'STRUCT_START';}
<struct><<EOF>> return "EOF_IN_STRUCT";
<struct>[\{] return "OPEN_IN_STRUCT";
<struct>\} { /*console.log('Ending struct');*/this.popState(); return 'STRUCT_STOP';}}
<struct>\} { /*console.log('Ending struct');*/this.popState(); return 'STRUCT_STOP';}}
<struct>[\n] /* nothing */
<struct>[^\{\}\n]* { /*console.log('lex-member: ' + yytext);*/ return "MEMBER";}
<struct>[^\{\}\n]* { /*console.log('lex-member: ' + yytext);*/ return "MEMBER";}
@ -40,7 +40,7 @@
\s*\|\> return 'EXTENSION';
\s*\> return 'DEPENDENCY';
\s*\< return 'DEPENDENCY';
\s*\* return 'COMPOSITION';
\s*\* return 'COMPOSITION';
\s*o return 'AGGREGATION';
\-\- return 'LINE';
\.\. return 'DOTTED_LINE';
@ -53,7 +53,7 @@
\= return 'EQUALS';
\w+ return 'ALPHA';
[!"#$%&'*+,-.`?\\/] return 'PUNCTUATION';
[0-9]+ return 'NUM';
[0-9]+ return 'NUM';
[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|
[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|
[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|

View File

@ -278,13 +278,13 @@ export const drawClass = function(elem, classDef, conf) {
};
export const parseMember = function(text) {
const fieldRegEx = /^(\+|-|~|#)?(\w+)(~\w+~|\[\])?\s+(\w+)$/;
const methodRegEx = /^(\+|-|~|#)?(\w+)\s?\(\s*(\w+(~\w+~|\[\])?\s*(\w+)?)?\s*\)\s?([*|$])?\s?(\w+(~\w+~|\[\])?)?\s*$/;
const fieldRegEx = /(\+|-|~|#)?(\w+)(~\w+~|\[\])?\s+(\w+)/;
const methodRegEx = /^([+|\-|~|#])?(\w+) *\( *(.*)\) *(\*|\$)? *(\w*[~|[\]]*\s*\w*~?)$/;
let fieldMatch = text.match(fieldRegEx);
let methodMatch = text.match(methodRegEx);
if (fieldMatch) {
if (fieldMatch && !methodMatch) {
return buildFieldDisplay(fieldMatch);
} else if (methodMatch) {
return buildMethodDisplay(methodMatch);
@ -294,56 +294,78 @@ export const parseMember = function(text) {
};
const buildFieldDisplay = function(parsedText) {
let visibility = parsedText[1] ? parsedText[1].trim() : '';
let fieldType = parsedText[2] ? parsedText[2].trim() : '';
let genericType = parsedText[3] ? parseGenericTypes(parsedText[3]) : '';
let fieldName = parsedText[4] ? parsedText[4].trim() : '';
let displayText = '';
try {
let visibility = parsedText[1] ? parsedText[1].trim() : '';
let fieldType = parsedText[2] ? parsedText[2].trim() : '';
let genericType = parsedText[3] ? parseGenericTypes(parsedText[3].trim()) : '';
let fieldName = parsedText[4] ? parsedText[4].trim() : '';
displayText = visibility + fieldType + genericType + ' ' + fieldName;
} catch (err) {
displayText = parsedText;
}
return {
displayText: visibility + fieldType + genericType + ' ' + fieldName,
displayText: displayText,
cssStyle: ''
};
};
const buildMethodDisplay = function(parsedText) {
let cssStyle = '';
let displayText = parsedText;
let displayText = '';
let visibility = parsedText[1] ? parsedText[1].trim() : '';
let methodName = parsedText[2] ? parsedText[2].trim() : '';
let parameters = parsedText[3] ? parseGenericTypes(parsedText[3]) : '';
let classifier = parsedText[6] ? parsedText[6].trim() : '';
let returnType = parsedText[7] ? ' : ' + parseGenericTypes(parsedText[7]).trim() : '';
try {
let visibility = parsedText[1] ? parsedText[1].trim() : '';
let methodName = parsedText[2] ? parsedText[2].trim() : '';
let parameters = parsedText[3] ? parseGenericTypes(parsedText[3].trim()) : '';
let classifier = parsedText[4] ? parsedText[4].trim() : '';
let returnType = parsedText[5] ? ' : ' + parseGenericTypes(parsedText[5]).trim() : '';
displayText = visibility + methodName + '(' + parameters + ')' + returnType;
displayText = visibility + methodName + '(' + parameters + ')' + returnType;
cssStyle = parseClassifier(classifier);
cssStyle = parseClassifier(classifier);
} catch (err) {
displayText = parsedText;
}
let member = {
return {
displayText: displayText,
cssStyle: cssStyle
};
return member;
};
const buildLegacyDisplay = function(text) {
// if for some reason we dont have any match, use old format to parse text
let memberText = '';
let displayText = '';
let cssStyle = '';
let memberText = '';
let returnType = '';
let methodStart = text.indexOf('(');
let methodEnd = text.indexOf(')');
if (methodStart > 1 && methodEnd > methodStart && methodEnd <= text.length) {
let parsedText = text.match(/(\+|-|~|#)?(\w+)/);
let visibility = parsedText[1] ? parsedText[1].trim() : '';
let methodName = parsedText[2];
let visibility = '';
let methodName = '';
let firstChar = text.substring(0, 1);
if (firstChar.match(/\w/)) {
methodName = text.substring(0, methodStart).trim();
} else {
if (firstChar.match(/\+|-|~|#/)) {
visibility = firstChar;
}
methodName = text.substring(1, methodStart).trim();
}
let parameters = text.substring(methodStart + 1, methodEnd);
let classifier = text.substring(methodEnd, methodEnd + 1);
let classifier = text.substring(methodEnd + 1, 1);
cssStyle = parseClassifier(classifier);
memberText = visibility + methodName + '(' + parseGenericTypes(parameters.trim()) + ')';
displayText = visibility + methodName + '(' + parseGenericTypes(parameters.trim()) + ')';
if (methodEnd < memberText.length) {
returnType = text.substring(methodEnd + 2).trim();
@ -353,15 +375,13 @@ const buildLegacyDisplay = function(text) {
}
} else {
// finally - if all else fails, just send the text back as written (other than parsing for generic types)
memberText = parseGenericTypes(text);
displayText = parseGenericTypes(text);
}
let member = {
displayText: memberText + returnType,
return {
displayText: displayText,
cssStyle: cssStyle
};
return member;
};
const addTspan = function(textEl, txt, isFirst, conf) {

View File

@ -83,6 +83,14 @@ describe('class member Renderer, ', function () {
expect(actual.cssStyle).toBe('');
});
it('should handle simple method declaration with multiple parameters', function () {
const str = 'foo(int id, object thing)';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('foo(int id, object thing)');
expect(actual.cssStyle).toBe('');
});
it('should handle simple method declaration with single item in parameters', function () {
const str = 'foo(id)';
let actual = svgDraw.parseMember(str);

View File

@ -232,7 +232,7 @@ const setClickFun = function(_id, functionName) {
elem.addEventListener(
'click',
function() {
window[functionName](id);
utils.runFunc(functionName, id);
},
false
);
@ -324,6 +324,7 @@ const setupToolTips = function(element) {
.on('mouseover', function() {
const el = select(this);
const title = el.attr('title');
// Dont try to draw a tooltip if no data is provided
if (title === null) {
return;
@ -336,8 +337,8 @@ const setupToolTips = function(element) {
.style('opacity', '.9');
tooltipElem
.html(el.attr('title'))
.style('left', rect.left + (rect.right - rect.left) / 2 + 'px')
.style('top', rect.top - 14 + document.body.scrollTop + 'px');
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
.style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px');
el.classed('hover', true);
})
.on('mouseout', function() {

View File

@ -181,8 +181,15 @@ export const addEdges = function(edges, g) {
edges.forEach(function(edge) {
cnt++;
// Identify Link
var linkId = 'L-' + edge.start + '-' + edge.end;
var linkNameStart = 'LS-' + edge.start;
var linkNameEnd = 'LE-' + edge.end;
const edgeData = {};
edgeData.id = 'id' + cnt;
//edgeData.id = 'id' + cnt;
// Set link type for rendering
if (edge.type === 'arrow_open') {
edgeData.arrowhead = 'none';
@ -210,12 +217,16 @@ export const addEdges = function(edges, g) {
if (typeof defaultLabelStyle !== 'undefined') {
labelStyle = defaultLabelStyle;
}
edgeData.thickness = 'normal';
edgeData.pattern = 'solid';
break;
case 'dotted':
style = 'fill:none;stroke-width:2px;stroke-dasharray:3;';
edgeData.thickness = 'normal';
edgeData.pattern = 'dotted';
break;
case 'thick':
style = ' stroke-width: 3.5px;fill:none';
edgeData.thickness = 'thick';
edgeData.pattern = 'solid';
break;
}
}
@ -241,7 +252,7 @@ export const addEdges = function(edges, g) {
if (getConfig().flowchart.htmlLabels && false) { // eslint-disable-line
edgeData.labelType = 'html';
edgeData.label = '<span class="edgeLabel">' + edge.text + '</span>';
edgeData.label = `<span id="L-${linkId}" class="edgeLabel L-${linkNameStart}' L-${linkNameEnd}">${edge.text}</span>`;
} else {
edgeData.labelType = 'text';
edgeData.label = edge.text.replace(common.lineBreakRegex, '\n');
@ -253,6 +264,10 @@ export const addEdges = function(edges, g) {
edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:');
}
}
edgeData.id = linkId;
edgeData.classes = 'flowchart-link ' + linkNameStart + ' ' + linkNameEnd;
// Add the edge to the graph
g.setEdge(edge.start, edge.end, edgeData, cnt);
});

View File

@ -166,6 +166,12 @@ export const addEdges = function(edges, g) {
edges.forEach(function(edge) {
cnt++;
// Identify Link
var linkId = 'L-' + edge.start + '-' + edge.end;
var linkNameStart = 'LS-' + edge.start;
var linkNameEnd = 'LE-' + edge.end;
const edgeData = {};
// Set link type for rendering
@ -223,7 +229,7 @@ export const addEdges = function(edges, g) {
if (getConfig().flowchart.htmlLabels) {
edgeData.labelType = 'html';
edgeData.label = '<span class="edgeLabel">' + edge.text + '</span>';
edgeData.label = `<span id="L-${linkId}" class="edgeLabel L-${linkNameStart}' L-${linkNameEnd}">${edge.text}</span>`;
} else {
edgeData.labelType = 'text';
edgeData.label = edge.text.replace(common.lineBreakRegex, '\n');
@ -235,6 +241,10 @@ export const addEdges = function(edges, g) {
edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:');
}
}
edgeData.id = linkId;
edgeData.class = linkNameStart + ' ' + linkNameEnd;
// Add the edge to the graph
g.setEdge(edge.start, edge.end, edgeData, cnt);
});

View File

@ -2,6 +2,7 @@ import moment from 'moment-mini';
import { sanitizeUrl } from '@braintree/sanitize-url';
import { logger } from '../../logger';
import { getConfig } from '../../config';
import utils from '../../utils';
const config = getConfig();
let dateFormat = '';
@ -520,7 +521,7 @@ const setClickFun = function(id, functionName, functionArgs) {
let rawTask = findTaskById(id);
if (typeof rawTask !== 'undefined') {
pushFun(id, () => {
window[functionName](...argList);
utils.runFunc(functionName, ...argList);
});
}
};

View File

@ -145,10 +145,11 @@ const setupNode = (g, parent, node, altFlag) => {
arrowType: '',
style: 'fill:none',
labelStyle: '',
classes: 'note-edge',
classes: 'transition note-edge',
arrowheadStyle: 'fill: #333',
labelpos: 'c',
labelType: 'text'
labelType: 'text',
thickness: 'normal'
});
} else {
g.setNode(node.id, nodeData);
@ -184,7 +185,9 @@ const setupDoc = (g, parent, doc, altFlag) => {
label: item.description,
arrowheadStyle: 'fill: #333',
labelpos: 'c',
labelType: 'text'
labelType: 'text',
thickness: 'normal',
classes: 'transition'
};
let startId = item.state1.id;
let endId = item.state2.id;

View File

@ -34,6 +34,11 @@
stroke-width: 1.5px;
}
.flowchart-link {
stroke: $lineColor;
fill: none;
}
.edgeLabel {
background-color: $edgeLabelBackground;
rect {

View File

@ -12,10 +12,13 @@
// }
:root {
--mermaid-font-family: '"trebuchet ms", verdana, arial, "Comic Sans MS", "Comic Sans", cursive';
--mermaid-font-family: '"trebuchet ms", verdana, arial';
--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive;
// --mermaid-alt-font-family: '"Lucida Console", Monaco, monospace';
}
/* Classes common for multiple diagrams */
.error-icon {
fill: $errorBkgColor;
}
@ -23,3 +26,29 @@
fill: $errorTextColor;
stroke: $errorTextColor;
}
.edge-thickness-normal {
// stroke: $lineColor;
stroke-width: 2px;
}
.edge-thickness-thick {
// stroke: $lineColor;
stroke-width: 3.5px
}
.edge-pattern-solid {
stroke-dasharray: 0;
}
.edge-pattern-dashed{
stroke-dasharray: 3;
}
.edge-pattern-dotted {
stroke-dasharray: 2;
}
.marker {
fill: $lineColor;
}
.marker.cross {
stroke: $lineColor;
}

View File

@ -240,6 +240,21 @@ export const formatUrl = (linkStr, config) => {
}
};
export const runFunc = (functionName, ...params) => {
var arrPaths = functionName.split('.');
var len = arrPaths.length - 1;
var fnName = arrPaths[len];
var obj = window;
for (var i = 0; i < len; i++) {
obj = obj[arrPaths[i]];
if (!obj) return;
}
obj[fnName](...params);
};
const distance = (p1, p2) =>
p1 && p2 ? Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2)) : 0;
@ -377,5 +392,6 @@ export default {
calcCardinalityPosition,
formatUrl,
getStylesFromArray,
generateId
generateId,
runFunc
};