Add the directive state ment for change rendering direction in composite states

This commit is contained in:
Knut Sveidqvist
2021-05-09 15:25:51 +02:00
parent e3164d8d44
commit 43f6ae7ba0
10 changed files with 216 additions and 50 deletions

View File

@@ -1,6 +1,6 @@
/** mermaid
* https://mermaidjs.github.io/
* (c) 2014-2015 Knut Sveidqvist
* (c) 2014-2021 Knut Sveidqvist
* MIT license.
*
* Based on js sequence diagrams jison grammr
@@ -35,36 +35,46 @@
%x LINE
%%
.*direction\s+TB[^\n]* return 'direction_tb';
.*direction\s+BT[^\n]* return 'direction_bt';
.*direction\s+RL[^\n]* return 'direction_rl';
.*direction\s+LR[^\n]* return 'direction_lr';
\%\%\{ { 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]* /* skip comments */{ /*console.log('Crap after close');*/ }
[\n]+ return 'NL';
[\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'; }
<SCALE>\d+ return 'WIDTH';
<SCALE>\s+"width" {this.popState();}
<INITIAL,struct>"state"\s+ { console.log('Starting STATE');this.pushState('STATE'); }
<INITIAL,struct>"state"\s+ { /*console.log('Starting STATE zxzx'+yy.getDirection());*/this.pushState('STATE'); }
<STATE>.*"<<fork>>" {this.popState();yytext=yytext.slice(0,-8).trim(); /*console.warn('Fork Fork: ',yytext);*/return 'FORK';}
<STATE>.*"<<join>>" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Join: ',yytext);*/return 'JOIN';}
<STATE>.*"<<choice>>" {this.popState();yytext=yytext.slice(0,-10).trim();/*console.warn('Fork Join: ',yytext);*/return 'CHOICE';}
<STATE>.*"[[fork]]" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Fork: ',yytext);*/return 'FORK';}
<STATE>.*"[[join]]" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Join: ',yytext);*/return 'JOIN';}
<STATE>.*"[[choice]]" {this.popState();yytext=yytext.slice(0,-10).trim();/*console.warn('Fork Join: ',yytext);*/return 'CHOICE';}
<STATE>["] { console.log('Starting STATE_STRING');this.begin("STATE_STRING");}
<struct>.*direction\s+TB[^\n]* { return 'direction_tb';}
<struct>.*direction\s+BT[^\n]* { return 'direction_bt';}
<struct>.*direction\s+RL[^\n]* { return 'direction_rl';}
<struct>.*direction\s+LR[^\n]* { return 'direction_lr';}
<STATE>["] { /*console.log('Starting STATE_STRING zxzx');*/this.begin("STATE_STRING");}
<STATE>\s*"as"\s+ {this.popState();this.pushState('STATE_ID');return "AS";}
<STATE_ID>[^\n\{]* {this.popState();/* console.log('STATE_ID', yytext);*/return "ID";}
<STATE_STRING>["] this.popState();
<STATE_STRING>[^"]* { console.log('Long description:', yytext);return "STATE_DESCR";}
<STATE_STRING>[^"]* { /*console.log('Long description:', yytext);*/return "STATE_DESCR";}
<STATE>[^\n\s\{]+ {/*console.log('COMPOSIT_STATE', yytext);*/return 'COMPOSIT_STATE';}
<STATE>\n {this.popState();}
<INITIAL,STATE>\{ {this.popState();this.pushState('struct'); /*console.log('begin struct', yytext);*/return 'STRUCT_START';}
@@ -144,7 +154,6 @@ statement
| COMPOSIT_STATE
| COMPOSIT_STATE STRUCT_START document STRUCT_STOP
{
/* console.warn('Adding document for state without id ', $1);*/
$$={ stmt: 'state', id: $1, type: 'default', description: '', doc: $3 }
}
@@ -161,7 +170,7 @@ statement
}
| STATE_DESCR AS ID STRUCT_START document STRUCT_STOP
{
//console.warn('Adding document for state with id ', $3, $4); yy.addDocument($3);
/*console.warn('Adding document for state with id zxzx', $3, $4, yy.getDirection());*/ yy.addDocument($3);
$$={ stmt: 'state', id: $3, type: 'default', description: $1, doc: $5 }
}
| FORK {
@@ -183,12 +192,23 @@ statement
}
| note NOTE_TEXT AS ID
| directive
| direction
;
directive
: openDirective typeDirective closeDirective
| openDirective typeDirective ':' argDirective closeDirective
;
direction
: direction_tb
{ yy.setDirection('TB');$$={stmt:'dir', value:'TB'};}
| direction_bt
{ yy.setDirection('BT');$$={stmt:'dir', value:'BT'};}
| direction_rl
{ yy.setDirection('RL'); $$={stmt:'dir', value:'RL'};}
| direction_lr
{ yy.setDirection('LR');$$={stmt:'dir', value:'LR'};}
;
eol
: NL

View File

@@ -67,6 +67,7 @@ const docTranslator = (parent, node, first) => {
const getRootDocV2 = () => {
docTranslator({ id: 'root' }, { id: 'root', doc: rootDoc }, true);
return { id: 'root', doc: rootDoc };
// Here
};
const extract = _doc => {
@@ -230,7 +231,11 @@ let classes = [];
const getClasses = () => classes;
const getDirection = () => 'TB';
let direction = 'TB';
const getDirection = () => direction;
const setDirection = dir => {
direction = dir;
};
export const relationType = {
AGGREGATION: 0,
@@ -253,6 +258,7 @@ export default {
getDirection,
addRelation,
getDividerId,
setDirection,
// addDescription,
cleanupLabel,
lineType,

View File

@@ -84,8 +84,10 @@ const setupNode = (g, parent, node, altFlag) => {
// group
if (!nodeDb[node.id].type && node.doc) {
log.info('Setting cluser for ', node.id);
log.info('Setting cluster for ', node.id, getDir(node));
console.info('Setting cluster for ', node.id, getDir(node));
nodeDb[node.id].type = 'group';
nodeDb[node.id].dir = getDir(node);
nodeDb[node.id].shape = node.type === 'divider' ? 'divider' : 'roundedWithTitle';
nodeDb[node.id].classes =
nodeDb[node.id].classes +
@@ -103,7 +105,7 @@ const setupNode = (g, parent, node, altFlag) => {
classes: nodeDb[node.id].classes, //classStr,
style: '', //styles.style,
id: node.id,
dir: altFlag ? 'LR' : 'TB',
dir: nodeDb[node.id].dir,
domId: 'state-' + node.id + '-' + cnt,
type: nodeDb[node.id].type,
padding: 15 //getConfig().flowchart.padding
@@ -208,7 +210,21 @@ const setupDoc = (g, parent, doc, altFlag) => {
}
});
};
const getDir = (nodes, defaultDir) => {
let dir = defaultDir || 'BT';
if (nodes.doc) {
for (let i = 0; i < nodes.doc.length; i++) {
const node = nodes.doc[i];
if (node.stmt === 'dir') {
dir = node.value;
}
}
}
if(nodes.id==='A') {
console.log('nodes.id',nodes.id, dir)
}
return dir;
};
/**
* Draws a flowchart in the tag with id: id based on the graph definition in text.
* @param text
@@ -216,6 +232,7 @@ const setupDoc = (g, parent, doc, altFlag) => {
*/
export const draw = function(text, id) {
log.info('Drawing state diagram (v2)', id);
console.info('Drawing state diagram (v2)', id);
stateDb.clear();
nodeDb = {};
const parser = state.parser;
@@ -234,13 +251,18 @@ export const draw = function(text, id) {
const nodeSpacing = conf.nodeSpacing || 50;
const rankSpacing = conf.rankSpacing || 50;
log.info(stateDb.getRootDocV2());
stateDb.extract(stateDb.getRootDocV2());
log.info(stateDb.getRootDocV2());
console.info(stateDb.getRootDocV2());
// Create the input mermaid.graph
const g = new graphlib.Graph({
multigraph: true,
compound: true
})
.setGraph({
rankdir: 'TB',
rankdir: getDir(stateDb.getRootDocV2()),
nodesep: nodeSpacing,
ranksep: rankSpacing,
marginx: 8,
@@ -250,10 +272,9 @@ export const draw = function(text, id) {
return {};
});
log.info(stateDb.getRootDocV2());
stateDb.extract(stateDb.getRootDocV2());
log.info(stateDb.getRootDocV2());
console.info('Setup node')
setupNode(g, undefined, stateDb.getRootDocV2(), true);
console.info('Setup node done')
// Set up an SVG group so that we can translate the final graph.
const svg = select(`[id="${id}"]`);