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
91 changes: 91 additions & 0 deletions external/stylelint/mozcentral-tokens.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* Copyright 2026 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

:root {
--background-color-box: initial;
--background-color-box-info: initial;
--background-color-canvas: initial;
--background-color-critical: initial;
--background-color-information: initial;
--background-color-success: initial;
--border-color: initial;
--border-color-deemphasized: initial;
--border-color-interactive: initial;
--border-color-interactive-hover: initial;
--border-radius-circle: initial;
--border-radius-large: initial;
--border-radius-medium: initial;
--border-radius-small: initial;
--border-radius-xsmall: initial;
--box-shadow-level-2: initial;
--box-shadow-level-3: initial;
--button-background-color: initial;
--button-background-color-active: initial;
--button-background-color-ghost-hover: initial;
--button-background-color-hover: initial;
--button-background-color-menu-active: initial;
--button-background-color-menu-hover: initial;
--button-border: initial;
--button-border-color: initial;
--button-border-color-active: initial;
--button-border-color-hover: initial;
--button-border-radius: initial;
--button-font-weight: initial;
--button-min-height: initial;
--button-opacity-disabled: initial;
--button-padding-block: initial;
--button-padding-inline: initial;
--button-text-color: initial;
--button-text-color-hover: initial;
--button-text-color-menu-active: initial;
--button-text-color-menu-hover: initial;
--button-text-color-primary: initial;
--color-accent-attention: initial;
--color-accent-primary: initial;
--color-accent-primary-active: initial;
--color-gray-15: initial;
--color-gray-85: initial;
--focus-outline: initial;
--focus-outline-inset: initial;
--focus-outline-offset: initial;
--font-size-root: initial;
--font-size-small: initial;
--font-weight: initial;
--icon-color: initial;
--icon-color-critical: initial;
--icon-color-information: initial;
--input-search-border-radius: initial;
--link-color: initial;
--link-color-hover: initial;
--panel-border-radius: initial;
--panel-menuitem-border-radius: initial;
--panel-menuitem-margin: initial;
--panel-menuitem-margin-inline: initial;
--panel-menuitem-padding: initial;
--panel-menuitem-padding-inline: initial;
--size-item-large: initial;
--size-item-medium: initial;
--space-large: initial;
--space-medium: initial;
--space-small: initial;
--space-xsmall: initial;
--space-xxsmall: initial;
--text-color: initial;
--text-color-deemphasized: initial;
--toolbar-background-color: initial;
--toolbarbutton-background-color-active: initial;
--toolbarbutton-background-color-hover: initial;
--toolbarbutton-icon-fill: initial;
}
3 changes: 2 additions & 1 deletion src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,8 @@ class Annotation {

annotationGlobals.structTreeRoot.addAnnotationIdToPage(
params.pageRef,
structParent
structParent,
this.ref
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -1980,7 +1980,7 @@ class PDFDocument {
for (const [name, promises] of fieldPromises) {
allPromises.push(
Promise.all(promises).then(fields => {
fields = fields.filter(field => !!field);
fields = fields.filter(Boolean);
if (fields.length > 0) {
allFields.set(name, fields);
}
Expand Down
4 changes: 2 additions & 2 deletions src/core/editor/pdf_editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -1291,7 +1291,7 @@ class PDFEditor {
}

await Promise.all(promises);
newAnnotations = newAnnotations.filter(annot => !!annot);
newAnnotations = newAnnotations.filter(Boolean);
pageData.annotations = newAnnotations.length > 0 ? newAnnotations : null;
pageData.documentData.hasSignatureAnnotations ||= hasSignatureAnnotations;
}
Expand Down Expand Up @@ -2377,7 +2377,7 @@ class PDFEditor {
const numPages = document.numPages;
const labelsByPageIndex = new Map();
const oldPageIndices = new Set(
this.oldPages.filter(p => !!p).map(({ page: { pageIndex } }) => pageIndex)
this.oldPages.filter(Boolean).map(({ page: { pageIndex } }) => pageIndex)
);
let currentLabel = null;
let stFirstIndex = -1;
Expand Down
2 changes: 1 addition & 1 deletion src/core/fonts.js
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ function createNameTable(name, proto) {
proto[0][8] || "Unknown", // 8.Manufacturer
proto[0][9] || "Unknown", // 9.Designer
];
const stringsBytes = strings.map(s => stringToBytes(s));
const stringsBytes = strings.map(stringToBytes);

// Mac want 1-byte per character strings while Windows want
// 2-bytes per character, so duplicate the names table
Expand Down
39 changes: 23 additions & 16 deletions src/core/struct_tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,22 @@ class StructTreeRoot {
: -1;
}

#addIdToPage(pageRef, id, type) {
#addIdToPage(pageRef, id, type, objId) {
if (!(pageRef instanceof Ref) || id < 0) {
return;
}
(this.structParentIds ??= new RefMap())
.getOrPutComputed(pageRef, makeArr)
.push([id, type]);
.push([id, type, objId]);
}

addAnnotationIdToPage(pageRef, id) {
this.#addIdToPage(pageRef, id, StructElementType.ANNOTATION);
addAnnotationIdToPage(pageRef, id, ref) {
this.#addIdToPage(
pageRef,
id,
StructElementType.ANNOTATION,
ref instanceof Ref ? ref.toString() : null
);
}

static async canCreateStructureTree({
Expand Down Expand Up @@ -728,7 +733,7 @@ class StructElementNode {
if (Array.isArray(headers)) {
const ids = headers
.filter(header => typeof header === "string")
.map(header => stringToPDFString(header));
.map(stringToPDFString);
if (ids.length > 0) {
map.set("headers", ids);
}
Expand Down Expand Up @@ -924,18 +929,20 @@ class StructTreePage {
if (!ids) {
return;
}
for (const [elemId, type] of ids) {
for (const [elemId, type, objId] of ids) {
const obj = parentTree.get(elemId);
if (obj) {
const elem = this.addNode(this.xref.fetchIfRef(obj), map);
if (
elem?.kids?.length === 1 &&
elem.kids[0].type === StructElementType.OBJECT
) {
// The node in the struct tree is wrapping an object (annotation
// or xobject), so we need to update the type of the node to match
// the type of the object.
elem.kids[0].type = type;
if (!obj) {
continue;
}
const elem = this.addNode(this.xref.fetchIfRef(obj), map);
if (!elem || !objId) {
continue;
}
// Match the annotation by object reference because its structure
// element may have other children.
for (const kid of elem.kids) {
if (kid.type === StructElementType.OBJECT && kid.refObjId === objId) {
kid.type = type;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ class WorkerMessageHandler {
}
await Promise.all(pagePromises);
const annotations = await Promise.all(annotationPromises);
return annotations.filter(a => !!a);
return annotations.filter(Boolean);
} finally {
if (task) {
finishWorkerTask(task);
Expand Down
2 changes: 1 addition & 1 deletion src/core/xfa/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ class EquateRange extends XFAObject {
for (let range of unicodeRange
.split(",")
.map(x => x.trim())
.filter(x => !!x)) {
.filter(Boolean)) {
range = range.split("-", 2).map(x => {
const found = x.match(unicodeRegex);
if (!found) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/xfa/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -5703,7 +5703,7 @@ class Text extends ContentObject {
if (typeof this[$content] === "string") {
return this[$content]
.split(/[\u2029\u2028\n]/)
.filter(line => !!line)
.filter(Boolean)
.join("\n");
}
return this[$content][$text]();
Expand Down
2 changes: 1 addition & 1 deletion src/core/xfa/xhtml.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ class XhtmlObject extends XmlObject {
xfaFont.letterSpacing = getMeasurement(value);
break;
case "margin":
const values = value.split(/ \t/).map(x => getMeasurement(x));
const values = value.split(/ \t/).map(getMeasurement);
switch (values.length) {
case 1:
margin.top =
Expand Down
13 changes: 9 additions & 4 deletions src/display/annotation_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -654,8 +654,8 @@ class AnnotationElement {
return;
}

const [rectBlX, rectBlY, rectTrX, rectTrY] = this.data.rect.map(x =>
Math.fround(x)
const [rectBlX, rectBlY, rectTrX, rectTrY] = this.data.rect.map(
Math.fround
);

if (quadPoints.length === 8) {
Expand Down Expand Up @@ -4212,9 +4212,14 @@ class AnnotationLayer {
this.div.append(fragment);
await Promise.all(promises);
if (this.#accessibilityManager) {
for (const element of this.#elements) {
const annotationIds = await this.#structTreeLayer?.getAnnotationIds();
for (const { contentElement } of this.#elements) {
if (annotationIds?.has(contentElement.id)) {
// The structure tree already positions this annotation.
continue;
}
this.#accessibilityManager.addPointerInTextLayer(
element.contentElement,
contentElement,
/* isRemovable = */ false
);
}
Expand Down
1 change: 1 addition & 0 deletions stylelint-mozcentral.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"plugins": ["./external/stylelint/no-unused-custom-properties.mjs"],
"referenceFiles": ["./external/stylelint/mozcentral-tokens.css"],
"rules": {
"no-unknown-custom-properties": true,
"pdfjs/no-unused-custom-properties": [
Expand Down
14 changes: 5 additions & 9 deletions test/integration/accessibility_spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -230,16 +230,12 @@ describe("accessibility", () => {
pages.map(async ([browserName, page]) => {
await page.waitForSelector(".structTree");

const isLinkedToStampAnnotation = await page.$eval(
".structTree [role='figure']",
el =>
document
.getElementById(el.getAttribute("aria-owns"))
.classList.contains("stampAnnotation")
const owners = await page.$$eval(
`[aria-owns~="pdfjs_internal_id_20R"]`,
elements =>
elements.map(element => element.closest(".structTree") !== null)
);
expect(isLinkedToStampAnnotation)
.withContext(`In ${browserName}`)
.toBeTrue();
expect(owners).withContext(`In ${browserName}`).toEqual([true]);
})
);
});
Expand Down
2 changes: 1 addition & 1 deletion test/integration/freetext_editor_spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -867,7 +867,7 @@ describe("FreeText Editor", () => {
}, proprName);

const rects = (await serialize("rect")).map(rect =>
rect.slice(0, 2).map(x => Math.floor(x))
rect.slice(0, 2).map(Math.floor)
);
const expected = [
[-28, 695],
Expand Down
12 changes: 9 additions & 3 deletions test/unit/api_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4899,7 +4899,10 @@ have written that much by now. So, here’s to squashing bugs.`);
{
role: "Link",
children: [
{ type: "object", id: "432R" },
{
type: "annotation",
id: "pdfjs_internal_id_432R",
},
{ type: "content", id: "p406R_mc34" },
],
},
Expand All @@ -4922,7 +4925,10 @@ have written that much by now. So, here’s to squashing bugs.`);
{
role: "Link",
children: [
{ type: "object", id: "433R" },
{
type: "annotation",
id: "pdfjs_internal_id_433R",
},
{ type: "content", id: "p406R_mc36" },
],
},
Expand All @@ -4948,7 +4954,7 @@ have written that much by now. So, here’s to squashing bugs.`);
{
role: "Link",
children: [
{ type: "object", id: "434R" },
{ type: "annotation", id: "pdfjs_internal_id_434R" },
{ type: "content", id: "p406R_mc10" },
],
},
Expand Down
2 changes: 1 addition & 1 deletion test/unit/display_utils_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ describe("display_utils", function () {
// Unlike other tests we cannot simply compare the HTML-strings since
// Chrome and Firefox produce different results. Instead we compare sets
// containing the individual parts of the HTML-strings.
const splitParts = s => new Set(s.split(/[<>/ ]+/).filter(x => x));
const splitParts = s => new Set(s.split(/[<>/ ]+/).filter(Boolean));

it("should render plain text", function () {
if (isNodeJS) {
Expand Down
10 changes: 5 additions & 5 deletions test/unit/name_number_tree_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { XRefMock } from "./test_utils.js";
describe("NameOrNumberTree", function () {
describe("NameTree", function () {
it("should return an empty map when root is null", function () {
const xref = new XRefMock([]);
const xref = new XRefMock();
const tree = new NameTree(null, xref);
expect(tree.getAll().size).toEqual(0);
});
Expand All @@ -30,7 +30,7 @@ describe("NameOrNumberTree", function () {
const root = new Dict();
root.set("Names", ["alpha", "value_a", "beta", "value_b"]);

const xref = new XRefMock([]);
const xref = new XRefMock();
const tree = new NameTree(root, xref);
const map = tree.getAll();

Expand Down Expand Up @@ -66,7 +66,7 @@ describe("NameOrNumberTree", function () {
const root = new Dict();
root.set("Kids", [inlineLeaf]);

const xref = new XRefMock([]);
const xref = new XRefMock();
const tree = new NameTree(root, xref);

// Should not throw even though the kid is an inline Dict (not a Ref).
Expand Down Expand Up @@ -126,7 +126,7 @@ describe("NameOrNumberTree", function () {
const root = new Dict();
root.set("Nums", [1, "one", 2, "two"]);

const xref = new XRefMock([]);
const xref = new XRefMock();
const tree = new NumberTree(root, xref);
const map = tree.getAll();

Expand All @@ -144,7 +144,7 @@ describe("NameOrNumberTree", function () {
const root = new Dict();
root.set("Kids", [inlineLeaf]);

const xref = new XRefMock([]);
const xref = new XRefMock();
const tree = new NumberTree(root, xref);

const map = tree.getAll();
Expand Down
Loading
Loading