Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions test/integration/text_layer_spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,104 @@ describe("Text layer", () => {
});
});

describe("doesn't jump when hovering on an empty area, with .markedContent", () => {
let pages;

beforeAll(async () => {
pages = await loadAndWait(
"chrome-text-selection-markedContent.pdf",
`.page[data-page-number = "1"] .endOfContent`
);
});
afterAll(async () => {
await closePages(pages);
});

it("in per-character selection mode", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
const [positionStart, positionEnd] = await Promise.all([
getSpanRectFromText(
page,
1,
"strengthen in the coming quarters as the railway projects under"
).then(middlePosition),
getSpanRectFromText(
page,
1,
"development enter the construction phase (estimated at around"
).then(belowEndPosition),
]);

await page.mouse.move(positionStart.x, positionStart.y);
await page.mouse.down();
await moveInSteps(page, positionStart, positionEnd, 20);
await page.mouse.up();

await expectAsync(page)
.withContext(`In ${browserName}`)
.toHaveRoughlySelected(
"rs as the railway projects under\n" +
"development enter the construction phase (estimated at "
);
})
);
});

it("in per-word selection mode", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
const [positionStart, positionEnd] = await Promise.all([
getSpanRectFromText(
page,
1,
"strengthen in the coming quarters as the railway projects under"
).then(middlePosition),
getSpanRectFromText(
page,
1,
"development enter the construction phase (estimated at around"
).then(belowEndPosition),
]);

if (browserName !== "firefox") {
await page.mouse.move(positionStart.x, positionStart.y);
await page.mouse.down({ clickCount: 1 });
await page.mouse.up({ clickCount: 1 });
await page.mouse.down({ clickCount: 2 });
} else {
// When running tests with Firefox we use WebDriver BiDi, for
// which puppeteer doesn't support emulating "double click and
// hold". We need to manually dispatch an action through the
// protocol.
// See https://github.com/puppeteer/puppeteer/issues/13745.
await page.mainFrame().browsingContext.performActions([
{
type: "pointer",
id: "__puppeteer_mouse",
actions: [
{ type: "pointerMove", ...positionStart },
{ type: "pointerDown", button: 0 },
{ type: "pointerUp", button: 0 },
{ type: "pointerDown", button: 0 },
],
},
]);
}
await moveInSteps(page, positionStart, positionEnd, 20);
await page.mouse.up();

await expectAsync(page)
.withContext(`In ${browserName}`)
.toHaveRoughlySelected(
"quarters as the railway projects under\n" +
"development enter the construction phase (estimated at around"
);
})
);
});
});

describe("when selecting over a link", () => {
let pages;

Expand Down
1 change: 1 addition & 0 deletions test/pdfs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -718,3 +718,4 @@
!issue19424.pdf
!issue18529.pdf
!issue16742.pdf
!chrome-text-selection-markedContent.pdf
Binary file not shown.
8 changes: 8 additions & 0 deletions web/text_layer_builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,14 @@ class TextLayerBuilder {
if (anchor.nodeType === Node.TEXT_NODE) {
anchor = anchor.parentNode;
}
if (!modifyStart && range.endOffset === 0) {
do {
while (!anchor.previousSibling) {
anchor = anchor.parentNode;
}
anchor = anchor.previousSibling;
} while (!anchor.childNodes.length);
}

const parentTextLayer = anchor.parentElement?.closest(".textLayer");
const endDiv = this.#textLayers.get(parentTextLayer);
Expand Down