123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- /* Copyright 2021 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.
- */
- const PDF_ROLE_TO_HTML_ROLE = {
- // Document level structure types
- Document: null, // There's a "document" role, but it doesn't make sense here.
- DocumentFragment: null,
- // Grouping level structure types
- Part: "group",
- Sect: "group", // XXX: There's a "section" role, but it's abstract.
- Div: "group",
- Aside: "note",
- NonStruct: "none",
- // Block level structure types
- P: null,
- // H<n>,
- H: "heading",
- Title: null,
- FENote: "note",
- // Sub-block level structure type
- Sub: "group",
- // General inline level structure types
- Lbl: null,
- Span: null,
- Em: null,
- Strong: null,
- Link: "link",
- Annot: "note",
- Form: "form",
- // Ruby and Warichu structure types
- Ruby: null,
- RB: null,
- RT: null,
- RP: null,
- Warichu: null,
- WT: null,
- WP: null,
- // List standard structure types
- L: "list",
- LI: "listitem",
- LBody: null,
- // Table standard structure types
- Table: "table",
- TR: "row",
- TH: "columnheader",
- TD: "cell",
- THead: "columnheader",
- TBody: null,
- TFoot: null,
- // Standard structure type Caption
- Caption: null,
- // Standard structure type Figure
- Figure: "figure",
- // Standard structure type Formula
- Formula: null,
- // standard structure type Artifact
- Artifact: null,
- };
- const HEADING_PATTERN = /^H(\d+)$/;
- class StructTreeLayerBuilder {
- #treeDom = undefined;
- get renderingDone() {
- return this.#treeDom !== undefined;
- }
- render(structTree) {
- if (this.#treeDom !== undefined) {
- return this.#treeDom;
- }
- const treeDom = this.#walk(structTree);
- treeDom?.classList.add("structTree");
- return (this.#treeDom = treeDom);
- }
- #setAttributes(structElement, htmlElement) {
- if (structElement.alt !== undefined) {
- htmlElement.setAttribute("aria-label", structElement.alt);
- }
- if (structElement.id !== undefined) {
- htmlElement.setAttribute("aria-owns", structElement.id);
- }
- if (structElement.lang !== undefined) {
- htmlElement.setAttribute("lang", structElement.lang);
- }
- }
- #walk(node) {
- if (!node) {
- return null;
- }
- const element = document.createElement("span");
- if ("role" in node) {
- const { role } = node;
- const match = role.match(HEADING_PATTERN);
- if (match) {
- element.setAttribute("role", "heading");
- element.setAttribute("aria-level", match[1]);
- } else if (PDF_ROLE_TO_HTML_ROLE[role]) {
- element.setAttribute("role", PDF_ROLE_TO_HTML_ROLE[role]);
- }
- }
- this.#setAttributes(node, element);
- if (node.children) {
- if (node.children.length === 1 && "id" in node.children[0]) {
- // Often there is only one content node so just set the values on the
- // parent node to avoid creating an extra span.
- this.#setAttributes(node.children[0], element);
- } else {
- for (const kid of node.children) {
- element.append(this.#walk(kid));
- }
- }
- }
- return element;
- }
- }
- export { StructTreeLayerBuilder };
|