mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
Merge branch 'develop' into feature/1460_add_link_target_to_flowchart_click
This commit is contained in:
commit
cf70678188
@ -224,6 +224,7 @@ erDiagram
|
||||
it('should render a user journey diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
%%{init: { 'logLevel': 0, 'theme': '${theme}'} }%%
|
||||
journey
|
||||
title My working day
|
||||
section Go to work
|
||||
@ -232,7 +233,8 @@ erDiagram
|
||||
Do work: 1: Me, Cat
|
||||
section Go home
|
||||
Go downstairs: 5: Me
|
||||
Sit down: 5: Me `,
|
||||
Sit down: 5: Me
|
||||
`,
|
||||
{theme}
|
||||
);
|
||||
cy.get('svg');
|
||||
|
880
dist/mermaid.core.js
vendored
880
dist/mermaid.core.js
vendored
File diff suppressed because one or more lines are too long
2
dist/mermaid.core.js.map
vendored
2
dist/mermaid.core.js.map
vendored
File diff suppressed because one or more lines are too long
880
dist/mermaid.js
vendored
880
dist/mermaid.js
vendored
File diff suppressed because one or more lines are too long
2
dist/mermaid.js.map
vendored
2
dist/mermaid.js.map
vendored
File diff suppressed because one or more lines are too long
10
dist/mermaid.min.js
vendored
10
dist/mermaid.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/mermaid.min.js.map
vendored
2
dist/mermaid.min.js.map
vendored
File diff suppressed because one or more lines are too long
@ -526,7 +526,7 @@ This might need adjustment to match your locale and preferences
|
||||
|
||||
## journey
|
||||
|
||||
The object containing configurations specific for sequence diagrams
|
||||
The object containing configurations specific for journey diagrams
|
||||
|
||||
### diagramMarginX
|
||||
|
||||
|
@ -593,7 +593,7 @@ const config = {
|
||||
axisFormat: '%Y-%m-%d'
|
||||
},
|
||||
/**
|
||||
* The object containing configurations specific for sequence diagrams
|
||||
* The object containing configurations specific for journey diagrams
|
||||
*/
|
||||
journey: {
|
||||
/**
|
||||
|
@ -113,8 +113,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'] |
|
||||
| thickness | Sets the thinkess of the edge. Can be \['normal', 'thick'\] |
|
||||
| pattern | Sets the pattern of the edge. Can be \['solid', 'dotted', 'dashed'\] |
|
||||
|
||||
|
||||
# Markers
|
||||
@ -122,7 +122,7 @@ Required edgeData for proper rendering:
|
||||
Define what markers that should be included in the diagram with the insert markers function. The function takes two arguments, first the element in which the markers should be included and a list of the markers that should be added.
|
||||
|
||||
Ex:
|
||||
insertMarkers(el, ['point', 'circle'])
|
||||
insertMarkers(el, \['point', 'circle'\])
|
||||
|
||||
The example above adds the markers point and cross. This means that edges with the arrowTypes arrow_cross, double_arrow_cross, arrow_point and double_arrow_cross will get the corresponding markers but arrowType arrow_cross will have no impact.
|
||||
|
||||
@ -136,4 +136,4 @@ Current markers:
|
||||
# Common functions used by the renderer to be implemented by the Db
|
||||
|
||||
getDirection
|
||||
getClasses
|
||||
getClasses
|
||||
|
@ -240,7 +240,7 @@ const barb = (elem, type) => {
|
||||
.attr('refY', 7)
|
||||
.attr('markerWidth', 20)
|
||||
.attr('markerHeight', 14)
|
||||
.attr('markerUnits', 0)
|
||||
.attr('markerUnits', 'strokeWidth')
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 19,7 L9,13 L14,7 L9,1 Z');
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { select } from 'd3';
|
||||
import { logger } from '../../logger';
|
||||
import { getConfig } from '../../config';
|
||||
import configApi, { getConfig } from '../../config';
|
||||
import common from '../common/common';
|
||||
import utils from '../../utils';
|
||||
import mermaidAPI from '../../mermaidAPI';
|
||||
|
||||
const MERMAID_DOM_ID_PREFIX = 'classid-';
|
||||
|
||||
@ -14,6 +15,10 @@ let classCounter = 0;
|
||||
|
||||
let funs = [];
|
||||
|
||||
export const parseDirective = function(statement, context, type) {
|
||||
mermaidAPI.parseDirective(this, statement, context, type);
|
||||
};
|
||||
|
||||
const splitClassNameAndType = function(id) {
|
||||
let genericType = '';
|
||||
let className = id;
|
||||
@ -288,6 +293,8 @@ const setupToolTips = function(element) {
|
||||
funs.push(setupToolTips);
|
||||
|
||||
export default {
|
||||
parseDirective,
|
||||
getConfig: () => configApi.getConfig().class,
|
||||
addClass,
|
||||
bindFunctions,
|
||||
clear,
|
||||
|
@ -242,69 +242,74 @@ describe('class diagram, ', function () {
|
||||
|
||||
it('should handle comments at the start', function () {
|
||||
const str =
|
||||
'%% Comment\n' +
|
||||
'classDiagram\n' +
|
||||
'class Class1 {\n' +
|
||||
'int : test\n' +
|
||||
'string : foo\n' +
|
||||
'test()\n' +
|
||||
'foo()\n' +
|
||||
'}';
|
||||
`%% Comment
|
||||
classDiagram
|
||||
class Class1 {
|
||||
int : test
|
||||
string : foo
|
||||
test()
|
||||
foo()
|
||||
}`;
|
||||
parser.parse(str);
|
||||
});
|
||||
|
||||
it('should handle comments at the end', function () {
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'class Class1 {\n' +
|
||||
'int : test\n' +
|
||||
'string : foo\n' +
|
||||
'test()\n' +
|
||||
'foo()\n' +
|
||||
'\n}' +
|
||||
'%% Comment\n';
|
||||
`classDiagram
|
||||
class Class1 {
|
||||
int : test
|
||||
string : foo
|
||||
test()
|
||||
foo()
|
||||
|
||||
}
|
||||
%% Comment
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
|
||||
it('should handle comments at the end no trailing newline', function () {
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'class Class1 {\n' +
|
||||
'int : test\n' +
|
||||
'string : foo\n' +
|
||||
'test()\n' +
|
||||
'foo()\n' +
|
||||
'}\n' +
|
||||
'%% Comment';
|
||||
`classDiagram
|
||||
class Class1 {
|
||||
int : test
|
||||
string : foo
|
||||
test()
|
||||
foo()
|
||||
}
|
||||
%% Comment`;
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
|
||||
it('should handle a comment with multiple line feeds', function () {
|
||||
const str =
|
||||
'classDiagram\n\n\n' +
|
||||
'%% Comment\n\n' +
|
||||
'class Class1 {\n' +
|
||||
'int : test\n' +
|
||||
'string : foo\n' +
|
||||
'test()\n' +
|
||||
'foo()\n' +
|
||||
'}';
|
||||
`classDiagram
|
||||
|
||||
|
||||
%% Comment
|
||||
|
||||
class Class1 {
|
||||
int : test
|
||||
string : foo
|
||||
test()
|
||||
foo()
|
||||
}`;
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
|
||||
it('should handle a comment with mermaid class diagram code in them', function () {
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'%% Comment Class01 <|-- Class02\n' +
|
||||
'class Class1 {\n' +
|
||||
'int : test\n' +
|
||||
'string : foo\n' +
|
||||
'test()\n' +
|
||||
'foo()\n' +
|
||||
'}';
|
||||
`classDiagram
|
||||
%% Comment Class01 <|-- Class02
|
||||
class Class1 {
|
||||
int : test
|
||||
string : foo
|
||||
test()
|
||||
foo()
|
||||
}`;
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
@ -640,7 +645,7 @@ describe('class diagram, ', function () {
|
||||
expect(testClass.cssClasses.length).toBe(1);
|
||||
expect(testClass.cssClasses[0]).toBe('clickable');
|
||||
});
|
||||
|
||||
|
||||
it('should associate link with tooltip', function () {
|
||||
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'link Class1 "google.com" "A tooltip"';
|
||||
parser.parse(str);
|
||||
|
@ -6,25 +6,31 @@
|
||||
|
||||
/* lexical grammar */
|
||||
%lex
|
||||
%x string generic struct
|
||||
%x string generic struct open_directive type_directive arg_directive
|
||||
|
||||
%%
|
||||
\%\%[^\n]*\n* /* do nothing */
|
||||
\n+ return 'NEWLINE';
|
||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
||||
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
||||
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
||||
\%\%(?!\{)*[^\n]*(\r?\n)+ /* skip comments */
|
||||
\%\%[^\n]*(\r?\n)* /* skip comments */
|
||||
(\r?\n)+ return 'NEWLINE';
|
||||
\s+ /* skip whitespace */
|
||||
"classDiagram-v2" return 'CLASS_DIAGRAM';
|
||||
"classDiagram" return 'CLASS_DIAGRAM';
|
||||
[\{] { this.begin("struct"); /*console.log('Starting struct');*/return 'STRUCT_START';}
|
||||
[{] { this.begin("struct"); /*console.log('Starting struct');*/ return 'STRUCT_START';}
|
||||
<struct><<EOF>> return "EOF_IN_STRUCT";
|
||||
<struct>[\{] return "OPEN_IN_STRUCT";
|
||||
<struct>\} { /*console.log('Ending struct');*/this.popState(); return 'STRUCT_STOP';}}
|
||||
<struct>[\n] /* nothing */
|
||||
<struct>[^\{\}\n]* { /*console.log('lex-member: ' + yytext);*/ return "MEMBER";}
|
||||
<struct>[{] return "OPEN_IN_STRUCT";
|
||||
<struct>[}] { /*console.log('Ending struct');*/this.popState(); return 'STRUCT_STOP';}}
|
||||
<struct>[\n] /* nothing */
|
||||
<struct>[^{}\n]* { /*console.log('lex-member: ' + yytext);*/ return "MEMBER";}
|
||||
|
||||
|
||||
|
||||
"class" return 'CLASS';
|
||||
//"click" return 'CLICK';
|
||||
//"click" return 'CLICK';
|
||||
"callback" return 'CALLBACK';
|
||||
"link" return 'LINK';
|
||||
"<<" return 'ANNOTATION_START';
|
||||
@ -126,11 +132,39 @@
|
||||
|
||||
%left '^'
|
||||
|
||||
%start mermaidDoc
|
||||
%start start
|
||||
|
||||
%% /* language grammar */
|
||||
|
||||
mermaidDoc: graphConfig;
|
||||
start
|
||||
: mermaidDoc
|
||||
| directive start
|
||||
;
|
||||
|
||||
mermaidDoc
|
||||
: graphConfig
|
||||
;
|
||||
|
||||
directive
|
||||
: openDirective typeDirective closeDirective NEWLINE
|
||||
| openDirective typeDirective ':' argDirective closeDirective NEWLINE
|
||||
;
|
||||
|
||||
openDirective
|
||||
: open_directive { yy.parseDirective('%%{', 'open_directive'); }
|
||||
;
|
||||
|
||||
typeDirective
|
||||
: type_directive { yy.parseDirective($1, 'type_directive'); }
|
||||
;
|
||||
|
||||
argDirective
|
||||
: arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); }
|
||||
;
|
||||
|
||||
closeDirective
|
||||
: close_directive { yy.parseDirective('}%%', 'close_directive', 'class'); }
|
||||
;
|
||||
|
||||
graphConfig
|
||||
: CLASS_DIAGRAM NEWLINE statements EOF
|
||||
@ -156,6 +190,7 @@ statement
|
||||
| methodStatement
|
||||
| annotationStatement
|
||||
| clickStatement
|
||||
| directive
|
||||
;
|
||||
|
||||
classStatement
|
||||
|
@ -35,13 +35,14 @@ export const sanitizeText = (text, config) => {
|
||||
if (
|
||||
config.flowchart &&
|
||||
(config.flowchart.htmlLabels === false || config.flowchart.htmlLabels === 'false')
|
||||
)
|
||||
) {
|
||||
htmlLabels = false;
|
||||
}
|
||||
|
||||
if (htmlLabels) {
|
||||
var level = config.securityLevel;
|
||||
const level = config.securityLevel;
|
||||
|
||||
if (level == 'antiscript') {
|
||||
if (level === 'antiscript') {
|
||||
txt = removeScript(txt);
|
||||
} else if (level !== 'loose') {
|
||||
// eslint-disable-line
|
||||
|
@ -2,6 +2,8 @@
|
||||
*
|
||||
*/
|
||||
import { logger } from '../../logger';
|
||||
import mermaidAPI from '../../mermaidAPI';
|
||||
import configApi from '../../config';
|
||||
|
||||
let entities = {};
|
||||
let relationships = [];
|
||||
@ -19,6 +21,10 @@ const Identification = {
|
||||
IDENTIFYING: 'IDENTIFYING'
|
||||
};
|
||||
|
||||
export const parseDirective = function(statement, context, type) {
|
||||
mermaidAPI.parseDirective(this, statement, context, type);
|
||||
};
|
||||
|
||||
const addEntity = function(name) {
|
||||
if (typeof entities[name] === 'undefined') {
|
||||
entities[name] = name;
|
||||
@ -67,6 +73,8 @@ const clear = function() {
|
||||
export default {
|
||||
Cardinality,
|
||||
Identification,
|
||||
parseDirective,
|
||||
getConfig: () => configApi.getConfig().er,
|
||||
addEntity,
|
||||
getEntities,
|
||||
addRelationship,
|
||||
|
@ -1,8 +1,17 @@
|
||||
%lex
|
||||
|
||||
%options case-insensitive
|
||||
%x open_directive type_directive arg_directive
|
||||
|
||||
%%
|
||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
||||
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
||||
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
||||
\%%(?!\{)[^\n]* /* skip comments */
|
||||
[^\}]\%\%[^\n]* /* skip comments */
|
||||
[\n]+ return 'NEWLINE';
|
||||
\s+ /* skip whitespace */
|
||||
[\s]+ return 'SPACE';
|
||||
\"[^"]*\" return 'WORD';
|
||||
@ -29,21 +38,36 @@ o\{ return 'ZERO_OR_MORE';
|
||||
|
||||
start
|
||||
: 'ER_DIAGRAM' document 'EOF' { /*console.log('finished parsing');*/ }
|
||||
| directive start
|
||||
;
|
||||
|
||||
document
|
||||
: /* empty */
|
||||
| document statement
|
||||
;
|
||||
: /* empty */ { $$ = [] }
|
||||
| document line {$1.push($2);$$ = $1}
|
||||
;
|
||||
|
||||
line
|
||||
: SPACE statement { $$ = $2 }
|
||||
| statement { $$ = $1 }
|
||||
| NEWLINE { $$=[];}
|
||||
| EOF { $$=[];}
|
||||
;
|
||||
|
||||
directive
|
||||
: openDirective typeDirective closeDirective 'NEWLINE'
|
||||
| openDirective typeDirective ':' argDirective closeDirective 'NEWLINE'
|
||||
;
|
||||
|
||||
statement
|
||||
: entityName relSpec entityName ':' role
|
||||
: directive
|
||||
| entityName relSpec entityName ':' role
|
||||
{
|
||||
yy.addEntity($1);
|
||||
yy.addEntity($3);
|
||||
yy.addEntity($1);
|
||||
yy.addEntity($3);
|
||||
yy.addRelationship($1, $5, $3, $2);
|
||||
/*console.log($1 + $2 + $3 + ':' + $5);*/
|
||||
};
|
||||
}
|
||||
;
|
||||
|
||||
entityName
|
||||
: 'ALPHANUM' { $$ = $1; /*console.log('Entity: ' + $1);*/ }
|
||||
@ -62,7 +86,7 @@ cardinality
|
||||
| 'ZERO_OR_MORE' { $$ = yy.Cardinality.ZERO_OR_MORE; }
|
||||
| 'ONE_OR_MORE' { $$ = yy.Cardinality.ONE_OR_MORE; }
|
||||
| 'ONLY_ONE' { $$ = yy.Cardinality.ONLY_ONE; }
|
||||
;
|
||||
;
|
||||
|
||||
relType
|
||||
: 'NON_IDENTIFYING' { $$ = yy.Identification.NON_IDENTIFYING; }
|
||||
@ -73,4 +97,21 @@ role
|
||||
: 'WORD' { $$ = $1.replace(/"/g, ''); }
|
||||
| 'ALPHANUM' { $$ = $1; }
|
||||
;
|
||||
|
||||
openDirective
|
||||
: open_directive { yy.parseDirective('%%{', 'open_directive'); }
|
||||
;
|
||||
|
||||
typeDirective
|
||||
: type_directive { yy.parseDirective($1, 'type_directive'); }
|
||||
;
|
||||
|
||||
argDirective
|
||||
: arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); }
|
||||
;
|
||||
|
||||
closeDirective
|
||||
: close_directive { yy.parseDirective('}%%', 'close_directive', 'er'); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { select } from 'd3';
|
||||
import { logger } from '../../logger'; // eslint-disable-line
|
||||
import utils from '../../utils';
|
||||
import { getConfig } from '../../config';
|
||||
import configApi, { getConfig } from '../../config';
|
||||
import common from '../common/common';
|
||||
import mermaidAPI from '../../mermaidAPI';
|
||||
|
||||
// const MERMAID_DOM_ID_PREFIX = 'mermaid-dom-id-';
|
||||
const MERMAID_DOM_ID_PREFIX = '';
|
||||
@ -20,6 +20,10 @@ let direction;
|
||||
// Functions to be run after graph rendering
|
||||
let funs = [];
|
||||
|
||||
export const parseDirective = function(statement, context, type) {
|
||||
mermaidAPI.parseDirective(this, statement, context, type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Function called by parser when a node definition has been found
|
||||
* @param id
|
||||
@ -618,6 +622,8 @@ const destructLink = (_str, _startStr) => {
|
||||
};
|
||||
|
||||
export default {
|
||||
parseDirective,
|
||||
getConfig: () => configApi.getConfig().flowchart,
|
||||
addVertex,
|
||||
addLink,
|
||||
updateLinkInterpolate,
|
||||
|
@ -9,8 +9,19 @@
|
||||
%x string
|
||||
%x dir
|
||||
%x vertex
|
||||
%x open_directive
|
||||
%x type_directive
|
||||
%x arg_directive
|
||||
%x close_directive
|
||||
|
||||
%%
|
||||
\%\%[^\n]*\n* /* do nothing */
|
||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
||||
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
||||
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
||||
\%\%(?!\{)[^\n]* /* skip comments */
|
||||
[^\}]\%\%[^\n]* /* skip comments */
|
||||
["] this.begin("string");
|
||||
<string>["] this.popState();
|
||||
<string>[^"]* return "STR";
|
||||
@ -25,10 +36,13 @@
|
||||
"flowchart" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';}
|
||||
"subgraph" return 'subgraph';
|
||||
"end"\b\s* return 'end';
|
||||
|
||||
"_self" return 'LINK_TARGET';
|
||||
"_blank" return 'LINK_TARGET';
|
||||
"_parent" return 'LINK_TARGET';
|
||||
"_top" return 'LINK_TARGET';
|
||||
|
||||
<dir>(\r?\n)*\s*\n { this.popState(); return 'NODIR'; }
|
||||
<dir>\s*"LR" { this.popState(); return 'DIR'; }
|
||||
<dir>\s*"RL" { this.popState(); return 'DIR'; }
|
||||
<dir>\s*"TB" { this.popState(); return 'DIR'; }
|
||||
@ -183,7 +197,7 @@
|
||||
"{" return 'DIAMOND_START'
|
||||
"}" return 'DIAMOND_STOP'
|
||||
"\"" return 'QUOTE';
|
||||
(\r|\n|\r\n)+ return 'NEWLINE';
|
||||
(\r?\n)+ return 'NEWLINE';
|
||||
\s return 'SPACE';
|
||||
<<EOF>> return 'EOF';
|
||||
|
||||
@ -193,11 +207,39 @@
|
||||
|
||||
%left '^'
|
||||
|
||||
%start mermaidDoc
|
||||
%start start
|
||||
|
||||
%% /* language grammar */
|
||||
|
||||
mermaidDoc: graphConfig document;
|
||||
start
|
||||
: mermaidDoc
|
||||
| directive start
|
||||
;
|
||||
|
||||
directive
|
||||
: openDirective typeDirective closeDirective separator
|
||||
| openDirective typeDirective ':' argDirective closeDirective separator
|
||||
;
|
||||
|
||||
openDirective
|
||||
: open_directive { yy.parseDirective('%%{', 'open_directive'); }
|
||||
;
|
||||
|
||||
typeDirective
|
||||
: type_directive { yy.parseDirective($1, 'type_directive'); }
|
||||
;
|
||||
|
||||
argDirective
|
||||
: arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); }
|
||||
;
|
||||
|
||||
closeDirective
|
||||
: close_directive { yy.parseDirective('}%%', 'close_directive', 'flowchart'); }
|
||||
;
|
||||
|
||||
mermaidDoc
|
||||
: graphConfig document
|
||||
;
|
||||
|
||||
document
|
||||
: /* empty */
|
||||
@ -222,6 +264,8 @@ line
|
||||
graphConfig
|
||||
: SPACE graphConfig
|
||||
| NEWLINE graphConfig
|
||||
| GRAPH NODIR
|
||||
{ yy.setDirection('TB');$$ = 'TB';}
|
||||
| GRAPH DIR FirstStmtSeperator
|
||||
{ yy.setDirection($2);$$ = $2;}
|
||||
// | GRAPH SPACE TAGEND FirstStmtSeperator
|
||||
|
@ -1,8 +1,9 @@
|
||||
import moment from 'moment-mini';
|
||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||
import { logger } from '../../logger';
|
||||
import { getConfig } from '../../config';
|
||||
import configApi, { getConfig } from '../../config';
|
||||
import utils from '../../utils';
|
||||
import mermaidAPI from '../../mermaidAPI';
|
||||
|
||||
let dateFormat = '';
|
||||
let axisFormat = '';
|
||||
@ -19,6 +20,10 @@ let inclusiveEndDates = false;
|
||||
// The serial order of the task in the script
|
||||
let lastOrder = 0;
|
||||
|
||||
export const parseDirective = function(statement, context, type) {
|
||||
mermaidAPI.parseDirective(this, statement, context, type);
|
||||
};
|
||||
|
||||
export const clear = function() {
|
||||
sections = [];
|
||||
tasks = [];
|
||||
@ -582,6 +587,8 @@ export const bindFunctions = function(element) {
|
||||
};
|
||||
|
||||
export default {
|
||||
parseDirective,
|
||||
getConfig: () => configApi.getConfig().gantt,
|
||||
clear,
|
||||
setDateFormat,
|
||||
getDateFormat,
|
||||
|
@ -11,7 +11,19 @@
|
||||
%x href
|
||||
%x callbackname
|
||||
%x callbackargs
|
||||
%x open_directive
|
||||
%x type_directive
|
||||
%x arg_directive
|
||||
%x close_directive
|
||||
%%
|
||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
||||
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
||||
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
||||
\%\%(?!\{)*[^\n]* /* skip comments */
|
||||
[^\}]\%\%*[^\n]* /* skip comments */
|
||||
\%\%*[^\n]*[\n]* /* do nothing */
|
||||
|
||||
[\n]+ return 'NL';
|
||||
\s+ /* skip whitespace */
|
||||
@ -77,7 +89,8 @@ that id.
|
||||
%% /* language grammar */
|
||||
|
||||
start
|
||||
: gantt document 'EOF' { return $2; }
|
||||
: directive start
|
||||
| gantt document 'EOF' { return $2; }
|
||||
;
|
||||
|
||||
document
|
||||
@ -102,8 +115,14 @@ statement
|
||||
| section {yy.addSection($1.substr(8));$$=$1.substr(8);}
|
||||
| clickStatement
|
||||
| taskTxt taskData {yy.addTask($1,$2);$$='task';}
|
||||
| directive
|
||||
;
|
||||
|
||||
directive
|
||||
: openDirective typeDirective closeDirective 'NL'
|
||||
| openDirective typeDirective ':' argDirective closeDirective 'NL'
|
||||
;
|
||||
|
||||
/*
|
||||
click allows any combination of href and call.
|
||||
*/
|
||||
@ -131,4 +150,22 @@ clickStatementDebug
|
||||
| click href callbackname callbackargs {$$=$1 + ' ' + $2 + ' ' + $3 + ' ' + $4;}
|
||||
|
||||
| click href {$$=$1 + ' ' + $2;}
|
||||
;%%
|
||||
;
|
||||
|
||||
openDirective
|
||||
: open_directive { yy.parseDirective('%%{', 'open_directive'); }
|
||||
;
|
||||
|
||||
typeDirective
|
||||
: type_directive { yy.parseDirective($1, 'type_directive'); }
|
||||
;
|
||||
|
||||
argDirective
|
||||
: arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); }
|
||||
;
|
||||
|
||||
closeDirective
|
||||
: close_directive { yy.parseDirective('}%%', 'close_directive', 'gantt'); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
@ -4,26 +4,34 @@
|
||||
* MIT license.
|
||||
*/
|
||||
%lex
|
||||
%x string
|
||||
%options case-insensitive
|
||||
|
||||
%{
|
||||
// Pre-lexer code can go here
|
||||
%}
|
||||
%x string
|
||||
%x title
|
||||
%x open_directive
|
||||
%x type_directive
|
||||
%x arg_directive
|
||||
%x close_directive
|
||||
|
||||
%%
|
||||
\%\%[^\n]* /* do nothing */
|
||||
\s+ /* skip whitespace */
|
||||
"pie" return 'pie' ;
|
||||
[\s\n\r]+ return 'NL' ;
|
||||
[\s]+ return 'space';
|
||||
"title"\s[^#\n;]+ return 'title';
|
||||
["] {/*console.log('begin str');*/this.begin("string");}
|
||||
<string>["] {/*console.log('pop-state');*/this.popState();}
|
||||
<string>[^"]* {/*console.log('ending string')*/return "STR";}
|
||||
":"[\s]*[\d]+(?:\.[\d]+)? return "VALUE";
|
||||
|
||||
<<EOF>> return 'EOF' ;
|
||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
||||
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
||||
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
||||
\%\%(?!\{)[^\n]* /* skip comments */
|
||||
[^\}]\%\%[^\n]* /* skip comments */{ console.log('Crap after close'); }
|
||||
[\n\r]+ return 'NEWLINE';
|
||||
\%\%[^\n]* /* do nothing */
|
||||
[\s]+ /* ignore */
|
||||
title { this.begin("title");return 'title'; }
|
||||
<title>(?!\n|;|#)*[^\n]* { this.popState(); return "title_value"; }
|
||||
["] { this.begin("string"); }
|
||||
<string>["] { this.popState(); }
|
||||
<string>[^"]* { return "txt"; }
|
||||
"pie" return 'PIE';
|
||||
":"[\s]*[\d]+(?:\.[\d]+)? return "value";
|
||||
<<EOF>> return 'EOF';
|
||||
|
||||
|
||||
/lex
|
||||
@ -33,8 +41,9 @@
|
||||
%% /* language grammar */
|
||||
|
||||
start
|
||||
// %{ : info document 'EOF' { return yy; } }
|
||||
: pie document 'EOF'
|
||||
: eol start
|
||||
| directive start
|
||||
| PIE document
|
||||
;
|
||||
|
||||
document
|
||||
@ -43,15 +52,41 @@ document
|
||||
;
|
||||
|
||||
line
|
||||
: statement { }
|
||||
| 'NL'
|
||||
: statement eol { $$ = $1 }
|
||||
;
|
||||
|
||||
statement
|
||||
: STR VALUE {
|
||||
/*console.log('str:'+$1+' value: '+$2)*/
|
||||
yy.addSection($1,yy.cleanupValue($2)); }
|
||||
| title {yy.setTitle($1.substr(6));$$=$1.substr(6);}
|
||||
:
|
||||
| txt value { yy.addSection($1,yy.cleanupValue($2)); }
|
||||
| title title_value { $$=$2.trim();yy.setTitle($$); }
|
||||
| directive
|
||||
;
|
||||
|
||||
directive
|
||||
: openDirective typeDirective closeDirective
|
||||
| openDirective typeDirective ':' argDirective closeDirective
|
||||
;
|
||||
|
||||
eol
|
||||
: NEWLINE
|
||||
| ';'
|
||||
| EOF
|
||||
;
|
||||
|
||||
openDirective
|
||||
: open_directive { yy.parseDirective('%%{', 'open_directive'); }
|
||||
;
|
||||
|
||||
typeDirective
|
||||
: type_directive { yy.parseDirective($1, 'type_directive'); }
|
||||
;
|
||||
|
||||
argDirective
|
||||
: arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); }
|
||||
;
|
||||
|
||||
closeDirective
|
||||
: close_directive { yy.parseDirective('}%%', 'close_directive', 'pie'); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
@ -12,16 +12,67 @@ describe('when parsing pie', function() {
|
||||
pie.parser.yy = pieDb;
|
||||
pie.parser.yy.clear();
|
||||
});
|
||||
it('should handle very simple pie', function() {
|
||||
const res = pie.parser.parse(`pie
|
||||
"ash" : 100
|
||||
`);
|
||||
const sections = pieDb.getSections();
|
||||
console.log('sections: ', sections);
|
||||
const section1 = sections['ash'];
|
||||
expect(section1).toBe(100);
|
||||
});
|
||||
it('should handle simple pie', function() {
|
||||
const res = pie.parser.parse('pie \n"ash" : 60\n"bat" : 40\n');
|
||||
const res = pie.parser.parse(`pie
|
||||
"ash" : 60
|
||||
"bat" : 40
|
||||
`);
|
||||
const sections = pieDb.getSections();
|
||||
console.log('sections: ', sections);
|
||||
const section1 = sections['ash'];
|
||||
expect(section1).toBe(60);
|
||||
});
|
||||
it('should handle simple pie with comments', function() {
|
||||
const res = pie.parser.parse(`pie
|
||||
%% comments
|
||||
"ash" : 60
|
||||
"bat" : 40
|
||||
`);
|
||||
const sections = pieDb.getSections();
|
||||
console.log('sections: ', sections);
|
||||
const section1 = sections['ash'];
|
||||
expect(section1).toBe(60);
|
||||
});
|
||||
|
||||
it('should handle simple pie with a directive', function() {
|
||||
const res = pie.parser.parse(`%%{init: {'logLevel':0}}%%
|
||||
pie
|
||||
"ash" : 60
|
||||
"bat" : 40
|
||||
`);
|
||||
const sections = pieDb.getSections();
|
||||
console.log('sections: ', sections);
|
||||
const section1 = sections['ash'];
|
||||
expect(section1).toBe(60);
|
||||
});
|
||||
|
||||
it('should handle simple pie with a title', function() {
|
||||
const res = pie.parser.parse(`pie title a 60/40 pie
|
||||
"ash" : 60
|
||||
"bat" : 40
|
||||
`);
|
||||
const sections = pieDb.getSections();
|
||||
const title = pieDb.getTitle();
|
||||
console.log('sections: ', sections);
|
||||
const section1 = sections['ash'];
|
||||
expect(section1).toBe(60);
|
||||
expect(title).toBe('a 60/40 pie');
|
||||
});
|
||||
|
||||
it('should handle simple pie with positive decimal', function() {
|
||||
const res = pie.parser.parse('pie \n"ash" : 60.67\n"bat" : 40\n');
|
||||
const res = pie.parser.parse(`pie
|
||||
"ash" : 60.67
|
||||
"bat" : 40
|
||||
`);
|
||||
const sections = pieDb.getSections();
|
||||
console.log('sections: ', sections);
|
||||
const section1 = sections['ash'];
|
||||
@ -30,7 +81,10 @@ describe('when parsing pie', function() {
|
||||
|
||||
it('should handle simple pie with negative decimal', function() {
|
||||
expect(() => {
|
||||
pie.parser.parse('pie \n"ash" : 60.67\n"bat" : 40..12\n');
|
||||
pie.parser.parse(`pie
|
||||
"ash" : 60.67
|
||||
"bat" : 40..12
|
||||
`);
|
||||
}).toThrowError();
|
||||
});
|
||||
});
|
||||
|
@ -2,10 +2,16 @@
|
||||
*
|
||||
*/
|
||||
import { logger } from '../../logger';
|
||||
import mermaidAPI from '../../mermaidAPI';
|
||||
import configApi from '../../config';
|
||||
|
||||
let sections = {};
|
||||
let title = '';
|
||||
|
||||
export const parseDirective = function(statement, context, type) {
|
||||
mermaidAPI.parseDirective(this, statement, context, type);
|
||||
};
|
||||
|
||||
const addSection = function(id, value) {
|
||||
if (typeof sections[id] === 'undefined') {
|
||||
sections[id] = value;
|
||||
@ -39,6 +45,8 @@ const clear = function() {
|
||||
// }
|
||||
|
||||
export default {
|
||||
parseDirective,
|
||||
getConfig: () => configApi.getConfig().pie,
|
||||
addSection,
|
||||
getSections,
|
||||
cleanupValue,
|
||||
|
@ -153,7 +153,7 @@ export const draw = (txt, id) => {
|
||||
});
|
||||
} catch (e) {
|
||||
logger.error('Error while rendering info diagram');
|
||||
logger.error(e.message);
|
||||
logger.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -13,34 +13,29 @@
|
||||
%options case-insensitive
|
||||
|
||||
// Special states for recognizing aliases
|
||||
%x ID
|
||||
%x ALIAS
|
||||
// A special state for grabbing text up to the first comment/newline
|
||||
%x ID ALIAS LINE
|
||||
|
||||
// Directive states
|
||||
%x OPEN_DIRECTIVE
|
||||
%x TYPE_DIRECTIVE
|
||||
%x ARG_DIRECTIVE
|
||||
|
||||
// A special state for grabbing text up to the first comment/newline
|
||||
%x LINE
|
||||
%x open_directive type_directive arg_directive
|
||||
|
||||
%%
|
||||
|
||||
\%\%\{ { this.begin('OPEN_DIRECTIVE'); return 'open_directive'; }
|
||||
<OPEN_DIRECTIVE>((?:(?!\}\%\%)[^:.])*) { this.begin('TYPE_DIRECTIVE'); return 'type_directive'; }
|
||||
<TYPE_DIRECTIVE>":" { this.popState(); this.begin('ARG_DIRECTIVE'); return ':'; }
|
||||
<TYPE_DIRECTIVE,ARG_DIRECTIVE>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
||||
<ARG_DIRECTIVE>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
||||
[\n]+ return 'NL';
|
||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
||||
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
||||
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
||||
[\n]+ return 'NEWLINE';
|
||||
\s+ /* skip all whitespace */
|
||||
<ID,ALIAS,LINE>((?!\n)\s)+ /* skip same-line whitespace */
|
||||
<INITIAL,ID,ALIAS,LINE,ARG_DIRECTIVE,TYPE_DIRECTIVE,OPEN_DIRECTIVE>\#[^\n]* /* skip comments */
|
||||
<INITIAL,ID,ALIAS,LINE,arg_directive,type_directive,open_directive>\#[^\n]* /* skip comments */
|
||||
\%%(?!\{)[^\n]* /* skip comments */
|
||||
[^\}]\%\%[^\n]* /* skip comments */
|
||||
"participant" { this.begin('ID'); return 'participant'; }
|
||||
<ID>[^\->:\n,;]+?(?=((?!\n)\s)+"as"(?!\n)\s|[#\n;]|$) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; }
|
||||
<ALIAS>"as" { this.popState(); this.popState(); this.begin('LINE'); return 'AS'; }
|
||||
<ALIAS>(?:) { this.popState(); this.popState(); return 'NL'; }
|
||||
<ALIAS>(?:) { this.popState(); this.popState(); return 'NEWLINE'; }
|
||||
"loop" { this.begin('LINE'); return 'loop'; }
|
||||
"rect" { this.begin('LINE'); return 'rect'; }
|
||||
"opt" { this.begin('LINE'); return 'opt'; }
|
||||
@ -58,10 +53,10 @@
|
||||
"deactivate" { this.begin('ID'); return 'deactivate'; }
|
||||
"title" return 'title';
|
||||
"sequenceDiagram" return 'SD';
|
||||
"autonumber" return 'autonumber';
|
||||
"autonumber" return 'autonumber';
|
||||
"," return ',';
|
||||
";" return 'NL';
|
||||
[^\+\->:\n,;]+ { yytext = yytext.trim(); return 'ACTOR'; }
|
||||
";" return 'NEWLINE';
|
||||
[^\+\->:\n,;]+((?!(\-x|\-\-x))[\-]*[^\+\->:\n,;]+)* { yytext = yytext.trim(); return 'ACTOR'; }
|
||||
"->>" return 'SOLID_ARROW';
|
||||
"-->>" return 'DOTTED_ARROW';
|
||||
"->" return 'SOLID_OPEN_ARROW';
|
||||
@ -71,7 +66,7 @@
|
||||
":"(?:(?:no)?wrap:)?[^#\n;]+ return 'TXT';
|
||||
"+" return '+';
|
||||
"-" return '-';
|
||||
<<EOF>> return 'NL';
|
||||
<<EOF>> return 'NEWLINE';
|
||||
. return 'INVALID';
|
||||
|
||||
/lex
|
||||
@ -84,7 +79,7 @@
|
||||
|
||||
start
|
||||
: SPACE start
|
||||
| NL start
|
||||
| NEWLINE start
|
||||
| directive start
|
||||
| SD document { yy.apply($2);return $2; }
|
||||
;
|
||||
@ -97,23 +92,23 @@ document
|
||||
line
|
||||
: SPACE statement { $$ = $2 }
|
||||
| statement { $$ = $1 }
|
||||
| NL { $$=[]; }
|
||||
| NEWLINE { $$=[]; }
|
||||
;
|
||||
|
||||
directive
|
||||
: openDirective typeDirective closeDirective 'NL'
|
||||
| openDirective typeDirective ':' argDirective closeDirective 'NL'
|
||||
: openDirective typeDirective closeDirective 'NEWLINE'
|
||||
| openDirective typeDirective ':' argDirective closeDirective 'NEWLINE'
|
||||
;
|
||||
|
||||
statement
|
||||
: 'participant' actor 'AS' restOfLine 'NL' {$2.description=yy.parseMessage($4); $$=$2;}
|
||||
| 'participant' actor 'NL' {$$=$2;}
|
||||
| signal 'NL'
|
||||
: 'participant' actor 'AS' restOfLine 'NEWLINE' {$2.description=yy.parseMessage($4); $$=$2;}
|
||||
| 'participant' actor 'NEWLINE' {$$=$2;}
|
||||
| signal 'NEWLINE'
|
||||
| autonumber {yy.enableSequenceNumbers()}
|
||||
| 'activate' actor 'NL' {$$={type: 'activeStart', signalType: yy.LINETYPE.ACTIVE_START, actor: $2};}
|
||||
| 'deactivate' actor 'NL' {$$={type: 'activeEnd', signalType: yy.LINETYPE.ACTIVE_END, actor: $2};}
|
||||
| note_statement 'NL'
|
||||
| title text2 'NL' {$$=[{type:'setTitle', text:$2}]}
|
||||
| 'activate' actor 'NEWLINE' {$$={type: 'activeStart', signalType: yy.LINETYPE.ACTIVE_START, actor: $2};}
|
||||
| 'deactivate' actor 'NEWLINE' {$$={type: 'activeEnd', signalType: yy.LINETYPE.ACTIVE_END, actor: $2};}
|
||||
| note_statement 'NEWLINE'
|
||||
| title text2 'NEWLINE' {$$=[{type:'setTitle', text:$2}]}
|
||||
| 'loop' restOfLine document end
|
||||
{
|
||||
$3.unshift({type: 'loopStart', loopText:yy.parseMessage($2), signalType: yy.LINETYPE.LOOP_START});
|
||||
|
@ -13,7 +13,7 @@ let sequenceNumbersEnabled = false;
|
||||
let wrapEnabled = false;
|
||||
|
||||
export const parseDirective = function(statement, context, type) {
|
||||
mermaidAPI.parseDirective(statement, context, type);
|
||||
mermaidAPI.parseDirective(this, statement, context, type);
|
||||
};
|
||||
|
||||
export const addActor = function(id, name, description) {
|
||||
@ -140,12 +140,12 @@ export const parseMessage = function(str) {
|
||||
text: _str.replace(/^[:]?(?:no)?wrap:/, '').trim(),
|
||||
wrap:
|
||||
_str.match(/^[:]?(?:no)?wrap:/) === null
|
||||
? common.hasBreaks(_str) || autoWrap()
|
||||
? common.hasBreaks(_str) || undefined
|
||||
: _str.match(/^[:]?wrap:/) !== null
|
||||
? true
|
||||
: _str.match(/^[:]?nowrap:/) !== null
|
||||
? false
|
||||
: autoWrap()
|
||||
: undefined
|
||||
};
|
||||
logger.debug('parseMessage:', message);
|
||||
return message;
|
||||
|
@ -93,6 +93,23 @@ Bob-->Alice: I am good thanks!`;
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[1].from).toBe('Bob');
|
||||
});
|
||||
it('it should handle dashes in actor names', function() {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice-in-Wonderland->Bob:Hello Bob, how are - you?
|
||||
Bob-->Alice-in-Wonderland:I am good thanks!`;
|
||||
|
||||
mermaidAPI.parse(str);
|
||||
const actors = parser.yy.getActors();
|
||||
expect(actors["Alice-in-Wonderland"].description).toBe('Alice-in-Wonderland');
|
||||
actors.Bob.description = 'Bob';
|
||||
|
||||
const messages = parser.yy.getMessages();
|
||||
|
||||
expect(messages.length).toBe(2);
|
||||
expect(messages[0].from).toBe('Alice-in-Wonderland');
|
||||
expect(messages[1].from).toBe('Bob');
|
||||
});
|
||||
it('it should alias participants', function() {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
@ -932,7 +949,6 @@ describe('when rendering a sequenceDiagram', function() {
|
||||
parser.yy = sequenceDb;
|
||||
parser.yy.clear();
|
||||
conf = parser.yy.getConfig();
|
||||
renderer.bounds.init();
|
||||
});
|
||||
['tspan', 'fo', 'old', undefined].forEach(function(textPlacement) {
|
||||
it(`
|
||||
|
@ -26,16 +26,27 @@
|
||||
%x FLOATING_NOTE
|
||||
%x FLOATING_NOTE_ID
|
||||
%x struct
|
||||
%x open_directive
|
||||
%x type_directive
|
||||
%x arg_directive
|
||||
%x close_directive
|
||||
|
||||
// A special state for grabbing text up to the first comment/newline
|
||||
%x LINE
|
||||
|
||||
%%
|
||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
||||
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
||||
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
||||
\%\%(?!\{)[^\n]* /* skip comments */
|
||||
[^\}]\%\%[^\n]* /* skip comments */{ console.log('Crap after close'); }
|
||||
|
||||
[\n]+ return 'NL';
|
||||
\s+ /* skip all whitespace */
|
||||
<ID,STATE,struct,LINE>((?!\n)\s)+ /* skip same-line whitespace */
|
||||
<INITIAL,ID,STATE,struct,LINE>\#[^\n]* /* skip comments */
|
||||
[\s]+ /* skip all whitespace */
|
||||
<ID,STATE,struct,LINE,open_directive,type_directive,arg_directive,close_directive>((?!\n)\s)+ /* skip same-line whitespace */
|
||||
<INITIAL,ID,STATE,struct,LINE,open_directive,type_directive,arg_directive,close_directive>\#[^\n]* /* skip comments */
|
||||
\%%[^\n]* /* skip comments */
|
||||
|
||||
"scale"\s+ { this.pushState('SCALE'); /* console.log('Got scale', yytext);*/ return 'scale'; }
|
||||
@ -93,6 +104,7 @@
|
||||
start
|
||||
: SPACE start
|
||||
| NL start
|
||||
| directive start
|
||||
| SD document { /*console.warn('Root document', $2);*/ yy.setRootDoc($2);return $2; }
|
||||
;
|
||||
|
||||
@ -165,6 +177,17 @@ statement
|
||||
$$={ stmt: 'state', id: $3.trim(), note:{position: $2.trim(), text: $4.trim()}};
|
||||
}
|
||||
| note NOTE_TEXT AS ID
|
||||
| directive
|
||||
;
|
||||
|
||||
directive
|
||||
: openDirective typeDirective closeDirective
|
||||
| openDirective typeDirective ':' argDirective closeDirective
|
||||
;
|
||||
|
||||
eol
|
||||
: NL
|
||||
| ';'
|
||||
;
|
||||
|
||||
idStatement
|
||||
@ -177,4 +200,20 @@ notePosition
|
||||
| right_of
|
||||
;
|
||||
|
||||
openDirective
|
||||
: open_directive { yy.parseDirective('%%{', 'open_directive'); }
|
||||
;
|
||||
|
||||
typeDirective
|
||||
: type_directive { yy.parseDirective($1, 'type_directive'); }
|
||||
;
|
||||
|
||||
argDirective
|
||||
: arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); }
|
||||
;
|
||||
|
||||
closeDirective
|
||||
: close_directive { yy.parseDirective('}%%', 'close_directive', 'state'); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
@ -1,9 +1,16 @@
|
||||
import { logger } from '../../logger';
|
||||
import { generateId } from '../../utils';
|
||||
import mermaidAPI from '../../mermaidAPI';
|
||||
import configApi from '../../config';
|
||||
|
||||
const clone = o => JSON.parse(JSON.stringify(o));
|
||||
|
||||
let rootDoc = [];
|
||||
|
||||
export const parseDirective = function(statement, context, type) {
|
||||
mermaidAPI.parseDirective(this, statement, context, type);
|
||||
};
|
||||
|
||||
const setRootDoc = o => {
|
||||
logger.info('Setting root doc', o);
|
||||
// rootDoc = { id: 'root', doc: o };
|
||||
@ -235,6 +242,8 @@ export const relationType = {
|
||||
const trimColon = str => (str && str[0] === ':' ? str.substr(1).trim() : str.trim());
|
||||
|
||||
export default {
|
||||
parseDirective,
|
||||
getConfig: () => configApi.getConfig().state,
|
||||
addState,
|
||||
clear,
|
||||
getState,
|
||||
|
@ -26,6 +26,16 @@ describe('state diagram, ', function() {
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
it('simple with directive', function() {
|
||||
const str = `%%{init: {'logLevel': 0 }}%%
|
||||
stateDiagram\n
|
||||
State1 : this is another string
|
||||
[*] --> State1
|
||||
State1 --> [*]
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
it('should handle relation definitions', function() {
|
||||
const str = `stateDiagram\n
|
||||
[*] --> State1
|
||||
@ -337,6 +347,9 @@ describe('state diagram, ', function() {
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
});
|
||||
describe('when parsing an ignored info graph it', function() {
|
||||
|
||||
xit('should handle if statements', function() {
|
||||
const str = `stateDiagram\n
|
||||
[*] --> "Order Submitted"
|
||||
|
@ -211,11 +211,11 @@ export const draw = function(text, id) {
|
||||
parser.yy = stateDb;
|
||||
|
||||
// Parse the graph definition
|
||||
try {
|
||||
parser.parse(text);
|
||||
} catch (err) {
|
||||
logger.debug('Parsing failed');
|
||||
}
|
||||
// try {
|
||||
parser.parse(text);
|
||||
// } catch (err) {
|
||||
// logger.error('Parsing failed', err);
|
||||
// }
|
||||
|
||||
// Fetch the default direction, use TD if none was found
|
||||
let dir = stateDb.getDirection();
|
||||
|
@ -1,3 +1,6 @@
|
||||
import mermaidAPI from '../../mermaidAPI';
|
||||
import configApi from '../../config';
|
||||
|
||||
let title = '';
|
||||
let currentSection = '';
|
||||
|
||||
@ -5,6 +8,10 @@ const sections = [];
|
||||
const tasks = [];
|
||||
const rawTasks = [];
|
||||
|
||||
export const parseDirective = function(statement, context, type) {
|
||||
mermaidAPI.parseDirective(this, statement, context, type);
|
||||
};
|
||||
|
||||
export const clear = function() {
|
||||
sections.length = 0;
|
||||
tasks.length = 0;
|
||||
@ -111,6 +118,8 @@ const getActors = function() {
|
||||
};
|
||||
|
||||
export default {
|
||||
parseDirective,
|
||||
getConfig: () => configApi.getConfig().journey,
|
||||
clear,
|
||||
setTitle,
|
||||
getTitle,
|
||||
|
@ -70,7 +70,8 @@ function drawActorLegend(diagram) {
|
||||
x: 40,
|
||||
y: yPos + 7,
|
||||
fill: '#666',
|
||||
text: person
|
||||
text: person,
|
||||
textMargin: conf.boxTextMargin | 5
|
||||
};
|
||||
svgDraw.drawText(diagram, labelData);
|
||||
|
||||
|
@ -5,12 +5,23 @@
|
||||
*/
|
||||
%lex
|
||||
%options case-insensitive
|
||||
|
||||
// Directive states
|
||||
%x open_directive type_directive arg_directive
|
||||
|
||||
|
||||
%%
|
||||
|
||||
[\n]+ return 'NL';
|
||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
||||
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
||||
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
||||
\%%(?!\{)[^\n]* /* skip comments */
|
||||
[^\}]\%\%[^\n]* /* skip comments */
|
||||
[\n]+ return 'NEWLINE';
|
||||
\s+ /* skip whitespace */
|
||||
\#[^\n]* /* skip comments */
|
||||
\%%[^\n]* /* skip comments */
|
||||
|
||||
"journey" return 'journey';
|
||||
"title"\s[^#\n;]+ return 'title';
|
||||
@ -31,6 +42,7 @@
|
||||
|
||||
start
|
||||
: journey document 'EOF' { return $2; }
|
||||
| directive start
|
||||
;
|
||||
|
||||
document
|
||||
@ -41,12 +53,36 @@ document
|
||||
line
|
||||
: SPACE statement { $$ = $2 }
|
||||
| statement { $$ = $1 }
|
||||
| NL { $$=[];}
|
||||
| NEWLINE { $$=[];}
|
||||
| EOF { $$=[];}
|
||||
;
|
||||
|
||||
directive
|
||||
: openDirective typeDirective closeDirective 'NEWLINE'
|
||||
| openDirective typeDirective ':' argDirective closeDirective 'NEWLINE'
|
||||
;
|
||||
|
||||
statement
|
||||
: title {yy.setTitle($1.substr(6));$$=$1.substr(6);}
|
||||
| section {yy.addSection($1.substr(8));$$=$1.substr(8);}
|
||||
| taskName taskData {yy.addTask($1, $2);$$='task';}
|
||||
| directive
|
||||
;
|
||||
|
||||
openDirective
|
||||
: open_directive { yy.parseDirective('%%{', 'open_directive'); }
|
||||
;
|
||||
|
||||
typeDirective
|
||||
: type_directive { yy.parseDirective($1, 'type_directive'); }
|
||||
;
|
||||
|
||||
argDirective
|
||||
: arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); }
|
||||
;
|
||||
|
||||
closeDirective
|
||||
: close_directive { yy.parseDirective('}%%', 'close_directive', 'journey'); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
@ -205,7 +205,7 @@ const render = function(id, _txt, cb, container) {
|
||||
} else {
|
||||
configApi.reset();
|
||||
const siteConfig = getSiteConfig();
|
||||
updateRendererConfigs(siteConfig);
|
||||
reinitialize(siteConfig);
|
||||
}
|
||||
|
||||
const cnf = getConfig();
|
||||
@ -438,7 +438,7 @@ const render = function(id, _txt, cb, container) {
|
||||
|
||||
let currentDirective = {};
|
||||
|
||||
const parseDirective = function(statement, context, type) {
|
||||
const parseDirective = function(p, statement, context, type) {
|
||||
try {
|
||||
if (statement !== undefined) {
|
||||
statement = statement.trim();
|
||||
@ -453,7 +453,7 @@ const parseDirective = function(statement, context, type) {
|
||||
currentDirective.args = JSON.parse(statement);
|
||||
break;
|
||||
case 'close_directive':
|
||||
handleDirective(currentDirective, type);
|
||||
handleDirective(p, currentDirective, type);
|
||||
currentDirective = null;
|
||||
break;
|
||||
}
|
||||
@ -466,7 +466,7 @@ const parseDirective = function(statement, context, type) {
|
||||
}
|
||||
};
|
||||
|
||||
const handleDirective = function(directive, type) {
|
||||
const handleDirective = function(p, directive, type) {
|
||||
logger.debug(`Directive type=${directive.type} with args:`, directive.args);
|
||||
switch (directive.type) {
|
||||
case 'init':
|
||||
@ -486,17 +486,9 @@ const handleDirective = function(directive, type) {
|
||||
}
|
||||
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);
|
||||
if (p && p['setWrap']) {
|
||||
p.setWrap(directive.type === 'wrap');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logger.warn(
|
||||
|
@ -14,8 +14,9 @@ const themes = {
|
||||
'flowchart-v2': flowchart,
|
||||
sequence,
|
||||
gantt,
|
||||
class: classDiagram,
|
||||
classDiagram,
|
||||
'classDiagram-v2': classDiagram,
|
||||
class: classDiagram,
|
||||
stateDiagram,
|
||||
state: stateDiagram,
|
||||
git,
|
||||
|
@ -155,5 +155,6 @@ class Theme {
|
||||
export const getThemeVariables = userOverrides => {
|
||||
const theme = new Theme();
|
||||
theme.calculate(userOverrides);
|
||||
console.info('Theme(dark)', { userOverrides, theme });
|
||||
return theme;
|
||||
};
|
||||
|
@ -161,5 +161,6 @@ class Theme {
|
||||
export const getThemeVariables = userOverrides => {
|
||||
const theme = new Theme();
|
||||
theme.calculate(userOverrides);
|
||||
console.info('Theme(default)', { userOverrides, theme });
|
||||
return theme;
|
||||
};
|
||||
|
@ -136,5 +136,6 @@ class Theme {
|
||||
export const getThemeVariables = userOverrides => {
|
||||
const theme = new Theme();
|
||||
theme.calculate(userOverrides);
|
||||
console.info('Theme(forest)', { userOverrides, theme });
|
||||
return theme;
|
||||
};
|
||||
|
@ -168,6 +168,6 @@ class Theme {
|
||||
export const getThemeVariables = userOverrides => {
|
||||
const theme = new Theme();
|
||||
theme.calculate(userOverrides);
|
||||
console.info('Theme', userOverrides, theme);
|
||||
console.info('Theme(neutral)', { userOverrides, theme });
|
||||
return theme;
|
||||
};
|
||||
|
@ -116,13 +116,13 @@ Alice->Bob: hi`;
|
||||
});
|
||||
it('should handle an init definition with config converted to the proper diagram configuration', function() {
|
||||
const str = `
|
||||
%%{init: { 'logLevel': 0, 'theme': 'dark', 'config': {'wrapEnabled': true} } }%%
|
||||
%%{init: { 'logLevel': 0, 'theme': 'dark', 'config': {'wrap': true} } }%%
|
||||
sequenceDiagram
|
||||
Alice->Bob: hi`;
|
||||
const type = utils.detectType(str);
|
||||
const init = utils.detectInit(str);
|
||||
expect(type).toBe('sequence');
|
||||
expect(init).toEqual({logLevel:0, theme:"dark", sequence: { wrapEnabled: true }});
|
||||
expect(init).toEqual({logLevel:0, theme:"dark", sequence: { wrap: true }});
|
||||
});
|
||||
it('should handle a multiline init definition', function() {
|
||||
const str = `
|
||||
|
Loading…
x
Reference in New Issue
Block a user