diff --git a/dist/dataflowchart.html b/dist/dataflowchart.html new file mode 100644 index 000000000..258a94201 --- /dev/null +++ b/dist/dataflowchart.html @@ -0,0 +1,53 @@ + + + + + + Mermaid Quick Test Page + + + + +

Data Flow Diagram Example

+
+ flowchart LR + DataStore[|borders:tb|Database] -->|input| Process((System)) -->|output| Entity[Customer]; +
+ +

Borders Example

+
+ flowchart TD + allSides[ stroke all sides ]; + allSides2[|borders:ltrb| stroke all sides ]; + rbSides[|borders:rb| stroke right and bottom sides ]; + ltSides[|borders:lt| stroke left and top sides ]; + lrSides[|borders:lr| stroke left and right sides ]; + noSide[|borders:no| stroke no side ]; +
+ + + + + + diff --git a/src/dagre-wrapper/nodes.js b/src/dagre-wrapper/nodes.js index b006f1343..40444f921 100644 --- a/src/dagre-wrapper/nodes.js +++ b/src/dagre-wrapper/nodes.js @@ -313,6 +313,8 @@ const rect = (parent, node) => { // add the rect const rect = shapeSvg.insert('rect', ':first-child'); + const totalWidth = bbox.width + node.padding; + const totalHeight = bbox.height + node.padding; rect .attr('class', 'basic label-container') .attr('style', node.style) @@ -320,8 +322,19 @@ const rect = (parent, node) => { .attr('ry', node.ry) .attr('x', -bbox.width / 2 - halfPadding) .attr('y', -bbox.height / 2 - halfPadding) - .attr('width', bbox.width + node.padding) - .attr('height', bbox.height + node.padding); + .attr('width', totalWidth) + .attr('height', totalHeight); + + if (node.props) { + const propKeys = new Set(Object.keys(node.props)); + if (node.props.borders) { + applyNodePropertyBorders(rect, node.props.borders, totalWidth, totalHeight); + propKeys.delete('borders'); + } + propKeys.forEach((propKey) => { + log.warn(`Unknown node property ${propKey}`); + }); + } updateNodeBounds(node, rect); @@ -332,6 +345,43 @@ const rect = (parent, node) => { return shapeSvg; }; +function applyNodePropertyBorders(rect, borders, totalWidth, totalHeight) { + const strokeDashArray = []; + const addBorder = (length) => { + strokeDashArray.push(length); + strokeDashArray.push(0); + }; + const skipBorder = (length) => { + strokeDashArray.push(0); + strokeDashArray.push(length); + }; + if (borders.includes('t')) { + log.debug('add top border'); + addBorder(totalWidth); + } else { + skipBorder(totalWidth); + } + if (borders.includes('r')) { + log.debug('add right border'); + addBorder(totalHeight); + } else { + skipBorder(totalHeight); + } + if (borders.includes('b')) { + log.debug('add bottom border'); + addBorder(totalWidth); + } else { + skipBorder(totalWidth); + } + if (borders.includes('l')) { + log.debug('add left border'); + addBorder(totalHeight); + } else { + skipBorder(totalHeight); + } + rect.attr('stroke-dasharray', strokeDashArray.join(' ')); +} + const rectWithTitle = (parent, node) => { // const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, 'node ' + node.classes); diff --git a/src/diagrams/flowchart/flowDb.js b/src/diagrams/flowchart/flowDb.js index ba326fb8a..e3b132b0c 100644 --- a/src/diagrams/flowchart/flowDb.js +++ b/src/diagrams/flowchart/flowDb.js @@ -52,8 +52,9 @@ export const lookUpDomId = function (id) { * @param style * @param classes * @param dir + * @param props */ -export const addVertex = function (_id, text, type, style, classes, dir) { +export const addVertex = function (_id, text, type, style, classes, dir, props = {}) { let txt; let id = _id; if (typeof id === 'undefined') { @@ -109,6 +110,7 @@ export const addVertex = function (_id, text, type, style, classes, dir) { if (typeof dir !== 'undefined') { vertices[id].dir = dir; } + vertices[id].props = props; }; /** diff --git a/src/diagrams/flowchart/flowRenderer-v2.js b/src/diagrams/flowchart/flowRenderer-v2.js index d7e55f0cf..b046d9c67 100644 --- a/src/diagrams/flowchart/flowRenderer-v2.js +++ b/src/diagrams/flowchart/flowRenderer-v2.js @@ -152,6 +152,7 @@ export const addVertices = function (vert, g, svgId) { width: vertex.type === 'group' ? 500 : undefined, dir: vertex.dir, type: vertex.type, + props: vertex.props, padding: getConfig().flowchart.padding, }); @@ -168,6 +169,7 @@ export const addVertices = function (vert, g, svgId) { width: vertex.type === 'group' ? 500 : undefined, type: vertex.type, dir: vertex.dir, + props: vertex.props, padding: getConfig().flowchart.padding, }); }); diff --git a/src/diagrams/flowchart/parser/flow.jison b/src/diagrams/flowchart/parser/flow.jison index a0b1b0019..b920720a4 100644 --- a/src/diagrams/flowchart/parser/flow.jison +++ b/src/diagrams/flowchart/parser/flow.jison @@ -118,6 +118,7 @@ that id. "])" return 'STADIUMEND'; "[[" return 'SUBROUTINESTART'; "]]" return 'SUBROUTINEEND'; +"[|" return 'VERTEX_WITH_PROPS_START'; "[(" return 'CYLINDERSTART'; ")]" return 'CYLINDEREND'; \- return 'MINUS'; @@ -380,6 +381,8 @@ vertex: idString SQS text SQE {$$ = $1;yy.addVertex($1,$3,'stadium');} | idString SUBROUTINESTART text SUBROUTINEEND {$$ = $1;yy.addVertex($1,$3,'subroutine');} + | idString VERTEX_WITH_PROPS_START ALPHA COLON ALPHA PIPE text SQE + {$$ = $1;yy.addVertex($1,$7,'rect',undefined,undefined,undefined, Object.fromEntries([[$3, $5]]));} | idString CYLINDERSTART text CYLINDEREND {$$ = $1;yy.addVertex($1,$3,'cylinder');} | idString PS text PE @@ -559,5 +562,5 @@ alphaNumToken : PUNCTUATION | AMP | UNICODE_TEXT | NUM| ALPHA | COLON | COMMA | idStringToken : ALPHA|UNDERSCORE |UNICODE_TEXT | NUM| COLON | COMMA | PLUS | MINUS | DOWN |EQUALS | MULT | BRKT | DOT | PUNCTUATION | AMP; -graphCodeTokens: STADIUMSTART | STADIUMEND | SUBROUTINESTART | SUBROUTINEEND | CYLINDERSTART | CYLINDEREND | 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 | SUBROUTINESTART | SUBROUTINEEND | VERTEX_WITH_PROPS_START | CYLINDERSTART | CYLINDEREND | 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; %%