mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-21 16:29:40 +02:00
Merge pull request #1582 from cmmoran/develop
Directive support for many diagrams, config bugfix
This commit is contained in:
@@ -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
|
||||
@@ -617,6 +621,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,6 +36,7 @@
|
||||
"flowchart" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';}
|
||||
"subgraph" return 'subgraph';
|
||||
"end"\b\s* return 'end';
|
||||
<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'; }
|
||||
@@ -179,7 +191,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';
|
||||
|
||||
@@ -189,11 +201,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 */
|
||||
@@ -218,6 +258,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'); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
Reference in New Issue
Block a user