From 9765d57a26779dd8bf753255c3cfa74a19563f0a Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Sun, 14 Jan 2024 19:06:06 +0100 Subject: [PATCH] [Editor] Extract all the lines when adding a FreeText annotation Fixes #17079. --- src/display/editor/freetext.js | 13 ++++--- test/integration/freetext_editor_spec.mjs | 46 +++++++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/display/editor/freetext.js b/src/display/editor/freetext.js index a55aee8ea5616..da2028db774a6 100644 --- a/src/display/editor/freetext.js +++ b/src/display/editor/freetext.js @@ -386,13 +386,14 @@ class FreeTextEditor extends AnnotationEditor { * @returns {string} */ #extractText() { - const divs = this.editorDiv.getElementsByTagName("div"); - if (divs.length === 0) { - return this.editorDiv.innerText; - } + // We don't use innerText because there are some bugs with line breaks. const buffer = []; - for (const div of divs) { - buffer.push(div.innerText.replace(/\r\n?|\n/, "")); + this.editorDiv.normalize(); + const EOL_PATTERN = /\r\n?|\n/g; + for (const child of this.editorDiv.childNodes) { + const content = + child.nodeType === Node.TEXT_NODE ? child.nodeValue : child.innerText; + buffer.push(content.replaceAll(EOL_PATTERN, "")); } return buffer.join("\n"); } diff --git a/test/integration/freetext_editor_spec.mjs b/test/integration/freetext_editor_spec.mjs index 74cb5134d9d0d..b2cd4f77d611b 100644 --- a/test/integration/freetext_editor_spec.mjs +++ b/test/integration/freetext_editor_spec.mjs @@ -3246,4 +3246,50 @@ describe("FreeText Editor", () => { ); }); }); + + describe("Freetext with several lines", () => { + let pages; + + beforeAll(async () => { + pages = await loadAndWait("empty.pdf", ".annotationEditorLayer"); + }); + + afterAll(async () => { + await closePages(pages); + }); + + it("must check that all lines are correctly exported", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + await switchToFreeText(page); + + const rect = await page.$eval(".annotationEditorLayer", el => { + // With Chrome something is wrong when serializing a DomRect, + // hence we extract the values and just return them. + const { x, y } = el.getBoundingClientRect(); + return { x, y }; + }); + + const data = "Hello\nPDF.js\nWorld\n!!"; + await page.mouse.click(rect.x + 100, rect.y + 100); + await page.waitForSelector(getEditorSelector(0), { + visible: true, + }); + await page.type(`${getEditorSelector(0)} .internal`, data); + + // Commit. + await page.keyboard.press("Escape"); + await page.waitForSelector( + `${getEditorSelector(0)} .overlay.enabled` + ); + + await waitForSerialized(page, 1); + const serialized = (await getSerialized(page))[0]; + expect(serialized.value) + .withContext(`In ${browserName}`) + .toEqual(data); + }) + ); + }); + }); });