@file-viewer/renderer-pdf 2.1.30 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -42,7 +42,7 @@ const options = {
42
42
  }
43
43
  ```
44
44
 
45
- When no explicit PDF asset URL is configured, the renderer first uses the public base exposed by build tools such as Vite and can fall back to the page entry script. An app deployed under `/workspace/` therefore still requests `/workspace/vendor/pdf/pdf.worker.mjs` while its current SPA route is `/workspace/c/`. UMI, custom proxies, and builds whose public path cannot be detected can set `pdf.assetBaseUrl: '/workspace/'` to pin the base for every PDF offline asset. If the host app did not run `file-viewer-copy-assets`, does not use `@file-viewer/vite-plugin`, or a local dev server falls back to HTML for that path, the renderer lazy-loads the packaged PDF.js worker handler as a compatibility fallback so preview does not fail with `Setting up fake worker failed`. For best performance, complete cMap/standard-font/WASM decoding, or strict offline deployments, still copy viewer assets and point these URLs at real static files. The pinned PDF.js 5.4 stable line loads local JBIG2, JPEG 2000, color-management, and related helpers through `wasmUrl`; viewer assets and the Vite plugin copy them without relying on the public internet.
45
+ When no explicit PDF asset URL is configured, the renderer first uses the public base exposed by build tools such as Vite and can fall back to the page entry script. An app deployed under `/workspace/` therefore still requests `/workspace/vendor/pdf/pdf.worker.mjs` while its current SPA route is `/workspace/c/`. UMI, custom proxies, and builds whose public path cannot be detected can set `pdf.assetBaseUrl: '/workspace/'` to pin the base for every PDF offline asset. Before creating a static Worker, the renderer reads the official PDF.js version marker; a stale Worker from an older deployment is rejected and the packaged same-version handler is used instead. If the host app did not run `file-viewer-copy-assets`, does not use `@file-viewer/vite-plugin`, or a local dev server falls back to HTML for that path, the same fallback prevents `Setting up fake worker failed`. For best performance, complete cMap/standard-font/WASM decoding, or strict offline deployments, still copy viewer assets and point these URLs at real static files. The pinned PDF.js 5.4 stable line loads local JBIG2, JPEG 2000, color-management, and related helpers through `wasmUrl`; viewer assets and the Vite plugin copy them without relying on the public internet.
46
46
 
47
47
  `cjkFontFallback` is enabled by default. When a PDF references `MicrosoftYaHei-Bold`, SimSun, SimHei, or another CJK font without embedding the font program, the renderer prefers an installed system font and otherwise aliases the original PDF font name to the bundled Noto Sans SC variable font. Only WOFF2 shards needed by the current page text are loaded. The first page waits for the font before rendering, and later pages are redrawn when they introduce new glyphs. Set the option to `false` to disable this behavior, or point `cjkFontFallbackPath` at a self-hosted directory with the same structure.
48
48
 
package/README.md CHANGED
@@ -42,7 +42,7 @@ const options = {
42
42
  }
43
43
  ```
44
44
 
45
- 默认未显式配置时,渲染器优先使用 Vite 等构建器提供的公开基址,并可从页面入口脚本回退识别部署子路径。因此应用部署在 `/workspace/`、当前 SPA 路由为 `/workspace/c/` 时,仍会请求 `/workspace/vendor/pdf/pdf.worker.mjs`。UMI、自定义代理或无法自动识别的构建环境可以设置 `pdf.assetBaseUrl: '/workspace/'` 固定全部 PDF 离线资源的基址。如果项目没有执行 `file-viewer-copy-assets`、没有使用 `@file-viewer/vite-plugin`,或者本地临时服务器把该路径回退成 HTML,PDF renderer 会自动懒加载包内 PDF.js worker handler 作为兼容兜底,避免 `Setting up fake worker failed` 直接中断预览。需要最佳性能、完整 cMap/standard fonts/WASM 解码或严格离线部署时,仍建议复制 viewer assets 并配置真实静态地址。当前锁定的 PDF.js 5.4 稳定线会通过 `wasmUrl` 本地加载 JBIG2、JPEG 2000、颜色管理等辅助资源;这些资源由 viewer assets 和 Vite 插件统一复制,不依赖公网。
45
+ 默认未显式配置时,渲染器优先使用 Vite 等构建器提供的公开基址,并可从页面入口脚本回退识别部署子路径。因此应用部署在 `/workspace/`、当前 SPA 路由为 `/workspace/c/` 时,仍会请求 `/workspace/vendor/pdf/pdf.worker.mjs`。UMI、自定义代理或无法自动识别的构建环境可以设置 `pdf.assetBaseUrl: '/workspace/'` 固定全部 PDF 离线资源的基址。创建静态 Worker 前会先读取 PDF.js 官方版本标记;若部署目录残留的旧 Worker 与当前 API 不一致,会拒绝旧文件并自动使用包内同版本 handler。项目未执行 `file-viewer-copy-assets`、未使用 `@file-viewer/vite-plugin`,或本地临时服务器把该路径回退成 HTML 时,也会使用同一兜底,避免 `Setting up fake worker failed` 直接中断预览。需要最佳性能、完整 cMap/standard fonts/WASM 解码或严格离线部署时,仍建议复制 viewer assets 并配置真实静态地址。当前锁定的 PDF.js 5.4 稳定线会通过 `wasmUrl` 本地加载 JBIG2、JPEG 2000、颜色管理等辅助资源;这些资源由 viewer assets 和 Vite 插件统一复制,不依赖公网。
46
46
 
47
47
  `cjkFontFallback` 默认开启。PDF 引用了 `MicrosoftYaHei-Bold`、宋体、黑体或其他中文字体但没有嵌入字体数据时,渲染器优先使用本机字体;本机缺失时,会把原 PDF 字体名映射到本地 Noto Sans SC 可变字体,并根据当前页实际文字只加载需要的 WOFF2 分片。首屏会在字体就绪后再渲染,后续页发现新字形时会自动重绘。可设为 `false` 完全关闭,或用 `cjkFontFallbackPath` 指向同结构的自托管字体目录。
48
48
 
package/dist/pdf.js CHANGED
@@ -1,21 +1,30 @@
1
- import { getDocument, GlobalWorkerOptions, PDFWorker as PdfJsWorker, PixelsPerInch, } from 'pdfjs-dist/legacy/build/pdf.mjs';
1
+ import { getDocument, GlobalWorkerOptions, PDFWorker as PdfJsWorker, PixelsPerInch, version as pdfJsVersion, } from 'pdfjs-dist/legacy/build/pdf.mjs';
2
2
  import { EventBus, GenericL10n, PDFFindController, PDFLinkService, PDFViewer, } from 'pdfjs-dist/legacy/web/pdf_viewer.mjs';
3
3
  import { registerFileViewerSearchProvider, registerFileViewerZoomProvider, unregisterFileViewerSearchProvider, unregisterFileViewerZoomProvider, registerFileViewerViewStateProvider, unregisterFileViewerViewStateProvider, createFileViewerZoomChangeEmitter, createFileViewerViewStateChange, createFileViewerViewStateChangeEmitter, createFileViewerTranslator, buildPrintPageStyle, formatCssPixels, DEFAULT_PDF_RANGE_CHUNK_SIZE, resolveFileViewerLocale, resolveFileViewerFitScale, } from '@file-viewer/core';
4
4
  import { DEFAULT_FILE_VIEWER_PDF_WORKER_PATH, resolveFileViewerPdfAssetUrls, resolveFileViewerRuntimeAssetBaseUrl, } from '@file-viewer/core/assets';
5
5
  import { pdfViewerStyle } from './pdfStyles.js';
6
6
  import { collectMalformedIdentityFontNames, createPdfCjkFontFallbackManager, detectMalformedIdentityCjkFontFamilies, } from './pdfFontFallback.js';
7
7
  import { PDF_FIT_HORIZONTAL_PADDING, PDF_PAGE_BORDER_WIDTH, resolvePdfFitViewportSize, } from './pdfFit.js';
8
+ import { capturePdfJsWorkerGlobal, scopePdfJsWorkerMessageHandler, } from './pdfWorkerGlobal.js';
9
+ import { readPdfJsWorkerVersion } from './pdfWorkerVersion.js';
8
10
  export const DEFAULT_FILE_VIEWER_PDF_WORKER_URL = DEFAULT_FILE_VIEWER_PDF_WORKER_PATH;
9
11
  const MIN_SCALE = 0.2;
10
12
  const MAX_SCALE = 3;
11
13
  const SCALE_STEP = 0.1;
12
14
  const PDF_EXPORT_MAX_PAGE_PIXELS = 8000000;
13
15
  const PDF_WORKER_PROBE_TIMEOUT_MS = 1200;
16
+ const PDF_WORKER_VERSION_PROBE_BYTES = 4096;
14
17
  const PDF_JS_DESTROY_CONSOLE_SUPPRESSION_MS = 1500;
15
18
  let bundledPdfWorkerModulePromise = null;
19
+ const scopePdfJsRootVariables = (style) => style.replace(/:root(\s*\{)/g, ':root,\n.pdf-shell$1');
16
20
  // PDF.js viewer CSS references image assets that are not shipped with the
17
21
  // on-demand renderer chunk, so keep the preview self-contained and 404-free.
18
- const normalizedPdfViewerStyle = pdfViewerStyle
22
+ // Its root custom properties also need a local scope: a :root selector inside
23
+ // Shadow DOM does not match the document root or the custom-element host.
24
+ const normalizedPdfViewerStyle = `${scopePdfJsRootVariables(pdfViewerStyle)}
25
+ .pdf-shell{background:var(--file-viewer-render-surface-background,#edf2f7)}
26
+ .pdf-wrapper{background:var(--file-viewer-render-surface-background,#e8edf4)}
27
+ `
19
28
  .replace(/--page-border-image:\s*url\(images\/shadow\.png\)\s*9 9 repeat;/g, '--page-border-image:none;')
20
29
  .replace(/background:\s*url\("\.\/images\/loading-icon\.gif"\)\s*center no-repeat;/g, 'background:none;');
21
30
  const pdfJsConsoleErrorSuppressions = new WeakMap();
@@ -234,21 +243,33 @@ const isJavaScriptLikeResponse = (response) => {
234
243
  contentType.includes('application/octet-stream') ||
235
244
  contentType.includes('text/plain');
236
245
  };
246
+ const readResponsePrefix = async (response, maximumBytes = PDF_WORKER_VERSION_PROBE_BYTES) => {
247
+ // Consume the response even when a server ignores Range. Cancelling after the
248
+ // prefix creates a browser-level ERR_ABORTED event that strict hosts treat as
249
+ // a failed asset request, despite the compatibility probe succeeding.
250
+ return (await response.text()).slice(0, maximumBytes);
251
+ };
237
252
  const loadBundledPdfWorkerModule = async () => {
238
253
  bundledPdfWorkerModulePromise !== null && bundledPdfWorkerModulePromise !== void 0 ? bundledPdfWorkerModulePromise : (bundledPdfWorkerModulePromise = import('pdfjs-dist/legacy/build/pdf.worker.mjs'));
239
254
  return bundledPdfWorkerModulePromise;
240
255
  };
241
- const installBundledPdfFakeWorker = async () => {
242
- var _a;
256
+ const createBundledPdfFakeWorker = async () => {
243
257
  const workerGlobal = globalThis;
244
- if ((_a = workerGlobal.pdfjsWorker) === null || _a === void 0 ? void 0 : _a.WorkerMessageHandler) {
245
- return;
246
- }
258
+ // pdf.worker.mjs assigns globalThis.pdfjsWorker as a module side effect, so
259
+ // capture the host namespace before importing it and restore that snapshot.
260
+ const hostWorkerGlobal = capturePdfJsWorkerGlobal(workerGlobal);
247
261
  const workerModule = await loadBundledPdfWorkerModule();
248
- workerGlobal.pdfjsWorker = {
249
- ...workerGlobal.pdfjsWorker,
250
- WorkerMessageHandler: workerModule.WorkerMessageHandler,
251
- };
262
+ const workerHandlerScope = scopePdfJsWorkerMessageHandler(workerGlobal, workerModule.WorkerMessageHandler, hostWorkerGlobal);
263
+ try {
264
+ const worker = new PdfJsWorker({
265
+ name: 'file-viewer-pdf-worker',
266
+ });
267
+ await worker.promise;
268
+ return worker;
269
+ }
270
+ finally {
271
+ workerHandlerScope.restore();
272
+ }
252
273
  };
253
274
  const resolvePdfWorkerUrl = (options, documentBaseUrl) => {
254
275
  return resolveFileViewerPdfAssetUrls(options, documentBaseUrl).workerUrl;
@@ -688,57 +709,78 @@ export default async function renderPdf(buffer, target, context) {
688
709
  targetWindow.requestAnimationFrame(writeLegacyCompatiblePageDimensions);
689
710
  });
690
711
  };
691
- const canUseResolvedPdfWorkerUrl = async (workerUrl) => {
712
+ const probeResolvedPdfWorkerUrl = async (workerUrl) => {
692
713
  var _a, _b;
693
714
  const fetcher = ((_a = targetWindow.fetch) === null || _a === void 0 ? void 0 : _a.bind(targetWindow)) || ((_b = globalThis.fetch) === null || _b === void 0 ? void 0 : _b.bind(globalThis));
694
715
  const AbortControllerCtor = targetWindow.AbortController || globalThis.AbortController;
695
716
  if (!fetcher || !AbortControllerCtor) {
696
- return false;
717
+ return { status: 'unavailable', workerVersion: null };
697
718
  }
698
719
  try {
699
720
  const parsed = new URL(workerUrl, documentRef.baseURI || targetWindow.location.href);
700
721
  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
701
- return false;
722
+ return { status: 'unavailable', workerVersion: null };
702
723
  }
703
724
  }
704
725
  catch {
705
- return false;
726
+ return { status: 'unavailable', workerVersion: null };
706
727
  }
707
728
  const controller = new AbortControllerCtor();
708
729
  const timer = targetWindow.setTimeout(() => controller.abort(), PDF_WORKER_PROBE_TIMEOUT_MS);
709
730
  try {
710
731
  const response = await fetcher(workerUrl, {
711
- method: 'HEAD',
732
+ method: 'GET',
712
733
  cache: 'no-cache',
734
+ headers: {
735
+ Range: `bytes=0-${PDF_WORKER_VERSION_PROBE_BYTES - 1}`,
736
+ },
713
737
  signal: controller.signal,
714
738
  });
715
- if (response.ok) {
716
- return isJavaScriptLikeResponse(response);
739
+ if ((!response.ok && response.status !== 206) || !isJavaScriptLikeResponse(response)) {
740
+ return { status: 'unavailable', workerVersion: null };
717
741
  }
718
- if (response.status !== 405 && response.status !== 501) {
719
- return false;
742
+ const workerVersion = readPdfJsWorkerVersion(await readResponsePrefix(response));
743
+ if (!workerVersion) {
744
+ return { status: 'unknown', workerVersion: null };
720
745
  }
721
- const fallbackResponse = await fetcher(workerUrl, {
722
- method: 'GET',
723
- cache: 'no-cache',
724
- headers: { Range: 'bytes=0-0' },
725
- signal: controller.signal,
726
- });
727
- return (fallbackResponse.ok || fallbackResponse.status === 206) &&
728
- isJavaScriptLikeResponse(fallbackResponse);
746
+ return {
747
+ status: workerVersion === pdfJsVersion ? 'compatible' : 'incompatible',
748
+ workerVersion,
749
+ };
729
750
  }
730
751
  catch {
731
- return false;
752
+ return { status: 'unavailable', workerVersion: null };
732
753
  }
733
754
  finally {
734
755
  targetWindow.clearTimeout(timer);
735
756
  }
736
757
  };
737
758
  const createPdfWorker = async () => {
759
+ var _a;
738
760
  const workerUrl = resolvePdfWorkerUrl(options, pdfRuntimeAssetBaseUrl);
761
+ const workerGlobal = globalThis;
762
+ if ((_a = workerGlobal.pdfjsWorker) === null || _a === void 0 ? void 0 : _a.WorkerMessageHandler) {
763
+ try {
764
+ // PDF.js prefers a preinstalled main-thread handler over workerSrc.
765
+ // Scope our bundled handler only until this PDFWorker captures it, so
766
+ // a vue-office/PDF.js 3.x global cannot hijack this renderer and the
767
+ // host can still use its original handler afterwards.
768
+ return await createBundledPdfFakeWorker();
769
+ }
770
+ catch (error) {
771
+ console.warn('[file-viewer] PDF.js 全局 Worker handler 隔离失败,继续探测静态 Worker。', error);
772
+ }
773
+ }
739
774
  const hasExplicitWorkerUrl = isConfiguredUrl(options === null || options === void 0 ? void 0 : options.workerUrl);
740
- const shouldUseRealWorker = !!(targetWindow === null || targetWindow === void 0 ? void 0 : targetWindow.Worker) &&
741
- (hasExplicitWorkerUrl || await canUseResolvedPdfWorkerUrl(workerUrl));
775
+ const workerProbe = (targetWindow === null || targetWindow === void 0 ? void 0 : targetWindow.Worker)
776
+ ? await probeResolvedPdfWorkerUrl(workerUrl)
777
+ : { status: 'unavailable', workerVersion: null };
778
+ if (workerProbe.status === 'incompatible') {
779
+ console.warn(`[file-viewer] PDF Worker ${workerProbe.workerVersion} 与 PDF.js API ${pdfJsVersion} 不匹配,` +
780
+ '改用包内同版本 PDF.js handler。');
781
+ }
782
+ const shouldUseRealWorker = !!(targetWindow === null || targetWindow === void 0 ? void 0 : targetWindow.Worker) && (workerProbe.status === 'compatible' ||
783
+ (hasExplicitWorkerUrl && workerProbe.status !== 'incompatible'));
742
784
  if (shouldUseRealWorker) {
743
785
  GlobalWorkerOptions.workerSrc = workerUrl;
744
786
  try {
@@ -753,7 +795,7 @@ export default async function renderPdf(buffer, target, context) {
753
795
  }
754
796
  }
755
797
  try {
756
- await installBundledPdfFakeWorker();
798
+ return await createBundledPdfFakeWorker();
757
799
  }
758
800
  catch (error) {
759
801
  console.warn('[file-viewer] PDF.js 包内 worker 兜底加载失败,继续使用 PDF.js 默认策略。', error);
@@ -1762,9 +1804,16 @@ export default async function renderPdf(buffer, target, context) {
1762
1804
  container.addEventListener('keydown', recordUserScrollIntent);
1763
1805
  container.addEventListener('scroll', scheduleScrollViewStateChange, { passive: true });
1764
1806
  if (targetWindow.ResizeObserver) {
1765
- resizeObserver = new targetWindow.ResizeObserver(() => scheduleFitAfterResize());
1807
+ resizeObserver = new targetWindow.ResizeObserver(() => {
1808
+ root.style.setProperty('--viewer-container-height', `${container.clientHeight}px`);
1809
+ scheduleFitAfterResize();
1810
+ });
1766
1811
  resizeObserver.observe(container);
1767
1812
  }
1813
+ // PDFViewer writes this value to documentElement, which cannot safely model
1814
+ // multiple differently-sized viewers. Keep a live shell-local value as well
1815
+ // so Shadow DOM and multi-instance layouts both resolve the dummy-page height.
1816
+ root.style.setProperty('--viewer-container-height', `${container.clientHeight}px`);
1768
1817
  syncUi();
1769
1818
  void loadFile();
1770
1819
  return {
@@ -0,0 +1,27 @@
1
+ export type PdfJsWorkerNamespace = {
2
+ WorkerMessageHandler?: unknown;
3
+ [key: string]: unknown;
4
+ };
5
+ export type PdfJsWorkerGlobal = {
6
+ pdfjsWorker?: PdfJsWorkerNamespace;
7
+ };
8
+ export type PdfJsWorkerHandlerInstallResult = 'installed' | 'replaced' | 'unchanged';
9
+ export type PdfJsWorkerHandlerScope = {
10
+ installResult: PdfJsWorkerHandlerInstallResult;
11
+ restore: () => boolean;
12
+ };
13
+ export type PdfJsWorkerGlobalSnapshot = {
14
+ hadOwnNamespace: boolean;
15
+ namespace: PdfJsWorkerNamespace | undefined;
16
+ };
17
+ export declare const capturePdfJsWorkerGlobal: (workerGlobal: PdfJsWorkerGlobal) => PdfJsWorkerGlobalSnapshot;
18
+ /**
19
+ * Temporarily own the fake-worker handler used by this renderer.
20
+ *
21
+ * Host applications can load another PDF.js build before File Viewer. Reusing
22
+ * that global handler is unsafe because PDF.js requires its API and worker
23
+ * versions to match exactly. The original namespace is restored after our
24
+ * PDFWorker has captured and initialized the bundled handler, so a host PDF.js
25
+ * build can continue using its own global afterwards.
26
+ */
27
+ export declare const scopePdfJsWorkerMessageHandler: (workerGlobal: PdfJsWorkerGlobal, WorkerMessageHandler: unknown, restoreSnapshot?: PdfJsWorkerGlobalSnapshot) => PdfJsWorkerHandlerScope;
@@ -0,0 +1,58 @@
1
+ export const capturePdfJsWorkerGlobal = (workerGlobal) => ({
2
+ hadOwnNamespace: Object.prototype.hasOwnProperty.call(workerGlobal, 'pdfjsWorker'),
3
+ namespace: workerGlobal.pdfjsWorker,
4
+ });
5
+ /**
6
+ * Temporarily own the fake-worker handler used by this renderer.
7
+ *
8
+ * Host applications can load another PDF.js build before File Viewer. Reusing
9
+ * that global handler is unsafe because PDF.js requires its API and worker
10
+ * versions to match exactly. The original namespace is restored after our
11
+ * PDFWorker has captured and initialized the bundled handler, so a host PDF.js
12
+ * build can continue using its own global afterwards.
13
+ */
14
+ export const scopePdfJsWorkerMessageHandler = (workerGlobal, WorkerMessageHandler, restoreSnapshot = capturePdfJsWorkerGlobal(workerGlobal)) => {
15
+ const currentNamespace = workerGlobal.pdfjsWorker;
16
+ const installResult = (currentNamespace === null || currentNamespace === void 0 ? void 0 : currentNamespace.WorkerMessageHandler) === WorkerMessageHandler
17
+ ? 'unchanged'
18
+ : (currentNamespace === null || currentNamespace === void 0 ? void 0 : currentNamespace.WorkerMessageHandler)
19
+ ? 'replaced'
20
+ : 'installed';
21
+ const installedNamespace = installResult === 'unchanged'
22
+ ? currentNamespace
23
+ : {
24
+ ...currentNamespace,
25
+ WorkerMessageHandler,
26
+ };
27
+ if (!installedNamespace) {
28
+ return {
29
+ installResult: 'unchanged',
30
+ restore: () => false,
31
+ };
32
+ }
33
+ if (installResult !== 'unchanged') {
34
+ workerGlobal.pdfjsWorker = installedNamespace;
35
+ }
36
+ const restorationIsNoop = restoreSnapshot.hadOwnNamespace &&
37
+ restoreSnapshot.namespace === installedNamespace;
38
+ let restoreAttempted = false;
39
+ return {
40
+ installResult,
41
+ restore: () => {
42
+ if (restorationIsNoop || restoreAttempted) {
43
+ return false;
44
+ }
45
+ restoreAttempted = true;
46
+ if (workerGlobal.pdfjsWorker !== installedNamespace) {
47
+ return false;
48
+ }
49
+ if (restoreSnapshot.hadOwnNamespace) {
50
+ workerGlobal.pdfjsWorker = restoreSnapshot.namespace;
51
+ }
52
+ else {
53
+ delete workerGlobal.pdfjsWorker;
54
+ }
55
+ return true;
56
+ },
57
+ };
58
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Read the version marker emitted by official PDF.js worker bundles.
3
+ *
4
+ * The marker is intentionally read from a small source prefix before a Worker
5
+ * is constructed. PDF.js does not reject an API/worker mismatch until the
6
+ * first document request, which is too late for `PDFWorker.promise` to be a
7
+ * useful compatibility probe.
8
+ */
9
+ export declare const readPdfJsWorkerVersion: (sourcePrefix: string) => string | null;
@@ -0,0 +1,23 @@
1
+ const PDF_JS_SEMVER_PATTERN = '(\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?)';
2
+ const PDF_JS_WORKER_VERSION_PATTERNS = [
3
+ new RegExp(`\\bpdfjsVersion\\s*=\\s*["']?${PDF_JS_SEMVER_PATTERN}`, 'i'),
4
+ new RegExp(`\\bworkerVersion\\s*=\\s*["']${PDF_JS_SEMVER_PATTERN}["']`, 'i'),
5
+ new RegExp(`\\bPDF\\.js\\s+v${PDF_JS_SEMVER_PATTERN}`, 'i'),
6
+ ];
7
+ /**
8
+ * Read the version marker emitted by official PDF.js worker bundles.
9
+ *
10
+ * The marker is intentionally read from a small source prefix before a Worker
11
+ * is constructed. PDF.js does not reject an API/worker mismatch until the
12
+ * first document request, which is too late for `PDFWorker.promise` to be a
13
+ * useful compatibility probe.
14
+ */
15
+ export const readPdfJsWorkerVersion = (sourcePrefix) => {
16
+ for (const pattern of PDF_JS_WORKER_VERSION_PATTERNS) {
17
+ const match = pattern.exec(sourcePrefix);
18
+ if (match === null || match === void 0 ? void 0 : match[1]) {
19
+ return match[1];
20
+ }
21
+ }
22
+ return null;
23
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@file-viewer/renderer-pdf",
3
- "version": "2.1.30",
3
+ "version": "2.2.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Standalone PDF renderer plugin for Flyfish File Viewer powered by PDF.js.",
@@ -54,7 +54,7 @@
54
54
  "LICENSE"
55
55
  ],
56
56
  "dependencies": {
57
- "@file-viewer/core": "2.1.30",
57
+ "@file-viewer/core": "2.2.1",
58
58
  "@fontsource-variable/noto-sans-sc": "5.2.10",
59
59
  "pdf-lib": "1.17.1",
60
60
  "pdfjs-dist": "5.4.624"