diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index 69eab8b62..02a5ff5e6 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -57,51 +57,64 @@
-
+    
 %%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
 %%
-graph BT
-a("`The **cat** in the hat} -- 1o --> b
-a -- 2o --> c
-a -- 3o --> d
-g --2i--> a
-d --1i--> a
-h --3i -->a
-b --> d(The dog in the hog)
-c --> d
-%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
-    
+graph LR
+  a{"`The **cat** in the hat`"} -- 1o --> b
+  a -- 2o --> c
+  a -- 3o --> d
+  g --2i--> a
+  d --1i--> a
+  h --3i -->a
+  b --> d(The dog in the hog)
+  c --> d
+
     
+      %%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
 flowchart LR
-b("`The dog in **the** hog... a a a a *very long text* about it
+b("`The dog in **the** hog.(1)
+NL`") --"`1o **bold**`"--> c
+
+    
+flowchart-elk LR
+b("`The dog in **the** hog.(1)
+NL`") --"`1o **bold**`"--> c
+
+    
+flowchart-elk LR
+b("`The dog in **the** hog.(1).. a a a a *very long text* about it
 Word!
 
-Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. `")
+Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. `") --> c
 
     
       %%{init: {"flowchart": {"htmlLabels": true}} }%%
-flowchart LR
-b("`The dog in **the** hog... a a a a *very long text* about it
+flowchart-elk LR
+b("`The dog in **the** hog(2)... a a a a *very long text* about it
 Word!
 Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. `")
 
     
       %%{init: {"flowchart": {"htmlLabels": false}} }%%
-flowchart LR
+flowchart-elk LR
 b("The dog in the hog... a very
long text about it
Word!")
 
     
       %%{init: {"flowchart": {"htmlLabels": true}} }%%
-flowchart LR
+flowchart-elk LR
 b("The dog in the hog... a very
long text about it
Word!")
 
     
-flowchart LR
+flowchart-elk LR
 subgraph "One"
   a("`The **cat**
-  in the hat`") -- 1o --> b{{"`The **dog** in the hog`"}}
+  in the hat`") -- "1o" --> b{{"`The **dog** in the hog`"}}
 end
 subgraph "`**Two**`"
   c("`The **cat**
@@ -129,7 +142,7 @@ mindmap
       id2["`The dog in **the** hog... a *very long text* about it
 Word!`"]
     
-    +%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%% flowchart TB %% I could not figure out how to use double quotes in labels in Mermaid @@ -185,7 +198,7 @@ flowchart TB
-+flowchart TB %% I could not figure out how to use double quotes in labels in Mermaid subgraph ibm[IBM Espresso CPU] @@ -241,7 +254,7 @@ flowchart TB >
-+flowchart LR B1 --be be--x B2 B1 --bo bo--o B3 @@ -274,7 +287,7 @@ flowchart TB B6 --> B5-+sequenceDiagram Customer->>+Stripe: Makes a payment request Stripe->>+Bank: Forwards the payment request to the bank @@ -287,7 +300,7 @@ sequenceDiagram Customer->>+Merchant: Receives goods or services-+mindmap root((mindmap)) Origins @@ -307,7 +320,7 @@ mindmap Mermaid
-+example-diagram@@ -332,8 +345,8 @@ mindmap flowchart: { // defaultRenderer: 'elk', useMaxWidth: false, - // htmlLabels: false, htmlLabels: false, + // htmlLabels: true, }, htmlLabels: false, gantt: { diff --git a/docs/config/setup/modules/defaultConfig.md b/docs/config/setup/modules/defaultConfig.md index 3b2e33842..6493a93db 100644 --- a/docs/config/setup/modules/defaultConfig.md +++ b/docs/config/setup/modules/defaultConfig.md @@ -14,7 +14,7 @@ #### Defined in -[defaultConfig.ts:2093](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L2093) +[defaultConfig.ts:2105](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L2105) --- diff --git a/packages/mermaid/src/Diagram.ts b/packages/mermaid/src/Diagram.ts index 3943a84c2..8e924f2fa 100644 --- a/packages/mermaid/src/Diagram.ts +++ b/packages/mermaid/src/Diagram.ts @@ -44,7 +44,6 @@ export class Diagram { // calls diagram.db.clear(), which would reset anything set by // extractFrontMatter(). this.parser.parse = (text: string) => originalParse(extractFrontMatter(text, this.db)); - // this.parser.parse = (text: string) => { // console.log('parse called'); // try { diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 157304149..c3ab7671e 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -385,6 +385,7 @@ export interface FlowchartDiagramConfig extends BaseDiagramConfig { curve?: string; padding?: number; defaultRenderer?: string; + wrappingWidth?: number; } export interface FontConfig { diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js index 4f83e938a..d4b7d37b8 100644 --- a/packages/mermaid/src/dagre-wrapper/edges.js +++ b/packages/mermaid/src/dagre-wrapper/edges.js @@ -19,7 +19,11 @@ export const insertEdgeLabel = (elem, edge) => { // Create the actual text element const labelElement = edge.labelType === 'markdown' - ? createText(elem, edge.label, { style: edge.labelStyle, useHtmlLabels }) + ? createText(elem, edge.label, { + style: edge.labelStyle, + useHtmlLabels, + addSvgBackground: true, + }) : createLabel(edge.label, edge.labelStyle); log.info('abc82', edge, edge.labelType); diff --git a/packages/mermaid/src/dagre-wrapper/nodes.js b/packages/mermaid/src/dagre-wrapper/nodes.js index 3e71f500a..dd0225770 100644 --- a/packages/mermaid/src/dagre-wrapper/nodes.js +++ b/packages/mermaid/src/dagre-wrapper/nodes.js @@ -997,6 +997,7 @@ export const insertNode = (elem, node, dir) => { el.attr('class', 'node default ' + node.class); } + /* MC: 7e790808-9c49-4f74-93de-15c22872377f */ nodeElems[node.id] = newEl; if (node.haveCallback) { diff --git a/packages/mermaid/src/dagre-wrapper/shapes/util.js b/packages/mermaid/src/dagre-wrapper/shapes/util.js index d362d08f6..b5de2bd6b 100644 --- a/packages/mermaid/src/dagre-wrapper/shapes/util.js +++ b/packages/mermaid/src/dagre-wrapper/shapes/util.js @@ -34,7 +34,7 @@ export const labelHelper = (parent, node, _classes, isNode) => { // text = textNode; text = createText(label, sanitizeText(decodeEntities(labelText), getConfig()), { useHtmlLabels: getConfig().flowchart.htmlLabels, - width: node.width || 200, + width: node.width || getConfig().flowchart.wrappingWidth, classes: 'markdown-node-label', }); } else { @@ -67,7 +67,7 @@ export const labelHelper = (parent, node, _classes, isNode) => { } else { label.attr('transform', 'translate(' + 0 + ', ' + -bbox.height / 2 + ')'); } - + label.insert('rect', ':first-child'); return { shapeSvg, bbox, halfPadding, label }; }; diff --git a/packages/mermaid/src/defaultConfig.ts b/packages/mermaid/src/defaultConfig.ts index 666efc364..4d8ebf4e8 100644 --- a/packages/mermaid/src/defaultConfig.ts +++ b/packages/mermaid/src/defaultConfig.ts @@ -258,6 +258,18 @@ const config: Partial= { * Default value: 'dagre-wrapper' */ defaultRenderer: 'dagre-wrapper', + /** + * | Parameter | Description | Type | Required | Values | + * | --------------- | ----------- | ------- | -------- | ----------------------- | + * | wrappingWidth | See notes | number | 4 | width of nodes where text is wrapped | + * + * **Notes:** + * + * When using markdown strings the text ius wrapped automatically, this + * value sets the max width of a text before it continues on a new line. + * Default value: 'dagre-wrapper' + */ + wrappingWidth: 200, }, /** The object containing configurations specific for sequence diagrams */ diff --git a/packages/mermaid/src/diagrams/flowchart/elk/flowRenderer-elk.js b/packages/mermaid/src/diagrams/flowchart/elk/flowRenderer-elk.js index 426d22dbb..1b1dd3c50 100644 --- a/packages/mermaid/src/diagrams/flowchart/elk/flowRenderer-elk.js +++ b/packages/mermaid/src/diagrams/flowchart/elk/flowRenderer-elk.js @@ -3,6 +3,7 @@ import { insertNode } from '../../../dagre-wrapper/nodes.js'; import insertMarkers from '../../../dagre-wrapper/markers.js'; import { insertEdgeLabel } from '../../../dagre-wrapper/edges.js'; import { findCommonAncestor } from './render-utils'; +import { labelHelper } from '../../../dagre-wrapper/shapes/util'; import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js'; import { getConfig } from '../../../config'; import { log } from '../../../logger'; @@ -52,7 +53,7 @@ export const addVertices = function (vert, svgId, root, doc, diagObj, parentLook if (vertex.classes.length > 0) { classStr = vertex.classes.join(' '); } - + classStr = classStr + ' flowchart-label'; const styles = getStylesFromArray(vertex.styles); // Use vertex id as text in the box if no text is provided by the graph definition @@ -61,40 +62,6 @@ export const addVertices = function (vert, svgId, root, doc, diagObj, parentLook // We create a SVG label, either by delegating to addHtmlLabel or manually let vertexNode; const labelData = { width: 0, height: 0 }; - if (evaluate(getConfig().flowchart.htmlLabels)) { - // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? - const node = { - label: vertexText.replace( - /fa[blrs]?:fa-[\w-]+/g, - (s) => `` - ), - }; - vertexNode = addHtmlLabel(svg, node).node(); - const bbox = vertexNode.getBBox(); - labelData.width = bbox.width; - labelData.height = bbox.height; - labelData.labelNode = vertexNode; - vertexNode.parentNode.removeChild(vertexNode); - } else { - const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text'); - svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:')); - - const rows = vertexText.split(common.lineBreakRegex); - - for (const row of rows) { - const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan'); - tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve'); - tspan.setAttribute('dy', '1em'); - tspan.setAttribute('x', '1'); - tspan.textContent = row; - svgLabel.appendChild(tspan); - } - vertexNode = svgLabel; - const bbox = vertexNode.getBBox(); - labelData.width = bbox.width; - labelData.height = bbox.height; - labelData.labelNode = vertexNode; - } const ports = [ { @@ -186,11 +153,13 @@ export const addVertices = function (vert, svgId, root, doc, diagObj, parentLook default: _shape = 'rect'; } + // Add the node const node = { labelStyle: styles.labelStyle, shape: _shape, labelText: vertexText, + labelType: vertex.labelType, rx: radious, ry: radious, class: classStr, @@ -209,10 +178,33 @@ export const addVertices = function (vert, svgId, root, doc, diagObj, parentLook }; let boundingBox; let nodeEl; + + // Add the element to the DOM if (node.type !== 'group') { nodeEl = insertNode(nodes, node, vertex.dir); boundingBox = nodeEl.node().getBBox(); + } else { + const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text'); + // svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:')); + // const rows = vertexText.split(common.lineBreakRegex); + // for (const row of rows) { + // const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan'); + // tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve'); + // tspan.setAttribute('dy', '1em'); + // tspan.setAttribute('x', '1'); + // tspan.textContent = row; + // svgLabel.appendChild(tspan); + // } + // vertexNode = svgLabel; + // const bbox = vertexNode.getBBox(); + const { shapeSvg, bbox } = labelHelper(nodes, node, undefined, true); + labelData.width = bbox.width; + labelData.wrappingWidth = getConfig().flowchart.wrappingWidth; + labelData.height = bbox.height; + labelData.labelNode = shapeSvg.node(); + node.labelData = labelData; } + // const { shapeSvg, bbox } = labelHelper(svg, node, undefined, true); const data = { id: vertex.id, @@ -520,7 +512,7 @@ export const addEdges = function (edges, diagObj, graph, svg) { edgeData.labelpos = 'c'; } - edgeData.labelType = 'text'; + edgeData.labelType = edge.labelType; edgeData.label = edge.text.replace(common.lineBreakRegex, '\n'); if (edge.style === undefined) { @@ -845,9 +837,17 @@ export const draw = async function (text, id, _version, diagObj) { log.info('Subgraphs - ', subGraphs); for (let i = subGraphs.length - 1; i >= 0; i--) { subG = subGraphs[i]; - diagObj.db.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir); + diagObj.db.addVertex( + subG.id, + { text: subG.title, type: subG.labelType }, + 'group', + undefined, + subG.classes, + subG.dir + ); } + // debugger; // Add an element in the svg to be used to hold the subgraphs container // elements const subGraphsEl = svg.insert('g').attr('class', 'subgraphs'); @@ -860,7 +860,7 @@ export const draw = async function (text, id, _version, diagObj) { // in order to get the size of the node. You can't get the size of a node // that is not in the dom so we need to add it to the dom, get the size // we will position the nodes when we get the layout from elkjs - graph = addVertices(vert, id, root, doc, diagObj, parentLookupDb, graph); + graph = addVertices(vert, id, root, doc, diagObj, parentLookupDb, graph, svg); // Time for the edges, we start with adding an element in the node to hold the edges const edgesEl = svg.insert('g').attr('class', 'edges edgePath'); @@ -887,6 +887,8 @@ export const draw = async function (text, id, _version, diagObj) { }, width: node.labelData.width, height: node.labelData.height, + // width: 100, + // height: 100, }, ]; delete node.x; @@ -895,6 +897,7 @@ export const draw = async function (text, id, _version, diagObj) { delete node.height; } }); + insertChildren(graph.children, parentLookupDb); log.info('after layout', JSON.stringify(graph, null, 2)); const g = await elk.layout(graph); diff --git a/packages/mermaid/src/diagrams/flowchart/elk/styles.ts b/packages/mermaid/src/diagrams/flowchart/elk/styles.ts index e8e7065a0..60659df45 100644 --- a/packages/mermaid/src/diagrams/flowchart/elk/styles.ts +++ b/packages/mermaid/src/diagrams/flowchart/elk/styles.ts @@ -81,7 +81,7 @@ const getStyles = (options: FlowChartStyleOptions) => .edgeLabel { background-color: ${options.edgeLabelBackground}; rect { - opacity: 0.5; + opacity: 0.85; background-color: ${options.edgeLabelBackground}; fill: ${options.edgeLabelBackground}; } @@ -132,6 +132,11 @@ const getStyles = (options: FlowChartStyleOptions) => // fill:#ccc; // // stroke:black; // } + + .flowchart-label text { + text-anchor: middle; + } + ${genSections(options)} `; diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.js b/packages/mermaid/src/diagrams/flowchart/flowDb.js index 26bc75c14..85dc5337e 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDb.js +++ b/packages/mermaid/src/diagrams/flowchart/flowDb.js @@ -143,6 +143,7 @@ export const addSingleLink = function (_start, _end, type) { // log.info('Got edge...', start, end); const edge = { start: start, end: end, type: undefined, text: '', labelType: 'text' }; + log.info('abc78 Got edge...', edge); const linkTextObj = type.text; if (linkTextObj !== undefined) { @@ -163,6 +164,7 @@ export const addSingleLink = function (_start, _end, type) { edges.push(edge); }; export const addLink = function (_start, _end, type) { + log.info('addLink (abc78)', _start, _end, type); let i, j; for (i = 0; i < _start.length; i++) { for (j = 0; j < _end.length; j++) { diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison index d21104d49..19ab80b05 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison @@ -438,13 +438,13 @@ arrowText: ; text: textToken - {$$={text:$1, type: 'text'};} + { $$={text:$1, type: 'text'};} | text textToken - {$$={text:$1.text+''+$2, type: 'text'};} + { $$={text:$1.text+''+$2, type: $1.type};} | STR - {$$={text: $1, type: 'text'};} + { $$={text: $1, type: 'text'};} | MD_STR - {$$={text: $1, type: 'markdown'};} + { $$={text: $1, type: 'markdown'};} ; diff --git a/packages/mermaid/src/rendering-util/createText.js b/packages/mermaid/src/rendering-util/createText.js index 0fc7dda54..1097cd0df 100644 --- a/packages/mermaid/src/rendering-util/createText.js +++ b/packages/mermaid/src/rendering-util/createText.js @@ -83,11 +83,13 @@ function createTspan(textElement, lineIndex, lineHeight) { * @param {number} width - The maximum allowed width of the text. * @param {object} g - The parent group element to append the formatted text. * @param {Array} structuredText - The structured text data to format. + * @param addBackground */ -function createFormattedText(width, g, structuredText) { +function createFormattedText(width, g, structuredText, addBackground = false) { const lineHeight = 1.1; - - const textElement = g.append('text').attr('y', '-10.1'); + const labelGroup = g.append('g'); + let bkg = labelGroup.insert('rect').attr('class', 'background'); + const textElement = labelGroup.append('text').attr('y', '-10.1'); // .attr('dominant-baseline', 'middle') // .attr('text-anchor', 'middle'); // .attr('text-anchor', 'middle'); @@ -118,8 +120,20 @@ function createFormattedText(width, g, structuredText) { } } }); - return textElement.node(); - // return g.node(); + if (addBackground) { + const bbox = textElement.node().getBBox(); + const padding = 2; + bkg + .attr('x', -padding) + .attr('y', -padding) + .attr('width', bbox.width + 2 * padding) + .attr('height', bbox.height + 2 * padding); + // .style('fill', 'red'); + + return labelGroup.node(); + } else { + return textElement.node(); + } } /** @@ -183,9 +197,17 @@ function updateTextContentAndStyles(tspan, wrappedLine) { export const createText = ( el, text = '', - { style = '', isTitle = false, classes = '', useHtmlLabels = true, isNode = true, width } = {} + { + style = '', + isTitle = false, + classes = '', + useHtmlLabels = true, + isNode = true, + width, + addSvgBackground = false, + } = {} ) => { - log.info('createText', text, style, isTitle, classes, useHtmlLabels, isNode); + log.info('createText', text, style, isTitle, classes, useHtmlLabels, isNode, addSvgBackground); if (useHtmlLabels) { // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? // text = text.replace(/\\n|\n/g, ' 
'); @@ -203,6 +225,8 @@ export const createText = ( return vertexNode; } else { const structuredText = markdownToLines(text); - return createFormattedText(width, el, structuredText); + + const svgLabel = createFormattedText(width, el, structuredText, addSvgBackground); + return svgLabel; } };