@file-viewer/renderer-pdf 2.1.1 → 2.1.3

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 (2) hide show
  1. package/dist/pdf.js +65 -37
  2. package/package.json +2 -2
package/dist/pdf.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { getDocument, GlobalWorkerOptions, PDFWorker as PdfJsWorker, PixelsPerInch, } from 'pdfjs-dist/legacy/build/pdf.mjs';
2
2
  import { EventBus, GenericL10n, PDFFindController, PDFLinkService, PDFViewer, } from 'pdfjs-dist/legacy/web/pdf_viewer.mjs';
3
- import { registerFileViewerSearchProvider, registerFileViewerZoomProvider, unregisterFileViewerSearchProvider, unregisterFileViewerZoomProvider, createFileViewerZoomChangeEmitter, buildPrintPageStyle, formatCssPixels, DEFAULT_PDF_RANGE_CHUNK_SIZE, } from '@file-viewer/core';
3
+ import { registerFileViewerSearchProvider, registerFileViewerZoomProvider, unregisterFileViewerSearchProvider, unregisterFileViewerZoomProvider, createFileViewerZoomChangeEmitter, createFileViewerTranslator, buildPrintPageStyle, formatCssPixels, DEFAULT_PDF_RANGE_CHUNK_SIZE, resolveFileViewerLocale, } from '@file-viewer/core';
4
4
  import { DEFAULT_FILE_VIEWER_PDF_WORKER_PATH, resolveFileViewerPdfAssetUrls, } from '@file-viewer/core/assets';
5
5
  import { pdfViewerStyle } from './pdfStyles.js';
6
6
  export const DEFAULT_FILE_VIEWER_PDF_WORKER_URL = DEFAULT_FILE_VIEWER_PDF_WORKER_PATH;
@@ -23,6 +23,20 @@ const createStyle = (documentRef) => {
23
23
  .pdf-page-thumb--thumbnail{width:46px;height:60px;overflow:hidden;background:#fff}
24
24
  .pdf-page-thumb--thumbnail img{display:block;width:100%;height:100%;object-fit:contain}
25
25
  .pdf-page-thumb--thumbnail span{display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%}
26
+ @media (max-width:720px){
27
+ .pdf-toolbar{flex-wrap:nowrap;gap:6px;min-height:44px;padding:5px 6px;overflow-x:auto;overflow-y:hidden;scrollbar-width:none}
28
+ .pdf-toolbar::-webkit-scrollbar{display:none}
29
+ .pdf-toolbar-group{flex:0 0 auto;height:32px;gap:4px;padding:0 4px;border-radius:7px}
30
+ .pdf-toolbar-group--zoom{margin-left:0}
31
+ .pdf-icon-button,.pdf-scale-button{height:26px;border-radius:5px}
32
+ .pdf-icon-button{width:26px;font-size:16px}
33
+ .pdf-scale-button{width:54px;font-size:12px}
34
+ .pdf-page-meter{min-width:52px;font-size:12px}
35
+ .pdf-page-meter strong{font-size:13px}
36
+ .pdf-rotation-meter{min-width:30px;font-size:12px}
37
+ .pdf-nav-pane{width:min(82vw,280px);max-width:calc(100% - 52px)}
38
+ .pdfViewer{padding:12px 8px 22px}
39
+ }
26
40
  `;
27
41
  return style;
28
42
  };
@@ -75,14 +89,14 @@ const waitForPaint = (view) => new Promise(resolve => {
75
89
  const resolvePdfWorkerUrl = (options, documentUrl) => {
76
90
  return resolveFileViewerPdfAssetUrls(options, documentUrl).workerUrl;
77
91
  };
78
- const buildOutlineItems = (items, prefix = 'outline') => items.map((item, index) => {
92
+ const buildOutlineItems = (items, prefix = 'outline', getFallbackTitle = index => `Outline ${index + 1}`) => items.map((item, index) => {
79
93
  const id = `${prefix}-${index}`;
80
94
  const children = Array.isArray(item.items)
81
- ? buildOutlineItems(item.items, id)
95
+ ? buildOutlineItems(item.items, id, getFallbackTitle)
82
96
  : [];
83
97
  return {
84
98
  id,
85
- title: item.title || `目录 ${index + 1}`,
99
+ title: item.title || getFallbackTitle(index),
86
100
  dest: item.dest || null,
87
101
  items: children,
88
102
  expanded: index < 4,
@@ -92,15 +106,25 @@ export default async function renderPdf(buffer, target, context) {
92
106
  var _a, _b;
93
107
  const documentRef = target.ownerDocument || document;
94
108
  const targetWindow = documentRef.defaultView || (typeof window !== 'undefined' ? window : null);
109
+ const t = createFileViewerTranslator(context === null || context === void 0 ? void 0 : context.options);
110
+ const resolvedLocale = resolveFileViewerLocale(context === null || context === void 0 ? void 0 : context.options);
95
111
  if (!targetWindow) {
96
- throw new Error('PDF preview requires a browser window');
112
+ throw new Error(t('pdf.error.browserWindow'));
97
113
  }
98
114
  const options = (_a = context === null || context === void 0 ? void 0 : context.options) === null || _a === void 0 ? void 0 : _a.pdf;
99
115
  const navigationEnabled = (options === null || options === void 0 ? void 0 : options.navigation) !== false;
100
116
  const toolbarVisible = (options === null || options === void 0 ? void 0 : options.toolbar) !== false;
101
117
  const thumbnailsEnabled = (options === null || options === void 0 ? void 0 : options.thumbnails) === true;
102
118
  const zoomEmitter = createFileViewerZoomChangeEmitter();
103
- let navVisible = (options === null || options === void 0 ? void 0 : options.navigation) === false ? false : (options === null || options === void 0 ? void 0 : options.defaultNavigationVisible) !== false;
119
+ const isCompactViewport = () => {
120
+ const width = target.clientWidth || targetWindow.innerWidth || 0;
121
+ return width > 0 && width <= 720;
122
+ };
123
+ let navVisible = (options === null || options === void 0 ? void 0 : options.navigation) === false
124
+ ? false
125
+ : typeof (options === null || options === void 0 ? void 0 : options.defaultNavigationVisible) === 'boolean'
126
+ ? options.defaultNavigationVisible
127
+ : !isCompactViewport();
104
128
  let navMode = 'pages';
105
129
  let loadStatus = 'loading';
106
130
  let errorMessage = '';
@@ -135,28 +159,29 @@ export default async function renderPdf(buffer, target, context) {
135
159
  root.dataset.viewerSearchProvider = 'pdf';
136
160
  root.dataset.viewerZoomProvider = 'pdf';
137
161
  const toolbar = createElement(documentRef, 'div', 'pdf-toolbar');
138
- const navToggleButton = createButton(documentRef, 'pdf-icon-button', '切换导航窗格');
162
+ const navToggleButton = createButton(documentRef, 'pdf-icon-button', t('pdf.toolbar.toggleNavigation'));
139
163
  navToggleButton.setAttribute('aria-pressed', String(navVisible));
140
164
  navToggleButton.append(createElement(documentRef, 'span', 'pdf-panel-icon'));
141
165
  const pageGroup = createElement(documentRef, 'div', 'pdf-toolbar-group');
142
- const previousPageButton = createButton(documentRef, 'pdf-icon-button', '上一页', '‹');
166
+ const previousPageButton = createButton(documentRef, 'pdf-icon-button', t('pdf.toolbar.previousPage'), '‹');
143
167
  const pageMeter = createElement(documentRef, 'span', 'pdf-page-meter');
144
168
  const pageMeterCurrent = createElement(documentRef, 'strong', undefined, '1');
145
169
  const pageMeterTotal = createElement(documentRef, 'span', undefined, '/ -');
146
170
  pageMeter.append(pageMeterCurrent, pageMeterTotal);
147
- const nextPageButton = createButton(documentRef, 'pdf-icon-button', '下一页', '›');
171
+ const nextPageButton = createButton(documentRef, 'pdf-icon-button', t('pdf.toolbar.nextPage'), '›');
148
172
  pageGroup.append(previousPageButton, pageMeter, nextPageButton);
149
173
  const zoomGroup = createElement(documentRef, 'div', 'pdf-toolbar-group pdf-toolbar-group--zoom');
150
- const zoomOutButton = createButton(documentRef, 'pdf-icon-button', '缩小', '−');
174
+ const zoomOutButton = createButton(documentRef, 'pdf-icon-button', t('pdf.toolbar.zoomOut'), '−');
151
175
  const scaleButton = createElement(documentRef, 'button', 'pdf-scale-button', '100%');
152
176
  scaleButton.type = 'button';
153
- scaleButton.title = '适合宽度';
154
- const zoomInButton = createButton(documentRef, 'pdf-icon-button', '放大', '+');
177
+ scaleButton.title = t('pdf.toolbar.fitWidth');
178
+ scaleButton.setAttribute('aria-label', t('pdf.toolbar.fitWidth'));
179
+ const zoomInButton = createButton(documentRef, 'pdf-icon-button', t('pdf.toolbar.zoomIn'), '+');
155
180
  zoomGroup.append(zoomOutButton, scaleButton, zoomInButton);
156
181
  const rotateGroup = createElement(documentRef, 'div', 'pdf-toolbar-group pdf-toolbar-group--rotate');
157
- const rotateLeftButton = createButton(documentRef, 'pdf-icon-button', '向左旋转', '↺');
182
+ const rotateLeftButton = createButton(documentRef, 'pdf-icon-button', t('pdf.toolbar.rotateLeft'), '↺');
158
183
  const rotationMeter = createElement(documentRef, 'span', 'pdf-rotation-meter', `${currentRotation}°`);
159
- const rotateRightButton = createButton(documentRef, 'pdf-icon-button', '向右旋转', '↻');
184
+ const rotateRightButton = createButton(documentRef, 'pdf-icon-button', t('pdf.toolbar.rotateRight'), '↻');
160
185
  rotateGroup.append(rotateLeftButton, rotationMeter, rotateRightButton);
161
186
  if (navigationEnabled) {
162
187
  toolbar.append(navToggleButton);
@@ -165,16 +190,16 @@ export default async function renderPdf(buffer, target, context) {
165
190
  const content = createElement(documentRef, 'div', 'pdf-content');
166
191
  const navPane = createElement(documentRef, 'aside', 'pdf-nav-pane');
167
192
  const navHead = createElement(documentRef, 'div', 'pdf-nav-head');
168
- const navTitle = createElement(documentRef, 'span', undefined, '页面导航');
169
- const navCount = createElement(documentRef, 'strong', undefined, '0 页');
193
+ const navTitle = createElement(documentRef, 'span', undefined, t('pdf.nav.pagesTitle'));
194
+ const navCount = createElement(documentRef, 'strong', undefined, t('pdf.nav.pageCount', { count: 0 }));
170
195
  navHead.append(navTitle, navCount);
171
196
  const navTabs = createElement(documentRef, 'div', 'pdf-nav-tabs');
172
197
  navTabs.setAttribute('role', 'tablist');
173
- navTabs.setAttribute('aria-label', 'PDF 导航类型');
174
- const pagesTab = createButton(documentRef, '', '页面');
175
- const outlineTab = createButton(documentRef, '', '目录');
176
- pagesTab.textContent = '页面';
177
- outlineTab.textContent = '目录';
198
+ navTabs.setAttribute('aria-label', t('pdf.nav.typeLabel'));
199
+ const pagesTab = createButton(documentRef, '', t('pdf.nav.pagesTab'));
200
+ const outlineTab = createButton(documentRef, '', t('pdf.nav.outlineTab'));
201
+ pagesTab.textContent = t('pdf.nav.pagesTab');
202
+ outlineTab.textContent = t('pdf.nav.outlineTab');
178
203
  pagesTab.setAttribute('role', 'tab');
179
204
  outlineTab.setAttribute('role', 'tab');
180
205
  navTabs.append(pagesTab, outlineTab);
@@ -184,7 +209,7 @@ export default async function renderPdf(buffer, target, context) {
184
209
  const container = createElement(documentRef, 'div', 'pdf-wrapper');
185
210
  container.dataset.viewerScrollContainer = 'true';
186
211
  const pdfViewerRoot = createElement(documentRef, 'div', 'pdfViewer');
187
- const stateNode = createElement(documentRef, 'div', 'pdf-state', '正在加载 PDF...');
212
+ const stateNode = createElement(documentRef, 'div', 'pdf-state', t('pdf.state.loading'));
188
213
  container.append(pdfViewerRoot, stateNode);
189
214
  viewport.append(container);
190
215
  content.append(navPane, viewport);
@@ -234,7 +259,7 @@ export default async function renderPdf(buffer, target, context) {
234
259
  else {
235
260
  thumb.textContent = String(page);
236
261
  }
237
- button.append(thumb, createElement(documentRef, 'span', 'pdf-page-label', `第 ${page} 页`));
262
+ button.append(thumb, createElement(documentRef, 'span', 'pdf-page-label', t('pdf.nav.pageLabel', { page })));
238
263
  button.addEventListener('click', () => goToPage(page));
239
264
  navList.append(button);
240
265
  }
@@ -258,7 +283,7 @@ export default async function renderPdf(buffer, target, context) {
258
283
  navList.append(button);
259
284
  });
260
285
  if (!entries.length) {
261
- navList.append(createElement(documentRef, 'div', 'pdf-outline-empty', '当前 PDF 没有可用目录'));
286
+ navList.append(createElement(documentRef, 'div', 'pdf-outline-empty', t('pdf.nav.outlineEmpty')));
262
287
  }
263
288
  };
264
289
  const paintPdfThumbnail = (pageNumber, thumb) => {
@@ -270,7 +295,7 @@ export default async function renderPdf(buffer, target, context) {
270
295
  }
271
296
  const image = documentRef.createElement('img');
272
297
  image.src = imageUrl;
273
- image.alt = `第 ${pageNumber} 页缩略图`;
298
+ image.alt = t('pdf.thumbnail.alt', { page: pageNumber });
274
299
  image.loading = 'lazy';
275
300
  thumb.replaceChildren(image);
276
301
  return true;
@@ -357,6 +382,7 @@ export default async function renderPdf(buffer, target, context) {
357
382
  void renderPdfThumbnail(pageNumber);
358
383
  };
359
384
  const syncUi = () => {
385
+ root.classList.toggle('pdf-shell--compact', isCompactViewport());
360
386
  root.classList.toggle('pdf-shell--nav-hidden', !navigationEnabled || !navVisible);
361
387
  root.classList.toggle('pdf-shell--toolbar-hidden', !toolbarVisible);
362
388
  navToggleButton.classList.toggle('pdf-icon-button--active', navVisible);
@@ -366,8 +392,10 @@ export default async function renderPdf(buffer, target, context) {
366
392
  outlineTab.classList.toggle('active', navMode === 'outline');
367
393
  pagesTab.setAttribute('aria-selected', navMode === 'pages' ? 'true' : 'false');
368
394
  outlineTab.setAttribute('aria-selected', navMode === 'outline' ? 'true' : 'false');
369
- navTitle.textContent = navMode === 'pages' ? '页面导航' : '目录导航';
370
- navCount.textContent = navMode === 'pages' ? `${pageCount} 页` : `${outlineCount()} 项`;
395
+ navTitle.textContent = navMode === 'pages' ? t('pdf.nav.pagesTitle') : t('pdf.nav.outlineTitle');
396
+ navCount.textContent = navMode === 'pages'
397
+ ? t('pdf.nav.pageCount', { count: pageCount })
398
+ : t('pdf.nav.itemCount', { count: outlineCount() });
371
399
  pageMeterCurrent.textContent = String(currentPage);
372
400
  pageMeterTotal.textContent = `/ ${pageCount || '-'}`;
373
401
  scaleButton.textContent = scaleText();
@@ -378,7 +406,7 @@ export default async function renderPdf(buffer, target, context) {
378
406
  zoomInButton.disabled = !canZoomIn();
379
407
  stateNode.hidden = loadStatus === 'ready';
380
408
  stateNode.classList.toggle('pdf-state--error', loadStatus === 'error');
381
- stateNode.textContent = loadStatus === 'error' ? errorMessage : '正在加载 PDF...';
409
+ stateNode.textContent = loadStatus === 'error' ? errorMessage : t('pdf.state.loading');
382
410
  renderNavList();
383
411
  };
384
412
  const writeLegacyCompatiblePageDimensions = () => {
@@ -711,7 +739,7 @@ export default async function renderPdf(buffer, target, context) {
711
739
  return;
712
740
  }
713
741
  outlineItems = Array.isArray(outline)
714
- ? buildOutlineItems(outline)
742
+ ? buildOutlineItems(outline, 'outline', index => t('pdf.nav.outlineFallbackTitle', { index: index + 1 }))
715
743
  : [];
716
744
  syncUi();
717
745
  }
@@ -730,7 +758,7 @@ export default async function renderPdf(buffer, target, context) {
730
758
  var _a, _b;
731
759
  const pdfDocument = pdfContext.document;
732
760
  if (!pdfDocument) {
733
- throw new Error('PDF 尚未加载完成,请稍后再试');
761
+ throw new Error(t('pdf.error.notLoaded'));
734
762
  }
735
763
  const page = await pdfDocument.getPage(Math.min(Math.max(pageNumber, 1), pdfDocument.numPages));
736
764
  const viewport = page.getViewport({
@@ -755,12 +783,12 @@ export default async function renderPdf(buffer, target, context) {
755
783
  var _a, _b;
756
784
  const pdfDocument = pdfContext.document;
757
785
  if (!pdfDocument) {
758
- throw new Error('PDF 尚未加载完成,请稍后再试');
786
+ throw new Error(t('pdf.error.notLoaded'));
759
787
  }
760
788
  const pagesHtml = [];
761
789
  for (let pageNumber = 1; pageNumber <= pdfDocument.numPages; pageNumber += 1) {
762
790
  if (destroyed) {
763
- throw new Error('PDF 已卸载,无法继续打印');
791
+ throw new Error(t('pdf.error.unloaded'));
764
792
  }
765
793
  const page = await pdfDocument.getPage(pageNumber);
766
794
  const baseViewport = page.getViewport({
@@ -777,12 +805,12 @@ export default async function renderPdf(buffer, target, context) {
777
805
  const canvas = documentRef.createElement('canvas');
778
806
  const canvasContext = canvas.getContext('2d');
779
807
  if (!canvasContext) {
780
- throw new Error('当前浏览器无法创建 PDF 打印画布');
808
+ throw new Error(t('pdf.error.canvasUnavailable'));
781
809
  }
782
810
  canvas.width = Math.ceil(renderViewport.width);
783
811
  canvas.height = Math.ceil(renderViewport.height);
784
812
  await page.render({ canvas, canvasContext, viewport: renderViewport }).promise;
785
- const pageTitle = `${exportOptions.title} - ${pageNumber} 页`;
813
+ const pageTitle = t('pdf.export.pageTitle', { title: exportOptions.title, page: pageNumber });
786
814
  const pageStyle = [
787
815
  `--viewer-print-page-width:${formatCssPixels(pageWidth)}`,
788
816
  `--viewer-print-page-height:${formatCssPixels(pageHeight)}`,
@@ -825,7 +853,7 @@ export default async function renderPdf(buffer, target, context) {
825
853
  eventBus,
826
854
  linkService: pdfLinkService,
827
855
  findController: pdfFindController,
828
- l10n: new GenericL10n('zh-CN'),
856
+ l10n: new GenericL10n(resolvedLocale),
829
857
  enableAutoLinking: false,
830
858
  });
831
859
  pdfContext.viewer = pdfViewer;
@@ -859,7 +887,7 @@ export default async function renderPdf(buffer, target, context) {
859
887
  });
860
888
  eventBus.on('pagerendered', scheduleLegacyPageDimensionPatch);
861
889
  if (!(context === null || context === void 0 ? void 0 : context.streamUrl) && !buffer.byteLength) {
862
- throw new Error('PDF 缺少可读取的数据源');
890
+ throw new Error(t('pdf.error.missingSource'));
863
891
  }
864
892
  const worker = createPdfWorker();
865
893
  const pdfAssets = resolveFileViewerPdfAssetUrls(options, documentRef.URL || documentRef.baseURI);
@@ -914,7 +942,7 @@ export default async function renderPdf(buffer, target, context) {
914
942
  return;
915
943
  }
916
944
  loadStatus = 'error';
917
- errorMessage = error instanceof Error ? error.message : 'PDF 加载失败';
945
+ errorMessage = error instanceof Error ? error.message : t('pdf.error.loadFailed');
918
946
  syncUi();
919
947
  }
920
948
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@file-viewer/renderer-pdf",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
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.1",
57
+ "@file-viewer/core": "^2.1.3",
58
58
  "pdfjs-dist": "^6.0.227"
59
59
  },
60
60
  "devDependencies": {