diff --git a/dist/index.html b/dist/index.html index 2fb6f2ab6..eb27c6593 100644 --- a/dist/index.html +++ b/dist/index.html @@ -300,6 +300,19 @@ click B testClick "click test" classDef someclass fill:#f96; class A someclass; +
+ graph TD + A([stadium shape test]) + A -->|Get money| B([Go shopping]) + B --> C([Let me think...
Do I want something for work,
something to spend every free second with,
or something to get around?]) + C -->|One| D([Laptop]) + C -->|Two| E([iPhone]) + C -->|Three| F([Car
wroom wroom]) + click A "index.html#link-clicked" "link test" + click B testClick "click test" + classDef someclass fill:#f96; + class A someclass; +

diff --git a/docs/flowchart.md b/docs/flowchart.md index a8e40a145..7f0603008 100644 --- a/docs/flowchart.md +++ b/docs/flowchart.md @@ -78,6 +78,17 @@ graph LR id1(This is the text in the box) ``` +### A stadium-shaped node + +``` +graph LR + id1([This is the text in the box]) +``` +```mermaid +graph LR + id1([This is the text in the box]) +``` + ### A node in the form of a circle ``` diff --git a/src/diagrams/flowchart/flowChartShapes.js b/src/diagrams/flowchart/flowChartShapes.js index ed69c4801..1da63ebe3 100644 --- a/src/diagrams/flowchart/flowChartShapes.js +++ b/src/diagrams/flowchart/flowChartShapes.js @@ -135,9 +135,29 @@ function rect_right_inv_arrow(parent, bbox, node) { return shapeSvg; } +function stadium(parent, bbox, node) { + const h = bbox.height; + const w = bbox.width + h / 4; + + const shapeSvg = parent + .insert('rect', ':first-child') + .attr('rx', h / 2) + .attr('ry', h / 2) + .attr('x', -w / 2) + .attr('y', -h / 2) + .attr('width', w) + .attr('height', h); + + node.intersect = function(point) { + return dagreD3.intersect.rect(node, point); + }; + return shapeSvg; +} + export function addToRender(render) { render.shapes().question = question; render.shapes().hexagon = hexagon; + render.shapes().stadium = stadium; // Add custom shape for box with inverted arrow on left side render.shapes().rect_left_inv_arrow = rect_left_inv_arrow; diff --git a/src/diagrams/flowchart/flowChartShapes.spec.js b/src/diagrams/flowchart/flowChartShapes.spec.js index de3f05a1d..415a4f026 100644 --- a/src/diagrams/flowchart/flowChartShapes.spec.js +++ b/src/diagrams/flowchart/flowChartShapes.spec.js @@ -1,6 +1,29 @@ import { addToRender } from './flowChartShapes'; describe('flowchart shapes', function() { + // rect-based shapes + [ + ['stadium', useWidth, useHeight] + ].forEach(function([shapeType, getW, getH]) { + it(`should add a ${shapeType} shape that renders a properly positioned rect element`, function() { + const mockRender = MockRender(); + const mockSvg = MockSvg(); + addToRender(mockRender); + + [[100, 100], [123, 45], [71, 300]].forEach(function([width, height]) { + const shape = mockRender.shapes()[shapeType](mockSvg, { width, height }, {}); + const w = width + height / 4; + const h = height; + const dx = -getW(w, h) / 2; + const dy = -getH(w, h) / 2; + expect(shape.__tag).toEqual('rect'); + expect(shape.__attrs).toHaveProperty('x', dx); + expect(shape.__attrs).toHaveProperty('y', dy); + }); + }); + }); + + // polygon-based shapes [ [ 'question', diff --git a/src/diagrams/flowchart/flowRenderer.js b/src/diagrams/flowchart/flowRenderer.js index 99eda4b3f..ee680532f 100644 --- a/src/diagrams/flowchart/flowRenderer.js +++ b/src/diagrams/flowchart/flowRenderer.js @@ -154,6 +154,9 @@ export const addVertices = function(vert, g, svgId) { case 'ellipse': _shape = 'ellipse'; break; + case 'stadium': + _shape = 'stadium'; + break; case 'group': _shape = 'rect'; break; diff --git a/src/diagrams/flowchart/flowRenderer.spec.js b/src/diagrams/flowchart/flowRenderer.spec.js index e1c1931a6..0e49dbf71 100644 --- a/src/diagrams/flowchart/flowRenderer.spec.js +++ b/src/diagrams/flowchart/flowRenderer.spec.js @@ -22,6 +22,7 @@ describe('the flowchart renderer', function() { ['odd_right', 'rect_left_inv_arrow'], ['circle', 'circle'], ['ellipse', 'ellipse'], + ['stadium', 'stadium'], ['group', 'rect'] ].forEach(function([type, expectedShape, expectedRadios = 0]) { it(`should add the correct shaped node to the graph for vertex type ${type}`, function() { diff --git a/src/diagrams/flowchart/parser/flow.jison b/src/diagrams/flowchart/parser/flow.jison index 80a53b01a..ec67972cf 100644 --- a/src/diagrams/flowchart/parser/flow.jison +++ b/src/diagrams/flowchart/parser/flow.jison @@ -82,6 +82,8 @@ \s*\=\=\s* return '=='; "(-" return '(-'; "-)" return '-)'; +"([" return 'STADIUMSTART'; +"])" return 'STADIUMEND'; \- return 'MINUS'; "." return 'DOT'; [\_] return 'UNDERSCORE'; @@ -96,8 +98,8 @@ [A-Za-z]+ return 'ALPHA'; "\\]" return 'TRAPEND'; "[/" return 'TRAPSTART'; -"/]" return 'INVTRAPEND'; -"[\\" return 'INVTRAPSTART'; +"/]" return 'INVTRAPEND'; +"[\\" return 'INVTRAPSTART'; [!"#$%&'*+,-.`?\\_/] return 'PUNCTUATION'; [\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]| [\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]| @@ -305,6 +307,10 @@ vertex: idString SQS text SQE {$$ = $1;yy.addVertex($1,$3,'ellipse');} | idString '(-' text '-)' spaceList {$$ = $1;yy.addVertex($1,$3,'ellipse');} + | idString STADIUMSTART text STADIUMEND + {$$ = $1;yy.addVertex($1,$3,'stadium');} + | idString STADIUMSTART text STADIUMEND spaceList + {$$ = $1;yy.addVertex($1,$3,'stadium');} | idString PS text PE {$$ = $1;yy.addVertex($1,$3,'round');} | idString PS text PE spaceList @@ -563,5 +569,5 @@ alphaNumToken : PUNCTUATION | UNICODE_TEXT | NUM| ALPHA | COLON | COMMA | PLUS idStringToken : ALPHA|UNDERSCORE |UNICODE_TEXT | NUM| COLON | COMMA | PLUS | MINUS | DOWN |EQUALS | MULT | BRKT | DOT | PUNCTUATION; -graphCodeTokens: TRAPSTART | TRAPEND | INVTRAPSTART | INVTRAPEND | PIPE | PS | PE | SQS | SQE | DIAMOND_START | DIAMOND_STOP | TAGSTART | TAGEND | ARROW_CROSS | ARROW_POINT | ARROW_CIRCLE | ARROW_OPEN | QUOTE | SEMI ; +graphCodeTokens: STADIUMSTART | STADIUMEND | TRAPSTART | TRAPEND | INVTRAPSTART | INVTRAPEND | PIPE | PS | PE | SQS | SQE | DIAMOND_START | DIAMOND_STOP | TAGSTART | TAGEND | ARROW_CROSS | ARROW_POINT | ARROW_CIRCLE | ARROW_OPEN | QUOTE | SEMI; %%