mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-02-04 07:13:25 +08:00
Updating support for the new type of strings for flowcharts-v2
This commit is contained in:
parent
fbeb016398
commit
63160293c7
@ -51,6 +51,9 @@
|
|||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-size: 72px;
|
font-size: 72px;
|
||||||
}
|
}
|
||||||
|
/* tspan {
|
||||||
|
font-size: 6px !important;
|
||||||
|
} */
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -58,7 +61,7 @@
|
|||||||
%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
|
%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
|
||||||
%%
|
%%
|
||||||
graph BT
|
graph BT
|
||||||
a{The cat in the hat} -- 1o --> b
|
a("`The **cat** in the hat} -- 1o --> b
|
||||||
a -- 2o --> c
|
a -- 2o --> c
|
||||||
a -- 3o --> d
|
a -- 3o --> d
|
||||||
g --2i--> a
|
g --2i--> a
|
||||||
@ -66,8 +69,47 @@ d --1i--> a
|
|||||||
h --3i -->a
|
h --3i -->a
|
||||||
b --> d(The dog in the hog)
|
b --> d(The dog in the hog)
|
||||||
c --> d
|
c --> d
|
||||||
|
%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram" class="mermaid2">
|
<pre id="diagram" class="mermaid">
|
||||||
|
flowchart LR
|
||||||
|
b("`The dog in **the** hog... 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": true}} }%%
|
||||||
|
flowchart LR
|
||||||
|
b("`The dog in **the** hog... 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
|
||||||
|
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
|
||||||
|
b("The dog in the hog... a very<br/>long text about it<br/>Word!")
|
||||||
|
</pre>
|
||||||
|
<pre id="diagram" class="mermaid">
|
||||||
|
flowchart LR
|
||||||
|
subgraph "One"
|
||||||
|
a("`The **cat**
|
||||||
|
in the hat`") -- 1o --> b{{"`The **dog** in the hog`"}}
|
||||||
|
end
|
||||||
|
subgraph "`**Two**`"
|
||||||
|
c("`The **cat**
|
||||||
|
in the hat`") -- "`1o **ipa**`" --> d("The dog in the hog")
|
||||||
|
end
|
||||||
|
</pre
|
||||||
|
>
|
||||||
|
<pre id="diagram" class="mermaid">
|
||||||
mindmap
|
mindmap
|
||||||
id1["`**Start2**
|
id1["`**Start2**
|
||||||
second line 😎 with long text that is wrapping to the next line`"]
|
second line 😎 with long text that is wrapping to the next line`"]
|
||||||
@ -83,8 +125,9 @@ mindmap
|
|||||||
<pre id="diagram" class="mermaid">
|
<pre id="diagram" class="mermaid">
|
||||||
mindmap
|
mindmap
|
||||||
id1["`**Start** with
|
id1["`**Start** with
|
||||||
|
|
||||||
a second line 😎`"]
|
a second line 😎`"]
|
||||||
|
id2["`The dog in **the** hog... a *very long text* about it
|
||||||
|
Word!`"]
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram" class="mermaid2">
|
<pre id="diagram" class="mermaid2">
|
||||||
%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
|
%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
|
||||||
@ -290,9 +333,9 @@ mindmap
|
|||||||
// defaultRenderer: 'elk',
|
// defaultRenderer: 'elk',
|
||||||
useMaxWidth: false,
|
useMaxWidth: false,
|
||||||
// htmlLabels: false,
|
// htmlLabels: false,
|
||||||
htmlLabels: true,
|
htmlLabels: false,
|
||||||
},
|
},
|
||||||
htmlLabels: true,
|
htmlLabels: false,
|
||||||
gantt: {
|
gantt: {
|
||||||
useMaxWidth: false,
|
useMaxWidth: false,
|
||||||
},
|
},
|
||||||
|
@ -44,6 +44,16 @@ export class Diagram {
|
|||||||
// calls diagram.db.clear(), which would reset anything set by
|
// calls diagram.db.clear(), which would reset anything set by
|
||||||
// extractFrontMatter().
|
// extractFrontMatter().
|
||||||
this.parser.parse = (text: string) => originalParse(extractFrontMatter(text, this.db));
|
this.parser.parse = (text: string) => originalParse(extractFrontMatter(text, this.db));
|
||||||
|
|
||||||
|
// this.parser.parse = (text: string) => {
|
||||||
|
// console.log('parse called');
|
||||||
|
// try {
|
||||||
|
// originalParse(extractFrontMatter(text, this.db));
|
||||||
|
// } catch (e) {
|
||||||
|
// console.log('parse called', e);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
this.parser.parser.yy = this.db;
|
this.parser.parser.yy = this.db;
|
||||||
if (diagram.init) {
|
if (diagram.init) {
|
||||||
diagram.init(cnf);
|
diagram.init(cnf);
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import intersectRect from './intersect/intersect-rect';
|
import intersectRect from './intersect/intersect-rect';
|
||||||
import { log } from '../logger';
|
import { log } from '../logger';
|
||||||
import createLabel from './createLabel';
|
import createLabel from './createLabel';
|
||||||
|
import { createText } from '../rendering-util/createText';
|
||||||
import { select } from 'd3';
|
import { select } from 'd3';
|
||||||
import { getConfig } from '../config';
|
import { getConfig } from '../config';
|
||||||
import { evaluate } from '../diagrams/common/common';
|
import { evaluate } from '../diagrams/common/common';
|
||||||
|
|
||||||
const rect = (parent, node) => {
|
const rect = (parent, node) => {
|
||||||
log.trace('Creating subgraph rect for ', node.id, node);
|
log.info('Creating subgraph rect for ', node.id, node);
|
||||||
|
|
||||||
// Add outer g element
|
// Add outer g element
|
||||||
const shapeSvg = parent
|
const shapeSvg = parent
|
||||||
@ -17,12 +18,18 @@ const rect = (parent, node) => {
|
|||||||
// add the rect
|
// add the rect
|
||||||
const rect = shapeSvg.insert('rect', ':first-child');
|
const rect = shapeSvg.insert('rect', ':first-child');
|
||||||
|
|
||||||
|
const useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels);
|
||||||
|
|
||||||
// Create the label and insert it after the rect
|
// Create the label and insert it after the rect
|
||||||
const label = shapeSvg.insert('g').attr('class', 'cluster-label');
|
const label = shapeSvg.insert('g').attr('class', 'cluster-label');
|
||||||
|
|
||||||
const text = label
|
// const text = label
|
||||||
.node()
|
// .node()
|
||||||
.appendChild(createLabel(node.labelText, node.labelStyle, undefined, true));
|
// .appendChild(createLabel(node.labelText, node.labelStyle, undefined, true));
|
||||||
|
const text =
|
||||||
|
node.labelType === 'markdown'
|
||||||
|
? createText(label, node.labelText, { style: node.labelStyle, useHtmlLabels })
|
||||||
|
: label.node().appendChild(createLabel(node.labelText, node.labelStyle, undefined, true));
|
||||||
|
|
||||||
// Get the size of the label
|
// Get the size of the label
|
||||||
let bbox = text.getBBox();
|
let bbox = text.getBBox();
|
||||||
@ -61,7 +68,7 @@ const rect = (parent, node) => {
|
|||||||
'transform',
|
'transform',
|
||||||
// This puts the labal on top of the box instead of inside it
|
// This puts the labal on top of the box instead of inside it
|
||||||
// 'translate(' + (node.x - bbox.width / 2) + ', ' + (node.y - node.height / 2 - bbox.height) + ')'
|
// 'translate(' + (node.x - bbox.width / 2) + ', ' + (node.y - node.height / 2 - bbox.height) + ')'
|
||||||
'translate(' + (node.x - bbox.width / 2) + ', ' + (node.y - node.height / 2) + ')'
|
'translate(' + node.x + ', ' + (node.y - node.height / 2) + ')'
|
||||||
);
|
);
|
||||||
|
|
||||||
const rectBox = rect.node().getBBox();
|
const rectBox = rect.node().getBBox();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { log } from '../logger';
|
import { log } from '../logger';
|
||||||
import createLabel from './createLabel';
|
import createLabel from './createLabel';
|
||||||
|
import { createText } from '../rendering-util/createText';
|
||||||
import { line, curveBasis, select } from 'd3';
|
import { line, curveBasis, select } from 'd3';
|
||||||
import { getConfig } from '../config';
|
import { getConfig } from '../config';
|
||||||
import utils from '../utils';
|
import utils from '../utils';
|
||||||
@ -14,8 +15,13 @@ export const clear = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const insertEdgeLabel = (elem, edge) => {
|
export const insertEdgeLabel = (elem, edge) => {
|
||||||
|
const useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels);
|
||||||
// Create the actual text element
|
// Create the actual text element
|
||||||
const labelElement = createLabel(edge.label, edge.labelStyle);
|
const labelElement =
|
||||||
|
edge.labelType === 'markdown'
|
||||||
|
? createText(elem, edge.label, { style: edge.labelStyle, useHtmlLabels })
|
||||||
|
: createLabel(edge.label, edge.labelStyle);
|
||||||
|
log.info('abc82', edge, edge.labelType);
|
||||||
|
|
||||||
// Create outer g, edgeLabel, this will be positioned after graph layout
|
// Create outer g, edgeLabel, this will be positioned after graph layout
|
||||||
const edgeLabel = elem.insert('g').attr('class', 'edgeLabel');
|
const edgeLabel = elem.insert('g').attr('class', 'edgeLabel');
|
||||||
@ -26,7 +32,7 @@ export const insertEdgeLabel = (elem, edge) => {
|
|||||||
|
|
||||||
// Center the label
|
// Center the label
|
||||||
let bbox = labelElement.getBBox();
|
let bbox = labelElement.getBBox();
|
||||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
if (useHtmlLabels) {
|
||||||
const div = labelElement.children[0];
|
const div = labelElement.children[0];
|
||||||
const dv = select(labelElement);
|
const dv = select(labelElement);
|
||||||
bbox = div.getBoundingClientRect();
|
bbox = div.getBoundingClientRect();
|
||||||
|
@ -313,19 +313,18 @@ const cylinder = (parent, node) => {
|
|||||||
const rect = (parent, node) => {
|
const rect = (parent, node) => {
|
||||||
const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, 'node ' + node.classes, true);
|
const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, 'node ' + node.classes, true);
|
||||||
|
|
||||||
log.trace('Classes = ', node.classes);
|
|
||||||
// add the rect
|
// add the rect
|
||||||
const rect = shapeSvg.insert('rect', ':first-child');
|
const rect = shapeSvg.insert('rect', ':first-child');
|
||||||
|
|
||||||
const totalWidth = bbox.width + node.padding;
|
const totalWidth = bbox.width + node.padding * 2;
|
||||||
const totalHeight = bbox.height + node.padding;
|
const totalHeight = bbox.height + node.padding * 2;
|
||||||
rect
|
rect
|
||||||
.attr('class', 'basic label-container')
|
.attr('class', 'basic label-container')
|
||||||
.attr('style', node.style)
|
.attr('style', node.style)
|
||||||
.attr('rx', node.rx)
|
.attr('rx', node.rx)
|
||||||
.attr('ry', node.ry)
|
.attr('ry', node.ry)
|
||||||
.attr('x', -bbox.width / 2 - halfPadding)
|
.attr('x', -bbox.width / 2 - node.padding)
|
||||||
.attr('y', -bbox.height / 2 - halfPadding)
|
.attr('y', -bbox.height / 2 - node.padding)
|
||||||
.attr('width', totalWidth)
|
.attr('width', totalWidth)
|
||||||
.attr('height', totalHeight);
|
.attr('height', totalHeight);
|
||||||
|
|
||||||
@ -352,7 +351,7 @@ const rect = (parent, node) => {
|
|||||||
const labelRect = (parent, node) => {
|
const labelRect = (parent, node) => {
|
||||||
const { shapeSvg } = labelHelper(parent, node, 'label', true);
|
const { shapeSvg } = labelHelper(parent, node, 'label', true);
|
||||||
|
|
||||||
log.trace('Classes = ', node.classes);
|
log.info('Classes = ', node.classes);
|
||||||
// add the rect
|
// add the rect
|
||||||
const rect = shapeSvg.insert('rect', ':first-child');
|
const rect = shapeSvg.insert('rect', ':first-child');
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import createLabel from '../createLabel';
|
import createLabel from '../createLabel';
|
||||||
|
import { createText } from '../../rendering-util/createText';
|
||||||
import { getConfig } from '../../config';
|
import { getConfig } from '../../config';
|
||||||
import { decodeEntities } from '../../mermaidAPI';
|
import { decodeEntities } from '../../mermaidAPI';
|
||||||
import { select } from 'd3';
|
import { select } from 'd3';
|
||||||
@ -27,9 +28,17 @@ export const labelHelper = (parent, node, _classes, isNode) => {
|
|||||||
labelText = typeof node.labelText === 'string' ? node.labelText : node.labelText[0];
|
labelText = typeof node.labelText === 'string' ? node.labelText : node.labelText[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const text = label
|
const textNode = label.node();
|
||||||
.node()
|
let text;
|
||||||
.appendChild(
|
if (node.labelType === 'markdown') {
|
||||||
|
// text = textNode;
|
||||||
|
text = createText(label, sanitizeText(decodeEntities(labelText), getConfig()), {
|
||||||
|
useHtmlLabels: getConfig().flowchart.htmlLabels,
|
||||||
|
width: node.width || 200,
|
||||||
|
classes: 'markdown-node-label',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
text = textNode.appendChild(
|
||||||
createLabel(
|
createLabel(
|
||||||
sanitizeText(decodeEntities(labelText), getConfig()),
|
sanitizeText(decodeEntities(labelText), getConfig()),
|
||||||
node.labelStyle,
|
node.labelStyle,
|
||||||
@ -37,6 +46,7 @@ export const labelHelper = (parent, node, _classes, isNode) => {
|
|||||||
isNode
|
isNode
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Get the size of the label
|
// Get the size of the label
|
||||||
let bbox = text.getBBox();
|
let bbox = text.getBBox();
|
||||||
@ -52,7 +62,11 @@ export const labelHelper = (parent, node, _classes, isNode) => {
|
|||||||
const halfPadding = node.padding / 2;
|
const halfPadding = node.padding / 2;
|
||||||
|
|
||||||
// Center the label
|
// Center the label
|
||||||
label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')');
|
if (getConfig().flowchart.htmlLabels) {
|
||||||
|
label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')');
|
||||||
|
} else {
|
||||||
|
label.attr('transform', 'translate(' + 0 + ', ' + -bbox.height / 2 + ')');
|
||||||
|
}
|
||||||
|
|
||||||
return { shapeSvg, bbox, halfPadding, label };
|
return { shapeSvg, bbox, halfPadding, label };
|
||||||
};
|
};
|
||||||
|
@ -59,13 +59,14 @@ export const lookUpDomId = function (id) {
|
|||||||
*
|
*
|
||||||
* @param _id
|
* @param _id
|
||||||
* @param text
|
* @param text
|
||||||
|
* @param textObj
|
||||||
* @param type
|
* @param type
|
||||||
* @param style
|
* @param style
|
||||||
* @param classes
|
* @param classes
|
||||||
* @param dir
|
* @param dir
|
||||||
* @param props
|
* @param props
|
||||||
*/
|
*/
|
||||||
export const addVertex = function (_id, text, type, style, classes, dir, props = {}) {
|
export const addVertex = function (_id, textObj, type, style, classes, dir, props = {}) {
|
||||||
let txt;
|
let txt;
|
||||||
let id = _id;
|
let id = _id;
|
||||||
if (id === undefined) {
|
if (id === undefined) {
|
||||||
@ -80,16 +81,17 @@ export const addVertex = function (_id, text, type, style, classes, dir, props =
|
|||||||
if (vertices[id] === undefined) {
|
if (vertices[id] === undefined) {
|
||||||
vertices[id] = {
|
vertices[id] = {
|
||||||
id: id,
|
id: id,
|
||||||
|
labelType: 'text',
|
||||||
domId: MERMAID_DOM_ID_PREFIX + id + '-' + vertexCounter,
|
domId: MERMAID_DOM_ID_PREFIX + id + '-' + vertexCounter,
|
||||||
styles: [],
|
styles: [],
|
||||||
classes: [],
|
classes: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
vertexCounter++;
|
vertexCounter++;
|
||||||
if (text !== undefined) {
|
if (textObj !== undefined) {
|
||||||
config = configApi.getConfig();
|
config = configApi.getConfig();
|
||||||
txt = sanitizeText(text.trim());
|
txt = sanitizeText(textObj.text.trim());
|
||||||
|
vertices[id].labelType = textObj.type;
|
||||||
// strip quotes if string starts and ends with a quote
|
// strip quotes if string starts and ends with a quote
|
||||||
if (txt[0] === '"' && txt[txt.length - 1] === '"') {
|
if (txt[0] === '"' && txt[txt.length - 1] === '"') {
|
||||||
txt = txt.substring(1, txt.length - 1);
|
txt = txt.substring(1, txt.length - 1);
|
||||||
@ -131,24 +133,26 @@ export const addVertex = function (_id, text, type, style, classes, dir, props =
|
|||||||
* @param _end
|
* @param _end
|
||||||
* @param type
|
* @param type
|
||||||
* @param linkText
|
* @param linkText
|
||||||
|
* @param linkTextObj
|
||||||
*/
|
*/
|
||||||
export const addSingleLink = function (_start, _end, type, linkText) {
|
export const addSingleLink = function (_start, _end, type) {
|
||||||
let start = _start;
|
let start = _start;
|
||||||
let end = _end;
|
let end = _end;
|
||||||
// if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start;
|
// if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start;
|
||||||
// if (end[0].match(/\d/)) end = MERMAID_DOM_ID_PREFIX + end;
|
// if (end[0].match(/\d/)) end = MERMAID_DOM_ID_PREFIX + end;
|
||||||
// log.info('Got edge...', start, end);
|
// log.info('Got edge...', start, end);
|
||||||
|
|
||||||
const edge = { start: start, end: end, type: undefined, text: '' };
|
const edge = { start: start, end: end, type: undefined, text: '', labelType: 'text' };
|
||||||
linkText = type.text;
|
const linkTextObj = type.text;
|
||||||
|
|
||||||
if (linkText !== undefined) {
|
if (linkTextObj !== undefined) {
|
||||||
edge.text = sanitizeText(linkText.trim());
|
edge.text = sanitizeText(linkTextObj.text.trim());
|
||||||
|
|
||||||
// strip quotes if string starts and ends with a quote
|
// strip quotes if string starts and ends with a quote
|
||||||
if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') {
|
if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') {
|
||||||
edge.text = edge.text.substring(1, edge.text.length - 1);
|
edge.text = edge.text.substring(1, edge.text.length - 1);
|
||||||
}
|
}
|
||||||
|
edge.labelType = linkTextObj.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type !== undefined) {
|
if (type !== undefined) {
|
||||||
@ -158,11 +162,11 @@ export const addSingleLink = function (_start, _end, type, linkText) {
|
|||||||
}
|
}
|
||||||
edges.push(edge);
|
edges.push(edge);
|
||||||
};
|
};
|
||||||
export const addLink = function (_start, _end, type, linktext) {
|
export const addLink = function (_start, _end, type) {
|
||||||
let i, j;
|
let i, j;
|
||||||
for (i = 0; i < _start.length; i++) {
|
for (i = 0; i < _start.length; i++) {
|
||||||
for (j = 0; j < _end.length; j++) {
|
for (j = 0; j < _end.length; j++) {
|
||||||
addSingleLink(_start[i], _end[j], type, linktext);
|
addSingleLink(_start[i], _end[j], type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -457,10 +461,9 @@ export const defaultStyle = function () {
|
|||||||
* @param _title
|
* @param _title
|
||||||
*/
|
*/
|
||||||
export const addSubGraph = function (_id, list, _title) {
|
export const addSubGraph = function (_id, list, _title) {
|
||||||
// console.log('addSubGraph', _id, list, _title);
|
let id = _id.text.trim();
|
||||||
let id = _id.trim();
|
let title = _title.text;
|
||||||
let title = _title;
|
if (_id === _title && _title.text.match(/\s/)) {
|
||||||
if (_id === _title && _title.match(/\s/)) {
|
|
||||||
id = undefined;
|
id = undefined;
|
||||||
}
|
}
|
||||||
/** @param a */
|
/** @param a */
|
||||||
@ -502,7 +505,14 @@ export const addSubGraph = function (_id, list, _title) {
|
|||||||
title = title || '';
|
title = title || '';
|
||||||
title = sanitizeText(title);
|
title = sanitizeText(title);
|
||||||
subCount = subCount + 1;
|
subCount = subCount + 1;
|
||||||
const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [], dir };
|
const subGraph = {
|
||||||
|
id: id,
|
||||||
|
nodes: nodeList,
|
||||||
|
title: title.trim(),
|
||||||
|
classes: [],
|
||||||
|
dir,
|
||||||
|
labelType: _title.type,
|
||||||
|
};
|
||||||
|
|
||||||
log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir);
|
log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir);
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
|
|||||||
if (vertex.classes.length > 0) {
|
if (vertex.classes.length > 0) {
|
||||||
classStr = vertex.classes.join(' ');
|
classStr = vertex.classes.join(' ');
|
||||||
}
|
}
|
||||||
|
classStr = classStr + ' flowchart-label';
|
||||||
const styles = getStylesFromArray(vertex.styles);
|
const styles = getStylesFromArray(vertex.styles);
|
||||||
|
|
||||||
// Use vertex id as text in the box if no text is provided by the graph definition
|
// Use vertex id as text in the box if no text is provided by the graph definition
|
||||||
@ -55,31 +55,36 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
|
|||||||
|
|
||||||
// We create a SVG label, either by delegating to addHtmlLabel or manually
|
// We create a SVG label, either by delegating to addHtmlLabel or manually
|
||||||
let vertexNode;
|
let vertexNode;
|
||||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
log.info('vertex', vertex, vertex.labelType);
|
||||||
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
|
if (vertex.labelType === 'markdown') {
|
||||||
const node = {
|
log.info('vertex', vertex, vertex.labelType);
|
||||||
label: vertexText.replace(
|
|
||||||
/fa[blrs]?:fa-[\w-]+/g,
|
|
||||||
(s) => `<i class='${s.replace(':', ' ')}'></i>`
|
|
||||||
),
|
|
||||||
};
|
|
||||||
vertexNode = addHtmlLabel(svg, node).node();
|
|
||||||
vertexNode.parentNode.removeChild(vertexNode);
|
|
||||||
} else {
|
} else {
|
||||||
const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text');
|
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||||
svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:'));
|
// 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();
|
||||||
|
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);
|
const rows = vertexText.split(common.lineBreakRegex);
|
||||||
|
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
||||||
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
|
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
|
||||||
tspan.setAttribute('dy', '1em');
|
tspan.setAttribute('dy', '1em');
|
||||||
tspan.setAttribute('x', '1');
|
tspan.setAttribute('x', '1');
|
||||||
tspan.textContent = row;
|
tspan.textContent = row;
|
||||||
svgLabel.appendChild(tspan);
|
svgLabel.appendChild(tspan);
|
||||||
|
}
|
||||||
|
vertexNode = svgLabel;
|
||||||
}
|
}
|
||||||
vertexNode = svgLabel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let radious = 0;
|
let radious = 0;
|
||||||
@ -146,6 +151,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
|
|||||||
labelStyle: styles.labelStyle,
|
labelStyle: styles.labelStyle,
|
||||||
shape: _shape,
|
shape: _shape,
|
||||||
labelText: vertexText,
|
labelText: vertexText,
|
||||||
|
labelType: vertex.labelType,
|
||||||
rx: radious,
|
rx: radious,
|
||||||
ry: radious,
|
ry: radious,
|
||||||
class: classStr,
|
class: classStr,
|
||||||
@ -165,6 +171,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
|
|||||||
|
|
||||||
log.info('setNode', {
|
log.info('setNode', {
|
||||||
labelStyle: styles.labelStyle,
|
labelStyle: styles.labelStyle,
|
||||||
|
labelType: vertex.labelType,
|
||||||
shape: _shape,
|
shape: _shape,
|
||||||
labelText: vertexText,
|
labelText: vertexText,
|
||||||
rx: radious,
|
rx: radious,
|
||||||
@ -312,7 +319,7 @@ export const addEdges = function (edges, g, diagObj) {
|
|||||||
edgeData.labelpos = 'c';
|
edgeData.labelpos = 'c';
|
||||||
}
|
}
|
||||||
|
|
||||||
edgeData.labelType = 'text';
|
edgeData.labelType = edge.labelType;
|
||||||
edgeData.label = edge.text.replace(common.lineBreakRegex, '\n');
|
edgeData.label = edge.text.replace(common.lineBreakRegex, '\n');
|
||||||
|
|
||||||
if (edge.style === undefined) {
|
if (edge.style === undefined) {
|
||||||
@ -405,7 +412,14 @@ export const draw = function (text, id, _version, diagObj) {
|
|||||||
for (let i = subGraphs.length - 1; i >= 0; i--) {
|
for (let i = subGraphs.length - 1; i >= 0; i--) {
|
||||||
subG = subGraphs[i];
|
subG = subGraphs[i];
|
||||||
log.info('Subgraph - ', subG);
|
log.info('Subgraph - ', subG);
|
||||||
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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the vertices/nodes and edges/links from the parsed graph definition
|
// Fetch the vertices/nodes and edges/links from the parsed graph definition
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
/* lexical grammar */
|
/* lexical grammar */
|
||||||
%lex
|
%lex
|
||||||
%x string
|
%x string
|
||||||
|
%x md_string
|
||||||
%x acc_title
|
%x acc_title
|
||||||
%x acc_descr
|
%x acc_descr
|
||||||
%x acc_descr_multiline
|
%x acc_descr_multiline
|
||||||
@ -37,6 +38,9 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
|||||||
<acc_descr_multiline>[\}] { this.popState(); }
|
<acc_descr_multiline>[\}] { this.popState(); }
|
||||||
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
|
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
|
||||||
// <acc_descr_multiline>.*[^\n]* { return "acc_descr_line"}
|
// <acc_descr_multiline>.*[^\n]* { return "acc_descr_line"}
|
||||||
|
["][`] { this.begin("md_string");}
|
||||||
|
<md_string>[^`"]+ { return "MD_STR";}
|
||||||
|
<md_string>[`]["] { this.popState();}
|
||||||
["] this.begin("string");
|
["] this.begin("string");
|
||||||
<string>["] this.popState();
|
<string>["] this.popState();
|
||||||
<string>[^"]* return "STR";
|
<string>[^"]* return "STR";
|
||||||
@ -434,11 +438,13 @@ arrowText:
|
|||||||
;
|
;
|
||||||
|
|
||||||
text: textToken
|
text: textToken
|
||||||
{$$=$1;}
|
{$$={text:$1, type: 'text'};}
|
||||||
| text textToken
|
| text textToken
|
||||||
{$$=$1+''+$2;}
|
{$$={text:$1.text+''+$2, type: 'text'};}
|
||||||
| STR
|
| STR
|
||||||
{$$=$1;}
|
{$$={text: $1, type: 'text'};}
|
||||||
|
| MD_STR
|
||||||
|
{$$={text: $1, type: 'markdown'};}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,6 +41,15 @@ const getStyles = (options: FlowChartStyleOptions) =>
|
|||||||
stroke: ${options.nodeBorder};
|
stroke: ${options.nodeBorder};
|
||||||
stroke-width: 1px;
|
stroke-width: 1px;
|
||||||
}
|
}
|
||||||
|
.flowchart-label text {
|
||||||
|
text-anchor: middle;
|
||||||
|
}
|
||||||
|
// .flowchart-label .text-outer-tspan {
|
||||||
|
// text-anchor: middle;
|
||||||
|
// }
|
||||||
|
// .flowchart-label .text-inner-tspan {
|
||||||
|
// text-anchor: start;
|
||||||
|
// }
|
||||||
|
|
||||||
.node .label {
|
.node .label {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -49,7 +49,7 @@ function addHtmlSpan(element, node, width, classes) {
|
|||||||
if (bbox.width === width) {
|
if (bbox.width === width) {
|
||||||
div.style('display', 'table');
|
div.style('display', 'table');
|
||||||
div.style('white-space', 'break-spaces');
|
div.style('white-space', 'break-spaces');
|
||||||
div.style('width', '200px');
|
div.style('width', width + 'px');
|
||||||
bbox = div.node().getBoundingClientRect();
|
bbox = div.node().getBoundingClientRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,8 +70,9 @@ function addHtmlSpan(element, node, width, classes) {
|
|||||||
function createTspan(textElement, lineIndex, lineHeight) {
|
function createTspan(textElement, lineIndex, lineHeight) {
|
||||||
return textElement
|
return textElement
|
||||||
.append('tspan')
|
.append('tspan')
|
||||||
|
.attr('class', 'text-outer-tspan')
|
||||||
.attr('x', 0)
|
.attr('x', 0)
|
||||||
.attr('y', lineIndex * lineHeight + 'em')
|
.attr('y', lineIndex * lineHeight - 0.1 + 'em')
|
||||||
.attr('dy', lineHeight + 'em');
|
.attr('dy', lineHeight + 'em');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,9 +87,13 @@ function createTspan(textElement, lineIndex, lineHeight) {
|
|||||||
function createFormattedText(width, g, structuredText) {
|
function createFormattedText(width, g, structuredText) {
|
||||||
const lineHeight = 1.1;
|
const lineHeight = 1.1;
|
||||||
|
|
||||||
const textElement = g.append('text');
|
const textElement = g.append('text').attr('y', '-10.1');
|
||||||
|
// .attr('dominant-baseline', 'middle')
|
||||||
structuredText.forEach((line, lineIndex) => {
|
// .attr('text-anchor', 'middle');
|
||||||
|
// .attr('text-anchor', 'middle');
|
||||||
|
let lineIndex = -1;
|
||||||
|
structuredText.forEach((line) => {
|
||||||
|
lineIndex++;
|
||||||
let tspan = createTspan(textElement, lineIndex, lineHeight);
|
let tspan = createTspan(textElement, lineIndex, lineHeight);
|
||||||
|
|
||||||
let words = [...line].reverse();
|
let words = [...line].reverse();
|
||||||
@ -108,10 +113,13 @@ function createFormattedText(width, g, structuredText) {
|
|||||||
updateTextContentAndStyles(tspan, wrappedLine);
|
updateTextContentAndStyles(tspan, wrappedLine);
|
||||||
|
|
||||||
wrappedLine = [];
|
wrappedLine = [];
|
||||||
tspan = createTspan(textElement, ++lineIndex, lineHeight);
|
lineIndex++;
|
||||||
|
tspan = createTspan(textElement, lineIndex, lineHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return textElement.node();
|
||||||
|
// return g.node();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,12 +132,36 @@ function createFormattedText(width, g, structuredText) {
|
|||||||
function updateTextContentAndStyles(tspan, wrappedLine) {
|
function updateTextContentAndStyles(tspan, wrappedLine) {
|
||||||
tspan.text('');
|
tspan.text('');
|
||||||
|
|
||||||
wrappedLine.forEach((word) => {
|
wrappedLine.forEach((word, index) => {
|
||||||
tspan
|
const innerTspan = tspan
|
||||||
.append('tspan')
|
.append('tspan')
|
||||||
.attr('font-style', word.type === 'em' ? 'italic' : 'normal')
|
.attr('font-style', word.type === 'em' ? 'italic' : 'normal')
|
||||||
.attr('font-weight', word.type === 'strong' ? 'bold' : 'normal')
|
.attr('class', 'text-inner-tspan')
|
||||||
.text(word.content + ' ');
|
.attr('font-weight', word.type === 'strong' ? 'bold' : 'normal');
|
||||||
|
const special = [
|
||||||
|
'<',
|
||||||
|
'>',
|
||||||
|
'&',
|
||||||
|
'"',
|
||||||
|
"'",
|
||||||
|
'.',
|
||||||
|
',',
|
||||||
|
':',
|
||||||
|
';',
|
||||||
|
'!',
|
||||||
|
'?',
|
||||||
|
'(',
|
||||||
|
')',
|
||||||
|
'[',
|
||||||
|
']',
|
||||||
|
'{',
|
||||||
|
'}',
|
||||||
|
];
|
||||||
|
if (index !== 0 && special.includes(word.content)) {
|
||||||
|
innerTspan.text(word.content);
|
||||||
|
} else {
|
||||||
|
innerTspan.text(' ' + word.content);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,6 +169,37 @@ it('markdownToLines - Mixed formatting', () => {
|
|||||||
expect(output).toEqual(expectedOutput);
|
expect(output).toEqual(expectedOutput);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('markdownToLines - Mixed formatting', () => {
|
||||||
|
const input = `The dog in **the** hog... a *very long text* about it
|
||||||
|
Word!`;
|
||||||
|
|
||||||
|
const expectedOutput = [
|
||||||
|
[
|
||||||
|
{ content: 'The', type: 'normal' },
|
||||||
|
{ content: 'dog', type: 'normal' },
|
||||||
|
{ content: 'in', type: 'normal' },
|
||||||
|
{ content: 'the', type: 'strong' },
|
||||||
|
{ content: 'hog', type: 'normal' },
|
||||||
|
{ content: '.', type: 'normal' },
|
||||||
|
{ content: '.', type: 'normal' },
|
||||||
|
{ content: '.', type: 'normal' },
|
||||||
|
{ content: 'a', type: 'normal' },
|
||||||
|
{ content: 'very', type: 'em' },
|
||||||
|
{ content: 'long', type: 'em' },
|
||||||
|
{ content: 'text', type: 'em' },
|
||||||
|
{ content: 'about', type: 'normal' },
|
||||||
|
{ content: 'it', type: 'normal' },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ content: 'Word', type: 'normal' },
|
||||||
|
{ content: '!', type: 'normal' },
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
const output = markdownToLines(input);
|
||||||
|
expect(output).toEqual(expectedOutput);
|
||||||
|
});
|
||||||
|
|
||||||
test('markdownToHTML - Basic test', () => {
|
test('markdownToHTML - Basic test', () => {
|
||||||
const input = `This is regular text
|
const input = `This is regular text
|
||||||
Here is a new line
|
Here is a new line
|
||||||
|
Loading…
x
Reference in New Issue
Block a user