fix: fix trailing line whitespaces layout shift (#8714)

pull/8745/head
Marcel Mraz 3 months ago committed by GitHub
parent 03028eaa8c
commit dfaaff4432
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -47,6 +47,41 @@ describe("Test wrapText", () => {
expect(res).toBe("don't wrap this number\n99,100.99");
});
it("should trim all trailing whitespaces", () => {
const text = "Hello ";
const maxWidth = 50;
const res = wrapText(text, font, maxWidth);
expect(res).toBe("Hello");
});
it("should trim all but one trailing whitespaces", () => {
const text = "Hello ";
const maxWidth = 60;
const res = wrapText(text, font, maxWidth);
expect(res).toBe("Hello ");
});
it("should keep preceding whitespaces and trim all trailing whitespaces", () => {
const text = " Hello World";
const maxWidth = 90;
const res = wrapText(text, font, maxWidth);
expect(res).toBe(" Hello\nWorld");
});
it("should keep some preceding whitespaces, trim trailing whitespaces, but kep those that fit in the trailing line", () => {
const text = " Hello World ";
const maxWidth = 90;
const res = wrapText(text, font, maxWidth);
expect(res).toBe(" Hello\nWorld ");
});
it("should trim keep those whitespace that fit in the trailing line", () => {
const text = "Hello Wo rl d ";
const maxWidth = 100;
const res = wrapText(text, font, maxWidth);
expect(res).toBe("Hello Wo\nrl d ");
});
it("should support multiple (multi-codepoint) emojis", () => {
const text = "😀🗺🔥👩🏽‍🦰👨‍👩‍👧‍👦🇨🇿";
const maxWidth = 1;

@ -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,

Loading…
Cancel
Save