From 78e4fead49736d0f52a0649792a7d28a06987f3b Mon Sep 17 00:00:00 2001 From: Itprdev Date: Thu, 28 Nov 2019 16:12:45 +0200 Subject: [PATCH 01/25] Feature request 552. Gnatt chart task with multiple dependencies --- src/diagrams/gantt/ganttDb.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/diagrams/gantt/ganttDb.js b/src/diagrams/gantt/ganttDb.js index 90f5066a0..c5b266414 100644 --- a/src/diagrams/gantt/ganttDb.js +++ b/src/diagrams/gantt/ganttDb.js @@ -134,18 +134,32 @@ const getStartDate = function(prevTime, dateFormat, str) { str = str.trim(); // Test for after - const re = /^after\s+([\d\w-]+)/; + const re = /^after\s+([\d\w- ]+)/; const afterStatement = re.exec(str.trim()); if (afterStatement !== null) { - const task = findTaskById(afterStatement[1]); + // check all after ids and take the latest + let latestEndingTask = null; + afterStatement[1].split(' ').forEach(function(id) { + let task = findTaskById(id); + if (typeof task !== 'undefined') { + if (!latestEndingTask) { + latestEndingTask = task; + } else { + if (task.endTime > latestEndingTask.endTime) { + latestEndingTask = task; + } + } + } + }); - if (typeof task === 'undefined') { + if (!latestEndingTask) { const dt = new Date(); dt.setHours(0, 0, 0, 0); return dt; + } else { + return latestEndingTask.endTime; } - return task.endTime; } // Check for actual date set From 6b5185abfbb20e2a01e418b890e4953201cbff74 Mon Sep 17 00:00:00 2001 From: Christian Klemm Date: Fri, 6 Dec 2019 21:41:16 +0100 Subject: [PATCH 02/25] Create pull_request_template.md --- .github/pull_request_template.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..c49956d65 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,7 @@ +## Summary +Brief description about the content of your PR. + +## Design Descisions +Describe the way your implementation works or what design descisions you made if applicable. + +Resolves # From 9a0df5afb0198fd0ce3c4e0672b9e9f1d392f383 Mon Sep 17 00:00:00 2001 From: Marc Faber Date: Sun, 8 Dec 2019 16:51:47 +0100 Subject: [PATCH 03/25] #723 Add stadium shape for flowchart nodes --- dist/index.html | 13 +++++++++++ docs/flowchart.md | 11 +++++++++ src/diagrams/flowchart/flowChartShapes.js | 20 ++++++++++++++++ .../flowchart/flowChartShapes.spec.js | 23 +++++++++++++++++++ src/diagrams/flowchart/flowRenderer.js | 3 +++ src/diagrams/flowchart/flowRenderer.spec.js | 1 + src/diagrams/flowchart/parser/flow.jison | 12 +++++++--- 7 files changed, 80 insertions(+), 3 deletions(-) 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; %% From 6fdf30357c625e53d194761351b2de072fe3d8df Mon Sep 17 00:00:00 2001 From: Justin Greywolf Date: Mon, 9 Dec 2019 17:41:26 -0800 Subject: [PATCH 04/25] 1104-Add support to designate a method as abstract Added logic to allow rendering of a method name with italics or underline based on modifier at beginning of name to set css style --- .../rendering/classDiagram.spec.js | 24 +++++++++++++++ docs/classDiagram.md | 30 ++++++++++++------- src/diagrams/class/classDiagram.spec.js | 22 ++++++++++++++ src/diagrams/class/classRenderer.js | 22 +++++++++++++- 4 files changed, 86 insertions(+), 12 deletions(-) diff --git a/cypress/integration/rendering/classDiagram.spec.js b/cypress/integration/rendering/classDiagram.spec.js index 29c4aba86..b2a0f6e0a 100644 --- a/cypress/integration/rendering/classDiagram.spec.js +++ b/cypress/integration/rendering/classDiagram.spec.js @@ -163,4 +163,28 @@ describe('Class diagram', () => { ); cy.get('svg'); }); + + it('5: should render a simple class diagram with abstract method', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : |someMethod() + `, + {} + ); + cy.get('svg'); + }); + + it('6: should render a simple class diagram with static method', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : $someMethod() + `, + {} + ); + cy.get('svg'); + }); }); diff --git a/docs/classDiagram.md b/docs/classDiagram.md index 6e838c6cd..c86685baf 100644 --- a/docs/classDiagram.md +++ b/docs/classDiagram.md @@ -105,17 +105,10 @@ Naming convention: a class name should be composed of alphanumeric (unicode allo UML provides mechanisms to represent class members, such as attributes and methods, and additional information about them. -#### Visibility -To specify the visibility of a class member (i.e. any attribute or method), these notations may be placed before the member's name, but is it optional: +Mermaid distinguishes between attributes and functions/methods based on if the **parenthesis** `()` are present or not. The ones with `()` are treated as functions/methods, and others as attributes. -- `+` Public -- `-` Private -- `#` Protected -- `~` Package -Mermaid distinguishes between attributes and functions/methods based on if the **parenthesis** `()` are present or not. The one with `()` are treated as functions/methods, and others as attributes. - -There are two ways to define the members of a class, and regardless of the whichever syntax is used to define the members, the output will still be same. The two different ways are : +There are two ways to define the members of a class, and regardless of whichever syntax is used to define the members, the output will still be same. The two different ways are : - Associate a member of a class using **:** (colon) followed by member name, useful to define one member at a time. For example: ``` @@ -125,7 +118,7 @@ There are two ways to define the members of a class, and regardless of the which BankAccount : +deposit(amount) BankAccount : +withdrawl(amount) ``` - ```mermaid + ``` mermaid classDiagram class BankAccount BankAccount : +String owner @@ -150,7 +143,22 @@ class BankAccount{ +BigDecimal balance +deposit(amount) +withdrawl(amount) -}``` +} +``` + + +#### Visibility +To specify the visibility of a class member (i.e. any attribute or method), these notations may be placed before the member's name, but it is optional: + +- `+` Public +- `-` Private +- `#` Protected +- `~` Package + +>_note_ you can also add additional _classifers_ to a method definition using the following notations (similar to visibliity above): +> - `|` Abstract e.g.: `|someAbstractMethod()` +> - `$` Static e.g.: `$someStaticMethod()` + ## Defining Relationship A relationship is a general term covering the specific types of logical connections found on class and object diagrams. diff --git a/src/diagrams/class/classDiagram.spec.js b/src/diagrams/class/classDiagram.spec.js index a1089d3d7..7c9252dc7 100644 --- a/src/diagrams/class/classDiagram.spec.js +++ b/src/diagrams/class/classDiagram.spec.js @@ -400,5 +400,27 @@ describe('class diagram, ', function () { expect(testClass.methods[0]).toBe('test()'); expect(testClass.methods[1]).toBe('foo()'); }); + + it('should handle abstract methods', function () { + const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : |someMethod()'; + parser.parse(str); + + const testClass = parser.yy.getClass('Class1'); + expect(testClass.annotations.length).toBe(0); + expect(testClass.members.length).toBe(0); + expect(testClass.methods.length).toBe(1); + expect(testClass.methods[0]).toBe('|someMethod()'); + }); + + it('should handle static methods', function () { + const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : $someMethod()'; + parser.parse(str); + + const testClass = parser.yy.getClass('Class1'); + expect(testClass.annotations.length).toBe(0); + expect(testClass.members.length).toBe(0); + expect(testClass.methods.length).toBe(1); + expect(testClass.methods[0]).toBe('$someMethod()'); + }); }); }); diff --git a/src/diagrams/class/classRenderer.js b/src/diagrams/class/classRenderer.js index 9814237c4..78a4c4332 100644 --- a/src/diagrams/class/classRenderer.js +++ b/src/diagrams/class/classRenderer.js @@ -281,10 +281,30 @@ const drawClass = function(elem, classDef) { logger.info('Rendering class ' + classDef); const addTspan = function(textEl, txt, isFirst) { + let displayText = txt; + let cssStyle = ''; + let classifier = txt.substring(0 , 1); + + switch (classifier) { + case '|': + cssStyle = 'font-style:italic;'; + displayText = txt.substring(1); + break; + case '$': + cssStyle = 'text-decoration:underline;'; + displayText = txt.substring(1); + break; + } + const tSpan = textEl .append('tspan') .attr('x', conf.padding) - .text(txt); + .text(displayText); + + if (cssStyle !== '') { + tSpan.attr('style', cssStyle); + } + if (!isFirst) { tSpan.attr('dy', conf.textHeight); } From 5b2f9351c77b26a539fcf323d239d93de0aa5d38 Mon Sep 17 00:00:00 2001 From: Justin Greywolf Date: Mon, 9 Dec 2019 18:13:06 -0800 Subject: [PATCH 05/25] Add support for abstract methods Added logic to allow rendering of a method name with italics or underline based on modifier at beginning of name to set css style --- .../rendering/classDiagram.spec.js | 4 +-- docs/classDiagram.md | 6 ++-- src/diagrams/class/classDb.js | 2 +- src/diagrams/class/classDiagram.spec.js | 8 ++--- src/diagrams/class/classRenderer.js | 30 +++++++++++-------- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/cypress/integration/rendering/classDiagram.spec.js b/cypress/integration/rendering/classDiagram.spec.js index b2a0f6e0a..b4ec832e3 100644 --- a/cypress/integration/rendering/classDiagram.spec.js +++ b/cypress/integration/rendering/classDiagram.spec.js @@ -169,7 +169,7 @@ describe('Class diagram', () => { ` classDiagram Class01 <|-- AveryLongClass : Cool - Class01 : |someMethod() + Class01 : someMethod()* `, {} ); @@ -181,7 +181,7 @@ describe('Class diagram', () => { ` classDiagram Class01 <|-- AveryLongClass : Cool - Class01 : $someMethod() + Class01 : someMethod()$ `, {} ); diff --git a/docs/classDiagram.md b/docs/classDiagram.md index c86685baf..dc61f79cf 100644 --- a/docs/classDiagram.md +++ b/docs/classDiagram.md @@ -155,9 +155,9 @@ To specify the visibility of a class member (i.e. any attribute or method), thes - `#` Protected - `~` Package ->_note_ you can also add additional _classifers_ to a method definition using the following notations (similar to visibliity above): -> - `|` Abstract e.g.: `|someAbstractMethod()` -> - `$` Static e.g.: `$someStaticMethod()` +>_note_ you can also include additional _classifers_ to a method definition by adding the following notations to the end of the method, i.e.: after the `()`: +> - `*` Abstract e.g.: `someAbstractMethod()*` +> - `$` Static e.g.: `someStaticMethod()$` ## Defining Relationship diff --git a/src/diagrams/class/classDb.js b/src/diagrams/class/classDb.js index 6cfbcf3f4..c04c3a78b 100644 --- a/src/diagrams/class/classDb.js +++ b/src/diagrams/class/classDb.js @@ -72,7 +72,7 @@ export const addMember = function(className, member) { if (memberString.startsWith('<<') && memberString.endsWith('>>')) { // Remove leading and trailing brackets theClass.annotations.push(memberString.substring(2, memberString.length - 2)); - } else if (memberString.endsWith(')')) { + } else if (memberString.indexOf(')') > 0) { theClass.methods.push(memberString); } else if (memberString) { theClass.members.push(memberString); diff --git a/src/diagrams/class/classDiagram.spec.js b/src/diagrams/class/classDiagram.spec.js index 7c9252dc7..ebdf381b0 100644 --- a/src/diagrams/class/classDiagram.spec.js +++ b/src/diagrams/class/classDiagram.spec.js @@ -402,25 +402,25 @@ describe('class diagram, ', function () { }); it('should handle abstract methods', function () { - const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : |someMethod()'; + const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()*'; parser.parse(str); const testClass = parser.yy.getClass('Class1'); expect(testClass.annotations.length).toBe(0); expect(testClass.members.length).toBe(0); expect(testClass.methods.length).toBe(1); - expect(testClass.methods[0]).toBe('|someMethod()'); + expect(testClass.methods[0]).toBe('someMethod()*'); }); it('should handle static methods', function () { - const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : $someMethod()'; + const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()$'; parser.parse(str); const testClass = parser.yy.getClass('Class1'); expect(testClass.annotations.length).toBe(0); expect(testClass.members.length).toBe(0); expect(testClass.methods.length).toBe(1); - expect(testClass.methods[0]).toBe('$someMethod()'); + expect(testClass.methods[0]).toBe('someMethod()$'); }); }); }); diff --git a/src/diagrams/class/classRenderer.js b/src/diagrams/class/classRenderer.js index 78a4c4332..9184574dd 100644 --- a/src/diagrams/class/classRenderer.js +++ b/src/diagrams/class/classRenderer.js @@ -283,24 +283,28 @@ const drawClass = function(elem, classDef) { const addTspan = function(textEl, txt, isFirst) { let displayText = txt; let cssStyle = ''; - let classifier = txt.substring(0 , 1); - - switch (classifier) { - case '|': - cssStyle = 'font-style:italic;'; - displayText = txt.substring(1); - break; - case '$': - cssStyle = 'text-decoration:underline;'; - displayText = txt.substring(1); - break; + let methodEnd = txt.indexOf(')') + 1; + + if (methodEnd > 1 && methodEnd <= txt.length) { + let classifier = txt.substring(methodEnd); + + switch (classifier) { + case '*': + cssStyle = 'font-style:italic;'; + break; + case '$': + cssStyle = 'text-decoration:underline;'; + break; + } + + displayText = txt.substring(0, methodEnd); } - + const tSpan = textEl .append('tspan') .attr('x', conf.padding) .text(displayText); - + if (cssStyle !== '') { tSpan.attr('style', cssStyle); } From 0deae4abf9674be4831dd4cbf18468c704999f12 Mon Sep 17 00:00:00 2001 From: Marc Faber Date: Tue, 10 Dec 2019 03:34:40 +0100 Subject: [PATCH 06/25] #910 set correct position and style for edge labels when using linkStyle, #1088 handle multiline texts in edge labels when using linkStyle --- dist/index.html | 12 +++++++++ src/diagrams/flowchart/flowRenderer.js | 22 +++++++-------- src/diagrams/flowchart/flowRenderer.spec.js | 30 ++++++++++++++++++++- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/dist/index.html b/dist/index.html index eb27c6593..615c9a537 100644 --- a/dist/index.html +++ b/dist/index.html @@ -313,6 +313,18 @@ class A someclass; classDef someclass fill:#f96; class A someclass; +
+ graph LR + A1[Multi
Line] -->|Multi
Line| B1(Multi
Line) + C1[Multi
Line] -->|Multi
Line| D1(Multi
Line) + E1[Multi
Line] -->|Multi
Line| F1(Multi
Line) + A2[Multi
Line] -->|Multi
Line| B2(Multi
Line) + C2[Multi
Line] -->|Multi
Line| D2(Multi
Line) + E2[Multi
Line] -->|Multi
Line| F2(Multi
Line) + linkStyle 0 stroke:DarkGray,stroke-width:2px + linkStyle 1 stroke:DarkGray,stroke-width:2px + linkStyle 2 stroke:DarkGray,stroke-width:2px +

diff --git a/src/diagrams/flowchart/flowRenderer.js b/src/diagrams/flowchart/flowRenderer.js index ee680532f..524742b39 100644 --- a/src/diagrams/flowchart/flowRenderer.js +++ b/src/diagrams/flowchart/flowRenderer.js @@ -239,18 +239,18 @@ export const addEdges = function(edges, g) { } } else { edgeData.arrowheadStyle = 'fill: #333'; - if (typeof edge.style === 'undefined') { - edgeData.labelpos = 'c'; - if (getConfig().flowchart.htmlLabels) { - edgeData.labelType = 'html'; - edgeData.label = '' + edge.text + ''; - } else { - edgeData.labelType = 'text'; - edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none'; - edgeData.label = edge.text.replace(/
/g, '\n'); - } + edgeData.labelpos = 'c'; + + if (getConfig().flowchart.htmlLabels) { + edgeData.labelType = 'html'; + edgeData.label = '' + edge.text + ''; } else { - edgeData.label = edge.text.replace(/
/g, '\n'); + edgeData.labelType = 'text'; + edgeData.label = edge.text.replace(/
/g, '\n'); + + if (typeof edge.style === 'undefined') { + edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none'; + } } } // Add the edge to the graph diff --git a/src/diagrams/flowchart/flowRenderer.spec.js b/src/diagrams/flowchart/flowRenderer.spec.js index 0e49dbf71..fe31292cc 100644 --- a/src/diagrams/flowchart/flowRenderer.spec.js +++ b/src/diagrams/flowchart/flowRenderer.spec.js @@ -1,4 +1,4 @@ -import { addVertices } from './flowRenderer'; +import { addVertices, addEdges } from './flowRenderer'; import { setConfig } from '../../config'; setConfig({ @@ -94,4 +94,32 @@ describe('the flowchart renderer', function() { expect(addedNodes[0][1]).toHaveProperty('labelStyle', expectedLabelStyle); }); }); + + describe('when adding edges to a graph', function() { + it('should handle multiline texts and set centered label position', function() { + const addedEdges = []; + const mockG = { + setEdge: function(s, e, data, c) { + addedEdges.push(data); + } + }; + addEdges( + [ + { text: 'Multi
Line' }, + { text: 'Multi
Line' }, + { text: 'Multi
Line' }, + { style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi
Line' }, + { style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi
Line' }, + { style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi
Line' } + ], + mockG, + 'svg-id' + ); + + addedEdges.forEach(function(edge) { + expect(edge).toHaveProperty('label', 'Multi\nLine'); + expect(edge).toHaveProperty('labelpos', 'c'); + }); + }); + }); }); From 1f4be7766224efdd574bcdec9c9f8bd9c848ae02 Mon Sep 17 00:00:00 2001 From: Marc Faber Date: Tue, 10 Dec 2019 03:48:12 +0100 Subject: [PATCH 07/25] Revert "#910 set correct position and style for edge labels when using linkStyle, #1088 handle multiline texts in edge labels when using linkStyle" - Sorry, forgot to push to a new branch. This reverts commit 0deae4abf9674be4831dd4cbf18468c704999f12. --- dist/index.html | 12 --------- src/diagrams/flowchart/flowRenderer.js | 20 +++++++------- src/diagrams/flowchart/flowRenderer.spec.js | 30 +-------------------- 3 files changed, 11 insertions(+), 51 deletions(-) diff --git a/dist/index.html b/dist/index.html index 615c9a537..eb27c6593 100644 --- a/dist/index.html +++ b/dist/index.html @@ -313,18 +313,6 @@ class A someclass; classDef someclass fill:#f96; class A someclass; -
- graph LR - A1[Multi
Line] -->|Multi
Line| B1(Multi
Line) - C1[Multi
Line] -->|Multi
Line| D1(Multi
Line) - E1[Multi
Line] -->|Multi
Line| F1(Multi
Line) - A2[Multi
Line] -->|Multi
Line| B2(Multi
Line) - C2[Multi
Line] -->|Multi
Line| D2(Multi
Line) - E2[Multi
Line] -->|Multi
Line| F2(Multi
Line) - linkStyle 0 stroke:DarkGray,stroke-width:2px - linkStyle 1 stroke:DarkGray,stroke-width:2px - linkStyle 2 stroke:DarkGray,stroke-width:2px -

diff --git a/src/diagrams/flowchart/flowRenderer.js b/src/diagrams/flowchart/flowRenderer.js index 524742b39..ee680532f 100644 --- a/src/diagrams/flowchart/flowRenderer.js +++ b/src/diagrams/flowchart/flowRenderer.js @@ -239,18 +239,18 @@ export const addEdges = function(edges, g) { } } else { edgeData.arrowheadStyle = 'fill: #333'; - edgeData.labelpos = 'c'; - - if (getConfig().flowchart.htmlLabels) { - edgeData.labelType = 'html'; - edgeData.label = '' + edge.text + ''; - } else { - edgeData.labelType = 'text'; - edgeData.label = edge.text.replace(/
/g, '\n'); - - if (typeof edge.style === 'undefined') { + if (typeof edge.style === 'undefined') { + edgeData.labelpos = 'c'; + if (getConfig().flowchart.htmlLabels) { + edgeData.labelType = 'html'; + edgeData.label = '' + edge.text + ''; + } else { + edgeData.labelType = 'text'; edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none'; + edgeData.label = edge.text.replace(/
/g, '\n'); } + } else { + edgeData.label = edge.text.replace(/
/g, '\n'); } } // Add the edge to the graph diff --git a/src/diagrams/flowchart/flowRenderer.spec.js b/src/diagrams/flowchart/flowRenderer.spec.js index fe31292cc..0e49dbf71 100644 --- a/src/diagrams/flowchart/flowRenderer.spec.js +++ b/src/diagrams/flowchart/flowRenderer.spec.js @@ -1,4 +1,4 @@ -import { addVertices, addEdges } from './flowRenderer'; +import { addVertices } from './flowRenderer'; import { setConfig } from '../../config'; setConfig({ @@ -94,32 +94,4 @@ describe('the flowchart renderer', function() { expect(addedNodes[0][1]).toHaveProperty('labelStyle', expectedLabelStyle); }); }); - - describe('when adding edges to a graph', function() { - it('should handle multiline texts and set centered label position', function() { - const addedEdges = []; - const mockG = { - setEdge: function(s, e, data, c) { - addedEdges.push(data); - } - }; - addEdges( - [ - { text: 'Multi
Line' }, - { text: 'Multi
Line' }, - { text: 'Multi
Line' }, - { style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi
Line' }, - { style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi
Line' }, - { style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi
Line' } - ], - mockG, - 'svg-id' - ); - - addedEdges.forEach(function(edge) { - expect(edge).toHaveProperty('label', 'Multi\nLine'); - expect(edge).toHaveProperty('labelpos', 'c'); - }); - }); - }); }); From 608445e64fec2bb5610ba8f46c8c30d1fade4d59 Mon Sep 17 00:00:00 2001 From: Marc Faber Date: Tue, 10 Dec 2019 03:51:37 +0100 Subject: [PATCH 08/25] #910 set correct position and style for edge labels when using linkStyle, #1088 handle multiline texts in edge labels when using linkStyle --- dist/index.html | 12 +++++++++ src/diagrams/flowchart/flowRenderer.js | 22 +++++++-------- src/diagrams/flowchart/flowRenderer.spec.js | 30 ++++++++++++++++++++- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/dist/index.html b/dist/index.html index eb27c6593..615c9a537 100644 --- a/dist/index.html +++ b/dist/index.html @@ -313,6 +313,18 @@ class A someclass; classDef someclass fill:#f96; class A someclass; +
+ graph LR + A1[Multi
Line] -->|Multi
Line| B1(Multi
Line) + C1[Multi
Line] -->|Multi
Line| D1(Multi
Line) + E1[Multi
Line] -->|Multi
Line| F1(Multi
Line) + A2[Multi
Line] -->|Multi
Line| B2(Multi
Line) + C2[Multi
Line] -->|Multi
Line| D2(Multi
Line) + E2[Multi
Line] -->|Multi
Line| F2(Multi
Line) + linkStyle 0 stroke:DarkGray,stroke-width:2px + linkStyle 1 stroke:DarkGray,stroke-width:2px + linkStyle 2 stroke:DarkGray,stroke-width:2px +

diff --git a/src/diagrams/flowchart/flowRenderer.js b/src/diagrams/flowchart/flowRenderer.js index ee680532f..524742b39 100644 --- a/src/diagrams/flowchart/flowRenderer.js +++ b/src/diagrams/flowchart/flowRenderer.js @@ -239,18 +239,18 @@ export const addEdges = function(edges, g) { } } else { edgeData.arrowheadStyle = 'fill: #333'; - if (typeof edge.style === 'undefined') { - edgeData.labelpos = 'c'; - if (getConfig().flowchart.htmlLabels) { - edgeData.labelType = 'html'; - edgeData.label = '' + edge.text + ''; - } else { - edgeData.labelType = 'text'; - edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none'; - edgeData.label = edge.text.replace(/
/g, '\n'); - } + edgeData.labelpos = 'c'; + + if (getConfig().flowchart.htmlLabels) { + edgeData.labelType = 'html'; + edgeData.label = '' + edge.text + ''; } else { - edgeData.label = edge.text.replace(/
/g, '\n'); + edgeData.labelType = 'text'; + edgeData.label = edge.text.replace(/
/g, '\n'); + + if (typeof edge.style === 'undefined') { + edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none'; + } } } // Add the edge to the graph diff --git a/src/diagrams/flowchart/flowRenderer.spec.js b/src/diagrams/flowchart/flowRenderer.spec.js index 0e49dbf71..fe31292cc 100644 --- a/src/diagrams/flowchart/flowRenderer.spec.js +++ b/src/diagrams/flowchart/flowRenderer.spec.js @@ -1,4 +1,4 @@ -import { addVertices } from './flowRenderer'; +import { addVertices, addEdges } from './flowRenderer'; import { setConfig } from '../../config'; setConfig({ @@ -94,4 +94,32 @@ describe('the flowchart renderer', function() { expect(addedNodes[0][1]).toHaveProperty('labelStyle', expectedLabelStyle); }); }); + + describe('when adding edges to a graph', function() { + it('should handle multiline texts and set centered label position', function() { + const addedEdges = []; + const mockG = { + setEdge: function(s, e, data, c) { + addedEdges.push(data); + } + }; + addEdges( + [ + { text: 'Multi
Line' }, + { text: 'Multi
Line' }, + { text: 'Multi
Line' }, + { style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi
Line' }, + { style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi
Line' }, + { style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi
Line' } + ], + mockG, + 'svg-id' + ); + + addedEdges.forEach(function(edge) { + expect(edge).toHaveProperty('label', 'Multi\nLine'); + expect(edge).toHaveProperty('labelpos', 'c'); + }); + }); + }); }); From 363d49b655756ae7bbf619b83d98690487b5d1e9 Mon Sep 17 00:00:00 2001 From: Justin Greywolf Date: Wed, 11 Dec 2019 10:34:51 -0800 Subject: [PATCH 09/25] Renumber render tests --- cypress/integration/rendering/classDiagram.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cypress/integration/rendering/classDiagram.spec.js b/cypress/integration/rendering/classDiagram.spec.js index 8049b120c..3ca5d7f51 100644 --- a/cypress/integration/rendering/classDiagram.spec.js +++ b/cypress/integration/rendering/classDiagram.spec.js @@ -188,7 +188,7 @@ describe('Class diagram', () => { cy.get('svg'); }); - it('5: should render a simple class diagram with Generic class', () => { + it('7: should render a simple class diagram with Generic class', () => { imgSnapshotTest( ` classDiagram @@ -208,7 +208,7 @@ describe('Class diagram', () => { cy.get('svg'); }); - it('6: should render a simple class diagram with Generic class and relations', () => { + it('8: should render a simple class diagram with Generic class and relations', () => { imgSnapshotTest( ` classDiagram From 1811318deadcd77ad116d760e94c75883eb437b3 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Wed, 11 Dec 2019 20:17:51 +0100 Subject: [PATCH 10/25] #1088 Adding rendering tests --- .../integration/rendering/flowchart.spec.js | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/cypress/integration/rendering/flowchart.spec.js b/cypress/integration/rendering/flowchart.spec.js index a27f3b50c..19dc312d7 100644 --- a/cypress/integration/rendering/flowchart.spec.js +++ b/cypress/integration/rendering/flowchart.spec.js @@ -396,4 +396,36 @@ describe('Flowcart', () => { { flowchart: { htmlLabels: false } } ); }); + it('15: Render Stadium shape', () => { + imgSnapshotTest( + ` 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;`, + { flowchart: { htmlLabels: false } } + ); + }); + it('16: Render Stadium shape', () => { + imgSnapshotTest( + `graph LR + A1[Multi
Line] -->|Multi
Line| B1(Multi
Line) + C1[Multi
Line] -->|Multi
Line| D1(Multi
Line) + E1[Multi
Line] -->|Multi
Line| F1(Multi
Line) + A2[Multi
Line] -->|Multi
Line| B2(Multi
Line) + C2[Multi
Line] -->|Multi
Line| D2(Multi
Line) + E2[Multi
Line] -->|Multi
Line| F2(Multi
Line) + linkStyle 0 stroke:DarkGray,stroke-width:2px + linkStyle 1 stroke:DarkGray,stroke-width:2px + linkStyle 2 stroke:DarkGray,stroke-width:2px + `, + { flowchart: { htmlLabels: false } } + ); + }); }); From fcf20215a69b870696ef140da7fd51b952ec8928 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Wed, 11 Dec 2019 21:12:48 +0100 Subject: [PATCH 11/25] #552 Adding rendering test --- cypress/integration/rendering/gantt.spec.js | 16 ++++++++++++++ cypress/platform/current.html | 23 ++++++++++++++------- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/cypress/integration/rendering/gantt.spec.js b/cypress/integration/rendering/gantt.spec.js index c1bdee040..027c893a7 100644 --- a/cypress/integration/rendering/gantt.spec.js +++ b/cypress/integration/rendering/gantt.spec.js @@ -38,4 +38,20 @@ describe('Sequencediagram', () => { {} ); }); + it('Multiple dependencies syntax', () => { + imgSnapshotTest( + ` + gantt + dateFormat YYYY-MM-DD + axisFormat %d/%m + title Adding GANTT diagram to mermaid + excludes weekdays 2014-01-10 + + apple :a, 2017-07-20, 1w + banana :crit, b, 2017-07-23, 1d + cherry :active, c, after b a, 1d + `, + {} + ); + }); }); diff --git a/cypress/platform/current.html b/cypress/platform/current.html index 283deff93..9e5267768 100644 --- a/cypress/platform/current.html +++ b/cypress/platform/current.html @@ -5,7 +5,7 @@ rel="stylesheet" />