Skip to content

Commit

Permalink
Adding support for markdown string in flowchart-elk
Browse files Browse the repository at this point in the history
  • Loading branch information
knsv committed Mar 29, 2023
1 parent 89193d7 commit 4caf7d7
Show file tree
Hide file tree
Showing 13 changed files with 147 additions and 83 deletions.
67 changes: 40 additions & 27 deletions cypress/platform/knsv2.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,51 +57,64 @@
</style>
</head>
<body>
<pre id="diagram" class="mermaid2">
<pre id="diagram" class="mermaid">
%%{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"}} }%%
</pre>
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
</pre
>
<pre id="diagram" class="mermaid">
%%{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
</pre
>
<pre id="diagram" class="mermaid">
flowchart-elk LR
b("`The dog in **the** hog.(1)
NL`") --"`1o **bold**`"--> c
</pre
>
<pre id="diagram" class="mermaid">
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
</pre
>
<pre id="diagram" class="mermaid">
%%{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. `")
</pre
>
<pre id="diagram" class="mermaid">
%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
flowchart-elk LR
b("The dog in the hog... a very<br/>long text about it<br/>Word!")
</pre>
<pre id="diagram" class="mermaid">
%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart LR
flowchart-elk LR
b("The dog in the hog... a very<br/>long text about it<br/>Word!")
</pre>
<pre id="diagram" class="mermaid">
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**
Expand Down Expand Up @@ -129,7 +142,7 @@
id2["`The dog in **the** hog... a *very long text* about it
Word!`"]
</pre>
<pre id="diagram" class="mermaid2">
<pre id="diagram" class="mermaid">
%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
flowchart TB
%% I could not figure out how to use double quotes in labels in Mermaid
Expand Down Expand Up @@ -185,7 +198,7 @@
</pre
>
<br />
<pre id="diagram" class="mermaid2">
<pre id="diagram" class="mermaid">
flowchart TB
%% I could not figure out how to use double quotes in labels in Mermaid
subgraph ibm[IBM Espresso CPU]
Expand Down Expand Up @@ -241,7 +254,7 @@
>
<br />
&nbsp;
<pre id="diagram" class="mermaid2">
<pre id="diagram" class="mermaid">
flowchart LR
B1 --be be--x B2
B1 --bo bo--o B3
Expand Down Expand Up @@ -274,7 +287,7 @@
B6 --> B5
</pre
>
<pre id="diagram" class="mermaid2">
<pre id="diagram" class="mermaid">
sequenceDiagram
Customer->>+Stripe: Makes a payment request
Stripe->>+Bank: Forwards the payment request to the bank
Expand All @@ -287,7 +300,7 @@
Customer->>+Merchant: Receives goods or services
</pre
>
<pre id="diagram" class="mermaid2">
<pre id="diagram" class="mermaid">
mindmap
root((mindmap))
Origins
Expand All @@ -307,7 +320,7 @@
Mermaid
</pre>
<br />
<pre id="diagram" class="mermaid2">
<pre id="diagram" class="mermaid">
example-diagram
</pre>

Expand All @@ -332,8 +345,8 @@
flowchart: {
// defaultRenderer: 'elk',
useMaxWidth: false,
// htmlLabels: false,
htmlLabels: false,
// htmlLabels: true,
},
htmlLabels: false,
gantt: {
Expand Down
2 changes: 1 addition & 1 deletion docs/config/setup/modules/defaultConfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

---

Expand Down
1 change: 0 additions & 1 deletion packages/mermaid/src/Diagram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions packages/mermaid/src/config.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ export interface FlowchartDiagramConfig extends BaseDiagramConfig {
curve?: string;
padding?: number;
defaultRenderer?: string;
wrappingWidth?: number;
}

export interface FontConfig {
Expand Down
6 changes: 5 additions & 1 deletion packages/mermaid/src/dagre-wrapper/edges.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions packages/mermaid/src/dagre-wrapper/nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions packages/mermaid/src/dagre-wrapper/shapes/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 };
};

Expand Down
12 changes: 12 additions & 0 deletions packages/mermaid/src/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,18 @@ const config: Partial<MermaidConfig> = {
* 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 */
Expand Down
79 changes: 41 additions & 38 deletions packages/mermaid/src/diagrams/flowchart/elk/flowRenderer-elk.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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
Expand All @@ -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) => `<i class='${s.replace(':', ' ')}'></i>`
),
};
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 = [
{
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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');
Expand All @@ -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');
Expand All @@ -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;
Expand All @@ -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);
Expand Down
Loading

0 comments on commit 4caf7d7

Please sign in to comment.