diff --git a/src/display/api.js b/src/display/api.js index b14be25d1..061c1ddae 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -1623,9 +1623,7 @@ class PDFPageProxy { * or `null` when no structure tree is present for the current page. */ getStructTree() { - return (this._structTreePromise ||= this._transport.getStructTree( - this._pageIndex - )); + return this._transport.getStructTree(this._pageIndex); } /** @@ -1659,7 +1657,6 @@ class PDFPageProxy { this._bitmaps.clear(); this._annotationPromises.clear(); this._jsActionsPromise = null; - this._structTreePromise = null; this.pendingCleanup = false; return Promise.all(waitOn); } @@ -1694,7 +1691,6 @@ class PDFPageProxy { this.objs.clear(); this._annotationPromises.clear(); this._jsActionsPromise = null; - this._structTreePromise = null; if (resetStats && this._stats) { this._stats = new StatTimer(); } diff --git a/web/pdf_page_view.js b/web/pdf_page_view.js index 80a217434..5f0d0577b 100644 --- a/web/pdf_page_view.js +++ b/web/pdf_page_view.js @@ -318,6 +318,33 @@ class PDFPageView { numTextDivs: textLayer.numTextDivs, error, }); + + if (this.structTreeLayerFactory) { + this.#renderStructTreeLayer(); + } + } + + /** + * The structure tree is currently only supported when the text layer is + * enabled and a canvas is used for rendering. + * + * The structure tree must be generated after the text layer for the + * aria-owns to work. + */ + async #renderStructTreeLayer() { + if (!this.textLayer) { + return; + } + this.structTreeLayer ||= + this.structTreeLayerFactory.createStructTreeLayerBuilder(); + + const tree = await (!this.structTreeLayer.renderingDone + ? this.pdfPage.getStructTree() + : null); + const treeDom = this.structTreeLayer?.render(tree); + if (treeDom) { + this.canvas?.append(treeDom); + } } async _buildXfaTextContentItems(textDivs) { @@ -578,6 +605,9 @@ class PDFPageView { this.textLayer.cancel(); this.textLayer = null; } + if (this.structTreeLayer && !this.textLayer) { + this.structTreeLayer = null; + } if ( this.annotationLayer && (!keepAnnotationLayer || !this.annotationLayer.div) @@ -598,10 +628,6 @@ class PDFPageView { this.xfaLayer = null; this.textHighlighter?.disable(); } - if (this._onTextLayerRendered) { - this.eventBus._off("textlayerrendered", this._onTextLayerRendered); - this._onTextLayerRendered = null; - } } cssTransform({ @@ -844,38 +870,6 @@ class PDFPageView { this._renderXfaLayer(); } - // The structure tree is currently only supported when the text layer is - // enabled and a canvas is used for rendering. - if (this.structTreeLayerFactory && this.textLayer && this.canvas) { - // The structure tree must be generated after the text layer for the - // aria-owns to work. - this._onTextLayerRendered = event => { - if (event.pageNumber !== this.id) { - return; - } - this.eventBus._off("textlayerrendered", this._onTextLayerRendered); - this._onTextLayerRendered = null; - - if (!this.canvas) { - return; // The canvas was removed, prevent errors below. - } - this.pdfPage.getStructTree().then(tree => { - if (!tree) { - return; - } - if (!this.canvas) { - return; // The canvas was removed, prevent errors below. - } - const treeDom = this.structTreeLayer.render(tree); - treeDom.classList.add("structTree"); - this.canvas.append(treeDom); - }); - }; - this.eventBus._on("textlayerrendered", this._onTextLayerRendered); - this.structTreeLayer = - this.structTreeLayerFactory.createStructTreeLayerBuilder(); - } - div.setAttribute("data-loaded", true); this.eventBus.dispatch("pagerender", { diff --git a/web/struct_tree_layer_builder.js b/web/struct_tree_layer_builder.js index 463756e96..5ebc29b1a 100644 --- a/web/struct_tree_layer_builder.js +++ b/web/struct_tree_layer_builder.js @@ -72,8 +72,19 @@ const PDF_ROLE_TO_HTML_ROLE = { const HEADING_PATTERN = /^H(\d+)$/; class StructTreeLayerBuilder { + #treeDom = undefined; + + get renderingDone() { + return this.#treeDom !== undefined; + } + render(structTree) { - return this.#walk(structTree); + if (this.#treeDom !== undefined) { + return this.#treeDom; + } + const treeDom = this.#walk(structTree); + treeDom?.classList.add("structTree"); + return (this.#treeDom = treeDom); } #setAttributes(structElement, htmlElement) {