Merge pull request #6 from mermaid-js/develop

sync fork
This commit is contained in:
GDFaber
2019-12-21 00:02:01 +01:00
committed by GitHub
12 changed files with 439 additions and 181 deletions

View File

@@ -428,4 +428,29 @@ describe('Flowcart', () => {
{ flowchart: { htmlLabels: false } } { flowchart: { htmlLabels: false } }
); );
}); });
it('17: Chaining of nodes', () => {
imgSnapshotTest(
`graph LR
a --> b --> c
`,
{ flowchart: { htmlLabels: false } }
);
});
it('18: Multiple nodes and chaining in one statement', () => {
imgSnapshotTest(
`graph LR
a --> b c--> d
`,
{ flowchart: { htmlLabels: false } }
);
});
it('19: Multiple nodes and chaining in one statement', () => {
imgSnapshotTest(
`graph TD
A[ h ] -- hello --> B[" test "]:::exClass C --> D;
classDef exClass background:#bbb,border:1px solid red;
`,
{ flowchart: { htmlLabels: false } }
);
});
}); });

View File

@@ -5,7 +5,7 @@
rel="stylesheet" rel="stylesheet"
/> />
<style> <style>
body {background: white} body {background: black}
h1 { color: white;} h1 { color: white;}
.arrowheadPath {fill: red;} .arrowheadPath {fill: red;}
@@ -17,26 +17,24 @@
<body> <body>
<h1>info below</h1> <h1>info below</h1>
<div style="display: flex;width: 100%; height: 100%"> <div style="display: flex;width: 100%; height: 100%">
<div class="mermaid" style="width: 100%; height: 100%">gantt <div class="mermaid" style="width: 100%; height: 100%">
dateFormat YYYY-MM-DD graph TB
axisFormat %d/%m A --> B
title Adding GANTT diagram to mermaid A ==> C
excludes weekdays 2014-01-10 A .-> D
A === E
apple :a, 2017-07-20, 1w A -.- F
banana :crit, b, 2017-07-23, 1d D -- Hello --> a
cherry :active, c, after b a, 1d D-- text including R TD space --xb
</div> </div>
</div> </div>
<script src="./mermaid.js"></script> <script src="./mermaid.js"></script>
<script> <script>
mermaid.initialize({ mermaid.initialize({
// theme: 'dark', theme: 'dark',
// arrowMarkerAbsolute: true, // arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}', // themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 3, logLevel: 0,
flowchart: { curve: 'linear', "htmlLabels": false }, flowchart: { curve: 'linear', "htmlLabels": false },
// gantt: { axisFormat: '%m/%d/%Y' }, // gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50 }, sequence: { actorMargin: 50 },

View File

@@ -102,7 +102,7 @@ export const addVertex = function(_id, text, type, style, classes) {
* @param type * @param type
* @param linktext * @param linktext
*/ */
export const addLink = function(_start, _end, type, linktext) { export const addSingleLink = function(_start, _end, type, linktext) {
let start = _start; let start = _start;
let end = _end; let end = _end;
if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start; if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start;
@@ -127,6 +127,14 @@ export const addLink = function(_start, _end, type, linktext) {
} }
edges.push(edge); edges.push(edge);
}; };
export const addLink = function(_start, _end, type, linktext) {
let i, j;
for (i = 0; i < _start.length; i++) {
for (j = 0; j < _end.length; j++) {
addSingleLink(_start[i], _end[j], type, linktext);
}
}
};
/** /**
* Updates a link's line interpolation algorithm * Updates a link's line interpolation algorithm
@@ -501,6 +509,130 @@ export const firstGraph = () => {
return false; return false;
}; };
const destructStartLink = _str => {
const str = _str.trim();
switch (str) {
case '<--':
return { type: 'arrow', stroke: 'normal' };
case 'x--':
return { type: 'arrow_cross', stroke: 'normal' };
case 'o--':
return { type: 'arrow_circle', stroke: 'normal' };
case '<-.':
return { type: 'arrow', stroke: 'dotted' };
case 'x-.':
return { type: 'arrow_cross', stroke: 'dotted' };
case 'o-.':
return { type: 'arrow_circle', stroke: 'dotted' };
case '<==':
return { type: 'arrow', stroke: 'thick' };
case 'x==':
return { type: 'arrow_cross', stroke: 'thick' };
case 'o==':
return { type: 'arrow_circle', stroke: 'thick' };
case '--':
return { type: 'arrow_open', stroke: 'normal' };
case '==':
return { type: 'arrow_open', stroke: 'thick' };
case '-.':
return { type: 'arrow_open', stroke: 'dotted' };
}
};
const destructEndLink = _str => {
const str = _str.trim();
switch (str) {
case '--x':
return { type: 'arrow_cross', stroke: 'normal' };
case '-->':
return { type: 'arrow', stroke: 'normal' };
case '<-->':
return { type: 'double_arrow_point', stroke: 'normal' };
case 'x--x':
return { type: 'double_arrow_cross', stroke: 'normal' };
case 'o--o':
return { type: 'double_arrow_circle', stroke: 'normal' };
case 'o.-o':
return { type: 'double_arrow_circle', stroke: 'dotted' };
case '<==>':
return { type: 'double_arrow_point', stroke: 'thick' };
case 'o==o':
return { type: 'double_arrow_circle', stroke: 'thick' };
case 'x==x':
return { type: 'double_arrow_cross', stroke: 'thick' };
case 'x.-x':
return { type: 'double_arrow_cross', stroke: 'dotted' };
case 'x-.-x':
return { type: 'double_arrow_cross', stroke: 'dotted' };
case '<.->':
return { type: 'double_arrow_point', stroke: 'dotted' };
case '<-.->':
return { type: 'double_arrow_point', stroke: 'dotted' };
case 'o-.-o':
return { type: 'double_arrow_circle', stroke: 'dotted' };
case '--o':
return { type: 'arrow_circle', stroke: 'normal' };
case '---':
return { type: 'arrow_open', stroke: 'normal' };
case '-.-x':
return { type: 'arrow_cross', stroke: 'dotted' };
case '-.->':
return { type: 'arrow', stroke: 'dotted' };
case '-.-o':
return { type: 'arrow_circle', stroke: 'dotted' };
case '-.-':
return { type: 'arrow_open', stroke: 'dotted' };
case '.-x':
return { type: 'arrow_cross', stroke: 'dotted' };
case '.->':
return { type: 'arrow', stroke: 'dotted' };
case '.-o':
return { type: 'arrow_circle', stroke: 'dotted' };
case '.-':
return { type: 'arrow_open', stroke: 'dotted' };
case '==x':
return { type: 'arrow_cross', stroke: 'thick' };
case '==>':
return { type: 'arrow', stroke: 'thick' };
case '==o':
return { type: 'arrow_circle', stroke: 'thick' };
case '===':
return { type: 'arrow_open', stroke: 'thick' };
}
};
const destructLink = (_str, _startStr) => {
const info = destructEndLink(_str);
let startInfo;
if (_startStr) {
startInfo = destructStartLink(_startStr);
console.log(startInfo, info);
if (startInfo.stroke !== info.stroke) {
return { type: 'INVALID', stroke: 'INVALID' };
}
if (startInfo.type === 'arrow_open') {
// -- xyz --> - take arrow type form ending
startInfo.type = info.type;
} else {
// x-- xyz --> - not supported
if (startInfo.type !== info.type) return { type: 'INVALID', stroke: 'INVALID' };
startInfo.type = 'double_' + startInfo.type;
}
if (startInfo.type === 'double_arrow') {
startInfo.type = 'double_arrow_point';
}
return startInfo;
}
return info;
};
export default { export default {
addVertex, addVertex,
addLink, addLink,
@@ -523,6 +655,7 @@ export default {
getDepthFirstPos, getDepthFirstPos,
indexNodes, indexNodes,
getSubGraphs, getSubGraphs,
destructLink,
lex: { lex: {
firstGraph firstGraph
} }

View File

@@ -87,7 +87,7 @@ describe('[Edges] when parsing', () => {
expect(edges[0].text).toBe(''); expect(edges[0].text).toBe('');
}); });
it('should handle double edged nodes with text on thick arrows', function() { it('should handle double edged nodes with text on thick arrows XYZ1', function() {
const res = flow.parser.parse('graph TD;\nA x== text ==x B;'); const res = flow.parser.parse('graph TD;\nA x== text ==x B;');
const vert = flow.parser.yy.getVertices(); const vert = flow.parser.yy.getVertices();

View File

@@ -22,6 +22,16 @@ describe('[Singlenodes] when parsing', () => {
expect(edges.length).toBe(0); expect(edges.length).toBe(0);
expect(vert['A'].styles.length).toBe(0); expect(vert['A'].styles.length).toBe(0);
}); });
it('should handle a single node with white space after it (SN1)', function() {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;A ;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert['A'].styles.length).toBe(0);
});
it('should handle a single square node', function() { it('should handle a single square node', function() {
// Silly but syntactically correct // Silly but syntactically correct

View File

@@ -182,7 +182,7 @@ describe('[Text] when parsing', () => {
expect(edges[0].stroke).toBe('normal'); expect(edges[0].stroke).toBe('normal');
}); });
it('it should handle dotted text on lines', function() { it('it should handle dotted text on lines (TD3)', function() {
const res = flow.parser.parse('graph TD;A-. test text with == .->B;'); const res = flow.parser.parse('graph TD;A-. test text with == .->B;');
const vert = flow.parser.yy.getVertices(); const vert = flow.parser.yy.getVertices();
@@ -265,7 +265,7 @@ describe('[Text] when parsing', () => {
expect(edges[0].text).toBe('text including URL space'); expect(edges[0].text).toBe('text including URL space');
}); });
it('should handle space and dir (TD)', function() { it('should handle space and dir (TD2)', function() {
const res = flow.parser.parse('graph TD;A-- text including R TD space --xB;'); const res = flow.parser.parse('graph TD;A-- text including R TD space --xB;');
const vert = flow.parser.yy.getVertices(); const vert = flow.parser.yy.getVertices();

View File

@@ -34,4 +34,179 @@ describe('when parsing flowcharts', function() {
expect(edges[1].type).toBe('arrow'); expect(edges[1].type).toBe('arrow');
expect(edges[1].text).toBe(''); expect(edges[1].text).toBe('');
}); });
it('should handle chaining of vertices', function() {
const res = flow.parser.parse(`
graph TD
A B --> C;
`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(vert['C'].id).toBe('C');
expect(edges.length).toBe(2);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('C');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
expect(edges[1].start).toBe('B');
expect(edges[1].end).toBe('C');
expect(edges[1].type).toBe('arrow');
expect(edges[1].text).toBe('');
});
it('should multiple vertices in link statement in the begining', function() {
const res = flow.parser.parse(`
graph TD
A-->B C;
`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(vert['C'].id).toBe('C');
expect(edges.length).toBe(2);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
expect(edges[1].start).toBe('A');
expect(edges[1].end).toBe('C');
expect(edges[1].type).toBe('arrow');
expect(edges[1].text).toBe('');
});
it('should multiple vertices in link statement at the end', function() {
const res = flow.parser.parse(`
graph TD
A B--> C D;
`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(vert['C'].id).toBe('C');
expect(vert['D'].id).toBe('D');
expect(edges.length).toBe(4);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('C');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
expect(edges[1].start).toBe('A');
expect(edges[1].end).toBe('D');
expect(edges[1].type).toBe('arrow');
expect(edges[1].text).toBe('');
expect(edges[2].start).toBe('B');
expect(edges[2].end).toBe('C');
expect(edges[2].type).toBe('arrow');
expect(edges[2].text).toBe('');
expect(edges[3].start).toBe('B');
expect(edges[3].end).toBe('D');
expect(edges[3].type).toBe('arrow');
expect(edges[3].text).toBe('');
});
it('should handle chaining of vertices at both ends at once', function() {
const res = flow.parser.parse(`
graph TD
A B--> C D;
`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(vert['C'].id).toBe('C');
expect(vert['D'].id).toBe('D');
expect(edges.length).toBe(4);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('C');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
expect(edges[1].start).toBe('A');
expect(edges[1].end).toBe('D');
expect(edges[1].type).toBe('arrow');
expect(edges[1].text).toBe('');
expect(edges[2].start).toBe('B');
expect(edges[2].end).toBe('C');
expect(edges[2].type).toBe('arrow');
expect(edges[2].text).toBe('');
expect(edges[3].start).toBe('B');
expect(edges[3].end).toBe('D');
expect(edges[3].type).toBe('arrow');
expect(edges[3].text).toBe('');
});
it('should handle chaining and multiple nodes in in link statement', function() {
const res = flow.parser.parse(`
graph TD
A --> B C --> D;
`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(vert['C'].id).toBe('C');
expect(vert['D'].id).toBe('D');
expect(edges.length).toBe(4);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('');
expect(edges[1].start).toBe('A');
expect(edges[1].end).toBe('C');
expect(edges[1].type).toBe('arrow');
expect(edges[1].text).toBe('');
expect(edges[2].start).toBe('B');
expect(edges[2].end).toBe('D');
expect(edges[2].type).toBe('arrow');
expect(edges[2].text).toBe('');
expect(edges[3].start).toBe('C');
expect(edges[3].end).toBe('D');
expect(edges[3].type).toBe('arrow');
expect(edges[3].text).toBe('');
});
it('should handle chaining and multiple nodes in in link statement with extra info in statements', function() {
const res = flow.parser.parse(`
graph TD
A[ h ] -- hello --> B[" test "]:::exClass C --> D;
classDef exClass background:#bbb,border:1px solid red;
`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const classes = flow.parser.yy.getClasses();
expect(classes['exClass'].styles.length).toBe(2);
expect(classes['exClass'].styles[0]).toBe('background:#bbb');
expect(classes['exClass'].styles[1]).toBe('border:1px solid red');
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(vert['B'].classes[0]).toBe('exClass');
expect(vert['C'].id).toBe('C');
expect(vert['D'].id).toBe('D');
expect(edges.length).toBe(4);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow');
expect(edges[0].text).toBe('hello');
expect(edges[1].start).toBe('A');
expect(edges[1].end).toBe('C');
expect(edges[1].type).toBe('arrow');
expect(edges[1].text).toBe('hello');
expect(edges[2].start).toBe('B');
expect(edges[2].end).toBe('D');
expect(edges[2].type).toBe('arrow');
expect(edges[2].text).toBe('');
expect(edges[3].start).toBe('C');
expect(edges[3].end).toBe('D');
expect(edges[3].type).toBe('arrow');
expect(edges[3].text).toBe('');
});
}); });

View File

@@ -8,6 +8,7 @@
%lex %lex
%x string %x string
%x dir %x dir
%x vertex
%% %%
\%\%[^\n]*\n* /* do nothing */ \%\%[^\n]*\n* /* do nothing */
["] this.begin("string"); ["] this.begin("string");
@@ -40,46 +41,46 @@
";" return 'SEMI'; ";" return 'SEMI';
"," return 'COMMA'; "," return 'COMMA';
"*" return 'MULT'; "*" return 'MULT';
\s*\-\-[x]\s* return 'ARROW_CROSS'; \s*\-\-[x]\s* return 'LINK';
\s*\-\-\>\s* return 'ARROW_POINT'; \s*\-\-\>\s* return 'LINK';
\s*\<\-\-\>\s* return 'DOUBLE_ARROW_POINT'; \s*\<\-\-\>\s* return 'LINK';
\s*[x]\-\-[x]\s* return 'DOUBLE_ARROW_CROSS'; \s*[x]\-\-[x]\s* return 'LINK';
\s*[o]\-\-[o]\s* return 'DOUBLE_ARROW_CIRCLE'; \s*[o]\-\-[o]\s* return 'LINK';
\s*[o]\.\-[o]\s* return 'DOUBLE_DOTTED_ARROW_CIRCLE'; \s*[o]\.\-[o]\s* return 'LINK';
\s*\<\=\=\>\s* return 'DOUBLE_THICK_ARROW_POINT'; \s*\<\=\=\>\s* return 'LINK';
\s*[o]\=\=[o]\s* return 'DOUBLE_THICK_ARROW_CIRCLE'; \s*[o]\=\=[o]\s* return 'LINK';
\s*[x]\=\=[x]\s* return 'DOUBLE_THICK_ARROW_CROSS'; \s*[x]\=\=[x]\s* return 'LINK';
\s*[x].\-[x]\s* return 'DOUBLE_DOTTED_ARROW_CROSS'; \s*[x].\-[x]\s* return 'LINK';
\s*[x]\-\.\-[x]\s* return 'DOUBLE_DOTTED_ARROW_CROSS'; \s*[x]\-\.\-[x]\s* return 'LINK';
\s*\<\.\-\>\s* return 'DOUBLE_DOTTED_ARROW_POINT'; \s*\<\.\-\>\s* return 'LINK';
\s*\<\-\.\-\>\s* return 'DOUBLE_DOTTED_ARROW_POINT'; \s*\<\-\.\-\>\s* return 'LINK';
\s*[o]\-\.\-[o]\s* return 'DOUBLE_DOTTED_ARROW_CIRCLE'; \s*[o]\-\.\-[o]\s* return 'LINK';
\s*\-\-[o]\s* return 'ARROW_CIRCLE'; \s*\-\-[o]\s* return 'LINK';
\s*\-\-\-\s* return 'ARROW_OPEN'; \s*\-\-\-\s* return 'LINK';
\s*\-\.\-[x]\s* return 'DOTTED_ARROW_CROSS'; \s*\-\.\-[x]\s* return 'LINK';
\s*\-\.\-\>\s* return 'DOTTED_ARROW_POINT'; \s*\-\.\-\>\s* return 'LINK';
\s*\-\.\-[o]\s* return 'DOTTED_ARROW_CIRCLE'; \s*\-\.\-[o]\s* return 'LINK';
\s*\-\.\-\s* return 'DOTTED_ARROW_OPEN'; \s*\-\.\-\s* return 'LINK';
\s*.\-[x]\s* return 'DOTTED_ARROW_CROSS'; \s*.\-[x]\s* return 'LINK';
\s*\.\-\>\s* return 'DOTTED_ARROW_POINT'; \s*\.\-\>\s* return 'LINK';
\s*\.\-[o]\s* return 'DOTTED_ARROW_CIRCLE'; \s*\.\-[o]\s* return 'LINK';
\s*\.\-\s* return 'DOTTED_ARROW_OPEN'; \s*\.\-\s* return 'LINK';
\s*\=\=[x]\s* return 'THICK_ARROW_CROSS'; \s*\=\=[x]\s* return 'LINK';
\s*\=\=\>\s* return 'THICK_ARROW_POINT'; \s*\=\=\>\s* return 'LINK';
\s*\=\=[o]\s* return 'THICK_ARROW_CIRCLE'; \s*\=\=[o]\s* return 'LINK';
\s*\=\=[\=]\s* return 'THICK_ARROW_OPEN'; \s*\=\=[\=]\s* return 'LINK';
\s*\<\-\-\s* return 'START_DOUBLE_ARROW_POINT'; \s*\<\-\-\s* return 'START_LINK';
\s*[x]\-\-\s* return 'START_DOUBLE_ARROW_CROSS'; \s*[x]\-\-\s* return 'START_LINK';
\s*[o]\-\-\s* return 'START_DOUBLE_ARROW_CIRCLE'; \s*[o]\-\-\s* return 'START_LINK';
\s*\<\-\.\s* return 'START_DOUBLE_DOTTED_ARROW_POINT'; \s*\<\-\.\s* return 'START_LINK';
\s*[x]\-\.\s* return 'START_DOUBLE_DOTTED_ARROW_CROSS'; \s*[x]\-\.\s* return 'START_LINK';
\s*[o]\-\.\s* return 'START_DOUBLE_DOTTED_ARROW_CIRCLE'; \s*[o]\-\.\s* return 'START_LINK';
\s*\<\=\=\s* return 'START_DOUBLE_THICK_ARROW_POINT'; \s*\<\=\=\s* return 'START_LINK';
\s*[x]\=\=\s* return 'START_DOUBLE_THICK_ARROW_CROSS'; \s*[x]\=\=\s* return 'START_LINK';
\s*[o]\=\=\s* return 'START_DOUBLE_THICK_ARROW_CIRCLE'; \s*[o]\=\=\s* return 'START_LINK';
\s*\-\-\s* return '--'; \s*\-\-\s* return 'START_LINK';
\s*\-\.\s* return '-.'; \s*\-\.\s* return 'START_LINK';
\s*\=\=\s* return '=='; \s*\=\=\s* return 'START_LINK';
"(-" return '(-'; "(-" return '(-';
"-)" return '-)'; "-)" return '-)';
"([" return 'STADIUMSTART'; "([" return 'STADIUMSTART';
@@ -94,6 +95,7 @@
"<" return 'TAGSTART'; "<" return 'TAGSTART';
">" return 'TAGEND'; ">" return 'TAGEND';
"^" return 'UP'; "^" return 'UP';
"\|" return 'SEP';
"v" return 'DOWN'; "v" return 'DOWN';
[A-Za-z]+ return 'ALPHA'; [A-Za-z]+ return 'ALPHA';
"\\]" return 'TRAPEND'; "\\]" return 'TRAPEND';
@@ -247,7 +249,7 @@ spaceList
statement statement
: verticeStatement separator : verticeStatement separator
{ $$=$1} { /* console.warn('finat vs', $1.nodes); */ $$=$1.nodes}
| styleStatement separator | styleStatement separator
{$$=[];} {$$=[];}
| linkStyleStatement separator | linkStyleStatement separator
@@ -285,72 +287,49 @@ separator: NEWLINE | SEMI | EOF ;
// {$$ = [$1];yy.setClass($1,$3)} // {$$ = [$1];yy.setClass($1,$3)}
// ; // ;
verticeStatement: verticeStatement link node { yy.addLink($1[0],$3[0],$2); $$ = $3.concat($1) }
|node { $$ = $1 } verticeStatement: verticeStatement link node
{ /* console.warn('vs',$1.stmt,$3); */ yy.addLink($1.stmt,$3,$2); $$ = { stmt: $3, nodes: $3.concat($1.nodes) } }
| verticeStatement link node spaceList
{ /* console.warn('vs',$1.stmt,$3); */ yy.addLink($1.stmt,$3,$2); $$ = { stmt: $3, nodes: $3.concat($1.nodes) } }
|node spaceList {/*console.warn('noda', $1);*/ $$ = {stmt: $1, nodes:$1 }}
|node { /*console.warn('noda', $1);*/ $$ = {stmt: $1, nodes:$1 }}
; ;
node: vertex node: vertex
{ $$ = [$1];} { /* console.warn('nod', $1); */ $$ = [$1];}
| node spaceList vertex
{ $$ = [$1[0], $3]; /*console.warn('pip', $1, $3, $$);*/ }
| vertex STYLE_SEPARATOR idString | vertex STYLE_SEPARATOR idString
{$$ = [$1];yy.setClass($1,$3)} {$$ = [$1];yy.setClass($1,$3)}
; ;
vertex: idString SQS text SQE vertex: idString SQS text SQE
{$$ = $1;yy.addVertex($1,$3,'square');} {$$ = $1;yy.addVertex($1,$3,'square');}
| idString SQS text SQE spaceList
{$$ = $1;yy.addVertex($1,$3,'square');}
| idString PS PS text PE PE | idString PS PS text PE PE
{$$ = $1;yy.addVertex($1,$4,'circle');} {$$ = $1;yy.addVertex($1,$4,'circle');}
| idString PS PS text PE PE spaceList
{$$ = $1;yy.addVertex($1,$4,'circle');}
| idString '(-' text '-)' | idString '(-' text '-)'
{$$ = $1;yy.addVertex($1,$3,'ellipse');} {$$ = $1;yy.addVertex($1,$3,'ellipse');}
| idString '(-' text '-)' spaceList
{$$ = $1;yy.addVertex($1,$3,'ellipse');}
| idString STADIUMSTART text STADIUMEND | idString STADIUMSTART text STADIUMEND
{$$ = $1;yy.addVertex($1,$3,'stadium');} {$$ = $1;yy.addVertex($1,$3,'stadium');}
| idString STADIUMSTART text STADIUMEND spaceList
{$$ = $1;yy.addVertex($1,$3,'stadium');}
| idString PS text PE | idString PS text PE
{$$ = $1;yy.addVertex($1,$3,'round');} {$$ = $1;yy.addVertex($1,$3,'round');}
| idString PS text PE spaceList
{$$ = $1;yy.addVertex($1,$3,'round');}
| idString DIAMOND_START text DIAMOND_STOP | idString DIAMOND_START text DIAMOND_STOP
{$$ = $1;yy.addVertex($1,$3,'diamond');} {$$ = $1;yy.addVertex($1,$3,'diamond');}
| idString DIAMOND_START text DIAMOND_STOP spaceList
{$$ = $1;yy.addVertex($1,$3,'diamond');}
| idString DIAMOND_START DIAMOND_START text DIAMOND_STOP DIAMOND_STOP | idString DIAMOND_START DIAMOND_START text DIAMOND_STOP DIAMOND_STOP
{$$ = $1;yy.addVertex($1,$4,'hexagon');} {$$ = $1;yy.addVertex($1,$4,'hexagon');}
| idString DIAMOND_START DIAMOND_START text DIAMOND_STOP DIAMOND_STOP spaceList
{$$ = $1;yy.addVertex($1,$4,'hexagon');}
| idString TAGEND text SQE | idString TAGEND text SQE
{$$ = $1;yy.addVertex($1,$3,'odd');} {$$ = $1;yy.addVertex($1,$3,'odd');}
| idString TAGEND text SQE spaceList
{$$ = $1;yy.addVertex($1,$3,'odd');}
| idString TRAPSTART text TRAPEND | idString TRAPSTART text TRAPEND
{$$ = $1;yy.addVertex($1,$3,'trapezoid');} {$$ = $1;yy.addVertex($1,$3,'trapezoid');}
| idString TRAPSTART text TRAPEND spaceList
{$$ = $1;yy.addVertex($1,$3,'trapezoid');}
| idString INVTRAPSTART text INVTRAPEND | idString INVTRAPSTART text INVTRAPEND
{$$ = $1;yy.addVertex($1,$3,'inv_trapezoid');} {$$ = $1;yy.addVertex($1,$3,'inv_trapezoid');}
| idString INVTRAPSTART text INVTRAPEND spaceList
{$$ = $1;yy.addVertex($1,$3,'inv_trapezoid');}
| idString TRAPSTART text INVTRAPEND | idString TRAPSTART text INVTRAPEND
{$$ = $1;yy.addVertex($1,$3,'lean_right');} {$$ = $1;yy.addVertex($1,$3,'lean_right');}
| idString TRAPSTART text INVTRAPEND spaceList
{$$ = $1;yy.addVertex($1,$3,'lean_right');}
| idString INVTRAPSTART text TRAPEND | idString INVTRAPSTART text TRAPEND
{$$ = $1;yy.addVertex($1,$3,'lean_left');} {$$ = $1;yy.addVertex($1,$3,'lean_left');}
| idString INVTRAPSTART text TRAPEND spaceList
{$$ = $1;yy.addVertex($1,$3,'lean_left');}
/* | idString SQS text TAGSTART
{$$ = $1;yy.addVertex($1,$3,'odd_right');}
| idString SQS text TAGSTART spaceList
{$$ = $1;yy.addVertex($1,$3,'odd_right');} */
| idString | idString
{$$ = $1;yy.addVertex($1);} { /*console.warn('h: ', $1);*/$$ = $1;yy.addVertex($1);}
| idString spaceList
{$$ = $1;yy.addVertex($1);}
; ;
@@ -363,92 +342,12 @@ link: linkStatement arrowText
{$1.text = $2;$$ = $1;} {$1.text = $2;$$ = $1;}
| linkStatement | linkStatement
{$$ = $1;} {$$ = $1;}
| '--' text ARROW_POINT | START_LINK text LINK
{$$ = {"type":"arrow","stroke":"normal","text":$2};} {var inf = yy.destructLink($3, $1); $$ = {"type":inf.type,"stroke":inf.stroke,"text":$2};}
| 'START_DOUBLE_ARROW_POINT' text ARROW_POINT
{$$ = {"type":"double_arrow_point","stroke":"normal","text":$2};}
| '--' text ARROW_CIRCLE
{$$ = {"type":"arrow_circle","stroke":"normal","text":$2};}
| 'START_DOUBLE_ARROW_CIRCLE' text ARROW_CIRCLE
{$$ = {"type":"double_arrow_circle","stroke":"normal","text":$2};}
| '--' text ARROW_CROSS
{$$ = {"type":"arrow_cross","stroke":"normal","text":$2};}
| 'START_DOUBLE_ARROW_CROSS' text ARROW_CROSS
{$$ = {"type":"double_arrow_cross","stroke":"normal","text":$2};}
| '--' text ARROW_OPEN
{$$ = {"type":"arrow_open","stroke":"normal","text":$2};}
| '-.' text DOTTED_ARROW_POINT
{$$ = {"type":"arrow","stroke":"dotted","text":$2};}
| 'START_DOUBLE_DOTTED_ARROW_POINT' text DOTTED_ARROW_POINT
{$$ = {"type":"double_arrow_point","stroke":"dotted","text":$2};}
| '-.' text DOTTED_ARROW_CIRCLE
{$$ = {"type":"arrow_circle","stroke":"dotted","text":$2};}
| 'START_DOUBLE_DOTTED_ARROW_CIRCLE' text DOTTED_ARROW_CIRCLE
{$$ = {"type":"double_arrow_circle","stroke":"dotted","text":$2};}
| '-.' text DOTTED_ARROW_CROSS
{$$ = {"type":"arrow_cross","stroke":"dotted","text":$2};}
| 'START_DOUBLE_DOTTED_ARROW_CROSS' text DOTTED_ARROW_CROSS
{$$ = {"type":"double_arrow_cross","stroke":"dotted","text":$2};}
| '-.' text DOTTED_ARROW_OPEN
{$$ = {"type":"arrow_open","stroke":"dotted","text":$2};}
| '==' text THICK_ARROW_POINT
{$$ = {"type":"arrow","stroke":"thick","text":$2};}
| 'START_DOUBLE_THICK_ARROW_POINT' text THICK_ARROW_POINT
{$$ = {"type":"double_arrow_point","stroke":"thick","text":$2};}
| '==' text THICK_ARROW_CIRCLE
{$$ = {"type":"arrow_circle","stroke":"thick","text":$2};}
| 'START_DOUBLE_THICK_ARROW_CIRCLE' text THICK_ARROW_CIRCLE
{$$ = {"type":"double_arrow_circle","stroke":"thick","text":$2};}
| '==' text THICK_ARROW_CROSS
{$$ = {"type":"arrow_cross","stroke":"thick","text":$2};}
| 'START_DOUBLE_THICK_ARROW_CROSS' text THICK_ARROW_CROSS
{$$ = {"type":"double_arrow_cross","stroke":"thick","text":$2};}
| '==' text THICK_ARROW_OPEN
{$$ = {"type":"arrow_open","stroke":"thick","text":$2};}
; ;
linkStatement: ARROW_POINT linkStatement: LINK
{$$ = {"type":"arrow","stroke":"normal"};} {var inf = yy.destructLink($1);$$ = {"type":inf.type,"stroke":inf.stroke};}
| DOUBLE_ARROW_POINT
{$$ = {"type":"double_arrow_point","stroke":"normal"};}
| ARROW_CIRCLE
{$$ = {"type":"arrow_circle","stroke":"normal"};}
| DOUBLE_ARROW_CIRCLE
{$$ = {"type":"double_arrow_circle","stroke":"normal"};}
| ARROW_CROSS
{$$ = {"type":"arrow_cross","stroke":"normal"};}
| DOUBLE_ARROW_CROSS
{$$ = {"type":"double_arrow_cross","stroke":"normal"};}
| ARROW_OPEN
{$$ = {"type":"arrow_open","stroke":"normal"};}
| DOTTED_ARROW_POINT
{$$ = {"type":"arrow","stroke":"dotted"};}
| DOUBLE_DOTTED_ARROW_POINT
{$$ = {"type":"double_arrow_point","stroke":"dotted"};}
| DOTTED_ARROW_CIRCLE
{$$ = {"type":"arrow_circle","stroke":"dotted"};}
| DOUBLE_DOTTED_ARROW_CIRCLE
{$$ = {"type":"double_arrow_circle","stroke":"dotted"};}
| DOTTED_ARROW_CROSS
{$$ = {"type":"arrow_cross","stroke":"dotted"};}
| DOUBLE_DOTTED_ARROW_CROSS
{$$ = {"type":"double_arrow_cross","stroke":"dotted"};}
| DOTTED_ARROW_OPEN
{$$ = {"type":"arrow_open","stroke":"dotted"};}
| THICK_ARROW_POINT
{$$ = {"type":"arrow","stroke":"thick"};}
| DOUBLE_THICK_ARROW_POINT
{$$ = {"type":"double_arrow_point","stroke":"thick"};}
| THICK_ARROW_CIRCLE
{$$ = {"type":"arrow_circle","stroke":"thick"};}
| DOUBLE_THICK_ARROW_CIRCLE
{$$ = {"type":"double_arrow_circle","stroke":"thick"};}
| THICK_ARROW_CROSS
{$$ = {"type":"arrow_cross","stroke":"thick"};}
| DOUBLE_THICK_ARROW_CROSS
{$$ = {"type":"double_arrow_cross","stroke":"thick"};}
| THICK_ARROW_OPEN
{$$ = {"type":"arrow_open","stroke":"thick"};}
; ;
arrowText: arrowText:
@@ -536,7 +435,7 @@ styleComponent: ALPHA | COLON | MINUS | NUM | UNIT | SPACE | HEX | BRKT | DOT |
/* Token lists */ /* Token lists */
textToken : textNoTagsToken | TAGSTART | TAGEND | '==' | '--' | PCT | DEFAULT; textToken : textNoTagsToken | TAGSTART | TAGEND | START_LINK | PCT | DEFAULT;
textNoTagsToken: alphaNumToken | SPACE | MINUS | keywords ; textNoTagsToken: alphaNumToken | SPACE | MINUS | keywords ;

View File

@@ -16,6 +16,7 @@ describe('when parsing subgraphs', function() {
const subgraphs = flow.parser.yy.getSubGraphs(); const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1); expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0]; const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(2); expect(subgraph.nodes.length).toBe(2);
expect(subgraph.nodes[0]).toBe('a2'); expect(subgraph.nodes[0]).toBe('a2');
expect(subgraph.nodes[1]).toBe('a1'); expect(subgraph.nodes[1]).toBe('a1');
@@ -191,6 +192,15 @@ describe('when parsing subgraphs', function() {
expect(edges[0].type).toBe('arrow'); expect(edges[0].type).toBe('arrow');
}); });
it('should handle subgraphs3', function() {
const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle \n\n c-->d \nend\n');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow');
});
it('should handle nested subgraphs', function() { it('should handle nested subgraphs', function() {
const str = const str =
'graph TD\n' + 'graph TD\n' +
@@ -218,6 +228,14 @@ describe('when parsing subgraphs', function() {
const vert = flow.parser.yy.getVertices(); const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges(); const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow');
});
it('should handle subgraphs with multi node statements in it', function() {
const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\na b --> c e\n end;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow'); expect(edges[0].type).toBe('arrow');
}); });
}); });

View File

@@ -49,7 +49,7 @@ line
statement statement
: STR VALUE { : STR VALUE {
console.log('str:'+$1+' value: '+$2) /*console.log('str:'+$1+' value: '+$2)*/
yy.addSection($1,yy.cleanupValue($2)); } yy.addSection($1,yy.cleanupValue($2)); }
| title {yy.setTitle($1.substr(6));$$=$1.substr(6);} | title {yy.setTitle($1.substr(6));$$=$1.substr(6);}
; ;

View File

@@ -116,7 +116,6 @@ const init = function() {
}; };
const initialize = function(config) { const initialize = function(config) {
logger.debug('Initializing mermaid ');
if (typeof config.mermaid !== 'undefined') { if (typeof config.mermaid !== 'undefined') {
if (typeof config.mermaid.startOnLoad !== 'undefined') { if (typeof config.mermaid.startOnLoad !== 'undefined') {
mermaid.startOnLoad = config.mermaid.startOnLoad; mermaid.startOnLoad = config.mermaid.startOnLoad;
@@ -126,6 +125,7 @@ const initialize = function(config) {
} }
} }
mermaidAPI.initialize(config); mermaidAPI.initialize(config);
logger.debug('Initializing mermaid ');
}; };
/** /**

View File

@@ -54,7 +54,7 @@
.grid .tick { .grid .tick {
stroke: $gridColor; stroke: $gridColor;
opacity: 0.3; opacity: 0.8;
shape-rendering: crispEdges; shape-rendering: crispEdges;
text { text {
font-family: 'trebuchet ms', verdana, arial; font-family: 'trebuchet ms', verdana, arial;