mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
fix: fix trailing line whitespaces layout shift (#8714)
This commit is contained in:
parent
03028eaa8c
commit
dfaaff4432
2 changed files with 70 additions and 2 deletions
|
@ -47,6 +47,41 @@ describe("Test wrapText", () => {
|
||||||
expect(res).toBe("don't wrap this number\n99,100.99");
|
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", () => {
|
it("should support multiple (multi-codepoint) emojis", () => {
|
||||||
const text = "😀🗺🔥👩🏽🦰👨👩👧👦🇨🇿";
|
const text = "😀🗺🔥👩🏽🦰👨👩👧👦🇨🇿";
|
||||||
const maxWidth = 1;
|
const maxWidth = 1;
|
||||||
|
|
|
@ -681,7 +681,7 @@ const wrapLine = (
|
||||||
|
|
||||||
lines.push(...precedingLines);
|
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;
|
currentLine = trailingLine;
|
||||||
currentLineWidth = getLineWidth(trailingLine, font, true);
|
currentLineWidth = getLineWidth(trailingLine, font, true);
|
||||||
iterator = tokenIterator.next();
|
iterator = tokenIterator.next();
|
||||||
|
@ -697,12 +697,45 @@ const wrapLine = (
|
||||||
|
|
||||||
// iterator done, push the trailing line if exists
|
// iterator done, push the trailing line if exists
|
||||||
if (currentLine) {
|
if (currentLine) {
|
||||||
lines.push(currentLine.trimEnd());
|
const trailingLine = trimTrailingLine(currentLine, font, maxWidth);
|
||||||
|
lines.push(trailingLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
return lines;
|
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 = (
|
export const wrapText = (
|
||||||
text: string,
|
text: string,
|
||||||
font: FontString,
|
font: FontString,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue