mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-01 14:46:41 +02:00
implemented knuth-plass line-breaking algorithm
Co-authored-by: pranavm2109 <mishrap@dickinson.edu>
This commit is contained in:
@@ -18,7 +18,7 @@ let maxWidth = 0;
|
|||||||
/** @param diagram - The diagram to draw to. */
|
/** @param diagram - The diagram to draw to. */
|
||||||
function drawActorLegend(diagram) {
|
function drawActorLegend(diagram) {
|
||||||
const conf = getConfig().journey;
|
const conf = getConfig().journey;
|
||||||
maxWidth = 0;
|
maxWidth = conf.maxLabelWidth; // Ensures we don't exceed this width
|
||||||
let yPos = 60;
|
let yPos = 60;
|
||||||
|
|
||||||
Object.keys(actors).forEach((person) => {
|
Object.keys(actors).forEach((person) => {
|
||||||
@@ -33,67 +33,62 @@ function drawActorLegend(diagram) {
|
|||||||
};
|
};
|
||||||
svgDraw.drawCircle(diagram, circleData);
|
svgDraw.drawCircle(diagram, circleData);
|
||||||
|
|
||||||
// Create temporary text element to measure width
|
const words = person.split(' '); // Split text into words
|
||||||
const tempText = diagram.append('text').attr('visibility', 'hidden').text(person);
|
const lines = [];
|
||||||
const textWidth = tempText.node().getBBox().width;
|
let currentLine = '';
|
||||||
tempText.remove();
|
|
||||||
const journeyConfigObject = getConfig().journey;
|
|
||||||
const maxLineLength = journeyConfigObject.maxLabelWidth;
|
|
||||||
let lines = [];
|
|
||||||
|
|
||||||
if (textWidth > maxLineLength) {
|
|
||||||
// Break the text into chunks regardless of word boundaries
|
|
||||||
let currentText = '';
|
|
||||||
const measureText = diagram.append('text').attr('visibility', 'hidden');
|
const measureText = diagram.append('text').attr('visibility', 'hidden');
|
||||||
|
|
||||||
for (const element of person) {
|
words.forEach((word, _index) => {
|
||||||
currentText += element;
|
const testLine = currentLine ? `${currentLine} ${word}` : word;
|
||||||
measureText.text(currentText);
|
measureText.text(testLine);
|
||||||
const currentWidth = measureText.node().getBBox().width;
|
const textWidth = measureText.node().getBBox().width;
|
||||||
|
|
||||||
if (currentWidth > maxLineLength && currentText.length > 1) {
|
if (textWidth > maxWidth) {
|
||||||
let lineToPush = currentText.slice(0, -1);
|
if (currentLine) {
|
||||||
|
lines.push(currentLine); // Push previous line before adding a new word
|
||||||
|
}
|
||||||
|
currentLine = word;
|
||||||
|
|
||||||
// If the line ends with a space, trim it and do not add a hyphen.
|
// If a single word is too long, break it
|
||||||
if (lineToPush.endsWith(' ')) {
|
if (measureText.node().getBBox().width > maxWidth) {
|
||||||
lineToPush = lineToPush.trimEnd();
|
let brokenWord = '';
|
||||||
|
for (const char of word) {
|
||||||
|
brokenWord += char;
|
||||||
|
measureText.text(brokenWord + '-');
|
||||||
|
if (measureText.node().getBBox().width > maxWidth) {
|
||||||
|
lines.push(brokenWord.slice(0, -1) + '-'); // Break word with a hyphen
|
||||||
|
brokenWord = char;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentLine = brokenWord;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
lineToPush = lineToPush + '-';
|
currentLine = testLine;
|
||||||
}
|
}
|
||||||
lines.push(lineToPush);
|
});
|
||||||
|
|
||||||
// If the breaking character is a space, start fresh; otherwise, start with the character.
|
if (currentLine) {
|
||||||
currentText = element === ' ' ? '' : element;
|
lines.push(currentLine);
|
||||||
}
|
|
||||||
}
|
|
||||||
if (currentText) {
|
|
||||||
lines.push(currentText);
|
|
||||||
}
|
}
|
||||||
measureText.remove();
|
measureText.remove();
|
||||||
} else {
|
|
||||||
lines = [person];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw the text lines
|
// Draw the text lines within the fixed width
|
||||||
lines.forEach((line, index) => {
|
lines.forEach((line, index) => {
|
||||||
const labelData = {
|
const labelData = {
|
||||||
x: 40,
|
x: 40,
|
||||||
y: yPos + 7 + index * 20,
|
y: yPos + 7 + index * 20,
|
||||||
fill: '#666',
|
fill: '#666',
|
||||||
text: line,
|
text: line,
|
||||||
textMargin: conf.boxTextMargin | 5,
|
textMargin: conf.boxTextMargin || 5,
|
||||||
};
|
};
|
||||||
const textElement = svgDraw.drawText(diagram, labelData);
|
svgDraw.drawText(diagram, labelData);
|
||||||
const lineWidth = textElement.node().getBBox().width;
|
|
||||||
|
|
||||||
if (lineWidth > maxWidth && lineWidth > conf?.leftMargin - lineWidth) {
|
|
||||||
maxWidth = lineWidth;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
yPos += Math.max(20, lines.length * 20);
|
yPos += Math.max(20, lines.length * 20);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Cleanup?
|
// TODO: Cleanup?
|
||||||
const conf = getConfig().journey;
|
const conf = getConfig().journey;
|
||||||
let leftMargin = 0;
|
let leftMargin = 0;
|
||||||
|
Reference in New Issue
Block a user