From c72582e587f7b98756a3cd2dc0faa5512cd5de7d Mon Sep 17 00:00:00 2001 From: Turtle Date: Wed, 4 Nov 2026 00:09:38 +0800 Subject: [PATCH] fix(ui-sidebar-documentpreview): attach the text layer node that carries its styles Append the builder's own container in onAppend instead of the callback argument, document the attach timing, and name the test after what it checks. Co-authored-by: Yudong Han <16971372+yudshj@users.noreply.github.com> --- .../ui-sidebar-documentpreview/src/client/pdf/text.ts | 7 ++++--- .../tests/pdf-text.client.spec.ts | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/client/ui-sidebar-documentpreview/src/client/pdf/text.ts b/packages/client/ui-sidebar-documentpreview/src/client/pdf/text.ts index 5a68740938..30bc8b2390 100644 --- a/packages/client/ui-sidebar-documentpreview/src/client/pdf/text.ts +++ b/packages/client/ui-sidebar-documentpreview/src/client/pdf/text.ts @@ -7,16 +7,17 @@ import type { RenderPdfText } from './document.ts' /** * Create a selectable overlay in a component-owned host. * @param host - absolute overlay matching the displayed canvas dimensions. - * @returns renderer that attaches the layer to `host` when its promise resolves; cancellation also releases its resize observer and DOM. + * @returns renderer that attaches the layer to `host` once its text is laid out, before its promise resolves; + * a cancelled layer is never attached, and cancellation also releases its resize observer and DOM. */ export function pdfTextRenderer(host: HTMLDivElement): RenderPdfText { return (page, viewport) => { let cancelled = false // PDF.js measures each text item against document styles; spans appended to a detached layer do not invalidate them. - const layer = new TextLayerBuilder({ pdfPage: page, onAppend: (div: HTMLDivElement) => { + const layer = new TextLayerBuilder({ pdfPage: page, onAppend: () => { // A cancellation after the text finishes but before this callback cannot stop the builder's continuation. if (cancelled) layer.cancel() - else host.append(div) + else host.append(container) } }) const container = layer.div container.style.setProperty('--total-scale-factor', String(viewport.scale * viewport.userUnit)) diff --git a/packages/client/ui-sidebar-documentpreview/tests/pdf-text.client.spec.ts b/packages/client/ui-sidebar-documentpreview/tests/pdf-text.client.spec.ts index 6c710c8e5f..eb89a377c9 100644 --- a/packages/client/ui-sidebar-documentpreview/tests/pdf-text.client.spec.ts +++ b/packages/client/ui-sidebar-documentpreview/tests/pdf-text.client.spec.ts @@ -25,7 +25,7 @@ import { pdfTextRenderer } from '../src/client/pdf/text.ts' afterEach(() => { vi.unstubAllGlobals(); vi.restoreAllMocks(); vi.clearAllMocks() }) -it('lays out text in a detached layer and attaches it once rendering finishes', async () => { +it('attaches the text layer only after rendering finishes', async () => { vi.stubGlobal('ResizeObserver', class { observe = vi.fn(); disconnect = vi.fn() }) const rendered = Promise.withResolvers() api.render.mockReturnValueOnce(rendered.promise)