fix(reader): patch embedpdf zoom to release startup gate on custom zoom

Apply a patch to @embedpdf/plugin-zoom@2.15.0 so numeric default zoom levels release the startup
viewport gate once resize metrics are measured.

Add unit test to verify custom zoom initialization and scale calculation under EmbedPDF.

Closes #1126
This commit is contained in:
neon
2026-08-24 22:21:18 +00:00
parent b264ef1132
commit 4c180fd58b
4 changed files with 87 additions and 2 deletions
@@ -0,0 +1,68 @@
import { afterEach, describe, expect, it } from 'vitest'
import { PluginRegistry, setDocumentLoaded, startLoadingDocument } from '@embedpdf/core'
import { Rotation, type PdfDocumentObject, type PdfEngine } from '@embedpdf/models'
import { ScrollPluginPackage, ScrollStrategy } from '@embedpdf/plugin-scroll'
import { ViewportPlugin, ViewportPluginPackage } from '@embedpdf/plugin-viewport'
import { ZoomPlugin, ZoomPluginPackage } from '@embedpdf/plugin-zoom'
describe('patched EmbedPDF custom zoom initialization', () => {
let registry: PluginRegistry | null = null
afterEach(async () => {
await registry?.destroy()
registry = null
})
it('applies a numeric default zoom and releases the startup gate after viewport measurement', async () => {
registry = new PluginRegistry({} as PdfEngine)
registry.registerPlugin(ViewportPluginPackage, { viewportGap: 12 })
registry.registerPlugin(ScrollPluginPackage, {
defaultStrategy: ScrollStrategy.Vertical,
defaultPageGap: 12,
defaultBufferSize: 3,
})
registry.registerPlugin(ZoomPluginPackage, {
defaultZoomLevel: 1.2,
minZoom: 0.25,
maxZoom: 4,
})
await registry.initialize()
const store = registry.getStore()
const documentId = 'custom-zoom-document'
const document: PdfDocumentObject = {
id: documentId,
pageCount: 1,
pages: [{ index: 0, size: { width: 600, height: 800 }, rotation: Rotation.Degree0, objectNumber: 1 }],
isEncrypted: false,
isOwnerUnlocked: true,
permissions: 0,
normalizedRotation: true,
}
store.dispatchToCore(startLoadingDocument(documentId, 'PDF'))
store.dispatchToCore(setDocumentLoaded(documentId, document))
const viewport = registry.getPlugin<ViewportPlugin>(ViewportPlugin.id)
const zoom = registry.getPlugin<ZoomPlugin>(ZoomPlugin.id)
expect(viewport?.provides().hasGate('zoom', documentId)).toBe(true)
viewport?.setViewportResizeMetrics(documentId, {
width: 1000,
height: 700,
clientWidth: 1000,
clientHeight: 700,
scrollTop: 0,
scrollLeft: 0,
scrollWidth: 1000,
scrollHeight: 700,
clientLeft: 0,
clientTop: 0,
})
await new Promise((resolve) => setTimeout(resolve, 175))
expect(viewport?.provides().hasGate('zoom', documentId)).toBe(false)
expect(zoom?.provides().forDocument(documentId).getState()).toMatchObject({ zoomLevel: 1.2, currentZoomLevel: 1.2 })
expect(store.getState().core.documents[documentId]?.scale).toBe(1.2)
})
})
@@ -0,0 +1,15 @@
diff --git a/dist/index.js b/dist/index.js
index f33d50ed18a00f00cba6b102f5e7ab18f141364e..bb9085c18a295b7ac1e621423e94652803a647fc 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -609,6 +609,10 @@ const _ZoomPlugin = class _ZoomPlugin extends BasePlugin {
recalcAuto(documentId, focus) {
const docState = this.getDocumentState(documentId);
if (!docState) return;
+ if (typeof docState.zoomLevel === "number") {
+ if (this.viewport.hasGate("zoom", documentId)) this.handleRequest({ level: docState.zoomLevel, focus }, documentId);
+ return;
+ }
if (docState.zoomLevel === ZoomMode.Automatic || docState.zoomLevel === ZoomMode.FitPage || docState.zoomLevel === ZoomMode.FitWidth) {
this.handleRequest({ level: docState.zoomLevel, focus }, documentId);
}
+3 -2
View File
@@ -30,6 +30,7 @@ patchedDependencies:
'@embedpdf/core@2.15.0': 2000da4fd605dad67860a28724f4ab90eafa7215b89abe29df3f001bebc15a77
'@embedpdf/engines@2.15.0': b4b3f0ea41ff20fd1f076c2b0a880f5b580a3ebdf5c69c95a7ee09a91183f924
'@embedpdf/plugin-scroll@2.15.0': ef47017e5f4370e4c13ae1a5b523683acaaa68db36290094f8badab4614c6d0d
'@embedpdf/plugin-zoom@2.15.0': 39f7f5ddd05c0dadd63f5fc076e679140d1b0f8761a4899176076b563e361d77
importers:
@@ -133,7 +134,7 @@ importers:
version: 2.15.0(@embedpdf/core@2.15.0(patch_hash=2000da4fd605dad67860a28724f4ab90eafa7215b89abe29df3f001bebc15a77)(preact@10.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(svelte@5.56.4(@typescript-eslint/types@8.67.0))(vue@3.5.41(typescript@6.0.3)))(preact@10.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(svelte@5.56.4(@typescript-eslint/types@8.67.0))(vue@3.5.41(typescript@6.0.3))
'@embedpdf/plugin-zoom':
specifier: 2.15.0
version: 2.15.0(bae5492da052cd1ccfa4d859ce720d47)
version: 2.15.0(patch_hash=39f7f5ddd05c0dadd63f5fc076e679140d1b0f8761a4899176076b563e361d77)(bae5492da052cd1ccfa4d859ce720d47)
'@fontsource-variable/fraunces':
specifier: ^5.3.0
version: 5.3.0
@@ -10542,7 +10543,7 @@ snapshots:
svelte: 5.56.4(@typescript-eslint/types@8.67.0)
vue: 3.5.41(typescript@6.0.3)
'@embedpdf/plugin-zoom@2.15.0(bae5492da052cd1ccfa4d859ce720d47)':
'@embedpdf/plugin-zoom@2.15.0(patch_hash=39f7f5ddd05c0dadd63f5fc076e679140d1b0f8761a4899176076b563e361d77)(bae5492da052cd1ccfa4d859ce720d47)':
dependencies:
'@embedpdf/core': 2.15.0(patch_hash=2000da4fd605dad67860a28724f4ab90eafa7215b89abe29df3f001bebc15a77)(preact@10.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(svelte@5.56.4(@typescript-eslint/types@8.67.0))(vue@3.5.41(typescript@6.0.3))
'@embedpdf/models': 2.15.0
+1
View File
@@ -54,6 +54,7 @@ patchedDependencies:
"@embedpdf/core@2.15.0": patches/@embedpdf__core@2.15.0.patch
"@embedpdf/engines@2.15.0": patches/@embedpdf__engines@2.15.0.patch
"@embedpdf/plugin-scroll@2.15.0": patches/@embedpdf__plugin-scroll@2.15.0.patch
"@embedpdf/plugin-zoom@2.15.0": patches/@embedpdf__plugin-zoom@2.15.0.patch
minimumReleaseAgeExclude:
- "@tsconfig/node24@24.0.5"
- "@vue/language-core@3.3.10"