mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-12 10:39:44 +02:00
Merge pull request #4416 from MikeJeffers/bug/4408
Fix #4408: Handle wrapping long words
This commit is contained in:
@@ -52,6 +52,17 @@ root[A root with a long text that wraps to keep the node size in check]
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('a root with wrapping text and long words that exceed width', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`mindmap
|
||||||
|
root[A few smaller words but then averylongsetofcharacterswithoutwhitespacetoseparate that we expect to wrapontonextlinesandnotexceedwidthparameters]
|
||||||
|
`,
|
||||||
|
{},
|
||||||
|
undefined,
|
||||||
|
shouldHaveRoot
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('a root with an icon', () => {
|
it('a root with an icon', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`mindmap
|
`mindmap
|
||||||
|
1054
docs/CHANGELOG.md
1054
docs/CHANGELOG.md
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -78,6 +78,22 @@ function createTspan(textElement, lineIndex, lineHeight) {
|
|||||||
.attr('dy', lineHeight + 'em');
|
.attr('dy', lineHeight + 'em');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the width of rendered text
|
||||||
|
* @param {object} parentNode
|
||||||
|
* @param {number} lineHeight
|
||||||
|
* @param {string} text
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
function computeWidthOfText(parentNode, lineHeight, text) {
|
||||||
|
const testElement = parentNode.append('text');
|
||||||
|
const testSpan = createTspan(testElement, 1, lineHeight);
|
||||||
|
updateTextContentAndStyles(testSpan, [{ content: text, type: 'normal' }]);
|
||||||
|
const textLength = testSpan.node().getComputedTextLength();
|
||||||
|
testElement.remove();
|
||||||
|
return textLength;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a formatted text element by breaking lines and applying styles based on
|
* Creates a formatted text element by breaking lines and applying styles based on
|
||||||
* the given structuredText.
|
* the given structuredText.
|
||||||
@@ -95,31 +111,44 @@ function createFormattedText(width, g, structuredText, addBackground = false) {
|
|||||||
// .attr('dominant-baseline', 'middle')
|
// .attr('dominant-baseline', 'middle')
|
||||||
// .attr('text-anchor', 'middle');
|
// .attr('text-anchor', 'middle');
|
||||||
// .attr('text-anchor', 'middle');
|
// .attr('text-anchor', 'middle');
|
||||||
let lineIndex = -1;
|
let lineIndex = 0;
|
||||||
structuredText.forEach((line) => {
|
structuredText.forEach((line) => {
|
||||||
lineIndex++;
|
/**
|
||||||
let tspan = createTspan(textElement, lineIndex, lineHeight);
|
* Preprocess raw string content of line data
|
||||||
|
* Creating an array of strings pre-split to satisfy width limit
|
||||||
let words = [...line].reverse();
|
*/
|
||||||
let currentWord;
|
let fullStr = line.map((data) => data.content).join(' ');
|
||||||
let wrappedLine = [];
|
let tempStr = '';
|
||||||
|
let linesUnderWidth = [];
|
||||||
while (words.length) {
|
let prevIndex = 0;
|
||||||
currentWord = words.pop();
|
if (computeWidthOfText(labelGroup, lineHeight, fullStr) <= width) {
|
||||||
wrappedLine.push(currentWord);
|
linesUnderWidth.push(fullStr);
|
||||||
|
} else {
|
||||||
updateTextContentAndStyles(tspan, wrappedLine);
|
for (let i = 0; i <= fullStr.length; i++) {
|
||||||
|
tempStr = fullStr.slice(prevIndex, i);
|
||||||
if (tspan.node().getComputedTextLength() > width) {
|
log.info(tempStr, prevIndex, i);
|
||||||
wrappedLine.pop();
|
if (computeWidthOfText(labelGroup, lineHeight, tempStr) > width) {
|
||||||
words.push(currentWord);
|
const subStr = fullStr.slice(prevIndex, i);
|
||||||
|
// Break at space if any
|
||||||
updateTextContentAndStyles(tspan, wrappedLine);
|
const lastSpaceIndex = subStr.lastIndexOf(' ');
|
||||||
|
if (lastSpaceIndex > -1) {
|
||||||
wrappedLine = [];
|
i = prevIndex + lastSpaceIndex + 1;
|
||||||
lineIndex++;
|
}
|
||||||
tspan = createTspan(textElement, lineIndex, lineHeight);
|
linesUnderWidth.push(fullStr.slice(prevIndex, i).trim());
|
||||||
|
prevIndex = i;
|
||||||
|
tempStr = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (tempStr != null) {
|
||||||
|
linesUnderWidth.push(tempStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** Add each prepared line as a tspan to the parent node */
|
||||||
|
const preparedLines = linesUnderWidth.map((w) => ({ content: w, type: line.type }));
|
||||||
|
for (const preparedLine of preparedLines) {
|
||||||
|
let tspan = createTspan(textElement, lineIndex, lineHeight);
|
||||||
|
updateTextContentAndStyles(tspan, [preparedLine]);
|
||||||
|
lineIndex++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (addBackground) {
|
if (addBackground) {
|
||||||
|
Reference in New Issue
Block a user