From c95adfaf74384e503e265719288e39e2a5315bd7 Mon Sep 17 00:00:00 2001 From: Marc Faber Date: Sun, 2 Feb 2020 22:59:59 +0100 Subject: [PATCH 1/3] #962 Set text color for flowchart link labels according to linkStyle definitions --- .../integration/rendering/flowchart.spec.js | 20 ++++++++----- dist/index.html | 6 ++-- docs/flowchart.md | 2 +- src/diagrams/flowchart/flowRenderer.js | 30 +++++++++++++++++-- 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/cypress/integration/rendering/flowchart.spec.js b/cypress/integration/rendering/flowchart.spec.js index 2c20090a4..60f6cfbe2 100644 --- a/cypress/integration/rendering/flowchart.spec.js +++ b/cypress/integration/rendering/flowchart.spec.js @@ -512,7 +512,7 @@ describe('Flowchart', () => { ); }); - it('24.1: Keep node label text (if already defined) when a style is applied', () => { + it('24: Keep node label text (if already defined) when a style is applied', () => { imgSnapshotTest( `graph LR A(( )) -->|step 1| B(( )) @@ -524,7 +524,7 @@ describe('Flowchart', () => { { flowchart: { htmlLabels: false } } ); }); -it('24.2: Handle link click events (link, anchor, mailto, other protocol, script)', () => { +it('25: Handle link click events (link, anchor, mailto, other protocol, script)', () => { imgSnapshotTest( `graph TB TITLE["Link Click Events
(click the nodes below)"] @@ -544,11 +544,13 @@ it('24.2: Handle link click events (link, anchor, mailto, other protocol, script ); }); - it('25: Set node text color according to style when html labels are enabled', () => { + it('26: Set text color of nodes and links according to styles when html labels are enabled', () => { imgSnapshotTest( `graph LR - A[red
text] --> B(blue
text) - C[/red
text/] --> D{blue
text} + A[red
text] -->|red
text| B(blue
text) + C[/red
text/] -->|blue
text| D{blue
text} + linkStyle 0 color:red; + linkStyle 1 stroke:DarkGray,stroke-width:2px,color:#0000ff style A color:red; style B color:blue; style C stroke:#ff0000,fill:#ffcccc,color:#ff0000 @@ -560,11 +562,13 @@ it('24.2: Handle link click events (link, anchor, mailto, other protocol, script ); }); - it('26: Set node text color according to style when html labels are disabled', () => { + it('27: Set text color of nodes and links according to styles when html labels are disabled', () => { imgSnapshotTest( `graph LR - A[red
text] --> B(blue
text) - C[/red
text/] --> D{blue
text} + A[red
text] -->|red
text| B(blue
text) + C[/red
text/] -->|blue
text| D{blue
text} + linkStyle 0 color:red; + linkStyle 1 stroke:DarkGray,stroke-width:2px,color:#0000ff style A color:red; style B color:blue; style C stroke:#ff0000,fill:#ffcccc,color:#ff0000 diff --git a/dist/index.html b/dist/index.html index 47293b4b6..9290199cc 100644 --- a/dist/index.html +++ b/dist/index.html @@ -371,8 +371,10 @@ graph TB
graph LR - A[red
text] --> B(blue
text) - C[/red
text/] --> D{blue
text} + A[red
text] -->|red
text| B(blue
text) + C[/red
text/] -->|blue
text| D{blue
text} + linkStyle 0 color:red; + linkStyle 1 stroke:DarkGray,stroke-width:2px,color:#0000ff style A color:red; style B color:blue; style C stroke:#ff0000,fill:#ffcccc,color:#ff0000 diff --git a/docs/flowchart.md b/docs/flowchart.md index b6bdabc2f..ee4f0e130 100644 --- a/docs/flowchart.md +++ b/docs/flowchart.md @@ -497,7 +497,7 @@ Instead of ids, the order number of when the link was defined in the graph is us defined in the linkStyle statement will belong to the fourth link in the graph: ``` -linkStyle 3 stroke:#ff3,stroke-width:4px; +linkStyle 3 stroke:#ff3,stroke-width:4px,color:red; ``` diff --git a/src/diagrams/flowchart/flowRenderer.js b/src/diagrams/flowchart/flowRenderer.js index decb382f8..94843de35 100644 --- a/src/diagrams/flowchart/flowRenderer.js +++ b/src/diagrams/flowchart/flowRenderer.js @@ -176,6 +176,25 @@ export const addVertices = function(vert, g, svgId) { * @param {Object} g The graph object */ export const addEdges = function(edges, g) { + const styleFromStyleArr = function(styleStr, arr, { label }) { + if (!label) { + // Create a compound style definition from the style definitions found for the node in the graph definition + for (let i = 0; i < arr.length; i++) { + if (typeof arr[i] !== 'undefined') { + styleStr = styleStr + arr[i] + ';'; + } + } + } else { + // create the style definition for the text, if property is a text-property + for (let i = 0; i < arr.length; i++) { + if (typeof arr[i] !== 'undefined') { + if (arr[i].startsWith('color:')) styleStr = styleStr + arr[i] + ';'; + } + } + } + return styleStr; + }; + let cnt = 0; let defaultStyle; @@ -195,10 +214,11 @@ export const addEdges = function(edges, g) { } let style = ''; + let labelStyle = ''; + if (typeof edge.style !== 'undefined') { - edge.style.forEach(function(s) { - style = style + s + ';'; - }); + style = styleFromStyleArr(style, edge.style, { label: false }); + labelStyle = styleFromStyleArr(labelStyle, edge.style, { label: true }); } else { switch (edge.stroke) { case 'normal': @@ -215,7 +235,9 @@ export const addEdges = function(edges, g) { break; } } + edgeData.style = style; + edgeData.labelStyle = labelStyle; if (typeof edge.interpolate !== 'undefined') { edgeData.curve = interpolateToCurve(edge.interpolate, d3.curveLinear); @@ -242,6 +264,8 @@ export const addEdges = function(edges, g) { if (typeof edge.style === 'undefined') { edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none'; + } else { + edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:'); } } } From 2dd4aa31e5f4f0a6a364499c11b9960afded1d16 Mon Sep 17 00:00:00 2001 From: Marc Faber Date: Tue, 4 Feb 2020 00:24:50 +0100 Subject: [PATCH 2/3] #962 moved "style from array" function to utils.js, added unit test --- src/diagrams/flowchart/flowRenderer.js | 61 ++------------ src/diagrams/flowchart/flowRenderer.spec.js | 93 +++++++++++++-------- src/utils.js | 21 ++++- 3 files changed, 86 insertions(+), 89 deletions(-) diff --git a/src/diagrams/flowchart/flowRenderer.js b/src/diagrams/flowchart/flowRenderer.js index 94843de35..b62c3ecbe 100644 --- a/src/diagrams/flowchart/flowRenderer.js +++ b/src/diagrams/flowchart/flowRenderer.js @@ -8,7 +8,7 @@ import { getConfig } from '../../config'; import dagreD3 from 'dagre-d3'; import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js'; import { logger } from '../../logger'; -import { interpolateToCurve } from '../../utils'; +import { interpolateToCurve, getStylesFromArray } from '../../utils'; import flowChartShapes from './flowChartShapes'; const conf = {}; @@ -28,25 +28,6 @@ export const addVertices = function(vert, g, svgId) { const svg = d3.select(`[id="${svgId}"]`); const keys = Object.keys(vert); - const styleFromStyleArr = function(styleStr, arr, { label }) { - if (!label) { - // Create a compound style definition from the style definitions found for the node in the graph definition - for (let i = 0; i < arr.length; i++) { - if (typeof arr[i] !== 'undefined') { - styleStr = styleStr + arr[i] + ';'; - } - } - } else { - // create the style definition for the text, if property is a text-property - for (let i = 0; i < arr.length; i++) { - if (typeof arr[i] !== 'undefined') { - if (arr[i].match('^color:|^text-align:')) styleStr = styleStr + arr[i] + ';'; - } - } - } - return styleStr; - }; - // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition keys.forEach(function(id) { const vertex = vert[id]; @@ -60,15 +41,7 @@ export const addVertices = function(vert, g, svgId) { classStr = vertex.classes.join(' '); } - /** - * Variable for storing the extracted style for the vertex - * @type {string} - */ - let style = ''; - // Create a compound style definition from the style definitions found for the node in the graph definition - style = styleFromStyleArr(style, vertex.styles, { label: false }); - let labelStyle = ''; - labelStyle = styleFromStyleArr(labelStyle, vertex.styles, { label: true }); + const styles = getStylesFromArray(vertex.styles); // Use vertex id as text in the box if no text is provided by the graph definition let vertexText = vertex.text !== undefined ? vertex.text : vertex.id; @@ -87,7 +60,7 @@ export const addVertices = function(vert, g, svgId) { vertexNode.parentNode.removeChild(vertexNode); } else { const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text'); - svgLabel.setAttribute('style', labelStyle.replace('color:', 'fill:')); + svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:')); const rows = vertexText.split(//gi); @@ -158,13 +131,13 @@ export const addVertices = function(vert, g, svgId) { // Add the node g.setNode(vertex.id, { labelType: 'svg', - labelStyle: labelStyle, + labelStyle: styles.labelStyle, shape: _shape, label: vertexNode, rx: radious, ry: radious, class: classStr, - style: style, + style: styles.style, id: vertex.id }); }); @@ -176,25 +149,6 @@ export const addVertices = function(vert, g, svgId) { * @param {Object} g The graph object */ export const addEdges = function(edges, g) { - const styleFromStyleArr = function(styleStr, arr, { label }) { - if (!label) { - // Create a compound style definition from the style definitions found for the node in the graph definition - for (let i = 0; i < arr.length; i++) { - if (typeof arr[i] !== 'undefined') { - styleStr = styleStr + arr[i] + ';'; - } - } - } else { - // create the style definition for the text, if property is a text-property - for (let i = 0; i < arr.length; i++) { - if (typeof arr[i] !== 'undefined') { - if (arr[i].startsWith('color:')) styleStr = styleStr + arr[i] + ';'; - } - } - } - return styleStr; - }; - let cnt = 0; let defaultStyle; @@ -217,8 +171,9 @@ export const addEdges = function(edges, g) { let labelStyle = ''; if (typeof edge.style !== 'undefined') { - style = styleFromStyleArr(style, edge.style, { label: false }); - labelStyle = styleFromStyleArr(labelStyle, edge.style, { label: true }); + const styles = getStylesFromArray(edge.style); + style = styles.style; + labelStyle = styles.labelStyle; } else { switch (edge.stroke) { case 'normal': diff --git a/src/diagrams/flowchart/flowRenderer.spec.js b/src/diagrams/flowchart/flowRenderer.spec.js index d691840ed..e3980ef1f 100644 --- a/src/diagrams/flowchart/flowRenderer.spec.js +++ b/src/diagrams/flowchart/flowRenderer.spec.js @@ -92,44 +92,40 @@ describe('the flowchart renderer', function() { expect(addedNodes[0][1].label.lastChild.innerHTML).toEqual('Line'); // node, line 2 }); }); - }); - [ - [['fill:#fff'], 'fill:#fff;', ''], - [['color:#ccc'], 'color:#ccc;', 'color:#ccc;'], - [['fill:#fff', 'color:#ccc'], 'fill:#fff;color:#ccc;', 'color:#ccc;'], [ - ['fill:#fff', 'color:#ccc', 'text-align:center'], - 'fill:#fff;color:#ccc;text-align:center;', - 'color:#ccc;text-align:center;' - ] - ].forEach(function([style, expectedStyle, expectedLabelStyle]) { - it(`should add the styles to style and/or labelStyle for style ${style}`, function() { - const addedNodes = []; - const mockG = { - setNode: function(id, object) { - addedNodes.push([id, object]); - } - }; - addVertices( - { - v1: { - type: 'rect', - id: 'my-node-id', - classes: [], - styles: style, - text: 'my vertex text' + [['fill:#fff'], 'fill:#fff;', ''], + [['color:#ccc'], '', 'color:#ccc;'], + [['fill:#fff', 'color:#ccc'], 'fill:#fff;', 'color:#ccc;'], + [['fill:#fff', 'color:#ccc', 'text-align:center'], 'fill:#fff;', 'color:#ccc;text-align:center;'] + ].forEach(function([style, expectedStyle, expectedLabelStyle]) { + it(`should add the styles to style and/or labelStyle for style ${style}`, function() { + const addedNodes = []; + const mockG = { + setNode: function(id, object) { + addedNodes.push([id, object]); } - }, - mockG, - 'svg-id' - ); - expect(addedNodes).toHaveLength(1); - expect(addedNodes[0][0]).toEqual('my-node-id'); - expect(addedNodes[0][1]).toHaveProperty('id', 'my-node-id'); - expect(addedNodes[0][1]).toHaveProperty('labelType', 'svg'); - expect(addedNodes[0][1]).toHaveProperty('style', expectedStyle); - expect(addedNodes[0][1]).toHaveProperty('labelStyle', expectedLabelStyle); + }; + addVertices( + { + v1: { + type: 'rect', + id: 'my-node-id', + classes: [], + styles: style, + text: 'my vertex text' + } + }, + mockG, + 'svg-id' + ); + expect(addedNodes).toHaveLength(1); + expect(addedNodes[0][0]).toEqual('my-node-id'); + expect(addedNodes[0][1]).toHaveProperty('id', 'my-node-id'); + expect(addedNodes[0][1]).toHaveProperty('labelType', 'svg'); + expect(addedNodes[0][1]).toHaveProperty('style', expectedStyle); + expect(addedNodes[0][1]).toHaveProperty('labelStyle', expectedLabelStyle); + }); }); }); @@ -161,5 +157,32 @@ describe('the flowchart renderer', function() { expect(edge).toHaveProperty('labelpos', 'c'); }); }); + + [ + [['stroke:DarkGray'], 'stroke:DarkGray;', ''], + [['color:red'], '', 'fill:red;'], + [['stroke:DarkGray', 'color:red'], 'stroke:DarkGray;', 'fill:red;'], + [['stroke:DarkGray', 'color:red', 'stroke-width:2px'], 'stroke:DarkGray;stroke-width:2px;', 'fill:red;'] + ].forEach(function([style, expectedStyle, expectedLabelStyle]) { + it(`should add the styles to style and/or labelStyle for style ${style}`, function() { + const addedEdges = []; + const mockG = { + setEdge: function(s, e, data, c) { + addedEdges.push(data); + } + }; + addEdges( + [ + { style: style, text: 'styling' } + ], + mockG, + 'svg-id' + ); + + expect(addedEdges).toHaveLength(1); + expect(addedEdges[0]).toHaveProperty('style', expectedStyle); + expect(addedEdges[0]).toHaveProperty('labelStyle', expectedLabelStyle); + }); + }); }); }); diff --git a/src/utils.js b/src/utils.js index 38010c41f..002dcc8b7 100644 --- a/src/utils.js +++ b/src/utils.js @@ -201,6 +201,24 @@ const calcCardinalityPosition = (isRelationTypePresent, points, initialPosition) return cardinalityPosition; }; +export const getStylesFromArray = arr => { + let style = ''; + let labelStyle = ''; + + for (let i = 0; i < arr.length; i++) { + if (typeof arr[i] !== 'undefined') { + // add text properties to label style definition + if (arr[i].startsWith('color:') || arr[i].startsWith('text-align:')) { + labelStyle = labelStyle + arr[i] + ';'; + } else { + style = style + arr[i] + ';'; + } + } + } + + return { style: style, labelStyle: labelStyle }; +}; + export default { detectType, isSubstringInArray, @@ -208,5 +226,6 @@ export default { calcLabelPosition, calcCardinalityPosition, sanitize, - formatUrl + formatUrl, + getStylesFromArray }; From a0e7789d508b1623a3d5e0f6499c8d0f02a22fcc Mon Sep 17 00:00:00 2001 From: Marc Faber Date: Tue, 4 Feb 2020 22:07:10 +0100 Subject: [PATCH 3/3] #962 added color setting for default link style --- cypress/integration/rendering/flowchart.spec.js | 4 ++++ dist/index.html | 2 ++ src/diagrams/flowchart/flowRenderer.js | 13 ++++++++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cypress/integration/rendering/flowchart.spec.js b/cypress/integration/rendering/flowchart.spec.js index 60f6cfbe2..9bc48a399 100644 --- a/cypress/integration/rendering/flowchart.spec.js +++ b/cypress/integration/rendering/flowchart.spec.js @@ -549,6 +549,8 @@ it('25: Handle link click events (link, anchor, mailto, other protocol, script)' `graph LR A[red
text] -->|red
text| B(blue
text) C[/red
text/] -->|blue
text| D{blue
text} + E{{default
style}} -->|default
style| F([default
style]) + linkStyle default color:Sienna; linkStyle 0 color:red; linkStyle 1 stroke:DarkGray,stroke-width:2px,color:#0000ff style A color:red; @@ -567,6 +569,8 @@ it('25: Handle link click events (link, anchor, mailto, other protocol, script)' `graph LR A[red
text] -->|red
text| B(blue
text) C[/red
text/] -->|blue
text| D{blue
text} + E{{default
style}} -->|default
style| F([default
style]) + linkStyle default color:Sienna; linkStyle 0 color:red; linkStyle 1 stroke:DarkGray,stroke-width:2px,color:#0000ff style A color:red; diff --git a/dist/index.html b/dist/index.html index 9290199cc..e28890ce7 100644 --- a/dist/index.html +++ b/dist/index.html @@ -373,6 +373,8 @@ graph TB graph LR A[red
text] -->|red
text| B(blue
text) C[/red
text/] -->|blue
text| D{blue
text} + E{{default
style}} -->|default
style| F([default
style]) + linkStyle default color:Sienna; linkStyle 0 color:red; linkStyle 1 stroke:DarkGray,stroke-width:2px,color:#0000ff style A color:red; diff --git a/src/diagrams/flowchart/flowRenderer.js b/src/diagrams/flowchart/flowRenderer.js index b62c3ecbe..3a25e6e74 100644 --- a/src/diagrams/flowchart/flowRenderer.js +++ b/src/diagrams/flowchart/flowRenderer.js @@ -152,8 +152,12 @@ export const addEdges = function(edges, g) { let cnt = 0; let defaultStyle; + let defaultLabelStyle; + if (typeof edges.defaultStyle !== 'undefined') { - defaultStyle = edges.defaultStyle.toString().replace(/,/g, ';'); + const defaultStyles = getStylesFromArray(edges.defaultStyle); + defaultStyle = defaultStyles.style; + defaultLabelStyle = defaultStyles.labelStyle; } edges.forEach(function(edge) { @@ -181,6 +185,9 @@ export const addEdges = function(edges, g) { if (typeof defaultStyle !== 'undefined') { style = defaultStyle; } + if (typeof defaultLabelStyle !== 'undefined') { + labelStyle = defaultLabelStyle; + } break; case 'dotted': style = 'fill:none;stroke-width:2px;stroke-dasharray:3;'; @@ -219,9 +226,9 @@ export const addEdges = function(edges, g) { if (typeof edge.style === 'undefined') { edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none'; - } else { - edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:'); } + + edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:'); } } // Add the edge to the graph