Merge branch 'sagea-sagea/sequencediagram-background-rect'

This commit is contained in:
knsv 2019-07-25 12:00:57 -07:00
commit 5b85fe9293
14 changed files with 394 additions and 90 deletions

36
__mocks__/d3.js vendored
View File

@ -1,17 +1,16 @@
/* eslint-env jest */
let NewD3 = function () {
function returnThis () {
return this
}
return {
append: function () {
return NewD3()
},
attr: function () {
return this
},
style: function () {
return this
},
text: function () {
return this
},
lower: returnThis,
attr: returnThis,
style: returnThis,
text: returnThis,
0: {
0: {
getBBox: function () {
@ -36,3 +35,22 @@ export const selectAll = function () {
export const curveBasis = 'basis'
export const curveLinear = 'linear'
export const curveCardinal = 'cardinal'
export const MockD3 = (name, parent) => {
const children = []
const elem = {
get __children () { return children },
get __name () { return name },
get __parent () { return parent }
}
elem.append = (name) => {
const mockElem = MockD3(name, elem)
children.push(mockElem)
return mockElem
}
elem.lower = jest.fn(() => elem)
elem.attr = jest.fn(() => elem)
elem.text = jest.fn(() => elem)
elem.style = jest.fn(() => elem)
return elem
}

4
dist/index.html vendored
View File

@ -305,12 +305,16 @@ sequenceDiagram
participant Alice
participant Bob
participant John as John<br/>Second Line
rect rgb(200, 220, 100)
rect rgb(200, 255, 200)
Alice ->> Bob: Hello Bob, how are you?
Bob-->>John: How about you John?
end
Bob--x Alice: I am good thanks!
Bob-x John: I am good thanks!
Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
Bob-->Alice: Checking with John...
end
alt either this
Alice->>John: Yes
else or this

View File

@ -32,4 +32,90 @@ describe('Sequencediagram', () => {
`,
{})
})
describe('background rects', async () => {
it('should render a single and nested rects', async () => {
await imgSnapshotTest(page, `
sequenceDiagram
participant A
participant B
participant C
participant D
participant E
participant G
A ->>+ B: Task 1
rect rgb(178, 102, 255)
B ->>+ C: Task 2
C -->>- B: Return
end
A ->> D: Task 3
rect rgb(0, 128, 255)
D ->>+ E: Task 4
rect rgb(0, 204, 0)
E ->>+ G: Task 5
G -->>- E: Return
end
E ->> E: Task 6
end
D -->> A: Complete
`, {})
})
it('should render rect around and inside loops', async () => {
await imgSnapshotTest(page, `
sequenceDiagram
A ->> B: 1
rect rgb(204, 0, 102)
loop check C
C ->> C: Every 10 seconds
end
end
A ->> B: 2
loop check D
C ->> D: 3
rect rgb(153, 153, 255)
D -->> D: 5
D --> C: 4
end
end
`, {})
})
it('should render rect around and inside alts', async () => {
await imgSnapshotTest(page, `
sequenceDiagram
A ->> B: 1
rect rgb(204, 0, 102)
alt yes
C ->> C: 1
else no
rect rgb(0, 204, 204)
C ->> C: 0
end
end
end
B ->> A: Return
`, {})
})
it('should render rect around and inside opts', async () => {
await imgSnapshotTest(page, `
sequenceDiagram
A ->> B: 1
rect rgb(204, 0, 102)
opt maybe
C -->> D: Do something
rect rgb(0, 204, 204)
C ->> C: 0
end
end
end
opt possibly
rect rgb(0, 204, 204)
C ->> C: 0
end
end
B ->> A: Return
`, {})
})
})
})

View File

@ -31,6 +31,7 @@
<ALIAS>"as" { this.popState(); this.popState(); this.begin('LINE'); return 'AS'; }
<ALIAS>(?:) { this.popState(); this.popState(); return 'NL'; }
"loop" { this.begin('LINE'); return 'loop'; }
"rect" { this.begin('LINE'); return 'rect'; }
"opt" { this.begin('LINE'); return 'opt'; }
"alt" { this.begin('LINE'); return 'alt'; }
"else" { this.begin('LINE'); return 'else'; }
@ -99,6 +100,11 @@ statement
$3.unshift({type: 'loopStart', loopText:$2, signalType: yy.LINETYPE.LOOP_START});
$3.push({type: 'loopEnd', loopText:$2, signalType: yy.LINETYPE.LOOP_END});
$$=$3;}
| 'rect' restOfLine document end
{
$3.unshift({type: 'rectStart', color:$2, signalType: yy.LINETYPE.RECT_START });
$3.push({type: 'rectEnd', color:$2, signalType: yy.LINETYPE.RECT_END });
$$=$3;}
| opt restOfLine document end
{
$3.unshift({type: 'optStart', optText:$2, signalType: yy.LINETYPE.OPT_START});

View File

@ -71,13 +71,13 @@
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
}
*/
var sequenceDiagram = (function(){
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,2],$V1=[1,3],$V2=[1,4],$V3=[2,4],$V4=[1,9],$V5=[1,11],$V6=[1,12],$V7=[1,14],$V8=[1,15],$V9=[1,17],$Va=[1,18],$Vb=[1,19],$Vc=[1,20],$Vd=[1,21],$Ve=[1,23],$Vf=[1,24],$Vg=[1,4,5,10,15,16,18,20,21,22,23,25,27,28,29,40],$Vh=[1,32],$Vi=[4,5,10,15,16,18,20,21,22,23,25,29,40],$Vj=[4,5,10,15,16,18,20,21,22,23,25,28,29,40],$Vk=[4,5,10,15,16,18,20,21,22,23,25,27,29,40],$Vl=[38,39,40];
var parser = (function(){
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,2],$V1=[1,3],$V2=[1,4],$V3=[2,4],$V4=[1,9],$V5=[1,11],$V6=[1,12],$V7=[1,14],$V8=[1,15],$V9=[1,17],$Va=[1,18],$Vb=[1,19],$Vc=[1,20],$Vd=[1,21],$Ve=[1,22],$Vf=[1,24],$Vg=[1,25],$Vh=[1,4,5,10,15,16,18,20,21,22,23,24,26,28,29,30,41],$Vi=[1,33],$Vj=[4,5,10,15,16,18,20,21,22,23,24,26,30,41],$Vk=[4,5,10,15,16,18,20,21,22,23,24,26,29,30,41],$Vl=[4,5,10,15,16,18,20,21,22,23,24,26,28,30,41],$Vm=[39,40,41];
var parser = {trace: function trace () { },
yy: {},
symbols_: {"error":2,"start":3,"SPACE":4,"NL":5,"SD":6,"document":7,"line":8,"statement":9,"participant":10,"actor":11,"AS":12,"restOfLine":13,"signal":14,"activate":15,"deactivate":16,"note_statement":17,"title":18,"text2":19,"loop":20,"end":21,"opt":22,"alt":23,"else_sections":24,"par":25,"par_sections":26,"and":27,"else":28,"note":29,"placement":30,"over":31,"actor_pair":32,"spaceList":33,",":34,"left_of":35,"right_of":36,"signaltype":37,"+":38,"-":39,"ACTOR":40,"SOLID_OPEN_ARROW":41,"DOTTED_OPEN_ARROW":42,"SOLID_ARROW":43,"DOTTED_ARROW":44,"SOLID_CROSS":45,"DOTTED_CROSS":46,"TXT":47,"$accept":0,"$end":1},
terminals_: {2:"error",4:"SPACE",5:"NL",6:"SD",10:"participant",12:"AS",13:"restOfLine",15:"activate",16:"deactivate",18:"title",20:"loop",21:"end",22:"opt",23:"alt",25:"par",27:"and",28:"else",29:"note",31:"over",34:",",35:"left_of",36:"right_of",38:"+",39:"-",40:"ACTOR",41:"SOLID_OPEN_ARROW",42:"DOTTED_OPEN_ARROW",43:"SOLID_ARROW",44:"DOTTED_ARROW",45:"SOLID_CROSS",46:"DOTTED_CROSS",47:"TXT"},
productions_: [0,[3,2],[3,2],[3,2],[7,0],[7,2],[8,2],[8,1],[8,1],[9,5],[9,3],[9,2],[9,3],[9,3],[9,2],[9,3],[9,4],[9,4],[9,4],[9,4],[26,1],[26,4],[24,1],[24,4],[17,4],[17,4],[33,2],[33,1],[32,3],[32,1],[30,1],[30,1],[14,5],[14,5],[14,4],[11,1],[37,1],[37,1],[37,1],[37,1],[37,1],[37,1],[19,1]],
symbols_: {"error":2,"start":3,"SPACE":4,"NL":5,"SD":6,"document":7,"line":8,"statement":9,"participant":10,"actor":11,"AS":12,"restOfLine":13,"signal":14,"activate":15,"deactivate":16,"note_statement":17,"title":18,"text2":19,"loop":20,"end":21,"rect":22,"opt":23,"alt":24,"else_sections":25,"par":26,"par_sections":27,"and":28,"else":29,"note":30,"placement":31,"over":32,"actor_pair":33,"spaceList":34,",":35,"left_of":36,"right_of":37,"signaltype":38,"+":39,"-":40,"ACTOR":41,"SOLID_OPEN_ARROW":42,"DOTTED_OPEN_ARROW":43,"SOLID_ARROW":44,"DOTTED_ARROW":45,"SOLID_CROSS":46,"DOTTED_CROSS":47,"TXT":48,"$accept":0,"$end":1},
terminals_: {2:"error",4:"SPACE",5:"NL",6:"SD",10:"participant",12:"AS",13:"restOfLine",15:"activate",16:"deactivate",18:"title",20:"loop",21:"end",22:"rect",23:"opt",24:"alt",26:"par",28:"and",29:"else",30:"note",32:"over",35:",",36:"left_of",37:"right_of",39:"+",40:"-",41:"ACTOR",42:"SOLID_OPEN_ARROW",43:"DOTTED_OPEN_ARROW",44:"SOLID_ARROW",45:"DOTTED_ARROW",46:"SOLID_CROSS",47:"DOTTED_CROSS",48:"TXT"},
productions_: [0,[3,2],[3,2],[3,2],[7,0],[7,2],[8,2],[8,1],[8,1],[9,5],[9,3],[9,2],[9,3],[9,3],[9,2],[9,3],[9,4],[9,4],[9,4],[9,4],[9,4],[27,1],[27,4],[25,1],[25,4],[17,4],[17,4],[34,2],[34,1],[33,3],[33,1],[31,1],[31,1],[14,5],[14,5],[14,4],[11,1],[38,1],[38,1],[38,1],[38,1],[38,1],[38,1],[19,1]],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
/* this == yyval */
@ -121,11 +121,17 @@ case 16:
break;
case 17:
$$[$0-1].unshift({type: 'rectStart', color:$$[$0-2], signalType: yy.LINETYPE.RECT_START });
$$[$0-1].push({type: 'rectEnd', color:$$[$0-2], signalType: yy.LINETYPE.RECT_END });
this.$=$$[$0-1];
break;
case 18:
$$[$0-1].unshift({type: 'optStart', optText:$$[$0-2], signalType: yy.LINETYPE.OPT_START});
$$[$0-1].push({type: 'optEnd', optText:$$[$0-2], signalType: yy.LINETYPE.OPT_END});
this.$=$$[$0-1];
break;
case 18:
case 19:
// Alt start
$$[$0-1].unshift({type: 'altStart', altText:$$[$0-2], signalType: yy.LINETYPE.ALT_START});
@ -134,7 +140,7 @@ case 18:
$$[$0-1].push({type: 'altEnd', signalType: yy.LINETYPE.ALT_END});
this.$=$$[$0-1];
break;
case 19:
case 20:
// Parallel start
$$[$0-1].unshift({type: 'parStart', parText:$$[$0-2], signalType: yy.LINETYPE.PAR_START});
@ -143,17 +149,17 @@ case 19:
$$[$0-1].push({type: 'parEnd', signalType: yy.LINETYPE.PAR_END});
this.$=$$[$0-1];
break;
case 21:
case 22:
this.$ = $$[$0-3].concat([{type: 'and', parText:$$[$0-1], signalType: yy.LINETYPE.PAR_AND}, $$[$0]]);
break;
case 23:
case 24:
this.$ = $$[$0-3].concat([{type: 'else', altText:$$[$0-1], signalType: yy.LINETYPE.ALT_ELSE}, $$[$0]]);
break;
case 24:
case 25:
this.$ = [$$[$0-1], {type:'addNote', placement:$$[$0-2], actor:$$[$0-1].actor, text:$$[$0]}];
break;
case 25:
case 26:
// Coerce actor_pair into a [to, from, ...] array
$$[$0-2] = [].concat($$[$0-1], $$[$0-1]).slice(0, 2);
@ -161,59 +167,59 @@ case 25:
$$[$0-2][1] = $$[$0-2][1].actor;
this.$ = [$$[$0-1], {type:'addNote', placement:yy.PLACEMENT.OVER, actor:$$[$0-2].slice(0, 2), text:$$[$0]}];
break;
case 28:
case 29:
this.$ = [$$[$0-2], $$[$0]];
break;
case 29:
case 30:
this.$ = $$[$0];
break;
case 30:
case 31:
this.$ = yy.PLACEMENT.LEFTOF;
break;
case 31:
case 32:
this.$ = yy.PLACEMENT.RIGHTOF;
break;
case 32:
case 33:
this.$ = [$$[$0-4],$$[$0-1],{type: 'addMessage', from:$$[$0-4].actor, to:$$[$0-1].actor, signalType:$$[$0-3], msg:$$[$0]},
{type: 'activeStart', signalType: yy.LINETYPE.ACTIVE_START, actor: $$[$0-1]}
]
break;
case 33:
case 34:
this.$ = [$$[$0-4],$$[$0-1],{type: 'addMessage', from:$$[$0-4].actor, to:$$[$0-1].actor, signalType:$$[$0-3], msg:$$[$0]},
{type: 'activeEnd', signalType: yy.LINETYPE.ACTIVE_END, actor: $$[$0-4]}
]
break;
case 34:
case 35:
this.$ = [$$[$0-3],$$[$0-1],{type: 'addMessage', from:$$[$0-3].actor, to:$$[$0-1].actor, signalType:$$[$0-2], msg:$$[$0]}]
break;
case 35:
case 36:
this.$={type: 'addActor', actor:$$[$0]}
break;
case 36:
case 37:
this.$ = yy.LINETYPE.SOLID_OPEN;
break;
case 37:
case 38:
this.$ = yy.LINETYPE.DOTTED_OPEN;
break;
case 38:
case 39:
this.$ = yy.LINETYPE.SOLID;
break;
case 39:
case 40:
this.$ = yy.LINETYPE.DOTTED;
break;
case 40:
case 41:
this.$ = yy.LINETYPE.SOLID_CROSS;
break;
case 41:
case 42:
this.$ = yy.LINETYPE.DOTTED_CROSS;
break;
case 42:
case 43:
this.$ = $$[$0].substring(1).trim().replace(/\\n/gm, "\n");
break;
}
},
table: [{3:1,4:$V0,5:$V1,6:$V2},{1:[3]},{3:5,4:$V0,5:$V1,6:$V2},{3:6,4:$V0,5:$V1,6:$V2},o([1,4,5,10,15,16,18,20,22,23,25,29,40],$V3,{7:7}),{1:[2,1]},{1:[2,2]},{1:[2,3],4:$V4,5:$V5,8:8,9:10,10:$V6,11:22,14:13,15:$V7,16:$V8,17:16,18:$V9,20:$Va,22:$Vb,23:$Vc,25:$Vd,29:$Ve,40:$Vf},o($Vg,[2,5]),{9:25,10:$V6,11:22,14:13,15:$V7,16:$V8,17:16,18:$V9,20:$Va,22:$Vb,23:$Vc,25:$Vd,29:$Ve,40:$Vf},o($Vg,[2,7]),o($Vg,[2,8]),{11:26,40:$Vf},{5:[1,27]},{11:28,40:$Vf},{11:29,40:$Vf},{5:[1,30]},{19:31,47:$Vh},{13:[1,33]},{13:[1,34]},{13:[1,35]},{13:[1,36]},{37:37,41:[1,38],42:[1,39],43:[1,40],44:[1,41],45:[1,42],46:[1,43]},{30:44,31:[1,45],35:[1,46],36:[1,47]},o([5,12,34,41,42,43,44,45,46,47],[2,35]),o($Vg,[2,6]),{5:[1,49],12:[1,48]},o($Vg,[2,11]),{5:[1,50]},{5:[1,51]},o($Vg,[2,14]),{5:[1,52]},{5:[2,42]},o($Vi,$V3,{7:53}),o($Vi,$V3,{7:54}),o($Vj,$V3,{24:55,7:56}),o($Vk,$V3,{26:57,7:58}),{11:61,38:[1,59],39:[1,60],40:$Vf},o($Vl,[2,36]),o($Vl,[2,37]),o($Vl,[2,38]),o($Vl,[2,39]),o($Vl,[2,40]),o($Vl,[2,41]),{11:62,40:$Vf},{11:64,32:63,40:$Vf},{40:[2,30]},{40:[2,31]},{13:[1,65]},o($Vg,[2,10]),o($Vg,[2,12]),o($Vg,[2,13]),o($Vg,[2,15]),{4:$V4,5:$V5,8:8,9:10,10:$V6,11:22,14:13,15:$V7,16:$V8,17:16,18:$V9,20:$Va,21:[1,66],22:$Vb,23:$Vc,25:$Vd,29:$Ve,40:$Vf},{4:$V4,5:$V5,8:8,9:10,10:$V6,11:22,14:13,15:$V7,16:$V8,17:16,18:$V9,20:$Va,21:[1,67],22:$Vb,23:$Vc,25:$Vd,29:$Ve,40:$Vf},{21:[1,68]},{4:$V4,5:$V5,8:8,9:10,10:$V6,11:22,14:13,15:$V7,16:$V8,17:16,18:$V9,20:$Va,21:[2,22],22:$Vb,23:$Vc,25:$Vd,28:[1,69],29:$Ve,40:$Vf},{21:[1,70]},{4:$V4,5:$V5,8:8,9:10,10:$V6,11:22,14:13,15:$V7,16:$V8,17:16,18:$V9,20:$Va,21:[2,20],22:$Vb,23:$Vc,25:$Vd,27:[1,71],29:$Ve,40:$Vf},{11:72,40:$Vf},{11:73,40:$Vf},{19:74,47:$Vh},{19:75,47:$Vh},{19:76,47:$Vh},{34:[1,77],47:[2,29]},{5:[1,78]},o($Vg,[2,16]),o($Vg,[2,17]),o($Vg,[2,18]),{13:[1,79]},o($Vg,[2,19]),{13:[1,80]},{19:81,47:$Vh},{19:82,47:$Vh},{5:[2,34]},{5:[2,24]},{5:[2,25]},{11:83,40:$Vf},o($Vg,[2,9]),o($Vj,$V3,{7:56,24:84}),o($Vk,$V3,{7:58,26:85}),{5:[2,32]},{5:[2,33]},{47:[2,28]},{21:[2,23]},{21:[2,21]}],
defaultActions: {5:[2,1],6:[2,2],32:[2,42],46:[2,30],47:[2,31],74:[2,34],75:[2,24],76:[2,25],81:[2,32],82:[2,33],83:[2,28],84:[2,23],85:[2,21]},
table: [{3:1,4:$V0,5:$V1,6:$V2},{1:[3]},{3:5,4:$V0,5:$V1,6:$V2},{3:6,4:$V0,5:$V1,6:$V2},o([1,4,5,10,15,16,18,20,22,23,24,26,30,41],$V3,{7:7}),{1:[2,1]},{1:[2,2]},{1:[2,3],4:$V4,5:$V5,8:8,9:10,10:$V6,11:23,14:13,15:$V7,16:$V8,17:16,18:$V9,20:$Va,22:$Vb,23:$Vc,24:$Vd,26:$Ve,30:$Vf,41:$Vg},o($Vh,[2,5]),{9:26,10:$V6,11:23,14:13,15:$V7,16:$V8,17:16,18:$V9,20:$Va,22:$Vb,23:$Vc,24:$Vd,26:$Ve,30:$Vf,41:$Vg},o($Vh,[2,7]),o($Vh,[2,8]),{11:27,41:$Vg},{5:[1,28]},{11:29,41:$Vg},{11:30,41:$Vg},{5:[1,31]},{19:32,48:$Vi},{13:[1,34]},{13:[1,35]},{13:[1,36]},{13:[1,37]},{13:[1,38]},{38:39,42:[1,40],43:[1,41],44:[1,42],45:[1,43],46:[1,44],47:[1,45]},{31:46,32:[1,47],36:[1,48],37:[1,49]},o([5,12,35,42,43,44,45,46,47,48],[2,36]),o($Vh,[2,6]),{5:[1,51],12:[1,50]},o($Vh,[2,11]),{5:[1,52]},{5:[1,53]},o($Vh,[2,14]),{5:[1,54]},{5:[2,43]},o($Vj,$V3,{7:55}),o($Vj,$V3,{7:56}),o($Vj,$V3,{7:57}),o($Vk,$V3,{25:58,7:59}),o($Vl,$V3,{27:60,7:61}),{11:64,39:[1,62],40:[1,63],41:$Vg},o($Vm,[2,37]),o($Vm,[2,38]),o($Vm,[2,39]),o($Vm,[2,40]),o($Vm,[2,41]),o($Vm,[2,42]),{11:65,41:$Vg},{11:67,33:66,41:$Vg},{41:[2,31]},{41:[2,32]},{13:[1,68]},o($Vh,[2,10]),o($Vh,[2,12]),o($Vh,[2,13]),o($Vh,[2,15]),{4:$V4,5:$V5,8:8,9:10,10:$V6,11:23,14:13,15:$V7,16:$V8,17:16,18:$V9,20:$Va,21:[1,69],22:$Vb,23:$Vc,24:$Vd,26:$Ve,30:$Vf,41:$Vg},{4:$V4,5:$V5,8:8,9:10,10:$V6,11:23,14:13,15:$V7,16:$V8,17:16,18:$V9,20:$Va,21:[1,70],22:$Vb,23:$Vc,24:$Vd,26:$Ve,30:$Vf,41:$Vg},{4:$V4,5:$V5,8:8,9:10,10:$V6,11:23,14:13,15:$V7,16:$V8,17:16,18:$V9,20:$Va,21:[1,71],22:$Vb,23:$Vc,24:$Vd,26:$Ve,30:$Vf,41:$Vg},{21:[1,72]},{4:$V4,5:$V5,8:8,9:10,10:$V6,11:23,14:13,15:$V7,16:$V8,17:16,18:$V9,20:$Va,21:[2,23],22:$Vb,23:$Vc,24:$Vd,26:$Ve,29:[1,73],30:$Vf,41:$Vg},{21:[1,74]},{4:$V4,5:$V5,8:8,9:10,10:$V6,11:23,14:13,15:$V7,16:$V8,17:16,18:$V9,20:$Va,21:[2,21],22:$Vb,23:$Vc,24:$Vd,26:$Ve,28:[1,75],30:$Vf,41:$Vg},{11:76,41:$Vg},{11:77,41:$Vg},{19:78,48:$Vi},{19:79,48:$Vi},{19:80,48:$Vi},{35:[1,81],48:[2,30]},{5:[1,82]},o($Vh,[2,16]),o($Vh,[2,17]),o($Vh,[2,18]),o($Vh,[2,19]),{13:[1,83]},o($Vh,[2,20]),{13:[1,84]},{19:85,48:$Vi},{19:86,48:$Vi},{5:[2,35]},{5:[2,25]},{5:[2,26]},{11:87,41:$Vg},o($Vh,[2,9]),o($Vk,$V3,{7:59,25:88}),o($Vl,$V3,{7:61,27:89}),{5:[2,33]},{5:[2,34]},{48:[2,29]},{21:[2,24]},{21:[2,22]}],
defaultActions: {5:[2,1],6:[2,2],33:[2,43],48:[2,31],49:[2,32],78:[2,35],79:[2,25],80:[2,26],85:[2,33],86:[2,34],87:[2,29],88:[2,24],89:[2,22]},
parseError: function parseError (str, hash) {
if (hash.recoverable) {
this.trace(str);
@ -252,15 +258,18 @@ parse: function parse(input) {
vstack.length = vstack.length - n;
lstack.length = lstack.length - n;
}
_token_stack:
var lex = function () {
function lex() {
var token;
token = lexer.lex() || EOF;
token = tstack.pop() || lexer.lex() || EOF;
if (typeof token !== 'number') {
if (token instanceof Array) {
tstack = token;
token = tstack.pop();
}
token = self.symbols_[token] || token;
}
return token;
};
}
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
while (true) {
state = stack[stack.length - 1];
@ -701,7 +710,7 @@ case 4:/* skip comments */
break;
case 5: this.begin('ID'); return 10;
break;
case 6: yy_.yytext = yy_.yytext.trim(); this.begin('ALIAS'); return 40;
case 6: yy_.yytext = yy_.yytext.trim(); this.begin('ALIAS'); return 41;
break;
case 7: this.popState(); this.popState(); this.begin('LINE'); return 12;
break;
@ -713,64 +722,66 @@ case 10: this.begin('LINE'); return 22;
break;
case 11: this.begin('LINE'); return 23;
break;
case 12: this.begin('LINE'); return 28;
case 12: this.begin('LINE'); return 24;
break;
case 13: this.begin('LINE'); return 25;
case 13: this.begin('LINE'); return 29;
break;
case 14: this.begin('LINE'); return 27;
case 14: this.begin('LINE'); return 26;
break;
case 15: this.popState(); return 13;
case 15: this.begin('LINE'); return 28;
break;
case 16:return 21;
case 16: this.popState(); return 13;
break;
case 17:return 35;
case 17:return 21;
break;
case 18:return 36;
break;
case 19:return 31;
case 19:return 37;
break;
case 20:return 29;
case 20:return 32;
break;
case 21: this.begin('ID'); return 15;
case 21:return 30;
break;
case 22: this.begin('ID'); return 16;
case 22: this.begin('ID'); return 15;
break;
case 23:return 18;
case 23: this.begin('ID'); return 16;
break;
case 24:return 6;
case 24:return 18;
break;
case 25:return 34;
case 25:return 6;
break;
case 26:return 5;
case 26:return 35;
break;
case 27: yy_.yytext = yy_.yytext.trim(); return 40;
case 27:return 5;
break;
case 28:return 43;
case 28: yy_.yytext = yy_.yytext.trim(); return 41;
break;
case 29:return 44;
break;
case 30:return 41;
case 30:return 45;
break;
case 31:return 42;
break;
case 32:return 45;
case 32:return 43;
break;
case 33:return 46;
break;
case 34:return 47;
break;
case 35:return 38;
case 35:return 48;
break;
case 36:return 39;
break;
case 37:return 5;
case 37:return 40;
break;
case 38:return 'INVALID';
case 38:return 5;
break;
case 39:return 'INVALID';
break;
}
},
rules: [/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:((?!\n)\s)+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:participant\b)/i,/^(?:[^\->:\n,;]+?(?=((?!\n)\s)+as(?!\n)\s|[#\n;]|$))/i,/^(?:as\b)/i,/^(?:(?:))/i,/^(?:loop\b)/i,/^(?:opt\b)/i,/^(?:alt\b)/i,/^(?:else\b)/i,/^(?:par\b)/i,/^(?:and\b)/i,/^(?:[^#\n;]*)/i,/^(?:end\b)/i,/^(?:left of\b)/i,/^(?:right of\b)/i,/^(?:over\b)/i,/^(?:note\b)/i,/^(?:activate\b)/i,/^(?:deactivate\b)/i,/^(?:title\b)/i,/^(?:sequenceDiagram\b)/i,/^(?:,)/i,/^(?:;)/i,/^(?:[^\+\->:\n,;]+)/i,/^(?:->>)/i,/^(?:-->>)/i,/^(?:->)/i,/^(?:-->)/i,/^(?:-[x])/i,/^(?:--[x])/i,/^(?::[^#\n;]+)/i,/^(?:\+)/i,/^(?:-)/i,/^(?:$)/i,/^(?:.)/i],
conditions: {"LINE":{"rules":[2,3,15],"inclusive":false},"ALIAS":{"rules":[2,3,7,8],"inclusive":false},"ID":{"rules":[2,3,6],"inclusive":false},"INITIAL":{"rules":[0,1,3,4,5,9,10,11,12,13,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"inclusive":true}}
rules: [/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:((?!\n)\s)+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:participant\b)/i,/^(?:[^\->:\n,;]+?(?=((?!\n)\s)+as(?!\n)\s|[#\n;]|$))/i,/^(?:as\b)/i,/^(?:(?:))/i,/^(?:loop\b)/i,/^(?:rect\b)/i,/^(?:opt\b)/i,/^(?:alt\b)/i,/^(?:else\b)/i,/^(?:par\b)/i,/^(?:and\b)/i,/^(?:[^#\n;]*)/i,/^(?:end\b)/i,/^(?:left of\b)/i,/^(?:right of\b)/i,/^(?:over\b)/i,/^(?:note\b)/i,/^(?:activate\b)/i,/^(?:deactivate\b)/i,/^(?:title\b)/i,/^(?:sequenceDiagram\b)/i,/^(?:,)/i,/^(?:;)/i,/^(?:[^\+\->:\n,;]+)/i,/^(?:->>)/i,/^(?:-->>)/i,/^(?:->)/i,/^(?:-->)/i,/^(?:-[x])/i,/^(?:--[x])/i,/^(?::[^#\n;]+)/i,/^(?:\+)/i,/^(?:-)/i,/^(?:$)/i,/^(?:.)/i],
conditions: {"LINE":{"rules":[2,3,16],"inclusive":false},"ALIAS":{"rules":[2,3,7,8],"inclusive":false},"ID":{"rules":[2,3,6],"inclusive":false},"INITIAL":{"rules":[0,1,3,4,5,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"inclusive":true}}
});
return lexer;
})();
@ -784,9 +795,9 @@ return new Parser;
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
exports.parser = sequenceDiagram;
exports.Parser = sequenceDiagram.Parser;
exports.parse = function () { return sequenceDiagram.parse.apply(sequenceDiagram, arguments); };
exports.parser = parser;
exports.Parser = parser.Parser;
exports.parse = function () { return parser.parse.apply(parser, arguments); };
exports.main = function commonjsMain (args) {
if (!args[1]) {
console.log('Usage: '+args[0]+' FILE');

View File

@ -66,7 +66,9 @@ export const LINETYPE = {
ACTIVE_END: 18,
PAR_START: 19,
PAR_AND: 20,
PAR_END: 21
PAR_END: 21,
RECT_START: 22,
RECT_END: 23
}
export const ARROWTYPE = {
@ -122,6 +124,12 @@ export const apply = function (param) {
case 'loopEnd':
addSignal(undefined, undefined, undefined, param.signalType)
break
case 'rectStart':
addSignal(undefined, undefined, param.color, param.signalType)
break
case 'rectEnd':
addSignal(undefined, undefined, undefined, param.signalType)
break
case 'optStart':
addSignal(undefined, undefined, param.optText, param.signalType)
break

View File

@ -369,6 +369,57 @@ describe('when parsing a sequenceDiagram', function () {
expect(messages[0].from).toBe('Alice')
expect(messages[1].from).toBe('Bob')
})
it('it should add a rect around sequence', function () {
const str = `
sequenceDiagram
Alice->Bob: Hello Bob, how are you?
%% Comment
rect rgb(200, 255, 200)
Note right of Bob: Bob thinks
Bob-->Alice: I am good thanks
end
`
parser.parse(str)
const actors = parser.yy.getActors()
expect(actors.Alice.description).toBe('Alice')
actors.Bob.description = 'Bob'
const messages = parser.yy.getMessages()
expect(messages[1].type).toEqual(parser.yy.LINETYPE.RECT_START)
expect(messages[1].message).toBe('rgb(200, 255, 200)')
expect(messages[2].type).toEqual(parser.yy.LINETYPE.NOTE)
expect(messages[3].type).toEqual(parser.yy.LINETYPE.DOTTED_OPEN)
expect(messages[4].type).toEqual(parser.yy.LINETYPE.RECT_END)
})
it('it should allow for nested rects', function () {
const str = `
sequenceDiagram
Alice->Bob: Hello Bob, how are you?
%% Comment
rect rgb(200, 255, 200)
rect rgb(0, 0, 0)
Note right of Bob: Bob thinks
end
Bob-->Alice: I am good thanks
end
`
parser.parse(str)
const actors = parser.yy.getActors()
expect(actors.Alice.description).toBe('Alice')
actors.Bob.description = 'Bob'
const messages = parser.yy.getMessages()
expect(messages[1].type).toEqual(parser.yy.LINETYPE.RECT_START)
expect(messages[1].message).toBe('rgb(200, 255, 200)')
expect(messages[2].type).toEqual(parser.yy.LINETYPE.RECT_START)
expect(messages[2].message).toBe('rgb(0, 0, 0)')
expect(messages[3].type).toEqual(parser.yy.LINETYPE.NOTE)
expect(messages[4].type).toEqual(parser.yy.LINETYPE.RECT_END)
expect(messages[5].type).toEqual(parser.yy.LINETYPE.DOTTED_OPEN)
expect(messages[6].type).toEqual(parser.yy.LINETYPE.RECT_END)
})
it('it should handle opt statements', function () {
const str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n\n' +
@ -929,6 +980,24 @@ describe('when rendering a sequenceDiagram', function () {
expect(bounds.stopx).toBe(0 + conf.width * 2 + conf.actorMargin)
expect(bounds.stopy).toBe(0 + 2 * conf.messageMargin + conf.height + 3 * conf.boxMargin + conf.boxTextMargin)
})
it('it should draw background rect', function () {
renderer.bounds.init()
const str = `
sequenceDiagram
Alice->Bob: Hello Bob, are you alright?
rect rgb(0, 0, 0)
Bob->Alice: I feel surrounded by darkness
end
`
parser.parse(str)
renderer.draw(str, 'tst')
const bounds = renderer.bounds.getBounds()
expect(bounds.startx).toBe(0)
expect(bounds.starty).toBe(0)
expect(bounds.stopx).toBe(0 + conf.width * 2 + conf.actorMargin)
expect(bounds.stopy).toBe(0 + 2 * conf.messageMargin + conf.height + 3 * conf.boxMargin)
})
})
describe('when rendering a sequenceDiagram with actor mirror activated', function () {

View File

@ -131,8 +131,8 @@ export const bounds = {
const activation = this.activations.splice(lastActorActivationIdx, 1)[0]
return activation
},
newLoop: function (title) {
this.sequenceItems.push({ startx: undefined, starty: this.verticalPos, stopx: undefined, stopy: undefined, title: title })
newLoop: function (title, fill) {
this.sequenceItems.push({ startx: undefined, starty: this.verticalPos, stopx: undefined, stopy: undefined, title: title, fill: fill })
},
endLoop: function () {
const loop = this.sequenceItems.pop()
@ -410,6 +410,16 @@ export const draw = function (text, id) {
svgDraw.drawLoop(diagram, loopData, 'loop', conf)
bounds.bumpVerticalPos(conf.boxMargin)
break
case parser.yy.LINETYPE.RECT_START:
bounds.bumpVerticalPos(conf.boxMargin)
bounds.newLoop(undefined, msg.message)
bounds.bumpVerticalPos(conf.boxMargin)
break
case parser.yy.LINETYPE.RECT_END:
const rectData = bounds.endLoop()
svgDraw.drawBackgroundRect(diagram, rectData)
bounds.bumpVerticalPos(conf.boxMargin)
break
case parser.yy.LINETYPE.OPT_START:
bounds.bumpVerticalPos(conf.boxMargin)
bounds.newLoop(msg.message)

View File

@ -167,6 +167,21 @@ export const drawLoop = function (elem, bounds, labelText, conf) {
}
}
/**
* Draws a background rectangle
* @param color - The fill color for the background
*/
export const drawBackgroundRect = function (elem, bounds) {
const rectElem = drawRect(elem, {
x: bounds.startx,
y: bounds.starty,
width: bounds.stopx - bounds.startx,
height: bounds.stopy - bounds.starty,
fill: bounds.fill,
class: 'rect'
})
rectElem.lower()
}
/**
* Setup arrow head and define the marker. The result is appended to the svg.
*/
@ -331,6 +346,7 @@ export default {
anchorElement,
drawActivation,
drawLoop,
drawBackgroundRect,
insertArrowHead,
insertSequenceNumber,
insertArrowCrossHead,

View File

@ -0,0 +1,76 @@
/* eslint-env jasmine */
const svgDraw = require('./svgDraw')
const { MockD3 } = require('d3')
describe('svgDraw', function () {
describe('drawRect', function () {
it('it should append a rectangle', function () {
const svg = MockD3('svg')
svgDraw.drawRect(svg, {
x: 10,
y: 10,
fill: '#ccc',
stroke: 'red',
width: '20',
height: '20',
rx: '10',
ry: '10',
class: 'unitTestRectangleClass'
})
expect(svg.__children.length).toBe(1)
const rect = svg.__children[0]
expect(rect.__name).toBe('rect')
expect(rect.attr).toHaveBeenCalledWith('x', 10)
expect(rect.attr).toHaveBeenCalledWith('y', 10)
expect(rect.attr).toHaveBeenCalledWith('fill', '#ccc')
expect(rect.attr).toHaveBeenCalledWith('stroke', 'red')
expect(rect.attr).toHaveBeenCalledWith('width', '20')
expect(rect.attr).toHaveBeenCalledWith('height', '20')
expect(rect.attr).toHaveBeenCalledWith('rx', '10')
expect(rect.attr).toHaveBeenCalledWith('ry', '10')
expect(rect.attr).toHaveBeenCalledWith('class', 'unitTestRectangleClass')
})
it('it should not add the class attribute if a class isn`t provided', () => {
const svg = MockD3('svg')
svgDraw.drawRect(svg, {
x: 10,
y: 10,
fill: '#ccc',
stroke: 'red',
width: '20',
height: '20',
rx: '10',
ry: '10'
})
expect(svg.__children.length).toBe(1)
const rect = svg.__children[0]
expect(rect.__name).toBe('rect')
expect(rect.attr).toHaveBeenCalledWith('fill', '#ccc')
expect(rect.attr).not.toHaveBeenCalledWith('class', expect.anything())
})
})
describe('drawBackgroundRect', function () {
it('it should append a rect before the previous element within a given bound', function () {
const svg = MockD3('svg')
const boundingRect = {
startx: 50,
starty: 200,
stopx: 150,
stopy: 260,
title: undefined,
fill: '#ccc'
}
svgDraw.drawBackgroundRect(svg, boundingRect)
expect(svg.__children.length).toBe(1)
const rect = svg.__children[0]
expect(rect.__name).toBe('rect')
expect(rect.attr).toHaveBeenCalledWith('x', 50)
expect(rect.attr).toHaveBeenCalledWith('y', 200)
expect(rect.attr).toHaveBeenCalledWith('width', 100)
expect(rect.attr).toHaveBeenCalledWith('height', 60)
expect(rect.attr).toHaveBeenCalledWith('fill', '#ccc')
expect(rect.attr).toHaveBeenCalledWith('class', 'rect')
expect(rect.lower).toHaveBeenCalled()
})
})
})