@file-viewer/core 2.0.11 → 2.1.0

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.
Files changed (114) hide show
  1. package/README.en.md +2 -2
  2. package/README.md +2 -2
  3. package/dist/config/options.d.ts +1 -1
  4. package/dist/config/options.js +1 -1
  5. package/dist/contracts/types.d.ts +71 -1
  6. package/dist/headless.d.ts +2 -2
  7. package/dist/headless.js +1 -1
  8. package/dist/index.d.ts +9 -6
  9. package/dist/index.js +105 -48
  10. package/dist/platform/assets.d.ts +3 -1
  11. package/dist/platform/assets.js +18 -2
  12. package/dist/registry/capabilities.d.ts +2 -2
  13. package/dist/registry/capabilities.js +2 -1
  14. package/dist/registry/formats.d.ts +20 -7
  15. package/dist/registry/formats.js +14 -5
  16. package/dist/registry/registry.d.ts +8 -1
  17. package/dist/registry/registry.js +29 -0
  18. package/dist/renderers/image.js +1 -10
  19. package/dist/renderers/index.d.ts +320 -2
  20. package/dist/renderers/index.js +27 -157
  21. package/dist/viewer/createViewer.js +86 -3
  22. package/package.json +17 -44
  23. package/dist/renderers/archive.d.ts +0 -2
  24. package/dist/renderers/archive.js +0 -547
  25. package/dist/renderers/archiveCache.d.ts +0 -10
  26. package/dist/renderers/archiveCache.js +0 -96
  27. package/dist/renderers/archiveFallback.d.ts +0 -7
  28. package/dist/renderers/archiveFallback.js +0 -166
  29. package/dist/renderers/archiveShared.d.ts +0 -23
  30. package/dist/renderers/archiveShared.js +0 -71
  31. package/dist/renderers/audio.d.ts +0 -8
  32. package/dist/renderers/audio.js +0 -219
  33. package/dist/renderers/cad.d.ts +0 -2
  34. package/dist/renderers/cad.js +0 -446
  35. package/dist/renderers/code.d.ts +0 -11
  36. package/dist/renderers/code.js +0 -233
  37. package/dist/renderers/data.d.ts +0 -7
  38. package/dist/renderers/data.js +0 -370
  39. package/dist/renderers/drawing.d.ts +0 -10
  40. package/dist/renderers/drawing.js +0 -882
  41. package/dist/renderers/eda.d.ts +0 -2
  42. package/dist/renderers/eda.js +0 -434
  43. package/dist/renderers/edaParser.d.ts +0 -77
  44. package/dist/renderers/edaParser.js +0 -569
  45. package/dist/renderers/email.d.ts +0 -2
  46. package/dist/renderers/email.js +0 -463
  47. package/dist/renderers/epub.d.ts +0 -2
  48. package/dist/renderers/epub.js +0 -331
  49. package/dist/renderers/geo.d.ts +0 -2
  50. package/dist/renderers/geo.js +0 -284
  51. package/dist/renderers/markdown.d.ts +0 -2
  52. package/dist/renderers/markdown.js +0 -83
  53. package/dist/renderers/model.d.ts +0 -2
  54. package/dist/renderers/model.js +0 -567
  55. package/dist/renderers/ofd.d.ts +0 -2
  56. package/dist/renderers/ofd.js +0 -256
  57. package/dist/renderers/openDocument.d.ts +0 -2
  58. package/dist/renderers/openDocument.js +0 -122
  59. package/dist/renderers/pdf.d.ts +0 -3
  60. package/dist/renderers/pdf.js +0 -1001
  61. package/dist/renderers/pdfStyles.d.ts +0 -1
  62. package/dist/renderers/pdfStyles.js +0 -1
  63. package/dist/renderers/pptx.d.ts +0 -2
  64. package/dist/renderers/pptx.js +0 -217
  65. package/dist/renderers/spreadsheet/state.d.ts +0 -80
  66. package/dist/renderers/spreadsheet/state.js +0 -96
  67. package/dist/renderers/spreadsheet/view.d.ts +0 -25
  68. package/dist/renderers/spreadsheet/view.js +0 -833
  69. package/dist/renderers/spreadsheet/worker/index.d.ts +0 -2
  70. package/dist/renderers/spreadsheet/worker/index.js +0 -1
  71. package/dist/renderers/spreadsheet/worker/sheetjs/SheetJsModel.d.ts +0 -73
  72. package/dist/renderers/spreadsheet/worker/sheetjs/SheetJsModel.js +0 -623
  73. package/dist/renderers/spreadsheet/worker/sheetjs/color.d.ts +0 -2
  74. package/dist/renderers/spreadsheet/worker/sheetjs/color.js +0 -73
  75. package/dist/renderers/spreadsheet/worker/sheetjs/index.d.ts +0 -1
  76. package/dist/renderers/spreadsheet/worker/sheetjs/index.js +0 -1
  77. package/dist/renderers/spreadsheet/worker/sheetjs/parser.d.ts +0 -18
  78. package/dist/renderers/spreadsheet/worker/sheetjs/parser.js +0 -106
  79. package/dist/renderers/spreadsheet/worker/sheetjs/sheet.worker.d.ts +0 -1
  80. package/dist/renderers/spreadsheet/worker/sheetjs/sheet.worker.js +0 -11
  81. package/dist/renderers/spreadsheet/worker/type.d.ts +0 -57
  82. package/dist/renderers/spreadsheet/worker/type.js +0 -1
  83. package/dist/renderers/spreadsheet.d.ts +0 -3
  84. package/dist/renderers/spreadsheet.js +0 -929
  85. package/dist/renderers/typst.d.ts +0 -8
  86. package/dist/renderers/typst.js +0 -547
  87. package/dist/renderers/umd/parser.d.ts +0 -30
  88. package/dist/renderers/umd/parser.js +0 -408
  89. package/dist/renderers/umd.d.ts +0 -2
  90. package/dist/renderers/umd.js +0 -297
  91. package/dist/renderers/video.d.ts +0 -8
  92. package/dist/renderers/video.js +0 -108
  93. package/dist/renderers/wordDoc.d.ts +0 -5
  94. package/dist/renderers/wordDoc.js +0 -284
  95. package/dist/renderers/wordDocx.d.ts +0 -5
  96. package/dist/renderers/wordDocx.js +0 -985
  97. package/dist/renderers/wordDocx.worker.d.ts +0 -1
  98. package/dist/renderers/wordDocx.worker.js +0 -96
  99. package/vendor/ofd/dltech/jbig2/arithmetic_decoder.js +0 -183
  100. package/vendor/ofd/dltech/jbig2/ccitt.js +0 -1070
  101. package/vendor/ofd/dltech/jbig2/compatibility.js +0 -12
  102. package/vendor/ofd/dltech/jbig2/core_utils.js +0 -180
  103. package/vendor/ofd/dltech/jbig2/is_node.js +0 -27
  104. package/vendor/ofd/dltech/jbig2/jbig2.js +0 -2589
  105. package/vendor/ofd/dltech/jbig2/jbig2_stream.js +0 -81
  106. package/vendor/ofd/dltech/jbig2/primitives.js +0 -387
  107. package/vendor/ofd/dltech/jbig2/stream.js +0 -1348
  108. package/vendor/ofd/dltech/jbig2/util.js +0 -972
  109. package/vendor/ofd/dltech/ofd/ofd.d.ts +0 -11
  110. package/vendor/ofd/dltech/ofd/ofd.js +0 -100
  111. package/vendor/ofd/dltech/ofd/ofd_parser.js +0 -395
  112. package/vendor/ofd/dltech/ofd/ofd_render.js +0 -473
  113. package/vendor/ofd/dltech/ofd/ofd_util.js +0 -350
  114. package/vendor/ofd/dltech/ofd/pipeline.js +0 -26
@@ -1,1001 +0,0 @@
1
- import { getDocument, GlobalWorkerOptions, PDFWorker as PdfJsWorker, PixelsPerInch, } from 'pdfjs-dist/legacy/build/pdf.mjs';
2
- import { EventBus, GenericL10n, PDFFindController, PDFLinkService, PDFViewer, } from 'pdfjs-dist/legacy/web/pdf_viewer.mjs';
3
- import { registerFileViewerSearchProvider, registerFileViewerZoomProvider, unregisterFileViewerSearchProvider, unregisterFileViewerZoomProvider, } from '../features/document/dom/index.js';
4
- import { createFileViewerZoomChangeEmitter } from '../features/document/zoom.js';
5
- import { buildPrintPageStyle, formatCssPixels, } from '../output/printLayout.js';
6
- import { DEFAULT_FILE_VIEWER_PDF_WORKER_PATH, resolveFileViewerPdfAssetUrls, } from '../platform/assets.js';
7
- import { DEFAULT_PDF_RANGE_CHUNK_SIZE } from '../source/loading.js';
8
- import { pdfViewerStyle } from './pdfStyles.js';
9
- export const DEFAULT_FILE_VIEWER_PDF_WORKER_URL = DEFAULT_FILE_VIEWER_PDF_WORKER_PATH;
10
- const MIN_SCALE = 0.2;
11
- const MAX_SCALE = 3;
12
- const SCALE_STEP = 0.1;
13
- const FIT_HORIZONTAL_PADDING = 28;
14
- const PAGE_BORDER_WIDTH = 18;
15
- const PDF_EXPORT_MAX_PAGE_PIXELS = 8000000;
16
- // PDF.js viewer CSS references image assets that are not shipped with the
17
- // on-demand renderer chunk, so keep the preview self-contained and 404-free.
18
- const normalizedPdfViewerStyle = pdfViewerStyle
19
- .replace(/--page-border-image:\s*url\(images\/shadow\.png\)\s*9 9 repeat;/g, '--page-border-image:none;')
20
- .replace(/background:\s*url\("\.\/images\/loading-icon\.gif"\)\s*center no-repeat;/g, 'background:none;');
21
- const createStyle = (documentRef) => {
22
- const style = documentRef.createElement('style');
23
- style.textContent = `${normalizedPdfViewerStyle}
24
- .pdf-state[hidden],.pdf-nav-pane[hidden]{display:none!important}
25
- .pdf-page-button--with-thumbnail{grid-template-columns:52px minmax(0,1fr);min-height:74px}
26
- .pdf-page-thumb--thumbnail{width:46px;height:60px;overflow:hidden;background:#fff}
27
- .pdf-page-thumb--thumbnail img{display:block;width:100%;height:100%;object-fit:contain}
28
- .pdf-page-thumb--thumbnail span{display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%}
29
- `;
30
- return style;
31
- };
32
- const createElement = (documentRef, tagName, className, text) => {
33
- const element = documentRef.createElement(tagName);
34
- if (className) {
35
- element.className = className;
36
- }
37
- if (text !== undefined) {
38
- element.textContent = text;
39
- }
40
- return element;
41
- };
42
- const createButton = (documentRef, className, title, label) => {
43
- const button = createElement(documentRef, 'button', className);
44
- button.type = 'button';
45
- button.title = title;
46
- button.setAttribute('aria-label', title);
47
- if (label !== undefined) {
48
- const labelNode = createElement(documentRef, 'span', undefined, label);
49
- labelNode.setAttribute('aria-hidden', 'true');
50
- button.append(labelNode);
51
- }
52
- return button;
53
- };
54
- const normalizeRotation = (rotation) => {
55
- const normalized = ((Math.round(rotation / 90) * 90) % 360 + 360) % 360;
56
- return (normalized === 90 || normalized === 180 || normalized === 270 ? normalized : 0);
57
- };
58
- const clampScale = (scale) => Number(Math.min(MAX_SCALE, Math.max(MIN_SCALE, scale)).toFixed(2));
59
- const createPdfSearchState = (query = '') => ({
60
- query,
61
- total: 0,
62
- currentIndex: -1,
63
- current: null,
64
- matches: [],
65
- });
66
- const escapeAttribute = (value) => value
67
- .replace(/&/g, '&')
68
- .replace(/"/g, '"')
69
- .replace(/</g, '&lt;')
70
- .replace(/>/g, '&gt;');
71
- const waitForPaint = (view) => new Promise(resolve => {
72
- if (view === null || view === void 0 ? void 0 : view.requestAnimationFrame) {
73
- view.requestAnimationFrame(() => resolve());
74
- return;
75
- }
76
- globalThis.setTimeout(resolve, 0);
77
- });
78
- const resolvePdfWorkerUrl = (options, documentUrl) => {
79
- return resolveFileViewerPdfAssetUrls(options, documentUrl).workerUrl;
80
- };
81
- const buildOutlineItems = (items, prefix = 'outline') => items.map((item, index) => {
82
- const id = `${prefix}-${index}`;
83
- const children = Array.isArray(item.items)
84
- ? buildOutlineItems(item.items, id)
85
- : [];
86
- return {
87
- id,
88
- title: item.title || `目录 ${index + 1}`,
89
- dest: item.dest || null,
90
- items: children,
91
- expanded: index < 4,
92
- };
93
- });
94
- export default async function renderPdf(buffer, target, context) {
95
- var _a, _b;
96
- const documentRef = target.ownerDocument || document;
97
- const targetWindow = documentRef.defaultView || (typeof window !== 'undefined' ? window : null);
98
- if (!targetWindow) {
99
- throw new Error('PDF preview requires a browser window');
100
- }
101
- const options = (_a = context === null || context === void 0 ? void 0 : context.options) === null || _a === void 0 ? void 0 : _a.pdf;
102
- const navigationEnabled = (options === null || options === void 0 ? void 0 : options.navigation) !== false;
103
- const toolbarVisible = (options === null || options === void 0 ? void 0 : options.toolbar) !== false;
104
- const thumbnailsEnabled = (options === null || options === void 0 ? void 0 : options.thumbnails) === true;
105
- const zoomEmitter = createFileViewerZoomChangeEmitter();
106
- let navVisible = (options === null || options === void 0 ? void 0 : options.navigation) === false ? false : (options === null || options === void 0 ? void 0 : options.defaultNavigationVisible) !== false;
107
- let navMode = 'pages';
108
- let loadStatus = 'loading';
109
- let errorMessage = '';
110
- let currentPage = 1;
111
- let pageCount = 0;
112
- let currentScale = 1;
113
- let autoFitWidth = true;
114
- let currentRotation = normalizeRotation((_b = options === null || options === void 0 ? void 0 : options.rotation) !== null && _b !== void 0 ? _b : 0);
115
- let outlineItems = [];
116
- let resizeObserver = null;
117
- let thumbnailObserver = null;
118
- let fitFrame = 0;
119
- let pageDimensionFrame = 0;
120
- let destroyed = false;
121
- let loadVersion = 0;
122
- let pdfSearchState = createPdfSearchState();
123
- let pdfMatchesCount = { current: 0, total: 0 };
124
- let pdfSearchOptions;
125
- let pdfSearchWaiters = [];
126
- const pdfThumbnails = new Map();
127
- const pendingPdfThumbnails = new Set();
128
- const pdfContext = {
129
- viewer: null,
130
- linkService: null,
131
- eventBus: null,
132
- findController: null,
133
- resource: null,
134
- document: null,
135
- search: '',
136
- };
137
- const root = createElement(documentRef, 'div', 'pdf-shell');
138
- root.dataset.viewerSearchProvider = 'pdf';
139
- root.dataset.viewerZoomProvider = 'pdf';
140
- const toolbar = createElement(documentRef, 'div', 'pdf-toolbar');
141
- const navToggleButton = createButton(documentRef, 'pdf-icon-button', '切换导航窗格');
142
- navToggleButton.setAttribute('aria-pressed', String(navVisible));
143
- navToggleButton.append(createElement(documentRef, 'span', 'pdf-panel-icon'));
144
- const pageGroup = createElement(documentRef, 'div', 'pdf-toolbar-group');
145
- const previousPageButton = createButton(documentRef, 'pdf-icon-button', '上一页', '‹');
146
- const pageMeter = createElement(documentRef, 'span', 'pdf-page-meter');
147
- const pageMeterCurrent = createElement(documentRef, 'strong', undefined, '1');
148
- const pageMeterTotal = createElement(documentRef, 'span', undefined, '/ -');
149
- pageMeter.append(pageMeterCurrent, pageMeterTotal);
150
- const nextPageButton = createButton(documentRef, 'pdf-icon-button', '下一页', '›');
151
- pageGroup.append(previousPageButton, pageMeter, nextPageButton);
152
- const zoomGroup = createElement(documentRef, 'div', 'pdf-toolbar-group pdf-toolbar-group--zoom');
153
- const zoomOutButton = createButton(documentRef, 'pdf-icon-button', '缩小', '−');
154
- const scaleButton = createElement(documentRef, 'button', 'pdf-scale-button', '100%');
155
- scaleButton.type = 'button';
156
- scaleButton.title = '适合宽度';
157
- const zoomInButton = createButton(documentRef, 'pdf-icon-button', '放大', '+');
158
- zoomGroup.append(zoomOutButton, scaleButton, zoomInButton);
159
- const rotateGroup = createElement(documentRef, 'div', 'pdf-toolbar-group pdf-toolbar-group--rotate');
160
- const rotateLeftButton = createButton(documentRef, 'pdf-icon-button', '向左旋转', '↺');
161
- const rotationMeter = createElement(documentRef, 'span', 'pdf-rotation-meter', `${currentRotation}°`);
162
- const rotateRightButton = createButton(documentRef, 'pdf-icon-button', '向右旋转', '↻');
163
- rotateGroup.append(rotateLeftButton, rotationMeter, rotateRightButton);
164
- if (navigationEnabled) {
165
- toolbar.append(navToggleButton);
166
- }
167
- toolbar.append(pageGroup, zoomGroup, rotateGroup);
168
- const content = createElement(documentRef, 'div', 'pdf-content');
169
- const navPane = createElement(documentRef, 'aside', 'pdf-nav-pane');
170
- const navHead = createElement(documentRef, 'div', 'pdf-nav-head');
171
- const navTitle = createElement(documentRef, 'span', undefined, '页面导航');
172
- const navCount = createElement(documentRef, 'strong', undefined, '0 页');
173
- navHead.append(navTitle, navCount);
174
- const navTabs = createElement(documentRef, 'div', 'pdf-nav-tabs');
175
- navTabs.setAttribute('role', 'tablist');
176
- navTabs.setAttribute('aria-label', 'PDF 导航类型');
177
- const pagesTab = createButton(documentRef, '', '页面');
178
- const outlineTab = createButton(documentRef, '', '目录');
179
- pagesTab.textContent = '页面';
180
- outlineTab.textContent = '目录';
181
- pagesTab.setAttribute('role', 'tab');
182
- outlineTab.setAttribute('role', 'tab');
183
- navTabs.append(pagesTab, outlineTab);
184
- const navList = createElement(documentRef, 'div');
185
- navPane.append(navHead, navTabs, navList);
186
- const viewport = createElement(documentRef, 'div', 'pdf-viewport');
187
- const container = createElement(documentRef, 'div', 'pdf-wrapper');
188
- container.dataset.viewerScrollContainer = 'true';
189
- const pdfViewerRoot = createElement(documentRef, 'div', 'pdfViewer');
190
- const stateNode = createElement(documentRef, 'div', 'pdf-state', '正在加载 PDF...');
191
- container.append(pdfViewerRoot, stateNode);
192
- viewport.append(container);
193
- content.append(navPane, viewport);
194
- root.append(content);
195
- if (toolbarVisible) {
196
- root.insertBefore(toolbar, content);
197
- }
198
- target.replaceChildren(createStyle(documentRef), root);
199
- const scaleText = () => `${Math.round(currentScale * 100)}%`;
200
- const rotationText = () => `${currentRotation}°`;
201
- const canGoPrevious = () => currentPage > 1;
202
- const canGoNext = () => currentPage < pageCount;
203
- const canZoomOut = () => currentScale > MIN_SCALE;
204
- const canZoomIn = () => currentScale < MAX_SCALE;
205
- const outlineCount = () => {
206
- const countItems = (items) => (items.reduce((total, item) => total + 1 + countItems(item.items), 0));
207
- return countItems(outlineItems);
208
- };
209
- const flattenedOutlineItems = () => {
210
- const result = [];
211
- const visit = (items, depth) => {
212
- items.forEach(item => {
213
- result.push({ item, depth });
214
- if (item.expanded && item.items.length) {
215
- visit(item.items, depth + 1);
216
- }
217
- });
218
- };
219
- visit(outlineItems, 0);
220
- return result;
221
- };
222
- const renderNavList = () => {
223
- navList.replaceChildren();
224
- navList.className = navMode === 'pages' ? 'pdf-page-list' : 'pdf-outline-list';
225
- if (navMode === 'pages') {
226
- thumbnailObserver === null || thumbnailObserver === void 0 ? void 0 : thumbnailObserver.disconnect();
227
- for (let page = 1; page <= pageCount; page += 1) {
228
- const button = createElement(documentRef, 'button', 'pdf-page-button');
229
- button.type = 'button';
230
- button.classList.toggle('pdf-page-button--active', page === currentPage);
231
- button.classList.toggle('pdf-page-button--with-thumbnail', thumbnailsEnabled);
232
- const thumb = createElement(documentRef, 'span', 'pdf-page-thumb');
233
- if (thumbnailsEnabled) {
234
- thumb.classList.add('pdf-page-thumb--thumbnail');
235
- queuePdfThumbnail(page, thumb);
236
- }
237
- else {
238
- thumb.textContent = String(page);
239
- }
240
- button.append(thumb, createElement(documentRef, 'span', 'pdf-page-label', `第 ${page} 页`));
241
- button.addEventListener('click', () => goToPage(page));
242
- navList.append(button);
243
- }
244
- return;
245
- }
246
- const entries = flattenedOutlineItems();
247
- entries.forEach(entry => {
248
- const button = createElement(documentRef, 'button', 'pdf-outline-button');
249
- button.type = 'button';
250
- button.style.setProperty('--outline-depth', String(entry.depth));
251
- const toggle = createElement(documentRef, 'span', 'pdf-outline-toggle');
252
- toggle.classList.toggle('pdf-outline-toggle--open', entry.item.expanded);
253
- toggle.classList.toggle('pdf-outline-toggle--empty', !entry.item.items.length);
254
- toggle.setAttribute('aria-hidden', 'true');
255
- toggle.addEventListener('click', event => {
256
- event.stopPropagation();
257
- toggleOutlineItem(entry.item);
258
- });
259
- button.append(toggle, createElement(documentRef, 'span', 'pdf-outline-title', entry.item.title));
260
- button.addEventListener('click', () => goToOutlineItem(entry.item));
261
- navList.append(button);
262
- });
263
- if (!entries.length) {
264
- navList.append(createElement(documentRef, 'div', 'pdf-outline-empty', '当前 PDF 没有可用目录'));
265
- }
266
- };
267
- const paintPdfThumbnail = (pageNumber, thumb) => {
268
- const imageUrl = pdfThumbnails.get(pageNumber);
269
- thumb.dataset.pdfThumbnailPage = String(pageNumber);
270
- if (!imageUrl) {
271
- thumb.replaceChildren(createElement(documentRef, 'span', undefined, String(pageNumber)));
272
- return false;
273
- }
274
- const image = documentRef.createElement('img');
275
- image.src = imageUrl;
276
- image.alt = `第 ${pageNumber} 页缩略图`;
277
- image.loading = 'lazy';
278
- thumb.replaceChildren(image);
279
- return true;
280
- };
281
- const renderPdfThumbnail = async (pageNumber) => {
282
- var _a, _b;
283
- const pdfDocument = pdfContext.document;
284
- if (!pdfDocument || pdfThumbnails.has(pageNumber) || pendingPdfThumbnails.has(pageNumber)) {
285
- return;
286
- }
287
- pendingPdfThumbnails.add(pageNumber);
288
- try {
289
- const page = await pdfDocument.getPage(pageNumber);
290
- if (destroyed || pdfContext.document !== pdfDocument) {
291
- return;
292
- }
293
- const baseViewport = page.getViewport({
294
- scale: PixelsPerInch.PDF_TO_CSS_UNITS,
295
- rotation: currentRotation,
296
- });
297
- const deviceScale = Math.min(2, Math.max(1, targetWindow.devicePixelRatio || 1));
298
- const thumbnailWidth = 46;
299
- const ratio = Math.min(1, thumbnailWidth / Math.max(baseViewport.width, 1));
300
- const renderViewport = page.getViewport({
301
- scale: PixelsPerInch.PDF_TO_CSS_UNITS * ratio * deviceScale,
302
- rotation: currentRotation,
303
- });
304
- const canvas = documentRef.createElement('canvas');
305
- const canvasContext = canvas.getContext('2d');
306
- if (!canvasContext) {
307
- return;
308
- }
309
- canvas.width = Math.max(1, Math.ceil(renderViewport.width));
310
- canvas.height = Math.max(1, Math.ceil(renderViewport.height));
311
- await page.render({ canvas, canvasContext, viewport: renderViewport }).promise;
312
- if (destroyed || pdfContext.document !== pdfDocument) {
313
- return;
314
- }
315
- pdfThumbnails.set(pageNumber, canvas.toDataURL('image/png'));
316
- canvas.width = 0;
317
- canvas.height = 0;
318
- (_b = (_a = page).cleanup) === null || _b === void 0 ? void 0 : _b.call(_a);
319
- navList
320
- .querySelectorAll(`.pdf-page-thumb--thumbnail[data-pdf-thumbnail-page="${pageNumber}"]`)
321
- .forEach(thumb => paintPdfThumbnail(pageNumber, thumb));
322
- }
323
- catch (error) {
324
- console.warn('[file-viewer] PDF 缩略图渲染失败。', error);
325
- }
326
- finally {
327
- pendingPdfThumbnails.delete(pageNumber);
328
- }
329
- };
330
- const ensureThumbnailObserver = () => {
331
- if (!thumbnailsEnabled || thumbnailObserver || typeof targetWindow.IntersectionObserver !== 'function') {
332
- return;
333
- }
334
- thumbnailObserver = new targetWindow.IntersectionObserver(entries => {
335
- entries.forEach(entry => {
336
- if (!entry.isIntersecting) {
337
- return;
338
- }
339
- const targetElement = entry.target;
340
- const pageNumber = Number(targetElement.dataset.pdfThumbnailPage || '0');
341
- thumbnailObserver === null || thumbnailObserver === void 0 ? void 0 : thumbnailObserver.unobserve(targetElement);
342
- if (pageNumber > 0) {
343
- void renderPdfThumbnail(pageNumber);
344
- }
345
- });
346
- }, {
347
- root: navList,
348
- rootMargin: '96px 0px',
349
- });
350
- };
351
- const queuePdfThumbnail = (pageNumber, thumb) => {
352
- if (paintPdfThumbnail(pageNumber, thumb)) {
353
- return;
354
- }
355
- ensureThumbnailObserver();
356
- if (thumbnailObserver) {
357
- thumbnailObserver.observe(thumb);
358
- return;
359
- }
360
- void renderPdfThumbnail(pageNumber);
361
- };
362
- const syncUi = () => {
363
- root.classList.toggle('pdf-shell--nav-hidden', !navigationEnabled || !navVisible);
364
- root.classList.toggle('pdf-shell--toolbar-hidden', !toolbarVisible);
365
- navToggleButton.classList.toggle('pdf-icon-button--active', navVisible);
366
- navToggleButton.setAttribute('aria-pressed', String(navVisible));
367
- navPane.hidden = !navigationEnabled || !navVisible;
368
- pagesTab.classList.toggle('active', navMode === 'pages');
369
- outlineTab.classList.toggle('active', navMode === 'outline');
370
- pagesTab.setAttribute('aria-selected', navMode === 'pages' ? 'true' : 'false');
371
- outlineTab.setAttribute('aria-selected', navMode === 'outline' ? 'true' : 'false');
372
- navTitle.textContent = navMode === 'pages' ? '页面导航' : '目录导航';
373
- navCount.textContent = navMode === 'pages' ? `${pageCount} 页` : `${outlineCount()} 项`;
374
- pageMeterCurrent.textContent = String(currentPage);
375
- pageMeterTotal.textContent = `/ ${pageCount || '-'}`;
376
- scaleButton.textContent = scaleText();
377
- rotationMeter.textContent = rotationText();
378
- previousPageButton.disabled = !canGoPrevious();
379
- nextPageButton.disabled = !canGoNext();
380
- zoomOutButton.disabled = !canZoomOut();
381
- zoomInButton.disabled = !canZoomIn();
382
- stateNode.hidden = loadStatus === 'ready';
383
- stateNode.classList.toggle('pdf-state--error', loadStatus === 'error');
384
- stateNode.textContent = loadStatus === 'error' ? errorMessage : '正在加载 PDF...';
385
- renderNavList();
386
- };
387
- const writeLegacyCompatiblePageDimensions = () => {
388
- var _a, _b;
389
- const pdfViewer = pdfContext.viewer;
390
- if (!pdfViewer) {
391
- return;
392
- }
393
- const totalPages = pageCount || pdfViewer.pagesCount || 0;
394
- for (let index = 0; index < totalPages; index += 1) {
395
- const pageView = pdfViewer.getPageView(index);
396
- const pageElement = (pageView === null || pageView === void 0 ? void 0 : pageView.div) ||
397
- pdfViewerRoot.querySelector(`.page[data-page-number="${index + 1}"]`);
398
- const width = (_a = pageView === null || pageView === void 0 ? void 0 : pageView.viewport) === null || _a === void 0 ? void 0 : _a.width;
399
- const height = (_b = pageView === null || pageView === void 0 ? void 0 : pageView.viewport) === null || _b === void 0 ? void 0 : _b.height;
400
- if (!pageElement || !Number.isFinite(width) || !Number.isFinite(height)) {
401
- continue;
402
- }
403
- pageElement.style.setProperty('width', `${Math.max(1, Math.round(width || 0))}px`, 'important');
404
- pageElement.style.setProperty('height', `${Math.max(1, Math.round(height || 0))}px`, 'important');
405
- }
406
- };
407
- const scheduleLegacyPageDimensionPatch = () => {
408
- targetWindow.cancelAnimationFrame(pageDimensionFrame);
409
- pageDimensionFrame = targetWindow.requestAnimationFrame(() => {
410
- writeLegacyCompatiblePageDimensions();
411
- targetWindow.requestAnimationFrame(writeLegacyCompatiblePageDimensions);
412
- });
413
- };
414
- const createPdfWorker = () => {
415
- if (!(targetWindow === null || targetWindow === void 0 ? void 0 : targetWindow.Worker)) {
416
- return null;
417
- }
418
- GlobalWorkerOptions.workerSrc = resolvePdfWorkerUrl(options, documentRef.URL || undefined);
419
- try {
420
- return PdfJsWorker.create({ name: 'file-viewer-pdf-worker' });
421
- }
422
- catch (error) {
423
- console.warn('[file-viewer] PDF Worker 无法创建,回退到 PDF.js 默认加载策略。', error);
424
- return null;
425
- }
426
- };
427
- const resolvePdfSearchWaiters = (state) => {
428
- const waiters = pdfSearchWaiters;
429
- pdfSearchWaiters = [];
430
- waiters.forEach(waiter => {
431
- targetWindow.clearTimeout(waiter.timer);
432
- waiter.resolve(state);
433
- });
434
- };
435
- const readPdfMatchesCount = () => {
436
- var _a;
437
- const findController = pdfContext.findController;
438
- if (!findController) {
439
- return { current: 0, total: 0 };
440
- }
441
- const pageMatches = findController.pageMatches || [];
442
- const selected = findController.selected;
443
- const total = pageMatches.reduce((sum, matches) => sum + ((matches === null || matches === void 0 ? void 0 : matches.length) || 0), 0);
444
- let current = 0;
445
- if (selected && selected.pageIdx >= 0 && selected.matchIdx >= 0 && total > 0) {
446
- for (let index = 0; index < selected.pageIdx; index += 1) {
447
- current += ((_a = pageMatches[index]) === null || _a === void 0 ? void 0 : _a.length) || 0;
448
- }
449
- current += selected.matchIdx + 1;
450
- }
451
- return { current, total };
452
- };
453
- const commitPdfSearchState = (matchesCount = readPdfMatchesCount(), query = pdfContext.search, shouldResolve = false) => {
454
- var _a;
455
- pdfMatchesCount = matchesCount;
456
- const current = Math.max(0, matchesCount.current || 0);
457
- const total = Math.max(0, matchesCount.total || 0);
458
- const selected = (_a = pdfContext.findController) === null || _a === void 0 ? void 0 : _a.selected;
459
- const page = selected && selected.pageIdx >= 0 ? selected.pageIdx + 1 : undefined;
460
- pdfSearchState = {
461
- query,
462
- total,
463
- currentIndex: current > 0 ? current - 1 : -1,
464
- current: current > 0
465
- ? {
466
- id: `pdf-search-match-${current}`,
467
- index: current - 1,
468
- text: query,
469
- anchor: null,
470
- page,
471
- }
472
- : null,
473
- matches: [],
474
- };
475
- if (shouldResolve) {
476
- resolvePdfSearchWaiters(pdfSearchState);
477
- }
478
- return pdfSearchState;
479
- };
480
- const waitForPdfSearchState = (query) => new Promise(resolve => {
481
- const timer = targetWindow.setTimeout(() => {
482
- const waiterIndex = pdfSearchWaiters.findIndex(waiter => waiter.resolve === resolve);
483
- if (waiterIndex >= 0) {
484
- pdfSearchWaiters.splice(waiterIndex, 1);
485
- }
486
- resolve(commitPdfSearchState(readPdfMatchesCount(), query));
487
- }, 1200);
488
- pdfSearchWaiters.push({ resolve, timer });
489
- });
490
- const handlePdfFindMatchesCount = (event) => {
491
- if (event.matchesCount) {
492
- commitPdfSearchState(event.matchesCount, pdfContext.search);
493
- }
494
- };
495
- const handlePdfFindControlState = (event) => {
496
- var _a;
497
- const query = typeof event.rawQuery === 'string' ? event.rawQuery : pdfContext.search;
498
- pdfContext.search = query;
499
- const matchesCount = ((_a = event.matchesCount) === null || _a === void 0 ? void 0 : _a.total) ? event.matchesCount : readPdfMatchesCount();
500
- const shouldResolve = event.state !== 3 && (matchesCount.total > 0 || event.state === 1);
501
- commitPdfSearchState(matchesCount, query, shouldResolve);
502
- };
503
- const clampHorizontalScroll = (scrollLeft) => {
504
- const maxScrollLeft = Math.max(0, container.scrollWidth - container.clientWidth);
505
- return Math.min(Math.max(0, scrollLeft), maxScrollLeft);
506
- };
507
- const restoreHorizontalScroll = (scrollLeft) => {
508
- container.scrollLeft = clampHorizontalScroll(scrollLeft);
509
- };
510
- const stabilizeHorizontalScroll = (scrollLeft) => {
511
- restoreHorizontalScroll(scrollLeft);
512
- void waitForPaint(targetWindow).then(() => restoreHorizontalScroll(scrollLeft));
513
- targetWindow.requestAnimationFrame(() => {
514
- restoreHorizontalScroll(scrollLeft);
515
- targetWindow.requestAnimationFrame(() => restoreHorizontalScroll(scrollLeft));
516
- });
517
- targetWindow.setTimeout(() => restoreHorizontalScroll(scrollLeft), 120);
518
- };
519
- const runPdfFind = async (query, searchOptionsInput, type, findPrevious = false) => {
520
- if (!pdfContext.eventBus) {
521
- return commitPdfSearchState({ current: 0, total: 0 }, query);
522
- }
523
- pdfContext.search = query;
524
- pdfSearchOptions = searchOptionsInput || pdfSearchOptions;
525
- const searchOptions = searchOptionsInput || pdfSearchOptions;
526
- const previousScrollLeft = clampHorizontalScroll(container.scrollLeft || 0);
527
- pdfContext.eventBus.dispatch('find', {
528
- source: root,
529
- type,
530
- query,
531
- phraseSearch: true,
532
- caseSensitive: !!(searchOptions === null || searchOptions === void 0 ? void 0 : searchOptions.caseSensitive),
533
- entireWord: !!(searchOptions === null || searchOptions === void 0 ? void 0 : searchOptions.wholeWord),
534
- highlightAll: true,
535
- findPrevious,
536
- matchDiacritics: false,
537
- });
538
- try {
539
- return await waitForPdfSearchState(query);
540
- }
541
- finally {
542
- stabilizeHorizontalScroll(previousScrollLeft);
543
- }
544
- };
545
- const clearPdfFind = () => {
546
- var _a;
547
- pdfContext.search = '';
548
- pdfSearchOptions = undefined;
549
- pdfMatchesCount = { current: 0, total: 0 };
550
- (_a = pdfContext.eventBus) === null || _a === void 0 ? void 0 : _a.dispatch('findbarclose', {
551
- source: root,
552
- });
553
- return commitPdfSearchState(pdfMatchesCount, '', true);
554
- };
555
- const getPdfZoomState = () => ({
556
- scale: currentScale,
557
- label: scaleText(),
558
- canZoomIn: !!pdfContext.viewer && canZoomIn(),
559
- canZoomOut: !!pdfContext.viewer && canZoomOut(),
560
- canReset: !!pdfContext.viewer,
561
- minScale: MIN_SCALE,
562
- maxScale: MAX_SCALE,
563
- });
564
- const setScale = (scale) => {
565
- if (!pdfContext.viewer) {
566
- return;
567
- }
568
- const normalizedScale = clampScale(scale);
569
- pdfContext.viewer.currentScale = normalizedScale;
570
- currentScale = normalizedScale;
571
- scheduleLegacyPageDimensionPatch();
572
- zoomEmitter.emit();
573
- syncUi();
574
- };
575
- const getPageWidthAtScaleOne = (pdfViewer) => {
576
- var _a;
577
- const pageView = pdfViewer.getPageView(0);
578
- const pdfPage = pageView === null || pageView === void 0 ? void 0 : pageView.pdfPage;
579
- if (pdfPage) {
580
- return pdfPage.getViewport({
581
- scale: PixelsPerInch.PDF_TO_CSS_UNITS,
582
- rotation: currentRotation,
583
- }).width;
584
- }
585
- const viewportWidth = (_a = pageView === null || pageView === void 0 ? void 0 : pageView.viewport) === null || _a === void 0 ? void 0 : _a.width;
586
- if (viewportWidth && currentScale) {
587
- return viewportWidth / currentScale;
588
- }
589
- return 0;
590
- };
591
- const getFitWidthScale = (pdfViewer) => {
592
- const pageWidth = getPageWidthAtScaleOne(pdfViewer);
593
- const containerWidth = container.clientWidth || targetWindow.innerWidth;
594
- const availableWidth = Math.max(containerWidth - FIT_HORIZONTAL_PADDING - PAGE_BORDER_WIDTH, 96);
595
- return pageWidth ? clampScale(availableWidth / pageWidth) : 1;
596
- };
597
- const fitToWidth = () => {
598
- if (!pdfContext.viewer) {
599
- return;
600
- }
601
- autoFitWidth = true;
602
- setScale(getFitWidthScale(pdfContext.viewer));
603
- void waitForPaint(targetWindow).then(() => {
604
- var _a;
605
- (_a = pdfContext.viewer) === null || _a === void 0 ? void 0 : _a.update();
606
- });
607
- };
608
- const scheduleFitToWidth = () => {
609
- if (!autoFitWidth || !pdfContext.viewer) {
610
- return;
611
- }
612
- targetWindow.cancelAnimationFrame(fitFrame);
613
- fitFrame = targetWindow.requestAnimationFrame(() => fitToWidth());
614
- };
615
- const zoomIn = () => {
616
- autoFitWidth = false;
617
- setScale(currentScale + SCALE_STEP);
618
- };
619
- const zoomOut = () => {
620
- autoFitWidth = false;
621
- setScale(currentScale - SCALE_STEP);
622
- };
623
- const applyRotation = (rotation) => {
624
- const normalized = normalizeRotation(rotation);
625
- currentRotation = normalized;
626
- pdfThumbnails.clear();
627
- pendingPdfThumbnails.clear();
628
- if (!pdfContext.viewer) {
629
- syncUi();
630
- return;
631
- }
632
- pdfContext.viewer.pagesRotation = normalized;
633
- void waitForPaint(targetWindow).then(() => {
634
- var _a;
635
- if (autoFitWidth) {
636
- fitToWidth();
637
- return;
638
- }
639
- (_a = pdfContext.viewer) === null || _a === void 0 ? void 0 : _a.update();
640
- scheduleLegacyPageDimensionPatch();
641
- syncUi();
642
- });
643
- };
644
- const runWithStableHorizontalScroll = (action) => {
645
- const previousScrollLeft = clampHorizontalScroll(container.scrollLeft || 0);
646
- const result = action();
647
- stabilizeHorizontalScroll(previousScrollLeft);
648
- if (result && typeof result.then === 'function') {
649
- void Promise.resolve(result).finally(() => stabilizeHorizontalScroll(previousScrollLeft));
650
- }
651
- };
652
- function goToPage(pageNumber) {
653
- if (!pdfContext.viewer || !pageCount) {
654
- return;
655
- }
656
- const nextPage = Math.min(pageCount, Math.max(1, pageNumber));
657
- runWithStableHorizontalScroll(() => {
658
- pdfContext.viewer.currentPageNumber = nextPage;
659
- currentPage = nextPage;
660
- syncUi();
661
- });
662
- }
663
- const toggleNav = () => {
664
- if (!navigationEnabled) {
665
- return;
666
- }
667
- navVisible = !navVisible;
668
- syncUi();
669
- void waitForPaint(targetWindow).then(() => {
670
- var _a;
671
- if (autoFitWidth) {
672
- fitToWidth();
673
- return;
674
- }
675
- (_a = pdfContext.viewer) === null || _a === void 0 ? void 0 : _a.update();
676
- });
677
- };
678
- const setNavMode = (mode) => {
679
- navMode = mode;
680
- syncUi();
681
- };
682
- const toggleOutlineItem = (item) => {
683
- if (!item.items.length) {
684
- return;
685
- }
686
- item.expanded = !item.expanded;
687
- syncUi();
688
- };
689
- const goToOutlineItem = (item) => {
690
- if (!item.dest || !pdfContext.linkService) {
691
- return;
692
- }
693
- runWithStableHorizontalScroll(() => pdfContext.linkService.goToDestination(item.dest));
694
- };
695
- const destroyPdfResource = async (resource) => {
696
- var _a;
697
- if (!resource) {
698
- return;
699
- }
700
- try {
701
- await resource.loadingTask.destroy();
702
- }
703
- catch (error) {
704
- console.warn('PDF 加载任务销毁失败', error);
705
- }
706
- finally {
707
- (_a = resource.worker) === null || _a === void 0 ? void 0 : _a.destroy();
708
- }
709
- };
710
- const loadOutline = async (pdfDocument) => {
711
- try {
712
- const outline = await pdfDocument.getOutline();
713
- if (destroyed || pdfContext.document !== pdfDocument) {
714
- return;
715
- }
716
- outlineItems = Array.isArray(outline)
717
- ? buildOutlineItems(outline)
718
- : [];
719
- syncUi();
720
- }
721
- catch (error) {
722
- console.warn('PDF 大纲读取失败', error);
723
- outlineItems = [];
724
- syncUi();
725
- }
726
- };
727
- const getPdfExportRatio = (width, height, mode) => {
728
- const preferredRatio = mode === 'print' ? 1.75 : 1.5;
729
- const maxRatio = Math.sqrt(PDF_EXPORT_MAX_PAGE_PIXELS / Math.max(width * height, 1));
730
- return Math.max(0.75, Math.min(preferredRatio, maxRatio));
731
- };
732
- const getPdfPrintPageSize = async (pageNumber = 1) => {
733
- var _a, _b;
734
- const pdfDocument = pdfContext.document;
735
- if (!pdfDocument) {
736
- throw new Error('PDF 尚未加载完成,请稍后再试');
737
- }
738
- const page = await pdfDocument.getPage(Math.min(Math.max(pageNumber, 1), pdfDocument.numPages));
739
- const viewport = page.getViewport({
740
- scale: PixelsPerInch.PDF_TO_CSS_UNITS,
741
- rotation: currentRotation,
742
- });
743
- (_b = (_a = page).cleanup) === null || _b === void 0 ? void 0 : _b.call(_a);
744
- return {
745
- width: Math.ceil(viewport.width),
746
- height: Math.ceil(viewport.height),
747
- };
748
- };
749
- const buildPdfPrintStyle = async () => {
750
- const size = await getPdfPrintPageSize();
751
- return buildPrintPageStyle({
752
- selector: '.viewer-export-content .pdf-export-page',
753
- width: size.width,
754
- height: size.height,
755
- });
756
- };
757
- const renderPdfPagesForExport = async (exportOptions) => {
758
- var _a, _b;
759
- const pdfDocument = pdfContext.document;
760
- if (!pdfDocument) {
761
- throw new Error('PDF 尚未加载完成,请稍后再试');
762
- }
763
- const pagesHtml = [];
764
- for (let pageNumber = 1; pageNumber <= pdfDocument.numPages; pageNumber += 1) {
765
- if (destroyed) {
766
- throw new Error('PDF 已卸载,无法继续打印');
767
- }
768
- const page = await pdfDocument.getPage(pageNumber);
769
- const baseViewport = page.getViewport({
770
- scale: PixelsPerInch.PDF_TO_CSS_UNITS,
771
- rotation: currentRotation,
772
- });
773
- const pageWidth = Math.ceil(baseViewport.width);
774
- const pageHeight = Math.ceil(baseViewport.height);
775
- const exportRatio = getPdfExportRatio(baseViewport.width, baseViewport.height, exportOptions.mode);
776
- const renderViewport = page.getViewport({
777
- scale: PixelsPerInch.PDF_TO_CSS_UNITS * exportRatio,
778
- rotation: currentRotation,
779
- });
780
- const canvas = documentRef.createElement('canvas');
781
- const canvasContext = canvas.getContext('2d');
782
- if (!canvasContext) {
783
- throw new Error('当前浏览器无法创建 PDF 打印画布');
784
- }
785
- canvas.width = Math.ceil(renderViewport.width);
786
- canvas.height = Math.ceil(renderViewport.height);
787
- await page.render({ canvas, canvasContext, viewport: renderViewport }).promise;
788
- const pageTitle = `${exportOptions.title} - 第 ${pageNumber} 页`;
789
- const pageStyle = [
790
- `--viewer-print-page-width:${formatCssPixels(pageWidth)}`,
791
- `--viewer-print-page-height:${formatCssPixels(pageHeight)}`,
792
- `width:${formatCssPixels(pageWidth)}`,
793
- `height:${formatCssPixels(pageHeight)}`,
794
- ].join(';');
795
- pagesHtml.push(`<section class="pdf-export-page viewer-print-page" style="${pageStyle}" aria-label="${escapeAttribute(pageTitle)}"><img src="${canvas.toDataURL('image/png')}" alt="${escapeAttribute(pageTitle)}" /></section>`);
796
- canvas.width = 0;
797
- canvas.height = 0;
798
- (_b = (_a = page).cleanup) === null || _b === void 0 ? void 0 : _b.call(_a);
799
- }
800
- return `<div class="pdf-export-document">${pagesHtml.join('')}</div>`;
801
- };
802
- const loadFile = async () => {
803
- var _a, _b;
804
- const requestVersion = ++loadVersion;
805
- loadStatus = 'loading';
806
- errorMessage = '';
807
- pdfContext.document = null;
808
- outlineItems = [];
809
- pdfThumbnails.clear();
810
- pendingPdfThumbnails.clear();
811
- thumbnailObserver === null || thumbnailObserver === void 0 ? void 0 : thumbnailObserver.disconnect();
812
- (_a = context === null || context === void 0 ? void 0 : context.registerExportAdapter) === null || _a === void 0 ? void 0 : _a.call(context, null);
813
- syncUi();
814
- let resource = null;
815
- try {
816
- if (destroyed || requestVersion !== loadVersion) {
817
- return;
818
- }
819
- const eventBus = new EventBus();
820
- const pdfLinkService = new PDFLinkService({ eventBus });
821
- const pdfFindController = new PDFFindController({
822
- eventBus,
823
- linkService: pdfLinkService,
824
- updateMatchesCountOnProgress: true,
825
- });
826
- const pdfViewer = new PDFViewer({
827
- container,
828
- eventBus,
829
- linkService: pdfLinkService,
830
- findController: pdfFindController,
831
- l10n: new GenericL10n('zh-CN'),
832
- enableAutoLinking: false,
833
- });
834
- pdfContext.viewer = pdfViewer;
835
- pdfContext.linkService = pdfLinkService;
836
- pdfContext.eventBus = eventBus;
837
- pdfContext.findController = pdfFindController;
838
- pdfLinkService.setViewer(pdfViewer);
839
- eventBus.on('updatefindmatchescount', handlePdfFindMatchesCount);
840
- eventBus.on('updatefindcontrolstate', handlePdfFindControlState);
841
- eventBus.on('pagesinit', () => {
842
- var _a;
843
- applyRotation(currentRotation);
844
- fitToWidth();
845
- scheduleLegacyPageDimensionPatch();
846
- loadStatus = 'ready';
847
- syncUi();
848
- (_a = context === null || context === void 0 ? void 0 : context.onProgressiveRender) === null || _a === void 0 ? void 0 : _a.call(context);
849
- if (pdfContext.search) {
850
- eventBus.dispatch('find', { type: '', query: pdfContext.search });
851
- }
852
- });
853
- eventBus.on('pagechanging', ({ pageNumber }) => {
854
- currentPage = pageNumber;
855
- syncUi();
856
- });
857
- eventBus.on('scalechanging', ({ scale }) => {
858
- currentScale = clampScale(scale);
859
- scheduleLegacyPageDimensionPatch();
860
- zoomEmitter.emit();
861
- syncUi();
862
- });
863
- eventBus.on('pagerendered', scheduleLegacyPageDimensionPatch);
864
- if (!(context === null || context === void 0 ? void 0 : context.streamUrl) && !buffer.byteLength) {
865
- throw new Error('PDF 缺少可读取的数据源');
866
- }
867
- const worker = createPdfWorker();
868
- const pdfAssets = resolveFileViewerPdfAssetUrls(options, documentRef.URL || documentRef.baseURI);
869
- const source = (context === null || context === void 0 ? void 0 : context.streamUrl)
870
- ? {
871
- url: context.streamUrl,
872
- rangeChunkSize: (options === null || options === void 0 ? void 0 : options.rangeChunkSize) || DEFAULT_PDF_RANGE_CHUNK_SIZE,
873
- withCredentials: (options === null || options === void 0 ? void 0 : options.withCredentials) === true,
874
- }
875
- : {
876
- data: buffer,
877
- };
878
- const loadingTask = getDocument({
879
- ...source,
880
- worker: worker || undefined,
881
- cMapUrl: pdfAssets.cMapUrl,
882
- wasmUrl: pdfAssets.wasmUrl,
883
- standardFontDataUrl: pdfAssets.standardFontDataUrl,
884
- useWorkerFetch: true,
885
- cMapPacked: true,
886
- enableXfa: true,
887
- });
888
- resource = { loadingTask, worker };
889
- pdfContext.resource = resource;
890
- const pdfDocument = await loadingTask.promise;
891
- if (destroyed || requestVersion !== loadVersion || pdfContext.resource !== resource) {
892
- if (pdfContext.resource === resource) {
893
- pdfContext.resource = null;
894
- await destroyPdfResource(resource);
895
- }
896
- return;
897
- }
898
- pageCount = pdfDocument.numPages;
899
- currentPage = 1;
900
- pdfContext.document = pdfDocument;
901
- (_b = context === null || context === void 0 ? void 0 : context.registerExportAdapter) === null || _b === void 0 ? void 0 : _b.call(context, {
902
- includeDocumentStyles: false,
903
- printStyle: buildPdfPrintStyle,
904
- toHtml: renderPdfPagesForExport,
905
- });
906
- void loadOutline(pdfDocument);
907
- pdfViewer.setDocument(pdfDocument);
908
- pdfLinkService.setDocument(pdfDocument, null);
909
- syncUi();
910
- }
911
- catch (error) {
912
- if (pdfContext.resource === resource) {
913
- pdfContext.resource = null;
914
- void destroyPdfResource(resource);
915
- }
916
- if (destroyed || requestVersion !== loadVersion) {
917
- return;
918
- }
919
- loadStatus = 'error';
920
- errorMessage = error instanceof Error ? error.message : 'PDF 加载失败';
921
- syncUi();
922
- }
923
- };
924
- registerFileViewerSearchProvider(root, {
925
- search: (query, searchOptions) => runPdfFind(query, searchOptions, '', false),
926
- next: () => pdfContext.search
927
- ? runPdfFind(pdfContext.search, undefined, 'again', false)
928
- : pdfSearchState,
929
- previous: () => pdfContext.search
930
- ? runPdfFind(pdfContext.search, undefined, 'again', true)
931
- : pdfSearchState,
932
- clear: clearPdfFind,
933
- getState: () => pdfSearchState,
934
- });
935
- registerFileViewerZoomProvider(root, {
936
- zoomIn: () => {
937
- zoomIn();
938
- return getPdfZoomState();
939
- },
940
- zoomOut: () => {
941
- zoomOut();
942
- return getPdfZoomState();
943
- },
944
- resetZoom: () => {
945
- fitToWidth();
946
- return getPdfZoomState();
947
- },
948
- setZoom: scale => {
949
- autoFitWidth = false;
950
- setScale(scale);
951
- return getPdfZoomState();
952
- },
953
- getState: getPdfZoomState,
954
- subscribe: zoomEmitter.subscribe,
955
- });
956
- navToggleButton.addEventListener('click', toggleNav);
957
- previousPageButton.addEventListener('click', () => goToPage(currentPage - 1));
958
- nextPageButton.addEventListener('click', () => goToPage(currentPage + 1));
959
- zoomOutButton.addEventListener('click', zoomOut);
960
- zoomInButton.addEventListener('click', zoomIn);
961
- scaleButton.addEventListener('click', fitToWidth);
962
- rotateLeftButton.addEventListener('click', () => applyRotation(currentRotation - 90));
963
- rotateRightButton.addEventListener('click', () => applyRotation(currentRotation + 90));
964
- pagesTab.addEventListener('click', () => setNavMode('pages'));
965
- outlineTab.addEventListener('click', () => setNavMode('outline'));
966
- if (targetWindow.ResizeObserver) {
967
- resizeObserver = new targetWindow.ResizeObserver(() => scheduleFitToWidth());
968
- resizeObserver.observe(container);
969
- }
970
- syncUi();
971
- void loadFile();
972
- return {
973
- $el: root,
974
- unmount() {
975
- var _a;
976
- destroyed = true;
977
- loadVersion += 1;
978
- targetWindow.cancelAnimationFrame(fitFrame);
979
- targetWindow.cancelAnimationFrame(pageDimensionFrame);
980
- thumbnailObserver === null || thumbnailObserver === void 0 ? void 0 : thumbnailObserver.disconnect();
981
- thumbnailObserver = null;
982
- resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect();
983
- resizeObserver = null;
984
- unregisterFileViewerSearchProvider(root);
985
- unregisterFileViewerZoomProvider(root);
986
- outlineItems = [];
987
- (_a = context === null || context === void 0 ? void 0 : context.registerExportAdapter) === null || _a === void 0 ? void 0 : _a.call(context, null);
988
- const resource = pdfContext.resource;
989
- pdfContext.viewer = null;
990
- pdfContext.linkService = null;
991
- pdfContext.eventBus = null;
992
- pdfContext.findController = null;
993
- pdfContext.document = null;
994
- pdfContext.resource = null;
995
- pdfSearchWaiters.forEach(waiter => targetWindow.clearTimeout(waiter.timer));
996
- pdfSearchWaiters = [];
997
- void destroyPdfResource(resource);
998
- target.replaceChildren();
999
- },
1000
- };
1001
- }