From 38c5e65c35c32a370d707cfaef817a01f3ad941b Mon Sep 17 00:00:00 2001 From: Minoru Nakata Date: Thu, 2 Feb 2017 17:16:26 +0900 Subject: [PATCH] add par statement to sequenceDiagram --- .../parser/sequenceDiagram.jison | 16 +++++ src/diagrams/sequenceDiagram/sequenceDb.js | 15 ++++- .../sequenceDiagram/sequenceDiagram.spec.js | 58 +++++++++++++++++++ .../sequenceDiagram/sequenceRenderer.js | 27 +++++++-- src/diagrams/sequenceDiagram/svgDraw.js | 18 ++++-- test/examples/seq.html | 15 +++++ 6 files changed, 136 insertions(+), 13 deletions(-) diff --git a/src/diagrams/sequenceDiagram/parser/sequenceDiagram.jison b/src/diagrams/sequenceDiagram/parser/sequenceDiagram.jison index 58772eae3..8a0f9a9e5 100644 --- a/src/diagrams/sequenceDiagram/parser/sequenceDiagram.jison +++ b/src/diagrams/sequenceDiagram/parser/sequenceDiagram.jison @@ -34,6 +34,8 @@ "opt" { this.begin('LINE'); return 'opt'; } "alt" { this.begin('LINE'); return 'alt'; } "else" { this.begin('LINE'); return 'else'; } +"par" { this.begin('LINE'); return 'par'; } +"and" { this.begin('LINE'); return 'and'; } [^#\n;]* { this.popState(); return 'restOfLine'; } "end" return 'end'; "left of" return 'left_of'; @@ -115,6 +117,20 @@ statement $3.push({type: 'altEnd', signalType: yy.LINETYPE.ALT_END}); $$=$3;} + | par restOfLine par_sections end + { + // Parallel start + $3.unshift({type: 'parStart', parText:$2, signalType: yy.LINETYPE.PAR_START}); + // Content in par is already in $3 + // End + $3.push({type: 'parEnd', signalType: yy.LINETYPE.PAR_END}); + $$=$3;} + ; + +par_sections + : document + | document and restOfLine par_sections + { $$ = $1.concat([{type: 'and', parText:$3, signalType: yy.LINETYPE.PAR_AND}, $4]); } ; note_statement diff --git a/src/diagrams/sequenceDiagram/sequenceDb.js b/src/diagrams/sequenceDiagram/sequenceDb.js index 257d55c11..3734ef0e6 100644 --- a/src/diagrams/sequenceDiagram/sequenceDb.js +++ b/src/diagrams/sequenceDiagram/sequenceDb.js @@ -71,7 +71,10 @@ exports.LINETYPE = { OPT_START : 15 , OPT_END : 16 , ACTIVE_START : 17 , - ACTIVE_END : 18 + ACTIVE_END : 18 , + PAR_START : 19 , + PAR_AND : 20 , + PAR_END : 21 }; exports.ARROWTYPE = { @@ -156,6 +159,16 @@ exports.apply = function(param){ break; case 'setTitle': exports.setTitle(param.text); + break; + case 'parStart': + exports.addSignal(undefined, undefined, param.parText, param.signalType); + break; + case 'and': + exports.addSignal(undefined, undefined, param.parText, param.signalType); + break; + case 'parEnd': + exports.addSignal(undefined, undefined, undefined, param.signalType); + break; } } }; diff --git a/src/diagrams/sequenceDiagram/sequenceDiagram.spec.js b/src/diagrams/sequenceDiagram/sequenceDiagram.spec.js index b66644e53..302dbaa5b 100644 --- a/src/diagrams/sequenceDiagram/sequenceDiagram.spec.js +++ b/src/diagrams/sequenceDiagram/sequenceDiagram.spec.js @@ -448,6 +448,32 @@ describe('when parsing a sequenceDiagram',function() { expect(messages[0].from).toBe('Alice'); expect(messages[1].from).toBe('Bob'); }); + it('it should handle par statements a sequenceDiagram', function () { + var str = 'sequenceDiagram\n' + + 'par Parallel one\n' + + 'Alice->>Bob: Hello Bob, how are you?\n' + + 'Bob-->>Alice: I am good thanks!\n' + + 'and Parallel two\n' + + 'Alice->>Bob: Are you OK?\n' + + 'Bob-->>Alice: Fine!\n' + + 'and Parallel three\n' + + 'Alice->>Bob: What do you think about it?\n' + + 'Bob-->>Alice: It\'s good!\n' + + 'end'; + + sq.parse(str); + var actors = sq.yy.getActors(); + + expect(actors.Alice.description).toBe('Alice'); + expect(actors.Bob.description).toBe('Bob'); + + var messages = sq.yy.getMessages(); + + expect(messages.length).toBe(10); + expect(messages[0].message).toBe('Parallel one'); + expect(messages[1].from).toBe('Alice'); + expect(messages[2].from).toBe('Bob'); + }); it('it should handle special characters in signals', function () { var str = 'sequenceDiagram\n' + 'Alice->Bob: -:<>,;# comment'; @@ -506,6 +532,21 @@ describe('when parsing a sequenceDiagram',function() { expect(messages[1].message).toBe('-:<>,'); expect(messages[3].message).toBe(',<>:-'); }); + it('it should handle special characters in par', function () { + var str = 'sequenceDiagram\n' + + 'Alice->Bob: Hello Bob, how are you?\n' + + 'par -:<>,;# comment\n' + + 'Bob-->Alice: I am good thanks!\n' + + 'and ,<>:-#; comment\n' + + 'Bob-->Alice: I am good thanks!\n' + + 'end'; + + sq.parse(str); + + var messages = sq.yy.getMessages(); + expect(messages[1].message).toBe('-:<>,'); + expect(messages[3].message).toBe(',<>:-'); + }); it('it should handle no-label loop', function () { var str = 'sequenceDiagram\n' + 'Alice->Bob: Hello Bob, how are you?\n' + @@ -543,6 +584,23 @@ describe('when parsing a sequenceDiagram',function() { sq.parse(str); + var messages = sq.yy.getMessages(); + expect(messages[1].message).toBe(''); + expect(messages[2].message).toBe('I am good thanks!'); + expect(messages[3].message).toBe(''); + expect(messages[4].message).toBe('I am good thanks!'); + }); + it('it should handle no-label par', function () { + var str = 'sequenceDiagram\n' + + 'Alice->Bob: Hello Bob, how are you?\n' + + 'par;' + + 'Bob-->Alice: I am good thanks!\n' + + 'and # comment\n' + + 'Bob-->Alice: I am good thanks!\n' + + 'end'; + + sq.parse(str); + var messages = sq.yy.getMessages(); expect(messages[1].message).toBe(''); expect(messages[2].message).toBe('I am good thanks!'); diff --git a/src/diagrams/sequenceDiagram/sequenceRenderer.js b/src/diagrams/sequenceDiagram/sequenceRenderer.js index 0253412d9..a690d7e53 100644 --- a/src/diagrams/sequenceDiagram/sequenceRenderer.js +++ b/src/diagrams/sequenceDiagram/sequenceRenderer.js @@ -134,10 +134,12 @@ exports.bounds = { var loop = this.sequenceItems.pop(); return loop; }, - addElseToLoop:function(message){ + addSectionToLoop: function(message) { var loop = this.sequenceItems.pop(); - loop.elsey = exports.bounds.getVerticalPos(); - loop.elseText = message; + loop.sections = loop.sections || []; + loop.sectionTitles = loop.sectionTitles || []; + loop.sections.push(exports.bounds.getVerticalPos()); + loop.sectionTitles.push(message); this.sequenceItems.push(loop); }, bumpVerticalPos:function(bump){ @@ -424,10 +426,8 @@ module.exports.draw = function (text, id) { exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin); break; case sq.yy.LINETYPE.ALT_ELSE: - - //exports.drawLoop(diagram, loopData); exports.bounds.bumpVerticalPos(conf.boxMargin); - loopData = exports.bounds.addElseToLoop(msg.message); + loopData = exports.bounds.addSectionToLoop(msg.message); exports.bounds.bumpVerticalPos(conf.boxMargin); break; case sq.yy.LINETYPE.ALT_END: @@ -436,6 +436,21 @@ module.exports.draw = function (text, id) { svgDraw.drawLoop(diagram, loopData,'alt', conf); exports.bounds.bumpVerticalPos(conf.boxMargin); break; + case sq.yy.LINETYPE.PAR_START: + exports.bounds.bumpVerticalPos(conf.boxMargin); + exports.bounds.newLoop(msg.message); + exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin); + break; + case sq.yy.LINETYPE.PAR_AND: + exports.bounds.bumpVerticalPos(conf.boxMargin); + loopData = exports.bounds.addSectionToLoop(msg.message); + exports.bounds.bumpVerticalPos(conf.boxMargin); + break; + case sq.yy.LINETYPE.PAR_END: + loopData = exports.bounds.endLoop(); + svgDraw.drawLoop(diagram, loopData, 'par', conf); + exports.bounds.bumpVerticalPos(conf.boxMargin); + break; default: try { lastMsg = msg; diff --git a/src/diagrams/sequenceDiagram/svgDraw.js b/src/diagrams/sequenceDiagram/svgDraw.js index cd0838cdb..b5870d42f 100644 --- a/src/diagrams/sequenceDiagram/svgDraw.js +++ b/src/diagrams/sequenceDiagram/svgDraw.js @@ -158,8 +158,10 @@ exports.drawLoop = function(elem,bounds,labelText, conf){ drawLoopLine(bounds.stopx , bounds.starty, bounds.stopx , bounds.stopy ); drawLoopLine(bounds.startx, bounds.stopy , bounds.stopx , bounds.stopy ); drawLoopLine(bounds.startx, bounds.starty, bounds.startx, bounds.stopy ); - if(typeof bounds.elsey !== 'undefined'){ - drawLoopLine(bounds.startx, bounds.elsey, bounds.stopx, bounds.elsey).style('stroke-dasharray', '3, 3'); + if (typeof bounds.sections !== 'undefined') { + bounds.sections.forEach(function(item) { + drawLoopLine(bounds.startx, item, bounds.stopx, item).style('stroke-dasharray', '3, 3'); + }); } var txt = exports.getTextObj(); @@ -181,10 +183,14 @@ exports.drawLoop = function(elem,bounds,labelText, conf){ exports.drawText(g,txt); - if (typeof bounds.elseText !== 'undefined' && bounds.elseText !== "") { - txt.text = '[ ' + bounds.elseText + ' ]'; - txt.y = bounds.elsey + 1.5 * conf.boxMargin; - exports.drawText(g, txt); + if (typeof bounds.sectionTitles !== 'undefined') { + bounds.sectionTitles.forEach(function(item, idx) { + if (item !== '') { + txt.text = '[ ' + item + ' ]'; + txt.y = bounds.sections[idx] + 1.5 * conf.boxMargin; + exports.drawText(g, txt); + } + }); } }; diff --git a/test/examples/seq.html b/test/examples/seq.html index 683814e91..a4b6225ad 100644 --- a/test/examples/seq.html +++ b/test/examples/seq.html @@ -122,6 +122,21 @@ Alice->>John the Long: Yes... John, how are you? John the Long-->>Alice: Super! + +

Parallel

+
+ sequenceDiagram + par Parallel one + Alice->>Bob: Hello Bob, how are you? + Bob-->>Alice: I am good thanks! + and Parallel two + Alice->>Bob: Are you OK? + Bob-->>Alice: Fine! + and Parallel three + Alice->>Bob: What do you think about it? + Bob-->>Alice: It's good! + end +