mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-02-08 00:21:11 +01:00
Hide the text in the text layer associated with MathML elements (bug 2009627)
The bug was supposed to be fixed by #20471 but here there are some annotations in the pdf. When those annotations are added to the DOM, the struct tree has to be rendered but without the text layer (because of asynchronicity). So this patch is making sure that the modifications in the text layer are done once the layer is rendered.
This commit is contained in:
parent
f40ab1a3f8
commit
cffd54e9c6
@ -498,4 +498,50 @@ describe("accessibility", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Text elements must be aria-hidden when there's MathML and annotations", () => {
|
||||
let pages;
|
||||
|
||||
beforeEach(async () => {
|
||||
pages = await loadAndWait("bug2009627.pdf", ".textLayer");
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await closePages(pages);
|
||||
});
|
||||
|
||||
it("must check that the text in text layer is aria-hidden", async () => {
|
||||
await Promise.all(
|
||||
pages.map(async ([browserName, page]) => {
|
||||
const isSanitizerSupported = await page.evaluate(() => {
|
||||
try {
|
||||
// eslint-disable-next-line no-undef
|
||||
return typeof Sanitizer !== "undefined";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
const ariaHidden = await page.evaluate(() =>
|
||||
Array.from(
|
||||
document.querySelectorAll(".structTree :has(> math)")
|
||||
).map(el =>
|
||||
document
|
||||
.getElementById(el.getAttribute("aria-owns"))
|
||||
.getAttribute("aria-hidden")
|
||||
)
|
||||
);
|
||||
if (isSanitizerSupported) {
|
||||
expect(ariaHidden)
|
||||
.withContext(`In ${browserName}`)
|
||||
.toEqual(["true", "true", "true"]);
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
`Pending in Chrome: Sanitizer API (in ${browserName}) is not supported`
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -867,3 +867,4 @@
|
||||
!bitmap-trailing-7fff-stripped.pdf
|
||||
!bitmap.pdf
|
||||
!bomb_giant.pdf
|
||||
!bug2009627.pdf
|
||||
|
||||
BIN
test/pdfs/bug2009627.pdf
Executable file
BIN
test/pdfs/bug2009627.pdf
Executable file
Binary file not shown.
@ -493,7 +493,7 @@ class PDFPageView extends BasePDFPageView {
|
||||
const treeDom = await this.structTreeLayer?.render();
|
||||
if (treeDom) {
|
||||
this.l10n.pause();
|
||||
this.structTreeLayer?.addElementsToTextLayer();
|
||||
this.structTreeLayer?.updateTextLayer();
|
||||
if (this.canvas && treeDom.parentNode !== this.canvas) {
|
||||
// Pause translation when inserting the structTree in the DOM.
|
||||
this.canvas.append(treeDom);
|
||||
|
||||
@ -184,6 +184,10 @@ class StructTreeLayerBuilder {
|
||||
|
||||
#elementsToAddToTextLayer = null;
|
||||
|
||||
#elementsToHideInTextLayer = null;
|
||||
|
||||
#elementsToStealFromTextLayer = null;
|
||||
|
||||
/**
|
||||
* @param {StructTreeLayerBuilderOptions} options
|
||||
*/
|
||||
@ -304,15 +308,49 @@ class StructTreeLayerBuilder {
|
||||
return true;
|
||||
}
|
||||
|
||||
addElementsToTextLayer() {
|
||||
if (!this.#elementsToAddToTextLayer) {
|
||||
return;
|
||||
updateTextLayer() {
|
||||
if (this.#elementsToAddToTextLayer) {
|
||||
for (const [id, img] of this.#elementsToAddToTextLayer) {
|
||||
document.getElementById(id)?.append(img);
|
||||
}
|
||||
this.#elementsToAddToTextLayer.clear();
|
||||
this.#elementsToAddToTextLayer = null;
|
||||
}
|
||||
for (const [id, img] of this.#elementsToAddToTextLayer) {
|
||||
document.getElementById(id)?.append(img);
|
||||
if (this.#elementsToHideInTextLayer) {
|
||||
for (const id of this.#elementsToHideInTextLayer) {
|
||||
const elem = document.getElementById(id);
|
||||
if (elem) {
|
||||
elem.ariaHidden = true;
|
||||
}
|
||||
}
|
||||
this.#elementsToHideInTextLayer.length = 0;
|
||||
this.#elementsToHideInTextLayer = null;
|
||||
}
|
||||
if (this.#elementsToStealFromTextLayer) {
|
||||
for (
|
||||
let i = 0, ii = this.#elementsToStealFromTextLayer.length;
|
||||
i < ii;
|
||||
i += 2
|
||||
) {
|
||||
const element = this.#elementsToStealFromTextLayer[i];
|
||||
const ids = this.#elementsToStealFromTextLayer[i + 1];
|
||||
let textContent = "";
|
||||
for (const id of ids) {
|
||||
const elem = document.getElementById(id);
|
||||
if (elem) {
|
||||
textContent += elem.textContent.trim() || "";
|
||||
// Aria-hide the element in order to avoid duplicate reading of the
|
||||
// math content by screen readers.
|
||||
elem.ariaHidden = "true";
|
||||
}
|
||||
}
|
||||
if (textContent) {
|
||||
element.textContent = textContent;
|
||||
}
|
||||
}
|
||||
this.#elementsToStealFromTextLayer.length = 0;
|
||||
this.#elementsToStealFromTextLayer = null;
|
||||
}
|
||||
this.#elementsToAddToTextLayer.clear();
|
||||
this.#elementsToAddToTextLayer = null;
|
||||
}
|
||||
|
||||
#walk(node) {
|
||||
@ -325,21 +363,13 @@ class StructTreeLayerBuilder {
|
||||
const { role } = node;
|
||||
if (MathMLElements.has(role)) {
|
||||
element = document.createElementNS(MathMLNamespace, role);
|
||||
let text = "";
|
||||
const ids = [];
|
||||
(this.#elementsToStealFromTextLayer ||= []).push(element, ids);
|
||||
for (const { type, id } of node.children || []) {
|
||||
if (type !== "content" || !id) {
|
||||
continue;
|
||||
if (type === "content" && id) {
|
||||
ids.push(id);
|
||||
}
|
||||
const elem = document.getElementById(id);
|
||||
if (!elem) {
|
||||
continue;
|
||||
}
|
||||
text += elem.textContent.trim() || "";
|
||||
// Aria-hide the element in order to avoid duplicate reading of the
|
||||
// math content by screen readers.
|
||||
elem.ariaHidden = "true";
|
||||
}
|
||||
element.textContent = text;
|
||||
} else {
|
||||
element = document.createElement("span");
|
||||
}
|
||||
@ -365,10 +395,7 @@ class StructTreeLayerBuilder {
|
||||
if (!id) {
|
||||
continue;
|
||||
}
|
||||
const elem = document.getElementById(id);
|
||||
if (elem) {
|
||||
elem.ariaHidden = true;
|
||||
}
|
||||
(this.#elementsToHideInTextLayer ||= []).push(id);
|
||||
}
|
||||
// For now, we don't want to keep the alt text if there's valid
|
||||
// MathML (see https://github.com/w3c/mathml-aam/issues/37).
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user