diff --git a/src/element/textElement.test.ts b/src/element/textElement.test.ts index e2c8ee43..c9027205 100644 --- a/src/element/textElement.test.ts +++ b/src/element/textElement.test.ts @@ -1,10 +1,17 @@ import { BOUND_TEXT_PADDING } from "../constants"; -import { wrapText } from "./textElement"; +import { measureText, wrapText } from "./textElement"; import { FontString } from "./types"; describe("Test wrapText", () => { const font = "20px Cascadia, width: Segoe UI Emoji" as FontString; + it("shouldn't add new lines for trailing spaces", () => { + const text = "Hello whats up "; + const maxWidth = 200 - BOUND_TEXT_PADDING * 2; + const res = wrapText(text, font, maxWidth); + expect(res).toBe("Hello whats up "); + }); + describe("When text doesn't contain new lines", () => { const text = "Hello whats up"; [ @@ -139,3 +146,37 @@ break it now`, }); }); }); + +describe("Test measureText", () => { + const font = "20px Cascadia, width: Segoe UI Emoji" as FontString; + const text = "Hello World"; + + it("should add correct attributes when maxWidth is passed", () => { + const maxWidth = 200 - BOUND_TEXT_PADDING * 2; + const res = measureText(text, font, maxWidth); + + expect(res.container).toMatchInlineSnapshot(` +
+ +
+ `); + }); + + it("should add correct attributes when maxWidth is not passed", () => { + const res = measureText(text, font); + + expect(res.container).toMatchInlineSnapshot(` +
+ +
+ `); + }); +}); diff --git a/src/element/textElement.ts b/src/element/textElement.ts index 4f39d361..3a03f936 100644 --- a/src/element/textElement.ts +++ b/src/element/textElement.ts @@ -49,11 +49,7 @@ export const redrawTextBoundingBox = ( maxWidth, ); } - const metrics = measureText( - textElement.originalText, - getFontString(textElement), - maxWidth, - ); + const metrics = measureText(text, getFontString(textElement), maxWidth); let coordY = textElement.y; let coordX = textElement.x; // Resize container and vertically center align the text @@ -272,7 +268,7 @@ export const measureText = ( container.style.minHeight = "1em"; if (maxWidth) { const lineHeight = getApproxLineHeight(font); - container.style.maxWidth = `${String(maxWidth)}px`; + container.style.width = `${String(maxWidth + 1)}px`; container.style.overflow = "hidden"; container.style.wordBreak = "break-word"; container.style.lineHeight = `${String(lineHeight)}px`; @@ -290,10 +286,12 @@ export const measureText = ( // Baseline is important for positioning text on canvas const baseline = span.offsetTop + span.offsetHeight; // Since span adds 1px extra width to the container - const width = container.offsetWidth + 1; + const width = container.offsetWidth - 1; const height = container.offsetHeight; - document.body.removeChild(container); + if (isTestEnv()) { + return { width, height, baseline, container }; + } return { width, height, baseline }; }; @@ -331,6 +329,12 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => { const lines: Array = []; const originalLines = text.split("\n"); const spaceWidth = getTextWidth(" ", font); + + const push = (str: string) => { + if (str.trim()) { + lines.push(str); + } + }; originalLines.forEach((originalLine) => { const words = originalLine.split(" "); // This means its newline so push it @@ -348,9 +352,7 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => { if (currentWordWidth >= maxWidth) { // push current line since the current word exceeds the max width // so will be appended in next line - if (currentLine) { - lines.push(currentLine); - } + push(currentLine); currentLine = ""; currentLineWidthTillNow = 0; while (words[index].length > 0) { @@ -364,7 +366,7 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => { if (currentLine.slice(-1) === " ") { currentLine = currentLine.slice(0, -1); } - lines.push(currentLine); + push(currentLine); currentLine = currentChar; currentLineWidthTillNow = width; if (currentLineWidthTillNow === maxWidth) { @@ -377,7 +379,7 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => { } // push current line if appending space exceeds max width if (currentLineWidthTillNow + spaceWidth >= maxWidth) { - lines.push(currentLine); + push(currentLine); currentLine = ""; currentLineWidthTillNow = 0; } else { @@ -396,7 +398,7 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => { currentLineWidthTillNow = getTextWidth(currentLine + word, font); if (currentLineWidthTillNow >= maxWidth) { - lines.push(currentLine); + push(currentLine); currentLineWidthTillNow = 0; currentLine = ""; @@ -407,7 +409,8 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => { // Push the word if appending space exceeds max width if (currentLineWidthTillNow + spaceWidth >= maxWidth) { - lines.push(currentLine.slice(0, -1)); + const word = currentLine.slice(0, -1); + push(word); currentLine = ""; currentLineWidthTillNow = 0; break; @@ -424,7 +427,7 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => { if (currentLine.slice(-1) === " ") { currentLine = currentLine.slice(0, -1); } - lines.push(currentLine); + push(currentLine); } } }); diff --git a/src/element/textWysiwyg.test.tsx b/src/element/textWysiwyg.test.tsx index f2ef40b5..d06d9236 100644 --- a/src/element/textWysiwyg.test.tsx +++ b/src/element/textWysiwyg.test.tsx @@ -861,7 +861,7 @@ describe("textWysiwyg", () => { resize(rectangle, "ne", [rectangle.x + 100, rectangle.y - 100]); expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(` Array [ - 109.5, + 110.5, 17, ] `); @@ -909,7 +909,7 @@ describe("textWysiwyg", () => { resize(rectangle, "ne", [rectangle.x + 100, rectangle.y - 100]); expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(` Array [ - 424, + 426, -539, ] `); @@ -1026,7 +1026,7 @@ describe("textWysiwyg", () => { mouse.up(rectangle.x + 100, rectangle.y + 50); expect(rectangle.x).toBe(80); expect(rectangle.y).toBe(85); - expect(text.x).toBe(89.5); + expect(text.x).toBe(90.5); expect(text.y).toBe(90); Keyboard.withModifierKeys({ ctrl: true }, () => { diff --git a/src/tests/data/__snapshots__/restore.test.ts.snap b/src/tests/data/__snapshots__/restore.test.ts.snap index 8af4f83c..444bc0ea 100644 --- a/src/tests/data/__snapshots__/restore.test.ts.snap +++ b/src/tests/data/__snapshots__/restore.test.ts.snap @@ -312,7 +312,7 @@ Object { "versionNonce": 0, "verticalAlign": "middle", "width": 100, - "x": -0.5, + "x": 0.5, "y": 0, } `; diff --git a/src/tests/linearElementEditor.test.tsx b/src/tests/linearElementEditor.test.tsx index c3366406..68d97171 100644 --- a/src/tests/linearElementEditor.test.tsx +++ b/src/tests/linearElementEditor.test.tsx @@ -1027,7 +1027,7 @@ describe("Test Linear Elements", () => { expect(getBoundTextElementPosition(container, textElement)) .toMatchInlineSnapshot(` Object { - "x": 386.5, + "x": 387.5, "y": 70, } `); @@ -1086,7 +1086,7 @@ describe("Test Linear Elements", () => { expect(getBoundTextElementPosition(container, textElement)) .toMatchInlineSnapshot(` Object { - "x": 189.5, + "x": 190.5, "y": 20, } `);