From f695e0ca62a64e6f6a8e206419a375a3b52b01f2 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Tue, 15 Jul 2025 21:11:05 +0200 Subject: [PATCH] Make the link annotations correctly announced by screen readers (bug 1708041) And focus the targeted page when the user clicks on a link. --- src/core/annotation.js | 4 +++ src/core/intersector.js | 17 +++++++--- src/display/annotation_layer.js | 46 +++++++++++++++++++++------ test/integration/annotation_spec.mjs | 45 ++++++++++++++++++++++++++ test/pdfs/.gitignore | 1 + test/pdfs/bug1708041.pdf | Bin 0 -> 38158 bytes web/pdf_link_service.js | 12 +++++++ 7 files changed, 111 insertions(+), 14 deletions(-) create mode 100644 test/pdfs/bug1708041.pdf diff --git a/src/core/annotation.js b/src/core/annotation.js index ba2237453..f4932c195 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -3833,6 +3833,10 @@ class LinkAnnotation extends Annotation { docAttachments: annotationGlobals.attachments, }); } + + get overlaysTextContent() { + return true; + } } class PopupAnnotation extends Annotation { diff --git a/src/core/intersector.js b/src/core/intersector.js index e50f86b25..acd54f2f6 100644 --- a/src/core/intersector.js +++ b/src/core/intersector.js @@ -24,7 +24,7 @@ class SingleIntersector { #maxY = -Infinity; - #quadPoints; + #quadPoints = null; #text = []; @@ -36,7 +36,13 @@ class SingleIntersector { constructor(annotation) { this.#annotation = annotation; - const quadPoints = (this.#quadPoints = annotation.data.quadPoints); + const quadPoints = annotation.data.quadPoints; + if (!quadPoints) { + // If there are no quad points, we use the rectangle to determine the + // bounds of the annotation. + [this.#minX, this.#minY, this.#maxX, this.#maxY] = annotation.data.rect; + return; + } for (let i = 0, ii = quadPoints.length; i < ii; i += 8) { this.#minX = Math.min(this.#minX, quadPoints[i]); @@ -44,6 +50,9 @@ class SingleIntersector { this.#minY = Math.min(this.#minY, quadPoints[i + 5]); this.#maxY = Math.max(this.#maxY, quadPoints[i + 1]); } + if (quadPoints.length > 8) { + this.#quadPoints = quadPoints; + } } overlaps(other) { @@ -73,7 +82,7 @@ class SingleIntersector { } const quadPoints = this.#quadPoints; - if (quadPoints.length === 8) { + if (!quadPoints) { // We've only one quad, so if we intersect min/max bounds then we // intersect the quad. return true; @@ -150,7 +159,7 @@ class Intersector { constructor(annotations) { for (const annotation of annotations) { - if (!annotation.data.quadPoints) { + if (!annotation.data.quadPoints && !annotation.data.rect) { continue; } const intersector = new SingleIntersector(annotation); diff --git a/src/display/annotation_layer.js b/src/display/annotation_layer.js index b28d11f18..8ff424df7 100644 --- a/src/display/annotation_layer.js +++ b/src/display/annotation_layer.js @@ -276,7 +276,10 @@ class AnnotationElement { const container = document.createElement("section"); container.setAttribute("data-annotation-id", data.id); - if (!(this instanceof WidgetAnnotationElement)) { + if ( + !(this instanceof WidgetAnnotationElement) && + !(this instanceof LinkAnnotationElement) + ) { container.tabIndex = 0; } const { style } = container; @@ -797,16 +800,21 @@ class LinkAnnotationElement extends AnnotationElement { linkService.addLinkAttributes(link, data.url, data.newWindow); isBound = true; } else if (data.action) { - this._bindNamedAction(link, data.action); + this._bindNamedAction(link, data.action, data.overlaidText); isBound = true; } else if (data.attachment) { - this.#bindAttachment(link, data.attachment, data.attachmentDest); + this.#bindAttachment( + link, + data.attachment, + data.overlaidText, + data.attachmentDest + ); isBound = true; } else if (data.setOCGState) { - this.#bindSetOCGState(link, data.setOCGState); + this.#bindSetOCGState(link, data.setOCGState, data.overlaidText); isBound = true; } else if (data.dest) { - this._bindLink(link, data.dest); + this._bindLink(link, data.dest, data.overlaidText); isBound = true; } else { if ( @@ -848,9 +856,10 @@ class LinkAnnotationElement extends AnnotationElement { * @private * @param {Object} link * @param {Object} destination + * @param {string} [overlaidText] * @memberof LinkAnnotationElement */ - _bindLink(link, destination) { + _bindLink(link, destination, overlaidText = "") { link.href = this.linkService.getDestinationHash(destination); link.onclick = () => { if (destination) { @@ -861,6 +870,9 @@ class LinkAnnotationElement extends AnnotationElement { if (destination || destination === /* isTooltipOnly = */ "") { this.#setInternalLink(); } + if (overlaidText) { + link.title = overlaidText; + } } /** @@ -869,14 +881,18 @@ class LinkAnnotationElement extends AnnotationElement { * @private * @param {Object} link * @param {Object} action + * @param {string} [overlaidText] * @memberof LinkAnnotationElement */ - _bindNamedAction(link, action) { + _bindNamedAction(link, action, overlaidText = "") { link.href = this.linkService.getAnchorUrl(""); link.onclick = () => { this.linkService.executeNamedAction(action); return false; }; + if (overlaidText) { + link.title = overlaidText; + } this.#setInternalLink(); } @@ -884,12 +900,15 @@ class LinkAnnotationElement extends AnnotationElement { * Bind attachments to the link element. * @param {Object} link * @param {Object} attachment - * @param {str} [dest] + * @param {string} [overlaidText] + * @param {string} [dest] */ - #bindAttachment(link, attachment, dest = null) { + #bindAttachment(link, attachment, overlaidText = "", dest = null) { link.href = this.linkService.getAnchorUrl(""); if (attachment.description) { link.title = attachment.description; + } else if (overlaidText) { + link.title = overlaidText; } link.onclick = () => { this.downloadManager?.openOrDownloadData( @@ -906,13 +925,17 @@ class LinkAnnotationElement extends AnnotationElement { * Bind SetOCGState actions to the link element. * @param {Object} link * @param {Object} action + * @param {string} [overlaidText] */ - #bindSetOCGState(link, action) { + #bindSetOCGState(link, action, overlaidText = "") { link.href = this.linkService.getAnchorUrl(""); link.onclick = () => { this.linkService.executeSetOCGState(action); return false; }; + if (overlaidText) { + link.title = overlaidText; + } this.#setInternalLink(); } @@ -947,6 +970,9 @@ class LinkAnnotationElement extends AnnotationElement { return false; }; } + if (data.overlaidText) { + link.title = data.overlaidText; + } if (!link.onclick) { link.onclick = () => false; diff --git a/test/integration/annotation_spec.mjs b/test/integration/annotation_spec.mjs index e1c68c09b..1ab1ee5ac 100644 --- a/test/integration/annotation_spec.mjs +++ b/test/integration/annotation_spec.mjs @@ -247,6 +247,51 @@ describe("Text widget", () => { }); }); +describe("Link annotations with internal destinations", () => { + describe("bug1708041.pdf", () => { + let pages; + + beforeEach(async () => { + pages = await loadAndWait( + "bug1708041.pdf", + ".page[data-page-number='1'] .annotationLayer" + ); + }); + + afterEach(async () => { + await closePages(pages); + }); + + it("must click on a link and check if it navigates to the correct page", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + const pageOneSelector = ".page[data-page-number='1']"; + const linkSelector = `${pageOneSelector} #pdfjs_internal_id_42R`; + await page.waitForSelector(linkSelector); + const linkTitle = await page.$eval(linkSelector, el => el.title); + expect(linkTitle) + .withContext(`In ${browserName}`) + .toEqual("Go to the last page"); + await page.click(linkSelector); + const pageSixTextLayerSelector = + ".page[data-page-number='6'] .textLayer"; + await page.waitForSelector(pageSixTextLayerSelector, { + visible: true, + }); + await page.waitForFunction( + sel => { + const textLayer = document.querySelector(sel); + return document.activeElement === textLayer; + }, + {}, + pageSixTextLayerSelector + ); + }) + ); + }); + }); +}); + describe("Annotation and storage", () => { describe("issue14023.pdf", () => { let pages; diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 852ffe8d0..2337dbcaf 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -734,3 +734,4 @@ !issue20062.pdf !issue20102.pdf !issue20065.pdf +!bug1708041.pdf diff --git a/test/pdfs/bug1708041.pdf b/test/pdfs/bug1708041.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bd3d68c6604e20ac807b35e8b1ebd1d66aa6e474 GIT binary patch literal 38158 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 { + if (evt.pageNumber === pageNumber) { + evt.source.textLayer.div.focus(); + ac.abort(); + } + }, + { signal: ac.signal } + ); } /**