@open-file-viewer/core 0.1.22 → 0.1.23
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.md +14 -2
- package/dist/index.cjs +227 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +227 -38
- package/dist/index.js.map +1 -1
- package/dist/style.css +43 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -123,6 +123,14 @@ pdfPlugin({
|
|
|
123
123
|
This keeps compatibility at the cost of holding one extra copy of the PDF in memory, so use it only
|
|
124
124
|
for affected environments.
|
|
125
125
|
|
|
126
|
+
For 360 Secure Browser, 360 Extreme Browser, and older Chromium kernels, `pdfPlugin()` defaults to
|
|
127
|
+
`compatibilityMode: "auto"`. It installs the `Promise.withResolvers` compatibility shim when needed
|
|
128
|
+
and selects the matching PDF.js legacy worker. If an enterprise browser hides its 360 user-agent
|
|
129
|
+
marker, force the compatibility path with `pdfPlugin({ compatibilityMode: "legacy" })`. When
|
|
130
|
+
self-hosting that worker, point `workerSrc` to the same-version
|
|
131
|
+
`pdfjs-dist/legacy/build/pdf.worker.min.mjs`. Use `compatibilityMode: "modern"` only when targeting
|
|
132
|
+
modern Chrome or Edge exclusively.
|
|
133
|
+
|
|
126
134
|
## High-Fidelity Office Conversion
|
|
127
135
|
|
|
128
136
|
Browser-side Office renderers cannot perfectly reproduce Word/WPS layout for files with anchored
|
|
@@ -251,7 +259,7 @@ Use `toolbar.render(ctx)` when you need to replace the toolbar completely. The c
|
|
|
251
259
|
|
|
252
260
|
## Locale and Fallback Text
|
|
253
261
|
|
|
254
|
-
|
|
262
|
+
Built-in states, fallback panels, toolbar labels, and plugin messages default to English. Set `locale: "zh-CN"` for Simplified Chinese, or override individual PDF, image, text, Office, and custom-plugin strings with `messages`:
|
|
255
263
|
|
|
256
264
|
```ts
|
|
257
265
|
createViewer({
|
|
@@ -260,12 +268,16 @@ createViewer({
|
|
|
260
268
|
locale: "zh-CN",
|
|
261
269
|
messages: {
|
|
262
270
|
unsupportedTitle: "No inline preview available",
|
|
263
|
-
downloadFile: "Download original file"
|
|
271
|
+
downloadFile: "Download original file",
|
|
272
|
+
pdfPreviewFailedTitle: "Unable to open report",
|
|
273
|
+
imageDownload: "Save original image"
|
|
264
274
|
},
|
|
265
275
|
plugins
|
|
266
276
|
});
|
|
267
277
|
```
|
|
268
278
|
|
|
279
|
+
The PDF viewer includes a synchronized page navigator with previous/next buttons and a numeric page input. Enter a page number and press Enter to jump directly to it.
|
|
280
|
+
|
|
269
281
|
## License
|
|
270
282
|
|
|
271
283
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -655,7 +655,36 @@ var defaultMessages = {
|
|
|
655
655
|
officeUnsupportedIntro: "\u5DF2\u8FDB\u5165 Office \u63D2\u4EF6\u3002{message}",
|
|
656
656
|
officeUnsupportedSupportedFormats: "\u5F53\u524D\u7248\u672C\u4F18\u5148\u652F\u6301 docx\u3001rtf\u3001odt/fodt\u3001xlsx/xls/csv/ods\u3001pptx/ppsx\u3001odp/fodp \u7684\u57FA\u7840\u5185\u5BB9\u9884\u89C8\u3002",
|
|
657
657
|
officeErrorWithMessage: "\u89E3\u6790\u5668\u8FD4\u56DE\uFF1A{message}",
|
|
658
|
-
officeErrorWithoutMessage: "\u89E3\u6790\u5668\u672A\u8FD4\u56DE\u5177\u4F53\u9519\u8BEF\u4FE1\u606F\u3002"
|
|
658
|
+
officeErrorWithoutMessage: "\u89E3\u6790\u5668\u672A\u8FD4\u56DE\u5177\u4F53\u9519\u8BEF\u4FE1\u606F\u3002",
|
|
659
|
+
officeConvertedTitle: "Office \u9AD8\u4FDD\u771F\u8F6C\u6362\u9884\u89C8",
|
|
660
|
+
officeConvertedPdfFailed: "Office \u8F6C\u6362\u540E\u7684 PDF \u65E0\u6CD5\u9884\u89C8",
|
|
661
|
+
pdfEncryptedTitle: "PDF \u5DF2\u52A0\u5BC6\uFF0C\u65E0\u6CD5\u5728\u7EBF\u9884\u89C8",
|
|
662
|
+
pdfEncryptedMessage: "\u8BF7\u4E0B\u8F7D\u540E\u4F7F\u7528\u5BC6\u7801\u6253\u5F00\uFF0C\u6216\u4E0A\u4F20\u89E3\u5BC6\u540E\u7684 PDF \u6587\u4EF6\u3002",
|
|
663
|
+
pdfPreviewFailedTitle: "PDF \u9884\u89C8\u5931\u8D25",
|
|
664
|
+
pdfCorruptedMessage: "\u8BE5 PDF \u6587\u4EF6\u53EF\u80FD\u5DF2\u635F\u574F\u6216\u683C\u5F0F\u65E0\u6548\u3002",
|
|
665
|
+
pdfCannotLoadMessage: "\u5F53\u524D\u6D4F\u89C8\u5668\u65E0\u6CD5\u52A0\u8F7D\u8BE5 PDF\u3002",
|
|
666
|
+
pdfDownload: "\u4E0B\u8F7D PDF",
|
|
667
|
+
pdfPageLoading: "\u9875\u9762 {page} \u52A0\u8F7D\u4E2D...",
|
|
668
|
+
pdfPageEmpty: "\u8BE5\u9875\u6CA1\u6709\u68C0\u6D4B\u5230\u53EF\u663E\u793A\u7684 PDF \u517C\u5BB9\u5185\u5BB9\u3002\u82E5\u8FD9\u662F Illustrator/AI \u6587\u4EF6\uFF0C\u53EF\u80FD\u53EA\u5305\u542B\u79C1\u6709\u7F16\u8F91\u6570\u636E\uFF0C\u5EFA\u8BAE\u5BFC\u51FA\u4E3A PDF/SVG/PNG \u540E\u9884\u89C8\u3002",
|
|
669
|
+
pdfPageRenderFailed: "\u65E0\u6CD5\u6E32\u67D3\u8BE5\u9875\u9762\u3002\u8BE5\u9875\u53EF\u80FD\u5305\u542B\u6D4F\u89C8\u5668 PDF \u5F15\u64CE\u6682\u4E0D\u652F\u6301\u7684\u56FE\u5F62\u3001\u5B57\u4F53\u6216\u538B\u7F29\u7279\u6027\u3002",
|
|
670
|
+
pdfPreviousPage: "\u4E0A\u4E00\u9875",
|
|
671
|
+
pdfNextPage: "\u4E0B\u4E00\u9875",
|
|
672
|
+
pdfPageInput: "\u5F53\u524D\u9875\u7801",
|
|
673
|
+
pdfPagePosition: "/ {total}",
|
|
674
|
+
pdfPageLabel: "\u7B2C {page} \u9875",
|
|
675
|
+
pdfSummaryPages: "\u9875\u6570",
|
|
676
|
+
pdfSummaryPageSizes: "\u9875\u9762\u5C3A\u5BF8",
|
|
677
|
+
pdfSummaryFit: "\u9002\u914D",
|
|
678
|
+
pdfSummaryActualSize: "\u539F\u59CB\u5927\u5C0F",
|
|
679
|
+
pdfSummaryFitWidth: "\u9002\u5408\u5BBD\u5EA6",
|
|
680
|
+
pdfSummaryZoom: "\u7F29\u653E",
|
|
681
|
+
imagePreviewFailedTitle: "\u56FE\u7247\u9884\u89C8\u5931\u8D25",
|
|
682
|
+
imagePreviewFailedMessage: "\u5F53\u524D\u6D4F\u89C8\u5668\u65E0\u6CD5\u76F4\u63A5\u663E\u793A\u8BE5\u56FE\u7247\uFF0C\u6587\u4EF6\u53EF\u80FD\u5DF2\u635F\u574F\u6216\u7F16\u7801\u6682\u4E0D\u53D7\u652F\u6301\u3002",
|
|
683
|
+
imageDownload: "\u4E0B\u8F7D\u56FE\u7247",
|
|
684
|
+
imageZoomOut: "\u7F29\u5C0F",
|
|
685
|
+
imageZoomIn: "\u653E\u5927",
|
|
686
|
+
imageRotate: "\u65CB\u8F6C\u56FE\u7247",
|
|
687
|
+
imageReset: "\u91CD\u7F6E\u56FE\u7247\u89C6\u56FE"
|
|
659
688
|
},
|
|
660
689
|
"en-US": {
|
|
661
690
|
loading: "Loading preview...",
|
|
@@ -704,7 +733,36 @@ var defaultMessages = {
|
|
|
704
733
|
officeUnsupportedIntro: "is handled by the Office plugin. {message}",
|
|
705
734
|
officeUnsupportedSupportedFormats: "This version prioritizes basic previews for docx, rtf, odt/fodt, xlsx/xls/csv/ods, pptx/ppsx, and odp/fodp files.",
|
|
706
735
|
officeErrorWithMessage: "Parser returned: {message}",
|
|
707
|
-
officeErrorWithoutMessage: "Parser did not return a specific error."
|
|
736
|
+
officeErrorWithoutMessage: "Parser did not return a specific error.",
|
|
737
|
+
officeConvertedTitle: "High-fidelity Office conversion preview",
|
|
738
|
+
officeConvertedPdfFailed: "The converted Office PDF could not be previewed",
|
|
739
|
+
pdfEncryptedTitle: "This PDF is encrypted and cannot be previewed online",
|
|
740
|
+
pdfEncryptedMessage: "Download and open it with the password, or upload a decrypted PDF file.",
|
|
741
|
+
pdfPreviewFailedTitle: "PDF preview failed",
|
|
742
|
+
pdfCorruptedMessage: "The PDF may be corrupted or use an invalid format.",
|
|
743
|
+
pdfCannotLoadMessage: "This browser could not load the PDF.",
|
|
744
|
+
pdfDownload: "Download PDF",
|
|
745
|
+
pdfPageLoading: "Loading page {page}...",
|
|
746
|
+
pdfPageEmpty: "No displayable PDF-compatible content was detected on this page. If this is an Illustrator/AI file, export it as PDF, SVG, or PNG before previewing.",
|
|
747
|
+
pdfPageRenderFailed: "This page could not be rendered. It may contain graphics, fonts, or compression features that the browser PDF engine does not support.",
|
|
748
|
+
pdfPreviousPage: "Previous page",
|
|
749
|
+
pdfNextPage: "Next page",
|
|
750
|
+
pdfPageInput: "Current page",
|
|
751
|
+
pdfPagePosition: "/ {total}",
|
|
752
|
+
pdfPageLabel: "Page {page}",
|
|
753
|
+
pdfSummaryPages: "Pages",
|
|
754
|
+
pdfSummaryPageSizes: "Page sizes",
|
|
755
|
+
pdfSummaryFit: "Fit",
|
|
756
|
+
pdfSummaryActualSize: "Actual size",
|
|
757
|
+
pdfSummaryFitWidth: "Fit width",
|
|
758
|
+
pdfSummaryZoom: "Zoom",
|
|
759
|
+
imagePreviewFailedTitle: "Image preview failed",
|
|
760
|
+
imagePreviewFailedMessage: "This browser cannot display the image. The file may be corrupted or use an unsupported encoding.",
|
|
761
|
+
imageDownload: "Download image",
|
|
762
|
+
imageZoomOut: "Zoom out",
|
|
763
|
+
imageZoomIn: "Zoom in",
|
|
764
|
+
imageRotate: "Rotate image",
|
|
765
|
+
imageReset: "Reset image view"
|
|
708
766
|
}
|
|
709
767
|
};
|
|
710
768
|
function resolveMessages(options) {
|
|
@@ -2215,7 +2273,7 @@ function imagePlugin() {
|
|
|
2215
2273
|
infoBar.hidden = false;
|
|
2216
2274
|
infoBar.removeAttribute("aria-hidden");
|
|
2217
2275
|
infoBar.style.removeProperty("display");
|
|
2218
|
-
stage.replaceChildren(createImageFallback(ctx.file.name, url));
|
|
2276
|
+
stage.replaceChildren(createImageFallback(ctx.file.name, url, ctx.options.messages));
|
|
2219
2277
|
ctx.toolbar?.refreshCommandSupport();
|
|
2220
2278
|
};
|
|
2221
2279
|
const setScale = (nextScale) => {
|
|
@@ -2240,13 +2298,13 @@ function imagePlugin() {
|
|
|
2240
2298
|
return () => button.removeEventListener("click", action);
|
|
2241
2299
|
};
|
|
2242
2300
|
const disposers = showInlineControls ? [
|
|
2243
|
-
addButton("-",
|
|
2244
|
-
addButton("+",
|
|
2245
|
-
addButton(
|
|
2301
|
+
addButton("-", ctx.options.messages.imageZoomOut, () => setScale(scale - 0.25)),
|
|
2302
|
+
addButton("+", ctx.options.messages.imageZoomIn, () => setScale(scale + 0.25)),
|
|
2303
|
+
addButton(ctx.options.messages.imageRotate, ctx.options.messages.imageRotate, () => {
|
|
2246
2304
|
rotation += 90;
|
|
2247
2305
|
updateTransform();
|
|
2248
2306
|
}),
|
|
2249
|
-
addButton(
|
|
2307
|
+
addButton(ctx.options.messages.imageReset, ctx.options.messages.imageReset, reset)
|
|
2250
2308
|
] : [];
|
|
2251
2309
|
if (showInlineControls) {
|
|
2252
2310
|
controls.append(zoomLabel);
|
|
@@ -2461,17 +2519,17 @@ function getTiffDimensions(ifd) {
|
|
|
2461
2519
|
height: Number(ifd.height || ifd.t257 || 0)
|
|
2462
2520
|
};
|
|
2463
2521
|
}
|
|
2464
|
-
function createImageFallback(fileName, url) {
|
|
2522
|
+
function createImageFallback(fileName, url, messages) {
|
|
2465
2523
|
const fallback = document.createElement("div");
|
|
2466
2524
|
fallback.className = "ofv-fallback";
|
|
2467
2525
|
const title = document.createElement("strong");
|
|
2468
|
-
title.textContent =
|
|
2526
|
+
title.textContent = messages.imagePreviewFailedTitle;
|
|
2469
2527
|
const meta = document.createElement("span");
|
|
2470
|
-
meta.textContent =
|
|
2528
|
+
meta.textContent = messages.imagePreviewFailedMessage;
|
|
2471
2529
|
const download = document.createElement("a");
|
|
2472
2530
|
download.href = url;
|
|
2473
2531
|
download.download = fileName;
|
|
2474
|
-
download.textContent =
|
|
2532
|
+
download.textContent = messages.imageDownload;
|
|
2475
2533
|
fallback.append(title, meta, download);
|
|
2476
2534
|
return fallback;
|
|
2477
2535
|
}
|
|
@@ -4832,17 +4890,20 @@ function pdfPlugin(options = {}) {
|
|
|
4832
4890
|
fit: ctx.options.fit,
|
|
4833
4891
|
zoom: ctx.options.zoom,
|
|
4834
4892
|
toolbar: ctx.toolbar,
|
|
4835
|
-
|
|
4836
|
-
encryptedMessage: "\u8BF7\u4E0B\u8F7D\u540E\u4F7F\u7528\u5BC6\u7801\u6253\u5F00\uFF0C\u6216\u4E0A\u4F20\u89E3\u5BC6\u540E\u7684 PDF \u6587\u4EF6\u3002",
|
|
4837
|
-
encryptedAction: "\u4E0B\u8F7D PDF",
|
|
4893
|
+
messages: ctx.options.messages,
|
|
4838
4894
|
revokeUrlOnDestroy: true
|
|
4839
4895
|
});
|
|
4840
4896
|
}
|
|
4841
4897
|
};
|
|
4842
4898
|
}
|
|
4843
4899
|
async function renderPdfDocumentPreview(options) {
|
|
4900
|
+
const useLegacyCompatibility = shouldUseLegacyPdfCompatibility(options.compatibilityMode);
|
|
4901
|
+
if (useLegacyCompatibility) {
|
|
4902
|
+
installPromiseWithResolversPolyfill();
|
|
4903
|
+
}
|
|
4844
4904
|
const pdf = options.pdfjs || await import("pdfjs-dist");
|
|
4845
|
-
|
|
4905
|
+
const messages = { ...defaultMessages["en-US"], ...options.messages };
|
|
4906
|
+
configurePdfWorker(pdf, options.workerSrc, useLegacyCompatibility);
|
|
4846
4907
|
const viewer = document.createElement("div");
|
|
4847
4908
|
viewer.className = "ofv-pdf-viewer";
|
|
4848
4909
|
if (options.title) {
|
|
@@ -4871,10 +4932,10 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4871
4932
|
url: options.fileUrl
|
|
4872
4933
|
};
|
|
4873
4934
|
const fallback = isEncryptedError(error) ? createEncryptedFallback(fileLike, options.fileUrl, {
|
|
4874
|
-
title: options.encryptedTitle ||
|
|
4875
|
-
message: options.encryptedMessage ||
|
|
4876
|
-
action: options.encryptedAction ||
|
|
4877
|
-
}) : createPdfFallback(options.fileName, options.fileUrl, normalizePdfError(error), options.fallbackTitle);
|
|
4935
|
+
title: options.encryptedTitle || messages.pdfEncryptedTitle,
|
|
4936
|
+
message: options.encryptedMessage || messages.pdfEncryptedMessage,
|
|
4937
|
+
action: options.encryptedAction || messages.pdfDownload
|
|
4938
|
+
}) : createPdfFallback(options.fileName, options.fileUrl, normalizePdfError(error, messages), messages, options.fallbackTitle);
|
|
4878
4939
|
if (!fallback.classList.contains("ofv-pdf-web-fallback")) {
|
|
4879
4940
|
options.viewport.classList.add("ofv-center");
|
|
4880
4941
|
}
|
|
@@ -4941,8 +5002,43 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4941
5002
|
let currentSize = options.size;
|
|
4942
5003
|
let zoomFactor = getInitialZoom({ options: { zoom: options.zoom ?? 1 } }, 0.25, 4);
|
|
4943
5004
|
let rotation = 0;
|
|
5005
|
+
let currentPage = 1;
|
|
5006
|
+
const goToPage = (page, scroll = true) => {
|
|
5007
|
+
currentPage = Math.min(pdfDocument.numPages, Math.max(1, Math.round(page) || 1));
|
|
5008
|
+
pageNavigator.setCurrent(currentPage);
|
|
5009
|
+
const wrapper = pageStates[currentPage - 1]?.wrapper;
|
|
5010
|
+
if (!scroll || !wrapper) {
|
|
5011
|
+
return;
|
|
5012
|
+
}
|
|
5013
|
+
const top = Math.max(0, wrapper.offsetTop - 16);
|
|
5014
|
+
if (typeof scroller.scrollTo === "function") {
|
|
5015
|
+
scroller.scrollTo({ top, behavior: "smooth" });
|
|
5016
|
+
} else {
|
|
5017
|
+
scroller.scrollTop = top;
|
|
5018
|
+
}
|
|
5019
|
+
};
|
|
5020
|
+
const pageNavigator = createPdfPageNavigator(pdfDocument.numPages, messages, (page) => goToPage(page));
|
|
5021
|
+
viewer.insertBefore(pageNavigator.element, summary);
|
|
5022
|
+
const handleScrollerScroll = () => {
|
|
5023
|
+
const scrollerRect = scroller.getBoundingClientRect();
|
|
5024
|
+
const targetY = scrollerRect.top + Math.min(Math.max(scroller.clientHeight * 0.25, 40), 180);
|
|
5025
|
+
let nearestPage = currentPage;
|
|
5026
|
+
let nearestDistance = Number.POSITIVE_INFINITY;
|
|
5027
|
+
pageStates.forEach((state, index) => {
|
|
5028
|
+
const distance = Math.abs(state.wrapper.getBoundingClientRect().top - targetY);
|
|
5029
|
+
if (distance < nearestDistance) {
|
|
5030
|
+
nearestDistance = distance;
|
|
5031
|
+
nearestPage = index + 1;
|
|
5032
|
+
}
|
|
5033
|
+
});
|
|
5034
|
+
if (nearestPage !== currentPage) {
|
|
5035
|
+
currentPage = nearestPage;
|
|
5036
|
+
pageNavigator.setCurrent(currentPage);
|
|
5037
|
+
}
|
|
5038
|
+
};
|
|
5039
|
+
scroller.addEventListener("scroll", handleScrollerScroll, { passive: true });
|
|
4944
5040
|
const updateSummary = () => {
|
|
4945
|
-
renderPdfSummary(summary, pdfDocument.numPages, pagesMeta, options.fit, zoomFactor);
|
|
5041
|
+
renderPdfSummary(summary, pdfDocument.numPages, pagesMeta, options.fit, zoomFactor, messages);
|
|
4946
5042
|
options.toolbar?.setZoom(zoomFactor);
|
|
4947
5043
|
};
|
|
4948
5044
|
const clearPage = (pageIdx) => {
|
|
@@ -4958,7 +5054,9 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4958
5054
|
state.canvas = null;
|
|
4959
5055
|
state.rendered = false;
|
|
4960
5056
|
state.wrapper.replaceChildren();
|
|
4961
|
-
state.wrapper.append(
|
|
5057
|
+
state.wrapper.append(
|
|
5058
|
+
createPageStatus("ofv-pdf-skeleton", formatPreviewMessage(messages.pdfPageLoading, { page: pageIdx + 1 }))
|
|
5059
|
+
);
|
|
4962
5060
|
};
|
|
4963
5061
|
const renderPage = async (pageIdx, size) => {
|
|
4964
5062
|
const state = pageStates[pageIdx];
|
|
@@ -5026,7 +5124,7 @@ async function renderPdfDocumentPreview(options) {
|
|
|
5026
5124
|
state.wrapper.appendChild(
|
|
5027
5125
|
createPageStatus(
|
|
5028
5126
|
"ofv-pdf-empty",
|
|
5029
|
-
|
|
5127
|
+
messages.pdfPageEmpty
|
|
5030
5128
|
)
|
|
5031
5129
|
);
|
|
5032
5130
|
}
|
|
@@ -5034,7 +5132,7 @@ async function renderPdfDocumentPreview(options) {
|
|
|
5034
5132
|
console.error(`Failed to render PDF page ${pageIdx + 1}:`, err);
|
|
5035
5133
|
state.rendered = false;
|
|
5036
5134
|
state.wrapper.replaceChildren(
|
|
5037
|
-
createPageStatus("ofv-pdf-error",
|
|
5135
|
+
createPageStatus("ofv-pdf-error", messages.pdfPageRenderFailed)
|
|
5038
5136
|
);
|
|
5039
5137
|
}
|
|
5040
5138
|
};
|
|
@@ -5075,9 +5173,10 @@ async function renderPdfDocumentPreview(options) {
|
|
|
5075
5173
|
const wrapper = document.createElement("div");
|
|
5076
5174
|
wrapper.className = "ofv-pdf-page-wrapper";
|
|
5077
5175
|
wrapper.setAttribute("data-page-index", String(i));
|
|
5176
|
+
wrapper.setAttribute("aria-label", formatPreviewMessage(messages.pdfPageLabel, { page: i + 1 }));
|
|
5078
5177
|
wrapper.style.width = `${w}px`;
|
|
5079
5178
|
wrapper.style.height = `${h}px`;
|
|
5080
|
-
wrapper.append(createPageStatus("ofv-pdf-skeleton",
|
|
5179
|
+
wrapper.append(createPageStatus("ofv-pdf-skeleton", formatPreviewMessage(messages.pdfPageLoading, { page: i + 1 })));
|
|
5081
5180
|
scroller.appendChild(wrapper);
|
|
5082
5181
|
pageStates.push({
|
|
5083
5182
|
wrapper,
|
|
@@ -5099,6 +5198,7 @@ async function renderPdfDocumentPreview(options) {
|
|
|
5099
5198
|
}
|
|
5100
5199
|
}, 0);
|
|
5101
5200
|
}
|
|
5201
|
+
goToPage(currentPage, false);
|
|
5102
5202
|
};
|
|
5103
5203
|
renderLayout(options.size);
|
|
5104
5204
|
let resizeTimer;
|
|
@@ -5139,6 +5239,8 @@ async function renderPdfDocumentPreview(options) {
|
|
|
5139
5239
|
},
|
|
5140
5240
|
destroy() {
|
|
5141
5241
|
options.toolbar?.setZoom(void 0);
|
|
5242
|
+
pageNavigator.destroy();
|
|
5243
|
+
scroller.removeEventListener("scroll", handleScrollerScroll);
|
|
5142
5244
|
window.clearTimeout(resizeTimer);
|
|
5143
5245
|
observer?.disconnect();
|
|
5144
5246
|
pageStates.forEach((state) => {
|
|
@@ -5184,15 +5286,15 @@ function getPdfAvailableWidth(width) {
|
|
|
5184
5286
|
const gutter = width < 160 ? 16 : 32;
|
|
5185
5287
|
return Math.max(1, width - gutter);
|
|
5186
5288
|
}
|
|
5187
|
-
function renderPdfSummary(summary, pages, pagesMeta, fit, zoomFactor) {
|
|
5289
|
+
function renderPdfSummary(summary, pages, pagesMeta, fit, zoomFactor, messages) {
|
|
5188
5290
|
summary.replaceChildren();
|
|
5189
|
-
appendPdfSummary(summary,
|
|
5291
|
+
appendPdfSummary(summary, messages.pdfSummaryPages, String(pages));
|
|
5190
5292
|
const pageSizes = formatPdfPageSizes(pagesMeta);
|
|
5191
5293
|
if (pageSizes) {
|
|
5192
|
-
appendPdfSummary(summary,
|
|
5294
|
+
appendPdfSummary(summary, messages.pdfSummaryPageSizes, pageSizes);
|
|
5193
5295
|
}
|
|
5194
|
-
appendPdfSummary(summary,
|
|
5195
|
-
appendPdfSummary(summary,
|
|
5296
|
+
appendPdfSummary(summary, messages.pdfSummaryFit, fit === "actual" ? messages.pdfSummaryActualSize : messages.pdfSummaryFitWidth);
|
|
5297
|
+
appendPdfSummary(summary, messages.pdfSummaryZoom, `${Math.round(zoomFactor * 100)}%`);
|
|
5196
5298
|
}
|
|
5197
5299
|
function appendPdfSummary(parent, label, value) {
|
|
5198
5300
|
const item = document.createElement("span");
|
|
@@ -5282,7 +5384,7 @@ function createPageStatus(className, text) {
|
|
|
5282
5384
|
status.textContent = text;
|
|
5283
5385
|
return status;
|
|
5284
5386
|
}
|
|
5285
|
-
function createPdfFallback(fileName, url, message, titleText =
|
|
5387
|
+
function createPdfFallback(fileName, url, message, messages, titleText = messages.pdfPreviewFailedTitle) {
|
|
5286
5388
|
if (isEmbeddableRemoteUrl(url)) {
|
|
5287
5389
|
return createPdfWebFallback(fileName, url);
|
|
5288
5390
|
}
|
|
@@ -5295,7 +5397,7 @@ function createPdfFallback(fileName, url, message, titleText = "PDF \u9884\u89C8
|
|
|
5295
5397
|
const download = document.createElement("a");
|
|
5296
5398
|
download.href = url;
|
|
5297
5399
|
download.download = fileName;
|
|
5298
|
-
download.textContent =
|
|
5400
|
+
download.textContent = messages.pdfDownload;
|
|
5299
5401
|
fallback.append(title, meta, download);
|
|
5300
5402
|
return fallback;
|
|
5301
5403
|
}
|
|
@@ -5314,23 +5416,109 @@ function createPdfWebFallback(fileName, url) {
|
|
|
5314
5416
|
function isEmbeddableRemoteUrl(url) {
|
|
5315
5417
|
return /^https?:\/\//i.test(url);
|
|
5316
5418
|
}
|
|
5317
|
-
function normalizePdfError(error) {
|
|
5419
|
+
function normalizePdfError(error, messages) {
|
|
5318
5420
|
const message = error instanceof Error ? error.message : String(error || "");
|
|
5319
5421
|
const name = typeof error === "object" && error !== null && "name" in error ? String(error.name) : "";
|
|
5320
5422
|
const lower = `${name} ${message}`.toLowerCase();
|
|
5321
5423
|
if (lower.includes("invalid") || lower.includes("missing") || lower.includes("corrupt")) {
|
|
5322
|
-
return
|
|
5424
|
+
return messages.pdfCorruptedMessage;
|
|
5323
5425
|
}
|
|
5324
|
-
return
|
|
5426
|
+
return messages.pdfCannotLoadMessage;
|
|
5427
|
+
}
|
|
5428
|
+
function createPdfPageNavigator(total, messages, onChange) {
|
|
5429
|
+
const element = document.createElement("div");
|
|
5430
|
+
element.className = "ofv-pdf-page-navigator";
|
|
5431
|
+
const previous = document.createElement("button");
|
|
5432
|
+
previous.type = "button";
|
|
5433
|
+
previous.textContent = "\u2039";
|
|
5434
|
+
previous.title = messages.pdfPreviousPage;
|
|
5435
|
+
previous.setAttribute("aria-label", messages.pdfPreviousPage);
|
|
5436
|
+
const input = document.createElement("input");
|
|
5437
|
+
input.type = "number";
|
|
5438
|
+
input.min = "1";
|
|
5439
|
+
input.max = String(total);
|
|
5440
|
+
input.value = "1";
|
|
5441
|
+
input.inputMode = "numeric";
|
|
5442
|
+
input.setAttribute("aria-label", messages.pdfPageInput);
|
|
5443
|
+
const position = document.createElement("span");
|
|
5444
|
+
position.textContent = formatPreviewMessage(messages.pdfPagePosition, { total });
|
|
5445
|
+
const next = document.createElement("button");
|
|
5446
|
+
next.type = "button";
|
|
5447
|
+
next.textContent = "\u203A";
|
|
5448
|
+
next.title = messages.pdfNextPage;
|
|
5449
|
+
next.setAttribute("aria-label", messages.pdfNextPage);
|
|
5450
|
+
const commit = () => onChange(Number(input.value));
|
|
5451
|
+
const handleKeydown = (event) => {
|
|
5452
|
+
if (event.key === "Enter") {
|
|
5453
|
+
commit();
|
|
5454
|
+
}
|
|
5455
|
+
};
|
|
5456
|
+
const handlePrevious = () => onChange(Number(input.value) - 1);
|
|
5457
|
+
const handleNext = () => onChange(Number(input.value) + 1);
|
|
5458
|
+
input.addEventListener("change", commit);
|
|
5459
|
+
input.addEventListener("keydown", handleKeydown);
|
|
5460
|
+
previous.addEventListener("click", handlePrevious);
|
|
5461
|
+
next.addEventListener("click", handleNext);
|
|
5462
|
+
element.append(previous, input, position, next);
|
|
5463
|
+
return {
|
|
5464
|
+
element,
|
|
5465
|
+
setCurrent(page) {
|
|
5466
|
+
input.value = String(page);
|
|
5467
|
+
previous.disabled = page <= 1;
|
|
5468
|
+
next.disabled = page >= total;
|
|
5469
|
+
},
|
|
5470
|
+
destroy() {
|
|
5471
|
+
input.removeEventListener("change", commit);
|
|
5472
|
+
input.removeEventListener("keydown", handleKeydown);
|
|
5473
|
+
previous.removeEventListener("click", handlePrevious);
|
|
5474
|
+
next.removeEventListener("click", handleNext);
|
|
5475
|
+
}
|
|
5476
|
+
};
|
|
5325
5477
|
}
|
|
5326
|
-
function configurePdfWorker(pdf, workerSrc) {
|
|
5478
|
+
function configurePdfWorker(pdf, workerSrc, legacy = false) {
|
|
5327
5479
|
if (workerSrc) {
|
|
5328
5480
|
pdf.GlobalWorkerOptions.workerSrc = workerSrc;
|
|
5329
5481
|
return;
|
|
5330
5482
|
}
|
|
5331
5483
|
if (!pdf.GlobalWorkerOptions.workerSrc && typeof window !== "undefined") {
|
|
5332
|
-
|
|
5484
|
+
const build = legacy ? "legacy/build" : "build";
|
|
5485
|
+
pdf.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdf.version}/${build}/pdf.worker.mjs`;
|
|
5486
|
+
}
|
|
5487
|
+
}
|
|
5488
|
+
function shouldUseLegacyPdfCompatibility(mode = "auto") {
|
|
5489
|
+
if (mode === "legacy") {
|
|
5490
|
+
return true;
|
|
5491
|
+
}
|
|
5492
|
+
if (mode === "modern") {
|
|
5493
|
+
return false;
|
|
5494
|
+
}
|
|
5495
|
+
const promise = Promise;
|
|
5496
|
+
if (typeof promise.withResolvers !== "function") {
|
|
5497
|
+
return true;
|
|
5498
|
+
}
|
|
5499
|
+
if (typeof navigator === "undefined") {
|
|
5500
|
+
return false;
|
|
5333
5501
|
}
|
|
5502
|
+
return /(?:QIHU|360SE|360EE)/i.test(navigator.userAgent);
|
|
5503
|
+
}
|
|
5504
|
+
function installPromiseWithResolversPolyfill() {
|
|
5505
|
+
const promise = Promise;
|
|
5506
|
+
if (typeof promise.withResolvers === "function") {
|
|
5507
|
+
return;
|
|
5508
|
+
}
|
|
5509
|
+
Object.defineProperty(promise, "withResolvers", {
|
|
5510
|
+
configurable: true,
|
|
5511
|
+
writable: true,
|
|
5512
|
+
value: () => {
|
|
5513
|
+
let resolve;
|
|
5514
|
+
let reject;
|
|
5515
|
+
const pending = new Promise((resolvePromise, rejectPromise) => {
|
|
5516
|
+
resolve = resolvePromise;
|
|
5517
|
+
reject = rejectPromise;
|
|
5518
|
+
});
|
|
5519
|
+
return { promise: pending, resolve, reject };
|
|
5520
|
+
}
|
|
5521
|
+
});
|
|
5334
5522
|
}
|
|
5335
5523
|
|
|
5336
5524
|
// src/plugins/epub.ts
|
|
@@ -7725,8 +7913,9 @@ async function renderConvertedOfficePreview(panel, ctx, options, conversionConte
|
|
|
7725
7913
|
fit: ctx.options.fit,
|
|
7726
7914
|
zoom: ctx.options.zoom,
|
|
7727
7915
|
toolbar: ctx.toolbar,
|
|
7728
|
-
|
|
7729
|
-
|
|
7916
|
+
messages: ctx.options.messages,
|
|
7917
|
+
title: ctx.options.messages.officeConvertedTitle,
|
|
7918
|
+
fallbackTitle: ctx.options.messages.officeConvertedPdfFailed,
|
|
7730
7919
|
revokeUrlOnDestroy: converted.revokeUrlOnDestroy
|
|
7731
7920
|
});
|
|
7732
7921
|
}
|