mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-24 01:39:53 +02:00
#4220 Handling paragraphs and html labels with classes in mindmaps.
This commit is contained in:
@@ -66,21 +66,24 @@ h --3i -->a
|
|||||||
b --> d(The dog in the hog)
|
b --> d(The dog in the hog)
|
||||||
c --> d
|
c --> d
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram" class="mermaid">
|
<pre id="diagram" class="mermaid2">
|
||||||
mindmap
|
mindmap
|
||||||
id1["`Start`"]
|
id1["`**Start2**
|
||||||
|
second line 😎 with long text that is wrapping to the next line`"]
|
||||||
id2["`Child **with bold** text`"]
|
id2["`Child **with bold** text`"]
|
||||||
id3["`Children of which some
|
id3["`Children of which some
|
||||||
is using *italic type of* text`"]
|
is using *italic type of* text`"]
|
||||||
id4[Child]
|
id4[Child]
|
||||||
|
id5["`Child
|
||||||
|
Row
|
||||||
|
and another
|
||||||
|
`"]
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram" class="mermaid2">
|
<pre id="diagram" class="mermaid">
|
||||||
mindmap
|
mindmap
|
||||||
id1["`Start
|
id1["`**Start** with
|
||||||
second line 😎`"]
|
|
||||||
id2[Child]
|
a second line 😎`"]
|
||||||
id3[Child]
|
|
||||||
id4[Child]
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram" class="mermaid2">
|
<pre id="diagram" class="mermaid2">
|
||||||
%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
|
%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
|
||||||
|
@@ -70,5 +70,12 @@ const getStyles = (options) =>
|
|||||||
.edge {
|
.edge {
|
||||||
fill: none;
|
fill: none;
|
||||||
}
|
}
|
||||||
|
.mindmap-node-label {
|
||||||
|
dy: 1em;
|
||||||
|
alignment-baseline: middle;
|
||||||
|
text-anchor: middle;
|
||||||
|
dominant-baseline: middle;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
export default getStyles;
|
export default getStyles;
|
||||||
|
@@ -204,7 +204,7 @@ const roundedRectBkg = function (elem, node) {
|
|||||||
* @returns {number} The height nodes dom element
|
* @returns {number} The height nodes dom element
|
||||||
*/
|
*/
|
||||||
export const drawNode = function (elem, node, fullSection, conf) {
|
export const drawNode = function (elem, node, fullSection, conf) {
|
||||||
const htmlLabels = false;
|
const htmlLabels = conf.htmlLabels;
|
||||||
const section = fullSection % (MAX_SECTIONS - 1);
|
const section = fullSection % (MAX_SECTIONS - 1);
|
||||||
const nodeElem = elem.append('g');
|
const nodeElem = elem.append('g');
|
||||||
node.section = section;
|
node.section = section;
|
||||||
@@ -217,19 +217,12 @@ export const drawNode = function (elem, node, fullSection, conf) {
|
|||||||
|
|
||||||
// Create the wrapped text element
|
// Create the wrapped text element
|
||||||
const textElem = nodeElem.append('g');
|
const textElem = nodeElem.append('g');
|
||||||
const newEl = createText(textElem, node.descr, { useHtmlLabels: htmlLabels, width: node.width });
|
const newEl = createText(textElem, node.descr, {
|
||||||
// const txt = textElem.node().appendChild(newEl);
|
useHtmlLabels: htmlLabels,
|
||||||
// const txt = textElem.append(newEl);
|
width: node.width,
|
||||||
// const txt = textElem
|
classes: 'mindmap-node-label',
|
||||||
// .append('text')
|
});
|
||||||
// .text(node.descr)
|
|
||||||
// .attr('dy', '1em')
|
|
||||||
// .attr('alignment-baseline', 'middle')
|
|
||||||
// .attr('dominant-baseline', 'middle')
|
|
||||||
// .attr('text-anchor', 'middle')
|
|
||||||
// .call(wrap, node.width);
|
|
||||||
// const newerEl = textElem.node().appendChild(newEl);
|
|
||||||
// setSize(textElem);
|
|
||||||
if (!htmlLabels) {
|
if (!htmlLabels) {
|
||||||
textElem
|
textElem
|
||||||
.attr('dy', '1em')
|
.attr('dy', '1em')
|
||||||
|
@@ -17,19 +17,22 @@ function applyStyle(dom, styleFn) {
|
|||||||
/**
|
/**
|
||||||
* @param element
|
* @param element
|
||||||
* @param {any} node
|
* @param {any} node
|
||||||
|
* @param width
|
||||||
|
* @param classes
|
||||||
* @returns {SVGForeignObjectElement} Node
|
* @returns {SVGForeignObjectElement} Node
|
||||||
*/
|
*/
|
||||||
function addHtmlSpan(element, node) {
|
function addHtmlSpan(element, node, width, classes) {
|
||||||
const fo = element.append('foreignObject');
|
const fo = element.append('foreignObject');
|
||||||
const newEl = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
|
// const newEl = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
|
||||||
|
// const newEl = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
|
||||||
const div = fo.append('xhtml:div');
|
const div = fo.append('xhtml:div');
|
||||||
|
// const div = body.append('div');
|
||||||
|
// const div = fo.append('div');
|
||||||
|
|
||||||
const label = node.label;
|
const label = node.label;
|
||||||
const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel';
|
const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel';
|
||||||
div.html(
|
div.html(
|
||||||
'<span class="' +
|
`<span class="${labelClass} ${classes}" ` +
|
||||||
labelClass +
|
|
||||||
'" ' +
|
|
||||||
(node.labelStyle ? 'style="' + node.labelStyle + '"' : '') +
|
(node.labelStyle ? 'style="' + node.labelStyle + '"' : '') +
|
||||||
'>' +
|
'>' +
|
||||||
label +
|
label +
|
||||||
@@ -37,16 +40,22 @@ function addHtmlSpan(element, node) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
applyStyle(div, node.labelStyle);
|
applyStyle(div, node.labelStyle);
|
||||||
div.style('display', 'inline-block');
|
div.style('display', 'table-cell');
|
||||||
const bbox = div.node().getBoundingClientRect();
|
div.style('white-space', 'nowrap');
|
||||||
|
div.style('max-width', width + 'px');
|
||||||
|
div.attr('xmlns', 'http://www.w3.org/1999/xhtml');
|
||||||
|
|
||||||
|
let bbox = div.node().getBoundingClientRect();
|
||||||
|
if (bbox.width === width) {
|
||||||
|
div.style('display', 'table');
|
||||||
|
div.style('white-space', 'break-spaces');
|
||||||
|
div.style('width', '200px');
|
||||||
|
bbox = div.node().getBoundingClientRect();
|
||||||
|
}
|
||||||
|
|
||||||
fo.style('width', bbox.width);
|
fo.style('width', bbox.width);
|
||||||
fo.style('height', bbox.height);
|
fo.style('height', bbox.height);
|
||||||
|
|
||||||
const divNode = div.node();
|
|
||||||
window.divNode = divNode;
|
|
||||||
// Fix for firefox
|
|
||||||
div.style('white-space', 'nowrap');
|
|
||||||
div.attr('xmlns', 'http://www.w3.org/1999/xhtml');
|
|
||||||
return fo.node();
|
return fo.node();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +167,7 @@ export const createText = (
|
|||||||
),
|
),
|
||||||
labelStyle: style.replace('fill:', 'color:'),
|
labelStyle: style.replace('fill:', 'color:'),
|
||||||
};
|
};
|
||||||
let vertexNode = addHtmlSpan(el, node);
|
let vertexNode = addHtmlSpan(el, node, width, classes);
|
||||||
return vertexNode;
|
return vertexNode;
|
||||||
} else {
|
} else {
|
||||||
const structuredText = markdownToLines(text);
|
const structuredText = markdownToLines(text);
|
||||||
|
@@ -1,12 +1,25 @@
|
|||||||
import SimpleMarkdown from '@khanacademy/simple-markdown';
|
import SimpleMarkdown from '@khanacademy/simple-markdown';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param markdown
|
||||||
|
*/
|
||||||
|
function preprocessMarkdown(markdown) {
|
||||||
|
// Replace multiple newlines with a single newline
|
||||||
|
const withoutMultipleNewlines = markdown.replace(/\n{2,}/g, '\n');
|
||||||
|
// Remove extra spaces at the beginning of each line
|
||||||
|
const withoutExtraSpaces = withoutMultipleNewlines.replace(/^\s+/gm, '');
|
||||||
|
return withoutExtraSpaces;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param markdown
|
* @param markdown
|
||||||
*/
|
*/
|
||||||
export function markdownToLines(markdown) {
|
export function markdownToLines(markdown) {
|
||||||
|
const preprocessedMarkdown = preprocessMarkdown(markdown);
|
||||||
const mdParse = SimpleMarkdown.defaultBlockParse;
|
const mdParse = SimpleMarkdown.defaultBlockParse;
|
||||||
const syntaxTree = mdParse(markdown);
|
const syntaxTree = mdParse(preprocessedMarkdown);
|
||||||
|
|
||||||
let lines = [[]];
|
let lines = [[]];
|
||||||
let currentLine = 0;
|
let currentLine = 0;
|
||||||
@@ -19,6 +32,7 @@ export function markdownToLines(markdown) {
|
|||||||
function processNode(node, parentType) {
|
function processNode(node, parentType) {
|
||||||
if (node.type === 'text') {
|
if (node.type === 'text') {
|
||||||
const textLines = node.content.split('\n');
|
const textLines = node.content.split('\n');
|
||||||
|
|
||||||
textLines.forEach((textLine, index) => {
|
textLines.forEach((textLine, index) => {
|
||||||
if (index !== 0) {
|
if (index !== 0) {
|
||||||
currentLine++;
|
currentLine++;
|
||||||
@@ -62,7 +76,7 @@ export function markdownToHTML(markdown) {
|
|||||||
*/
|
*/
|
||||||
function output(node) {
|
function output(node) {
|
||||||
if (node.type === 'text') {
|
if (node.type === 'text') {
|
||||||
return node.content.replace(/\n/g, '<br>');
|
return node.content.replace(/\n/g, '<br/>');
|
||||||
} else if (node.type === 'strong') {
|
} else if (node.type === 'strong') {
|
||||||
return `<strong>${node.content.map(output).join('')}</strong>`;
|
return `<strong>${node.content.map(output).join('')}</strong>`;
|
||||||
} else if (node.type === 'em') {
|
} else if (node.type === 'em') {
|
||||||
|
@@ -95,6 +95,47 @@ test('markdownToLines - Only bold formatting', () => {
|
|||||||
expect(output).toEqual(expectedOutput);
|
expect(output).toEqual(expectedOutput);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('markdownToLines - paragraph 1', () => {
|
||||||
|
const input = `**Start** with
|
||||||
|
a second line`;
|
||||||
|
|
||||||
|
const expectedOutput = [
|
||||||
|
[
|
||||||
|
{ content: 'Start', type: 'strong' },
|
||||||
|
{ content: 'with', type: 'normal' },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ content: 'a', type: 'normal' },
|
||||||
|
{ content: 'second', type: 'normal' },
|
||||||
|
{ content: 'line', type: 'normal' },
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
const output = markdownToLines(input);
|
||||||
|
expect(output).toEqual(expectedOutput);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('markdownToLines - paragraph', () => {
|
||||||
|
const input = `**Start** with
|
||||||
|
|
||||||
|
a second line`;
|
||||||
|
|
||||||
|
const expectedOutput = [
|
||||||
|
[
|
||||||
|
{ content: 'Start', type: 'strong' },
|
||||||
|
{ content: 'with', type: 'normal' },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ content: 'a', type: 'normal' },
|
||||||
|
{ content: 'second', type: 'normal' },
|
||||||
|
{ content: 'line', type: 'normal' },
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
const output = markdownToLines(input);
|
||||||
|
expect(output).toEqual(expectedOutput);
|
||||||
|
});
|
||||||
|
|
||||||
test('markdownToLines - Only italic formatting', () => {
|
test('markdownToLines - Only italic formatting', () => {
|
||||||
const input = `This is an *italic* test`;
|
const input = `This is an *italic* test`;
|
||||||
|
|
||||||
@@ -134,7 +175,7 @@ Here is a new line
|
|||||||
There is some words **with a bold** section
|
There is some words **with a bold** section
|
||||||
Here is a line *with an italic* section`;
|
Here is a line *with an italic* section`;
|
||||||
|
|
||||||
const expectedOutput = `<p>This is regular text<br>Here is a new line<br>There is some words <strong>with a bold</strong> section<br>Here is a line <em>with an italic</em> section</p>`;
|
const expectedOutput = `<p>This is regular text<br/>Here is a new line<br/>There is some words <strong>with a bold</strong> section<br/>Here is a line <em>with an italic</em> section</p>`;
|
||||||
|
|
||||||
const output = markdownToHTML(input);
|
const output = markdownToHTML(input);
|
||||||
expect(output).toEqual(expectedOutput);
|
expect(output).toEqual(expectedOutput);
|
||||||
@@ -151,7 +192,7 @@ test('markdownToHTML - No formatting', () => {
|
|||||||
const input = `This is a simple test
|
const input = `This is a simple test
|
||||||
with no formatting`;
|
with no formatting`;
|
||||||
|
|
||||||
const expectedOutput = `<p>This is a simple test<br>with no formatting</p>`;
|
const expectedOutput = `<p>This is a simple test<br/>with no formatting</p>`;
|
||||||
const output = markdownToHTML(input);
|
const output = markdownToHTML(input);
|
||||||
expect(output).toEqual(expectedOutput);
|
expect(output).toEqual(expectedOutput);
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user