mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-10 09:39:38 +02:00
Merge branch 'develop' into enhancement/4158_Add_primary_key_beginning_with_asterisk
This commit is contained in:
@@ -264,6 +264,113 @@ class C13["With Città foreign language"]
|
|||||||
const str = 'classDiagram\n' + 'note "test"\n';
|
const str = 'classDiagram\n' + 'note "test"\n';
|
||||||
parser.parse(str);
|
parser.parse(str);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const keywords = [
|
||||||
|
'direction',
|
||||||
|
'classDiagram',
|
||||||
|
'classDiagram-v2',
|
||||||
|
'namespace',
|
||||||
|
'{}',
|
||||||
|
'{',
|
||||||
|
'}',
|
||||||
|
'()',
|
||||||
|
'(',
|
||||||
|
')',
|
||||||
|
'[]',
|
||||||
|
'[',
|
||||||
|
']',
|
||||||
|
'class',
|
||||||
|
'\n',
|
||||||
|
'cssClass',
|
||||||
|
'callback',
|
||||||
|
'link',
|
||||||
|
'click',
|
||||||
|
'note',
|
||||||
|
'note for',
|
||||||
|
'<<',
|
||||||
|
'>>',
|
||||||
|
'call ',
|
||||||
|
'~',
|
||||||
|
'~Generic~',
|
||||||
|
'_self',
|
||||||
|
'_blank',
|
||||||
|
'_parent',
|
||||||
|
'_top',
|
||||||
|
'<|',
|
||||||
|
'|>',
|
||||||
|
'>',
|
||||||
|
'<',
|
||||||
|
'*',
|
||||||
|
'o',
|
||||||
|
'\\',
|
||||||
|
'--',
|
||||||
|
'..',
|
||||||
|
'-->',
|
||||||
|
'--|>',
|
||||||
|
': label',
|
||||||
|
':::',
|
||||||
|
'.',
|
||||||
|
'+',
|
||||||
|
'alphaNum',
|
||||||
|
'!',
|
||||||
|
'0123',
|
||||||
|
'function()',
|
||||||
|
'function(arg1, arg2)',
|
||||||
|
];
|
||||||
|
|
||||||
|
it.each(keywords)('should handle a note with %s in it', function (keyword: string) {
|
||||||
|
const str = `classDiagram
|
||||||
|
note "This is a keyword: ${keyword}. It truly is."
|
||||||
|
`;
|
||||||
|
parser.parse(str);
|
||||||
|
expect(classDb.getNotes()[0].text).toEqual(`This is a keyword: ${keyword}. It truly is.`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(keywords)(
|
||||||
|
'should handle note with %s at beginning of string',
|
||||||
|
function (keyword: string) {
|
||||||
|
const str = `classDiagram
|
||||||
|
note "${keyword}"`;
|
||||||
|
|
||||||
|
parser.parse(str);
|
||||||
|
expect(classDb.getNotes()[0].text).toEqual(`${keyword}`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it.each(keywords)('should handle a "note for" with a %s in it', function (keyword: string) {
|
||||||
|
const str = `classDiagram
|
||||||
|
class Something {
|
||||||
|
int id
|
||||||
|
string name
|
||||||
|
}
|
||||||
|
note for Something "This is a keyword: ${keyword}. It truly is."
|
||||||
|
`;
|
||||||
|
|
||||||
|
parser.parse(str);
|
||||||
|
expect(classDb.getNotes()[0].text).toEqual(`This is a keyword: ${keyword}. It truly is.`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(keywords)(
|
||||||
|
'should handle a "note for" with a %s at beginning of string',
|
||||||
|
function (keyword: string) {
|
||||||
|
const str = `classDiagram
|
||||||
|
class Something {
|
||||||
|
int id
|
||||||
|
string name
|
||||||
|
}
|
||||||
|
note for Something "${keyword}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
parser.parse(str);
|
||||||
|
expect(classDb.getNotes()[0].text).toEqual(`${keyword}`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it.each(keywords)('should elicit error for %s after NOTE token', function (keyword: string) {
|
||||||
|
const str = `classDiagram
|
||||||
|
note ${keyword}`;
|
||||||
|
expect(() => parser.parse(str)).toThrowError(/(Expecting\s'STR'|Unrecognized\stext)/);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when parsing class defined in brackets', function () {
|
describe('when parsing class defined in brackets', function () {
|
||||||
|
@@ -24,31 +24,50 @@
|
|||||||
%x namespace
|
%x namespace
|
||||||
%x namespace-body
|
%x namespace-body
|
||||||
%%
|
%%
|
||||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||||
.*direction\s+TB[^\n]* return 'direction_tb';
|
.*direction\s+TB[^\n]* return 'direction_tb';
|
||||||
.*direction\s+BT[^\n]* return 'direction_bt';
|
.*direction\s+BT[^\n]* return 'direction_bt';
|
||||||
.*direction\s+RL[^\n]* return 'direction_rl';
|
.*direction\s+RL[^\n]* return 'direction_rl';
|
||||||
.*direction\s+LR[^\n]* return 'direction_lr';
|
.*direction\s+LR[^\n]* return 'direction_lr';
|
||||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||||
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
||||||
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
||||||
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
||||||
\%\%(?!\{)*[^\n]*(\r?\n?)+ /* skip comments */
|
\%\%(?!\{)*[^\n]*(\r?\n?)+ /* skip comments */
|
||||||
\%\%[^\n]*(\r?\n)* /* skip comments */
|
\%\%[^\n]*(\r?\n)* /* skip comments */
|
||||||
accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; }
|
accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; }
|
||||||
<acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; }
|
<acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; }
|
||||||
accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; }
|
accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; }
|
||||||
<acc_descr>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; }
|
<acc_descr>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; }
|
||||||
accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
|
accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
|
||||||
<acc_descr_multiline>[\}] { this.popState(); }
|
<acc_descr_multiline>[\}] { this.popState(); }
|
||||||
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
|
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
|
||||||
|
|
||||||
\s*(\r?\n)+ return 'NEWLINE';
|
\s*(\r?\n)+ return 'NEWLINE';
|
||||||
\s+ /* skip whitespace */
|
\s+ /* skip whitespace */
|
||||||
|
|
||||||
"classDiagram-v2" return 'CLASS_DIAGRAM';
|
"classDiagram-v2" return 'CLASS_DIAGRAM';
|
||||||
"classDiagram" return 'CLASS_DIAGRAM';
|
"classDiagram" return 'CLASS_DIAGRAM';
|
||||||
"[*]" return 'EDGE_STATE';
|
"[*]" return 'EDGE_STATE';
|
||||||
|
|
||||||
|
/*
|
||||||
|
---interactivity command---
|
||||||
|
'call' adds a callback to the specified node. 'call' can only be specified when
|
||||||
|
the line was introduced with 'click'.
|
||||||
|
'call <callback_name>(<callback_args>)' attaches the function 'callback_name' with the specified
|
||||||
|
arguments to the node that was specified by 'click'.
|
||||||
|
Function arguments are optional: 'call <callback_name>()' simply executes 'callback_name' without any arguments.
|
||||||
|
*/
|
||||||
|
<INITIAL>"call"[\s]+ this.begin("callback_name");
|
||||||
|
<callback_name>\([\s]*\) this.popState();
|
||||||
|
<callback_name>\( this.popState(); this.begin("callback_args");
|
||||||
|
<callback_name>[^(]* return 'CALLBACK_NAME';
|
||||||
|
<callback_args>\) this.popState();
|
||||||
|
<callback_args>[^)]* return 'CALLBACK_ARGS';
|
||||||
|
|
||||||
|
<string>["] this.popState();
|
||||||
|
<string>[^"]* return "STR";
|
||||||
|
<*>["] this.begin("string");
|
||||||
|
|
||||||
<INITIAL,namespace>"namespace" { this.begin('namespace'); return 'NAMESPACE'; }
|
<INITIAL,namespace>"namespace" { this.begin('namespace'); return 'NAMESPACE'; }
|
||||||
<namespace>\s*(\r?\n)+ { this.popState(); return 'NEWLINE'; }
|
<namespace>\s*(\r?\n)+ { this.popState(); return 'NEWLINE'; }
|
||||||
@@ -60,26 +79,26 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
|||||||
<namespace-body>\s+ /* skip whitespace */
|
<namespace-body>\s+ /* skip whitespace */
|
||||||
<namespace-body>"[*]" return 'EDGE_STATE';
|
<namespace-body>"[*]" return 'EDGE_STATE';
|
||||||
|
|
||||||
<INITIAL,namespace-body>"class" { this.begin('class'); return 'CLASS';}
|
<INITIAL,namespace-body>"class" { this.begin('class'); return 'CLASS';}
|
||||||
<class>\s*(\r?\n)+ { this.popState(); return 'NEWLINE'; }
|
<class>\s*(\r?\n)+ { this.popState(); return 'NEWLINE'; }
|
||||||
<class>\s+ /* skip whitespace */
|
<class>\s+ /* skip whitespace */
|
||||||
<class>[}] { this.popState(); this.popState(); return 'STRUCT_STOP';}
|
<class>[}] { this.popState(); this.popState(); return 'STRUCT_STOP';}
|
||||||
<class>[{] { this.begin("class-body"); return 'STRUCT_START';}
|
<class>[{] { this.begin("class-body"); return 'STRUCT_START';}
|
||||||
<class-body>[}] { this.popState(); return 'STRUCT_STOP'; }
|
<class-body>[}] { this.popState(); return 'STRUCT_STOP'; }
|
||||||
<class-body><<EOF>> return "EOF_IN_STRUCT";
|
<class-body><<EOF>> return "EOF_IN_STRUCT";
|
||||||
<class-body>"[*]" { return 'EDGE_STATE';}
|
<class-body>"[*]" { return 'EDGE_STATE';}
|
||||||
<class-body>[{] return "OPEN_IN_STRUCT";
|
<class-body>[{] return "OPEN_IN_STRUCT";
|
||||||
<class-body>[\n] /* nothing */
|
<class-body>[\n] /* nothing */
|
||||||
<class-body>[^{}\n]* { return "MEMBER";}
|
<class-body>[^{}\n]* { return "MEMBER";}
|
||||||
|
|
||||||
<*>"cssClass" return 'CSSCLASS';
|
<*>"cssClass" return 'CSSCLASS';
|
||||||
<*>"callback" return 'CALLBACK';
|
<*>"callback" return 'CALLBACK';
|
||||||
<*>"link" return 'LINK';
|
<*>"link" return 'LINK';
|
||||||
<*>"click" return 'CLICK';
|
<*>"click" return 'CLICK';
|
||||||
<*>"note for" return 'NOTE_FOR';
|
<*>"note for" return 'NOTE_FOR';
|
||||||
<*>"note" return 'NOTE';
|
<*>"note" return 'NOTE';
|
||||||
<*>"<<" return 'ANNOTATION_START';
|
<*>"<<" return 'ANNOTATION_START';
|
||||||
<*>">>" return 'ANNOTATION_END';
|
<*>">>" return 'ANNOTATION_END';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
---interactivity command---
|
---interactivity command---
|
||||||
@@ -87,64 +106,43 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
|||||||
line was introduced with 'click'.
|
line was introduced with 'click'.
|
||||||
'href "<link>"' attaches the specified link to the node that was specified by 'click'.
|
'href "<link>"' attaches the specified link to the node that was specified by 'click'.
|
||||||
*/
|
*/
|
||||||
<*>"href"[\s]+["] this.begin("href");
|
<*>"href" return 'HREF';
|
||||||
<href>["] this.popState();
|
|
||||||
<href>[^"]* return 'HREF';
|
|
||||||
|
|
||||||
/*
|
<generic>[~] this.popState();
|
||||||
---interactivity command---
|
<generic>[^~]* return "GENERICTYPE";
|
||||||
'call' adds a callback to the specified node. 'call' can only be specified when
|
<*>"~" this.begin("generic");
|
||||||
the line was introduced with 'click'.
|
|
||||||
'call <callback_name>(<callback_args>)' attaches the function 'callback_name' with the specified
|
|
||||||
arguments to the node that was specified by 'click'.
|
|
||||||
Function arguments are optional: 'call <callback_name>()' simply executes 'callback_name' without any arguments.
|
|
||||||
*/
|
|
||||||
<*>"call"[\s]+ this.begin("callback_name");
|
|
||||||
<callback_name>\([\s]*\) this.popState();
|
|
||||||
<callback_name>\( this.popState(); this.begin("callback_args");
|
|
||||||
<callback_name>[^(]* return 'CALLBACK_NAME';
|
|
||||||
<callback_args>\) this.popState();
|
|
||||||
<callback_args>[^)]* return 'CALLBACK_ARGS';
|
|
||||||
|
|
||||||
<generic>[~] this.popState();
|
<bqstring>[`] this.popState();
|
||||||
<generic>[^~]* return "GENERICTYPE";
|
<bqstring>[^`]+ return "BQUOTE_STR";
|
||||||
<*>[~] this.begin("generic");
|
<*>[`] this.begin("bqstring");
|
||||||
|
|
||||||
<string>["] this.popState();
|
<*>"_self" return 'LINK_TARGET';
|
||||||
<string>[^"]* return "STR";
|
<*>"_blank" return 'LINK_TARGET';
|
||||||
<*>["] this.begin("string");
|
<*>"_parent" return 'LINK_TARGET';
|
||||||
|
<*>"_top" return 'LINK_TARGET';
|
||||||
|
|
||||||
<bqstring>[`] this.popState();
|
<*>\s*\<\| return 'EXTENSION';
|
||||||
<bqstring>[^`]+ return "BQUOTE_STR";
|
<*>\s*\|\> return 'EXTENSION';
|
||||||
<*>[`] this.begin("bqstring");
|
<*>\s*\> return 'DEPENDENCY';
|
||||||
|
<*>\s*\< return 'DEPENDENCY';
|
||||||
<*>"_self" return 'LINK_TARGET';
|
<*>\s*\* return 'COMPOSITION';
|
||||||
<*>"_blank" return 'LINK_TARGET';
|
<*>\s*o return 'AGGREGATION';
|
||||||
<*>"_parent" return 'LINK_TARGET';
|
<*>\s*\(\) return 'LOLLIPOP';
|
||||||
<*>"_top" return 'LINK_TARGET';
|
<*>\-\- return 'LINE';
|
||||||
|
<*>\.\. return 'DOTTED_LINE';
|
||||||
<*>\s*\<\| return 'EXTENSION';
|
<*>":"{1}[^:\n;]+ return 'LABEL';
|
||||||
<*>\s*\|\> return 'EXTENSION';
|
<*>":"{3} return 'STYLE_SEPARATOR';
|
||||||
<*>\s*\> return 'DEPENDENCY';
|
<*>\- return 'MINUS';
|
||||||
<*>\s*\< return 'DEPENDENCY';
|
<*>"." return 'DOT';
|
||||||
<*>\s*\* return 'COMPOSITION';
|
<*>\+ return 'PLUS';
|
||||||
<*>\s*o return 'AGGREGATION';
|
<*>\% return 'PCT';
|
||||||
<*>\s*\(\) return 'LOLLIPOP';
|
<*>"=" return 'EQUALS';
|
||||||
<*>\-\- return 'LINE';
|
<*>\= return 'EQUALS';
|
||||||
<*>\.\. return 'DOTTED_LINE';
|
<*>\w+ return 'ALPHA';
|
||||||
<*>":"{1}[^:\n;]+ return 'LABEL';
|
<*>"[" return 'SQS';
|
||||||
<*>":"{3} return 'STYLE_SEPARATOR';
|
<*>"]" return 'SQE';
|
||||||
<*>\- return 'MINUS';
|
<*>[!"#$%&'*+,-.`?\\/] return 'PUNCTUATION';
|
||||||
<*>"." return 'DOT';
|
<*>[0-9]+ return 'NUM';
|
||||||
<*>\+ return 'PLUS';
|
|
||||||
<*>\% return 'PCT';
|
|
||||||
<*>"=" return 'EQUALS';
|
|
||||||
<*>\= return 'EQUALS';
|
|
||||||
<*>\w+ return 'ALPHA';
|
|
||||||
<*>"[" return 'SQS';
|
|
||||||
<*>"]" return 'SQE';
|
|
||||||
<*>[!"#$%&'*+,-.`?\\/] return 'PUNCTUATION';
|
|
||||||
<*>[0-9]+ return 'NUM';
|
|
||||||
<*>[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|
|
<*>[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|
|
||||||
[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|
|
[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|
|
||||||
[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|
|
[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|
|
||||||
@@ -206,9 +204,9 @@ Function arguments are optional: 'call <callback_name>()' simply executes 'callb
|
|||||||
[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|
|
[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|
|
||||||
[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|
|
[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|
|
||||||
[\uFFD2-\uFFD7\uFFDA-\uFFDC]
|
[\uFFD2-\uFFD7\uFFDA-\uFFDC]
|
||||||
return 'UNICODE_TEXT';
|
return 'UNICODE_TEXT';
|
||||||
<*>\s return 'SPACE';
|
<*>\s return 'SPACE';
|
||||||
<*><<EOF>> return 'EOF';
|
<*><<EOF>> return 'EOF';
|
||||||
|
|
||||||
/lex
|
/lex
|
||||||
|
|
||||||
@@ -391,10 +389,10 @@ clickStatement
|
|||||||
| CLICK className CALLBACK_NAME STR {$$ = $1;yy.setClickEvent($2, $3);yy.setTooltip($2, $4);}
|
| CLICK className CALLBACK_NAME STR {$$ = $1;yy.setClickEvent($2, $3);yy.setTooltip($2, $4);}
|
||||||
| CLICK className CALLBACK_NAME CALLBACK_ARGS {$$ = $1;yy.setClickEvent($2, $3, $4);}
|
| CLICK className CALLBACK_NAME CALLBACK_ARGS {$$ = $1;yy.setClickEvent($2, $3, $4);}
|
||||||
| CLICK className CALLBACK_NAME CALLBACK_ARGS STR {$$ = $1;yy.setClickEvent($2, $3, $4);yy.setTooltip($2, $5);}
|
| CLICK className CALLBACK_NAME CALLBACK_ARGS STR {$$ = $1;yy.setClickEvent($2, $3, $4);yy.setTooltip($2, $5);}
|
||||||
| CLICK className HREF {$$ = $1;yy.setLink($2, $3);}
|
| CLICK className HREF STR {$$ = $1;yy.setLink($2, $4);}
|
||||||
| CLICK className HREF LINK_TARGET {$$ = $1;yy.setLink($2, $3, $4);}
|
| CLICK className HREF STR LINK_TARGET {$$ = $1;yy.setLink($2, $4, $5);}
|
||||||
| CLICK className HREF STR {$$ = $1;yy.setLink($2, $3);yy.setTooltip($2, $4);}
|
| CLICK className HREF STR STR {$$ = $1;yy.setLink($2, $4);yy.setTooltip($2, $5);}
|
||||||
| CLICK className HREF STR LINK_TARGET {$$ = $1;yy.setLink($2, $3, $5);yy.setTooltip($2, $4);}
|
| CLICK className HREF STR STR LINK_TARGET {$$ = $1;yy.setLink($2, $4, $6);yy.setTooltip($2, $5);}
|
||||||
;
|
;
|
||||||
|
|
||||||
cssClassStatement
|
cssClassStatement
|
||||||
|
@@ -63,20 +63,6 @@ export const draw = function (text, id, _version, diagObj) {
|
|||||||
const diagram = root.select(`[id='${id}']`);
|
const diagram = root.select(`[id='${id}']`);
|
||||||
insertMarkers(diagram);
|
insertMarkers(diagram);
|
||||||
|
|
||||||
// Layout graph, Create a new directed graph
|
|
||||||
const graph = new graphlib.Graph({
|
|
||||||
multigraph: true,
|
|
||||||
compound: true,
|
|
||||||
// acyclicer: 'greedy',
|
|
||||||
rankdir: 'RL',
|
|
||||||
// ranksep: '20'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Default to assigning a new object as a label for each new edge.
|
|
||||||
graph.setDefaultEdgeLabel(function () {
|
|
||||||
return {};
|
|
||||||
});
|
|
||||||
|
|
||||||
const rootDoc = diagObj.db.getRootDoc();
|
const rootDoc = diagObj.db.getRootDoc();
|
||||||
renderDoc(rootDoc, diagram, undefined, false, root, doc, diagObj);
|
renderDoc(rootDoc, diagram, undefined, false, root, doc, diagObj);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user