|
@@ -681,7 +681,7 @@ const wrapLine = (
|
|
|
|
|
|
lines.push(...precedingLines);
|
|
|
|
|
|
- // trailing line of the wrapped word might still be joined with next token/s
|
|
|
+ // trailing line of the wrapped word might -still be joined with next token/s
|
|
|
currentLine = trailingLine;
|
|
|
currentLineWidth = getLineWidth(trailingLine, font, true);
|
|
|
iterator = tokenIterator.next();
|
|
@@ -697,12 +697,45 @@ const wrapLine = (
|
|
|
|
|
|
// iterator done, push the trailing line if exists
|
|
|
if (currentLine) {
|
|
|
- lines.push(currentLine.trimEnd());
|
|
|
+ const trailingLine = trimTrailingLine(currentLine, font, maxWidth);
|
|
|
+ lines.push(trailingLine);
|
|
|
}
|
|
|
|
|
|
return lines;
|
|
|
};
|
|
|
|
|
|
+// similarly to browsers, does not trim all whitespaces, but only those exceeding the maxWidth
|
|
|
+const trimTrailingLine = (line: string, font: FontString, maxWidth: number) => {
|
|
|
+ const shouldTrimWhitespaces = getLineWidth(line, font, true) > maxWidth;
|
|
|
+
|
|
|
+ if (!shouldTrimWhitespaces) {
|
|
|
+ return line;
|
|
|
+ }
|
|
|
+
|
|
|
+ // defensively default to `trimeEnd` in case the regex does not match
|
|
|
+ let [, trimmedLine, whitespaces] = line.match(/^(.+?)(\s+)$/) ?? [
|
|
|
+ line,
|
|
|
+ line.trimEnd(),
|
|
|
+ "",
|
|
|
+ ];
|
|
|
+
|
|
|
+ let trimmedLineWidth = getLineWidth(trimmedLine, font, true);
|
|
|
+
|
|
|
+ for (const whitespace of Array.from(whitespaces)) {
|
|
|
+ const _charWidth = charWidth.calculate(whitespace, font);
|
|
|
+ const testLineWidth = trimmedLineWidth + _charWidth;
|
|
|
+
|
|
|
+ if (testLineWidth > maxWidth) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ trimmedLine = trimmedLine + whitespace;
|
|
|
+ trimmedLineWidth = testLineWidth;
|
|
|
+ }
|
|
|
+
|
|
|
+ return trimmedLine;
|
|
|
+};
|
|
|
+
|
|
|
export const wrapText = (
|
|
|
text: string,
|
|
|
font: FontString,
|