@open-file-viewer/core 0.1.20 → 0.1.21
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/dist/index.cjs +223 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -1
- package/dist/index.d.ts +35 -1
- package/dist/index.js +223 -62
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -569,7 +569,40 @@ var defaultMessages = {
|
|
|
569
569
|
size: "\u5927\u5C0F",
|
|
570
570
|
source: "\u6765\u6E90",
|
|
571
571
|
remoteUrl: "\u8FDC\u7A0B URL",
|
|
572
|
-
localFile: "\u672C\u5730/\u5185\u5B58\u6587\u4EF6"
|
|
572
|
+
localFile: "\u672C\u5730/\u5185\u5B58\u6587\u4EF6",
|
|
573
|
+
textPlainLanguage: "\u7EAF\u6587\u672C",
|
|
574
|
+
textLineCount: "{count} \u884C",
|
|
575
|
+
textWrap: "\u6362\u884C",
|
|
576
|
+
textCopy: "\u590D\u5236",
|
|
577
|
+
textCopied: "\u5DF2\u590D\u5236",
|
|
578
|
+
textCopyFailed: "\u590D\u5236\u5931\u8D25",
|
|
579
|
+
textDownload: "\u4E0B\u8F7D",
|
|
580
|
+
textDownloadReady: "\u4E0B\u8F7D\u5DF2\u51C6\u5907",
|
|
581
|
+
textLargeFileNotice: "\u6587\u4EF6\u8F83\u5927\uFF0C\u5F53\u524D\u5C55\u793A\u524D {size}\uFF0C\u590D\u5236\u548C\u4E0B\u8F7D\u4ECD\u4F1A\u4F7F\u7528\u5B8C\u6574\u5185\u5BB9\u3002",
|
|
582
|
+
textHighlightSkipped: "\u5185\u5BB9\u8F83\u5927\uFF0C\u5DF2\u8DF3\u8FC7\u8BED\u6CD5\u9AD8\u4EAE\u4EE5\u4FDD\u6301\u6EDA\u52A8\u6D41\u7545\u3002",
|
|
583
|
+
textPreviewFailedTitle: "\u6587\u672C\u9884\u89C8\u5931\u8D25",
|
|
584
|
+
textPreviewFailedMessage: "\u65E0\u6CD5\u8BFB\u53D6\u8BE5\u6587\u672C\u5185\u5BB9\uFF0C\u53EF\u80FD\u662F\u8FDC\u7A0B\u6587\u4EF6\u4E0D\u53EF\u8BBF\u95EE\u6216\u54CD\u5E94\u72B6\u6001\u5F02\u5E38\u3002",
|
|
585
|
+
textOpenOriginal: "\u6253\u5F00\u539F\u6587\u4EF6",
|
|
586
|
+
officeLegacyConversionTitle: "Office \u8F6C\u6362\u63D0\u793A",
|
|
587
|
+
officeLegacyBinaryNotice: "\u5C5E\u4E8E\u65E7\u7248 Microsoft Office \u4E8C\u8FDB\u5236\u683C\u5F0F\uFF0C\u6D4F\u89C8\u5668\u5185\u65E0\u6CD5\u9AD8\u4FDD\u771F\u89E3\u6790\uFF1B\u5F53\u524D\u4EC5\u5C55\u793A\u53EF\u4FE1\u6587\u672C\u7247\u6BB5\u548C\u7ED3\u6784\u6307\u7EB9\uFF0C\u5B8C\u6574\u6392\u7248\u5EFA\u8BAE\u63A5\u5165 LibreOffice/OnlyOffice \u670D\u52A1\u7AEF\u8F6C\u6362\u4E3A PDF/HTML\u3002",
|
|
588
|
+
officeLegacyMetaFormatType: "\u683C\u5F0F\u7C7B\u578B",
|
|
589
|
+
officeLegacyMetaFileStructure: "\u6587\u4EF6\u7ED3\u6784",
|
|
590
|
+
officeLegacyOleDetected: "\u68C0\u6D4B\u5230 OLE Compound File \u7B7E\u540D",
|
|
591
|
+
officeLegacyOleMissing: "\u672A\u68C0\u6D4B\u5230\u6807\u51C6 OLE \u7B7E\u540D\uFF0C\u6309\u539F\u59CB\u4E8C\u8FDB\u5236\u5C1D\u8BD5\u63D0\u53D6",
|
|
592
|
+
officeLegacyMetaTextFragments: "\u6587\u672C\u7247\u6BB5",
|
|
593
|
+
officeLegacyTextFragmentCount: "{count} \u6BB5",
|
|
594
|
+
officeLegacyMetaParseStatus: "\u89E3\u6790\u72B6\u6001",
|
|
595
|
+
officeLegacyReadableFragments: "\u53EF\u8BFB\u6587\u672C\u7247\u6BB5",
|
|
596
|
+
officeLegacyNoText: "\u672A\u63D0\u53D6\u5230\u7A33\u5B9A\u53EF\u8BFB\u6587\u672C\u3002\u8BE5\u6587\u4EF6\u53EF\u80FD\u7ECF\u8FC7\u538B\u7F29\u3001\u52A0\u5BC6\uFF0C\u6216\u6587\u672C\u7F16\u7801\u65E0\u6CD5\u5728\u6D4F\u89C8\u5668\u7AEF\u53EF\u9760\u8BC6\u522B\uFF1B\u8BF7\u4F7F\u7528\u670D\u52A1\u7AEF LibreOffice/OnlyOffice \u8F6C\u6362\u540E\u9884\u89C8\u3002",
|
|
597
|
+
officeLegacyWordParseFailed: "Word \u4E8C\u8FDB\u5236\u89E3\u6790\u5931\u8D25\uFF1A{message}",
|
|
598
|
+
officeSheetParseFailed: "\u8868\u683C\u89E3\u6790\u5931\u8D25\uFF1A{message}",
|
|
599
|
+
officeUnsupportedTitle: "Office \u57FA\u7840\u9884\u89C8",
|
|
600
|
+
officeUnsupportedLegacyMessage: "\u8BE5\u683C\u5F0F\u5C5E\u4E8E\u8001\u4E8C\u8FDB\u5236\u6216\u4E13\u6709\u683C\u5F0F\uFF0C\u6D4F\u89C8\u5668\u5185\u65E0\u6CD5\u53EF\u9760\u89E3\u6790\uFF1B\u5EFA\u8BAE\u63A5\u5165 LibreOffice/OnlyOffice \u670D\u52A1\u7AEF\u8F6C\u6362\u4E3A PDF/HTML \u540E\u9884\u89C8\u3002",
|
|
601
|
+
officeUnsupportedGenericMessage: "\u8BE5\u683C\u5F0F\u901A\u5E38\u9700\u8981\u670D\u52A1\u7AEF\u8F6C\u6362\u6216\u4E13\u7528\u89E3\u6790\u5668\u624D\u80FD\u9AD8\u4FDD\u771F\u9884\u89C8\u3002",
|
|
602
|
+
officeUnsupportedIntro: "\u5DF2\u8FDB\u5165 Office \u63D2\u4EF6\u3002{message}",
|
|
603
|
+
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",
|
|
604
|
+
officeErrorWithMessage: "\u89E3\u6790\u5668\u8FD4\u56DE\uFF1A{message}",
|
|
605
|
+
officeErrorWithoutMessage: "\u89E3\u6790\u5668\u672A\u8FD4\u56DE\u5177\u4F53\u9519\u8BEF\u4FE1\u606F\u3002"
|
|
573
606
|
},
|
|
574
607
|
"en-US": {
|
|
575
608
|
loading: "Loading preview...",
|
|
@@ -585,7 +618,40 @@ var defaultMessages = {
|
|
|
585
618
|
size: "Size",
|
|
586
619
|
source: "Source",
|
|
587
620
|
remoteUrl: "Remote URL",
|
|
588
|
-
localFile: "Local or in-memory file"
|
|
621
|
+
localFile: "Local or in-memory file",
|
|
622
|
+
textPlainLanguage: "plain text",
|
|
623
|
+
textLineCount: "{count} lines",
|
|
624
|
+
textWrap: "Wrap",
|
|
625
|
+
textCopy: "Copy",
|
|
626
|
+
textCopied: "Copied",
|
|
627
|
+
textCopyFailed: "Copy failed",
|
|
628
|
+
textDownload: "Download",
|
|
629
|
+
textDownloadReady: "Download ready",
|
|
630
|
+
textLargeFileNotice: "Large file, showing the first {size}. Copy and download still use the full content.",
|
|
631
|
+
textHighlightSkipped: "Large content, syntax highlighting was skipped to keep scrolling smooth.",
|
|
632
|
+
textPreviewFailedTitle: "Text preview failed",
|
|
633
|
+
textPreviewFailedMessage: "Unable to read this text content. The remote file may be unreachable or returned an invalid response.",
|
|
634
|
+
textOpenOriginal: "Open original file",
|
|
635
|
+
officeLegacyConversionTitle: "Office conversion guidance",
|
|
636
|
+
officeLegacyBinaryNotice: "belongs to a legacy Microsoft Office binary format that cannot be rendered with high fidelity in the browser. The preview shows trusted text fragments and structural fingerprints; use a LibreOffice/OnlyOffice server conversion to PDF/HTML for complete layout fidelity.",
|
|
637
|
+
officeLegacyMetaFormatType: "Format type",
|
|
638
|
+
officeLegacyMetaFileStructure: "File structure",
|
|
639
|
+
officeLegacyOleDetected: "OLE Compound File signature detected",
|
|
640
|
+
officeLegacyOleMissing: "No standard OLE signature detected; extracting from raw binary data",
|
|
641
|
+
officeLegacyMetaTextFragments: "Text fragments",
|
|
642
|
+
officeLegacyTextFragmentCount: "{count} fragments",
|
|
643
|
+
officeLegacyMetaParseStatus: "Parse status",
|
|
644
|
+
officeLegacyReadableFragments: "Readable text fragments",
|
|
645
|
+
officeLegacyNoText: "No stable readable text was extracted. The file may be compressed, encrypted, or use text encoding that cannot be reliably recognized in the browser; use LibreOffice/OnlyOffice server conversion before previewing.",
|
|
646
|
+
officeLegacyWordParseFailed: "Word binary parse failed: {message}",
|
|
647
|
+
officeSheetParseFailed: "Spreadsheet parse failed: {message}",
|
|
648
|
+
officeUnsupportedTitle: "Office basic preview",
|
|
649
|
+
officeUnsupportedLegacyMessage: "This is a legacy binary or proprietary format that cannot be reliably parsed in the browser; convert it to PDF/HTML through LibreOffice/OnlyOffice on the server before previewing.",
|
|
650
|
+
officeUnsupportedGenericMessage: "This format usually needs server-side conversion or a dedicated parser for high-fidelity preview.",
|
|
651
|
+
officeUnsupportedIntro: "is handled by the Office plugin. {message}",
|
|
652
|
+
officeUnsupportedSupportedFormats: "This version prioritizes basic previews for docx, rtf, odt/fodt, xlsx/xls/csv/ods, pptx/ppsx, and odp/fodp files.",
|
|
653
|
+
officeErrorWithMessage: "Parser returned: {message}",
|
|
654
|
+
officeErrorWithoutMessage: "Parser did not return a specific error."
|
|
589
655
|
}
|
|
590
656
|
};
|
|
591
657
|
function resolveMessages(options) {
|
|
@@ -594,6 +660,9 @@ function resolveMessages(options) {
|
|
|
594
660
|
...options.messages
|
|
595
661
|
};
|
|
596
662
|
}
|
|
663
|
+
function formatPreviewMessage(template, values) {
|
|
664
|
+
return template.replace(/\{(\w+)\}/g, (match, key) => String(values[key] ?? match));
|
|
665
|
+
}
|
|
597
666
|
|
|
598
667
|
// src/plugins/fallback.ts
|
|
599
668
|
function fallbackPlugin() {
|
|
@@ -664,9 +733,10 @@ function formatFallbackBytes(bytes) {
|
|
|
664
733
|
function createViewer(options) {
|
|
665
734
|
const container = resolveContainer(options.container);
|
|
666
735
|
applyBoxSize(container, options.width, options.height);
|
|
736
|
+
const customClassNames = parseClassNameTokens(options.className);
|
|
667
737
|
container.classList.add("ofv-root");
|
|
668
|
-
if (
|
|
669
|
-
container.classList.add(
|
|
738
|
+
if (customClassNames.length > 0) {
|
|
739
|
+
container.classList.add(...customClassNames);
|
|
670
740
|
}
|
|
671
741
|
const theme = applyTheme(container, options.theme || "light");
|
|
672
742
|
const host = document.createElement("div");
|
|
@@ -810,12 +880,15 @@ function createViewer(options) {
|
|
|
810
880
|
theme.destroy();
|
|
811
881
|
container.replaceChildren();
|
|
812
882
|
container.classList.remove("ofv-root");
|
|
813
|
-
if (
|
|
814
|
-
container.classList.remove(
|
|
883
|
+
if (customClassNames.length > 0) {
|
|
884
|
+
container.classList.remove(...customClassNames);
|
|
815
885
|
}
|
|
816
886
|
}
|
|
817
887
|
};
|
|
818
888
|
}
|
|
889
|
+
function parseClassNameTokens(className) {
|
|
890
|
+
return className?.trim().split(/\s+/).filter(Boolean) ?? [];
|
|
891
|
+
}
|
|
819
892
|
function destroyPreviewInstance(instance) {
|
|
820
893
|
if (!instance) {
|
|
821
894
|
return;
|
|
@@ -941,6 +1014,7 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
941
1014
|
let previousButton;
|
|
942
1015
|
let nextButton;
|
|
943
1016
|
let zoomResetButton;
|
|
1017
|
+
let fullscreenButton;
|
|
944
1018
|
let currentZoom;
|
|
945
1019
|
const commandButtons = [];
|
|
946
1020
|
const customButtons = [];
|
|
@@ -1046,13 +1120,14 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1046
1120
|
return;
|
|
1047
1121
|
}
|
|
1048
1122
|
if (id === "fullscreen" && options.fullscreen !== false) {
|
|
1049
|
-
addButton(
|
|
1123
|
+
fullscreenButton = addButton(
|
|
1050
1124
|
getToolbarLabel(options, id),
|
|
1051
1125
|
getToolbarTitle(options, id),
|
|
1052
1126
|
() => getContext().fullscreen(),
|
|
1053
1127
|
void 0,
|
|
1054
1128
|
options.icons?.fullscreen
|
|
1055
1129
|
);
|
|
1130
|
+
updateFullscreenButton();
|
|
1056
1131
|
return;
|
|
1057
1132
|
}
|
|
1058
1133
|
if (id === "print" && options.print) {
|
|
@@ -1154,6 +1229,32 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1154
1229
|
updateCustomButtons();
|
|
1155
1230
|
refreshCustomRender();
|
|
1156
1231
|
}
|
|
1232
|
+
function isFullscreenActive() {
|
|
1233
|
+
return Boolean(
|
|
1234
|
+
typeof document !== "undefined" && element.parentElement && document.fullscreenElement === element.parentElement
|
|
1235
|
+
);
|
|
1236
|
+
}
|
|
1237
|
+
function updateFullscreenButton() {
|
|
1238
|
+
if (!fullscreenButton) {
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
const active = isFullscreenActive();
|
|
1242
|
+
const id = active ? "exit-fullscreen" : "fullscreen";
|
|
1243
|
+
const icon = active ? options.icons?.["exit-fullscreen"] ?? options.icons?.fullscreen : options.icons?.fullscreen;
|
|
1244
|
+
setToolbarButtonContent(fullscreenButton, getToolbarLabel(options, id), icon);
|
|
1245
|
+
const title = getToolbarTitle(options, id);
|
|
1246
|
+
fullscreenButton.title = title;
|
|
1247
|
+
fullscreenButton.setAttribute("aria-label", title);
|
|
1248
|
+
fullscreenButton.setAttribute("aria-pressed", String(active));
|
|
1249
|
+
}
|
|
1250
|
+
const handleFullscreenChange = () => {
|
|
1251
|
+
updateFullscreenButton();
|
|
1252
|
+
refreshCustomRender();
|
|
1253
|
+
};
|
|
1254
|
+
if (typeof document !== "undefined") {
|
|
1255
|
+
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
1256
|
+
disposers.push(() => document.removeEventListener("fullscreenchange", handleFullscreenChange));
|
|
1257
|
+
}
|
|
1157
1258
|
const refreshCustomRender = () => {
|
|
1158
1259
|
if (!options.render) {
|
|
1159
1260
|
return;
|
|
@@ -1227,6 +1328,9 @@ function createToolbarContext({
|
|
|
1227
1328
|
viewport,
|
|
1228
1329
|
canPrevious: index > 0,
|
|
1229
1330
|
canNext: index < length - 1,
|
|
1331
|
+
isFullscreen: Boolean(
|
|
1332
|
+
typeof document !== "undefined" && element.parentElement && document.fullscreenElement === element.parentElement
|
|
1333
|
+
),
|
|
1230
1334
|
zoom,
|
|
1231
1335
|
zoomLabel: zoom === void 0 ? void 0 : formatToolbarZoom(zoom),
|
|
1232
1336
|
async previous() {
|
|
@@ -1245,7 +1349,15 @@ function createToolbarContext({
|
|
|
1245
1349
|
}
|
|
1246
1350
|
},
|
|
1247
1351
|
fullscreen() {
|
|
1248
|
-
|
|
1352
|
+
const target = element.parentElement;
|
|
1353
|
+
if (!target) {
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1356
|
+
if (typeof document !== "undefined" && document.fullscreenElement === target) {
|
|
1357
|
+
void document.exitFullscreen?.();
|
|
1358
|
+
} else {
|
|
1359
|
+
void target.requestFullscreen?.();
|
|
1360
|
+
}
|
|
1249
1361
|
},
|
|
1250
1362
|
print() {
|
|
1251
1363
|
printPreview(viewport);
|
|
@@ -1264,6 +1376,7 @@ var defaultToolbarLabels = {
|
|
|
1264
1376
|
"rotate-right": "Rotate",
|
|
1265
1377
|
download: "Download",
|
|
1266
1378
|
fullscreen: "Fullscreen",
|
|
1379
|
+
"exit-fullscreen": "Exit fullscreen",
|
|
1267
1380
|
print: "Print",
|
|
1268
1381
|
search: "Search"
|
|
1269
1382
|
};
|
|
@@ -1277,6 +1390,7 @@ var defaultToolbarTitles = {
|
|
|
1277
1390
|
"rotate-right": "Rotate right",
|
|
1278
1391
|
download: "Download file",
|
|
1279
1392
|
fullscreen: "Open preview fullscreen",
|
|
1393
|
+
"exit-fullscreen": "Exit fullscreen",
|
|
1280
1394
|
print: "Print preview",
|
|
1281
1395
|
search: "Search preview text"
|
|
1282
1396
|
};
|
|
@@ -1515,6 +1629,9 @@ function collectSearchableTextNodes(root) {
|
|
|
1515
1629
|
if (["SCRIPT", "STYLE", "TEXTAREA", "INPUT", "BUTTON"].includes(parent.tagName)) {
|
|
1516
1630
|
return NodeFilter.FILTER_REJECT;
|
|
1517
1631
|
}
|
|
1632
|
+
if (hasHiddenSearchAncestor(parent, root)) {
|
|
1633
|
+
return NodeFilter.FILTER_REJECT;
|
|
1634
|
+
}
|
|
1518
1635
|
return NodeFilter.FILTER_ACCEPT;
|
|
1519
1636
|
}
|
|
1520
1637
|
});
|
|
@@ -1525,6 +1642,19 @@ function collectSearchableTextNodes(root) {
|
|
|
1525
1642
|
}
|
|
1526
1643
|
return nodes;
|
|
1527
1644
|
}
|
|
1645
|
+
function hasHiddenSearchAncestor(element, root) {
|
|
1646
|
+
let current = element;
|
|
1647
|
+
while (current) {
|
|
1648
|
+
if (current.hidden || current.getAttribute("aria-hidden") === "true" || current.style.display === "none" || current.style.visibility === "hidden") {
|
|
1649
|
+
return true;
|
|
1650
|
+
}
|
|
1651
|
+
if (current === root) {
|
|
1652
|
+
break;
|
|
1653
|
+
}
|
|
1654
|
+
current = current.parentElement;
|
|
1655
|
+
}
|
|
1656
|
+
return false;
|
|
1657
|
+
}
|
|
1528
1658
|
function printPreview(viewport) {
|
|
1529
1659
|
const frame = document.createElement("iframe");
|
|
1530
1660
|
frame.className = "ofv-print-frame";
|
|
@@ -4022,7 +4152,7 @@ function textPlugin() {
|
|
|
4022
4152
|
const isMarkdown = lang === "markdown";
|
|
4023
4153
|
const text = await readText(ctx.file.source).catch((error) => void 0);
|
|
4024
4154
|
if (text === void 0) {
|
|
4025
|
-
const fallback = createTextFallback(ctx.file.name, ctx.file.url);
|
|
4155
|
+
const fallback = createTextFallback(ctx.file.name, ctx.options.messages, ctx.file.url);
|
|
4026
4156
|
ctx.viewport.classList.add("ofv-center");
|
|
4027
4157
|
ctx.viewport.append(fallback);
|
|
4028
4158
|
return {
|
|
@@ -4194,10 +4324,11 @@ function textPlugin() {
|
|
|
4194
4324
|
title.className = "ofv-code-title";
|
|
4195
4325
|
const fileName = document.createElement("strong");
|
|
4196
4326
|
fileName.textContent = ctx.file.name;
|
|
4327
|
+
const messages = ctx.options.messages;
|
|
4197
4328
|
const meta = document.createElement("span");
|
|
4198
4329
|
meta.textContent = [
|
|
4199
|
-
lang === "none" ?
|
|
4200
|
-
|
|
4330
|
+
lang === "none" ? messages.textPlainLanguage : lang,
|
|
4331
|
+
formatPreviewMessage(messages.textLineCount, { count: totalLines.toLocaleString() }),
|
|
4201
4332
|
formatBytes(ctx.file.size ?? (ctx.file.source instanceof Blob ? ctx.file.source.size : text.length))
|
|
4202
4333
|
].join(" \xB7 ");
|
|
4203
4334
|
title.append(fileName, meta);
|
|
@@ -4209,7 +4340,7 @@ function textPlugin() {
|
|
|
4209
4340
|
const wrapButton = document.createElement("button");
|
|
4210
4341
|
wrapButton.type = "button";
|
|
4211
4342
|
wrapButton.className = "ofv-code-action";
|
|
4212
|
-
wrapButton.textContent =
|
|
4343
|
+
wrapButton.textContent = messages.textWrap;
|
|
4213
4344
|
wrapButton.setAttribute("aria-pressed", String(defaultWrapped));
|
|
4214
4345
|
wrapButton.addEventListener("click", () => {
|
|
4215
4346
|
const wrapped = wrapper.classList.toggle("is-wrapped");
|
|
@@ -4218,14 +4349,14 @@ function textPlugin() {
|
|
|
4218
4349
|
const copyButton = document.createElement("button");
|
|
4219
4350
|
copyButton.type = "button";
|
|
4220
4351
|
copyButton.className = "ofv-code-action";
|
|
4221
|
-
copyButton.textContent =
|
|
4352
|
+
copyButton.textContent = messages.textCopy;
|
|
4222
4353
|
copyButton.addEventListener("click", async () => {
|
|
4223
4354
|
copyButton.disabled = true;
|
|
4224
4355
|
try {
|
|
4225
4356
|
await copyToClipboard(text);
|
|
4226
|
-
status.textContent =
|
|
4357
|
+
status.textContent = messages.textCopied;
|
|
4227
4358
|
} catch {
|
|
4228
|
-
status.textContent =
|
|
4359
|
+
status.textContent = messages.textCopyFailed;
|
|
4229
4360
|
} finally {
|
|
4230
4361
|
copyButton.disabled = false;
|
|
4231
4362
|
}
|
|
@@ -4233,10 +4364,10 @@ function textPlugin() {
|
|
|
4233
4364
|
const downloadButton = document.createElement("button");
|
|
4234
4365
|
downloadButton.type = "button";
|
|
4235
4366
|
downloadButton.className = "ofv-code-action";
|
|
4236
|
-
downloadButton.textContent =
|
|
4367
|
+
downloadButton.textContent = messages.textDownload;
|
|
4237
4368
|
downloadButton.addEventListener("click", () => {
|
|
4238
4369
|
downloadText(ctx.file.name, text);
|
|
4239
|
-
status.textContent =
|
|
4370
|
+
status.textContent = messages.textDownloadReady;
|
|
4240
4371
|
});
|
|
4241
4372
|
actions.append(wrapButton, copyButton, downloadButton, status);
|
|
4242
4373
|
header.append(title, actions);
|
|
@@ -4261,13 +4392,13 @@ function textPlugin() {
|
|
|
4261
4392
|
if (truncated) {
|
|
4262
4393
|
const notice = document.createElement("div");
|
|
4263
4394
|
notice.className = "ofv-code-notice";
|
|
4264
|
-
notice.textContent =
|
|
4395
|
+
notice.textContent = formatPreviewMessage(messages.textLargeFileNotice, { size: formatBytes(codeText.length) });
|
|
4265
4396
|
wrapper.append(notice);
|
|
4266
4397
|
}
|
|
4267
4398
|
if (!shouldHighlight) {
|
|
4268
4399
|
const notice = document.createElement("div");
|
|
4269
4400
|
notice.className = "ofv-code-notice";
|
|
4270
|
-
notice.textContent =
|
|
4401
|
+
notice.textContent = messages.textHighlightSkipped;
|
|
4271
4402
|
wrapper.append(notice);
|
|
4272
4403
|
}
|
|
4273
4404
|
wrapper.appendChild(body);
|
|
@@ -4334,19 +4465,19 @@ function normalizeFileName2(name) {
|
|
|
4334
4465
|
const baseName = name.split(/[\\/]/).pop() || name;
|
|
4335
4466
|
return baseName.toLowerCase();
|
|
4336
4467
|
}
|
|
4337
|
-
function createTextFallback(fileName, url) {
|
|
4468
|
+
function createTextFallback(fileName, messages, url) {
|
|
4338
4469
|
const fallback = document.createElement("div");
|
|
4339
4470
|
fallback.className = "ofv-fallback";
|
|
4340
4471
|
const title = document.createElement("strong");
|
|
4341
|
-
title.textContent =
|
|
4472
|
+
title.textContent = messages.textPreviewFailedTitle;
|
|
4342
4473
|
const meta = document.createElement("span");
|
|
4343
|
-
meta.textContent =
|
|
4474
|
+
meta.textContent = messages.textPreviewFailedMessage;
|
|
4344
4475
|
fallback.append(title, meta);
|
|
4345
4476
|
if (url) {
|
|
4346
4477
|
const download = document.createElement("a");
|
|
4347
4478
|
download.href = url;
|
|
4348
4479
|
download.download = fileName;
|
|
4349
|
-
download.textContent =
|
|
4480
|
+
download.textContent = messages.textOpenOriginal;
|
|
4350
4481
|
fallback.append(download);
|
|
4351
4482
|
}
|
|
4352
4483
|
return fallback;
|
|
@@ -7408,7 +7539,7 @@ function officePlugin(options = {}) {
|
|
|
7408
7539
|
} else if (packageFormat === "docx" && !fileIsDocx(extension)) {
|
|
7409
7540
|
disposeDocxFit = await renderDocx(panel, arrayBuffer, ctx.options.fit);
|
|
7410
7541
|
} else if (packageFormat === "xlsx" && !sheetExtensions.has(extension)) {
|
|
7411
|
-
await renderSheet(panel, arrayBuffer, "xlsx");
|
|
7542
|
+
await renderSheet(panel, arrayBuffer, "xlsx", ctx.options.messages);
|
|
7412
7543
|
} else if (packageFormat === "pptx" && !["pptx", "pptm", "ppsx", "ppsm", "potx", "potm"].includes(extension)) {
|
|
7413
7544
|
await renderPptx(panel, arrayBuffer);
|
|
7414
7545
|
} else if (fileIsDocx(extension)) {
|
|
@@ -7421,9 +7552,9 @@ function officePlugin(options = {}) {
|
|
|
7421
7552
|
renderOpenDocumentXml(panel, "FODT \u6587\u6863", await readTextFromBuffer(arrayBuffer));
|
|
7422
7553
|
} else if (extension === "fods") {
|
|
7423
7554
|
renderFlatOds(panel, await readTextFromBuffer(arrayBuffer));
|
|
7424
|
-
} else if (packagedOfficeCandidates.has(extension) && await renderPackagedOfficePreview(panel, arrayBuffer, extension, ctx.options.fit)) {
|
|
7555
|
+
} else if (packagedOfficeCandidates.has(extension) && await renderPackagedOfficePreview(panel, arrayBuffer, extension, ctx.options.fit, ctx.options.messages)) {
|
|
7425
7556
|
} else if (sheetExtensions.has(extension)) {
|
|
7426
|
-
await renderSheet(panel, arrayBuffer, extension);
|
|
7557
|
+
await renderSheet(panel, arrayBuffer, extension, ctx.options.messages);
|
|
7427
7558
|
} else if (["pptx", "pptm", "ppsx", "ppsm", "potx", "potm"].includes(extension)) {
|
|
7428
7559
|
await renderPptx(panel, arrayBuffer);
|
|
7429
7560
|
} else if (extension === "odp") {
|
|
@@ -7431,11 +7562,11 @@ function officePlugin(options = {}) {
|
|
|
7431
7562
|
} else if (extension === "fodp") {
|
|
7432
7563
|
renderOpenDocumentPresentationXml(panel, await readTextFromBuffer(arrayBuffer));
|
|
7433
7564
|
} else if (extension === "doc" || extension === "dot") {
|
|
7434
|
-
renderLegacyWordBinary(panel, extension, arrayBuffer);
|
|
7565
|
+
renderLegacyWordBinary(panel, extension, arrayBuffer, ctx.options.messages);
|
|
7435
7566
|
} else if (isLegacyOfficeBinary(extension)) {
|
|
7436
|
-
renderLegacyOfficeBinary(panel, extension, arrayBuffer);
|
|
7567
|
+
renderLegacyOfficeBinary(panel, extension, arrayBuffer, ctx.options.messages);
|
|
7437
7568
|
} else {
|
|
7438
|
-
renderUnsupportedOffice(panel, extension || ctx.file.extension || "office");
|
|
7569
|
+
renderUnsupportedOffice(panel, extension || ctx.file.extension || "office", ctx.options.messages);
|
|
7439
7570
|
}
|
|
7440
7571
|
const controller = createOfficeZoomController(panel, ctx);
|
|
7441
7572
|
ctx.toolbar?.refreshCommandSupport();
|
|
@@ -8780,7 +8911,7 @@ function renderPlainDocument(panel, title, text) {
|
|
|
8780
8911
|
section.append(pre);
|
|
8781
8912
|
panel.append(section);
|
|
8782
8913
|
}
|
|
8783
|
-
async function renderSheet(panel, arrayBuffer, extension) {
|
|
8914
|
+
async function renderSheet(panel, arrayBuffer, extension, messages) {
|
|
8784
8915
|
const xlsx = await import("xlsx");
|
|
8785
8916
|
let workbook;
|
|
8786
8917
|
try {
|
|
@@ -8793,10 +8924,16 @@ async function renderSheet(panel, arrayBuffer, extension) {
|
|
|
8793
8924
|
}) : xlsx.read(arrayBuffer, { type: "array", cellDates: true, cellNF: true, cellStyles: true });
|
|
8794
8925
|
} catch (error) {
|
|
8795
8926
|
if (isLegacyOfficeBinary(extension)) {
|
|
8796
|
-
renderLegacyOfficeBinary(
|
|
8927
|
+
renderLegacyOfficeBinary(
|
|
8928
|
+
panel,
|
|
8929
|
+
extension,
|
|
8930
|
+
arrayBuffer,
|
|
8931
|
+
messages,
|
|
8932
|
+
formatPreviewMessage(messages.officeSheetParseFailed, { message: normalizeOfficeError(error, messages) })
|
|
8933
|
+
);
|
|
8797
8934
|
return;
|
|
8798
8935
|
}
|
|
8799
|
-
renderSheetFallback(panel, extension, normalizeOfficeError(error));
|
|
8936
|
+
renderSheetFallback(panel, extension, normalizeOfficeError(error, messages));
|
|
8800
8937
|
return;
|
|
8801
8938
|
}
|
|
8802
8939
|
const chartPreviews = await readWorkbookCharts(arrayBuffer).catch(() => []);
|
|
@@ -10057,10 +10194,15 @@ function pptxRenderTimeoutMs() {
|
|
|
10057
10194
|
function normalizePptxLayout(container) {
|
|
10058
10195
|
const slideCanvases = findPptxSlideCanvases(container);
|
|
10059
10196
|
for (const slide of slideCanvases) {
|
|
10060
|
-
slide
|
|
10197
|
+
if (!hasInlineBackground(slide)) {
|
|
10198
|
+
slide.style.backgroundColor = "#FFFFFF";
|
|
10199
|
+
}
|
|
10061
10200
|
}
|
|
10062
10201
|
normalizePptxMirroredText(container);
|
|
10063
10202
|
}
|
|
10203
|
+
function hasInlineBackground(element) {
|
|
10204
|
+
return Boolean(element.style.background || element.style.backgroundColor || element.style.backgroundImage);
|
|
10205
|
+
}
|
|
10064
10206
|
function normalizePptxMirroredText(container) {
|
|
10065
10207
|
const mirroredContainers = Array.from(container.querySelectorAll("div")).filter((element) => {
|
|
10066
10208
|
const text = element.textContent?.trim();
|
|
@@ -10152,7 +10294,7 @@ function renderOpenDocumentPresentationXml(panel, xml) {
|
|
|
10152
10294
|
renderPresentationInsight(panel, inspectOpenDocumentPresentation("FODP \u6F14\u793A\u6587\u7A3F", xml, 0));
|
|
10153
10295
|
renderOpenDocumentPresentation(panel, "FODP \u6F14\u793A\u6587\u7A3F", xml, []);
|
|
10154
10296
|
}
|
|
10155
|
-
async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit) {
|
|
10297
|
+
async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit, messages) {
|
|
10156
10298
|
let zip;
|
|
10157
10299
|
try {
|
|
10158
10300
|
zip = await JSZip3.loadAsync(arrayBuffer);
|
|
@@ -10167,7 +10309,7 @@ async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit) {
|
|
|
10167
10309
|
return true;
|
|
10168
10310
|
}
|
|
10169
10311
|
if (hasEntry("xl/workbook.xml")) {
|
|
10170
|
-
await renderSheet(panel, arrayBuffer, extension);
|
|
10312
|
+
await renderSheet(panel, arrayBuffer, extension, messages);
|
|
10171
10313
|
return true;
|
|
10172
10314
|
}
|
|
10173
10315
|
if (hasEntry("ppt/presentation.xml")) {
|
|
@@ -10598,41 +10740,50 @@ function legacyOfficeFormatLabel(extension) {
|
|
|
10598
10740
|
}
|
|
10599
10741
|
return "PowerPoint Binary File Format";
|
|
10600
10742
|
}
|
|
10601
|
-
function renderLegacyWordBinary(panel, extension, arrayBuffer) {
|
|
10743
|
+
function renderLegacyWordBinary(panel, extension, arrayBuffer, messages) {
|
|
10602
10744
|
try {
|
|
10603
10745
|
renderLegacyWordDocument(panel, parseLegacyWordDocument(arrayBuffer));
|
|
10604
10746
|
} catch (error) {
|
|
10605
|
-
renderLegacyOfficeBinary(
|
|
10747
|
+
renderLegacyOfficeBinary(
|
|
10748
|
+
panel,
|
|
10749
|
+
extension,
|
|
10750
|
+
arrayBuffer,
|
|
10751
|
+
messages,
|
|
10752
|
+
formatPreviewMessage(messages.officeLegacyWordParseFailed, { message: normalizeOfficeError(error, messages) })
|
|
10753
|
+
);
|
|
10606
10754
|
}
|
|
10607
10755
|
}
|
|
10608
|
-
function renderLegacyOfficeBinary(panel, extension, arrayBuffer, parseError) {
|
|
10756
|
+
function renderLegacyOfficeBinary(panel, extension, arrayBuffer, messages, parseError) {
|
|
10609
10757
|
const fragments = extractLegacyOfficeText(arrayBuffer);
|
|
10610
10758
|
panel.replaceChildren();
|
|
10611
|
-
const section = createSection(
|
|
10759
|
+
const section = createSection(messages.officeLegacyConversionTitle);
|
|
10612
10760
|
section.classList.add("ofv-office-conversion");
|
|
10613
10761
|
const format = document.createElement("p");
|
|
10614
10762
|
const strong = document.createElement("strong");
|
|
10615
10763
|
strong.textContent = `.${extension}`;
|
|
10616
|
-
format.append(
|
|
10617
|
-
strong,
|
|
10618
|
-
document.createTextNode(
|
|
10619
|
-
" \u5C5E\u4E8E\u65E7\u7248 Microsoft Office \u4E8C\u8FDB\u5236\u683C\u5F0F\uFF0C\u6D4F\u89C8\u5668\u5185\u65E0\u6CD5\u9AD8\u4FDD\u771F\u89E3\u6790\uFF1B\u5F53\u524D\u4EC5\u5C55\u793A\u53EF\u4FE1\u6587\u672C\u7247\u6BB5\u548C\u7ED3\u6784\u6307\u7EB9\uFF0C\u5B8C\u6574\u6392\u7248\u5EFA\u8BAE\u63A5\u5165 LibreOffice/OnlyOffice \u670D\u52A1\u7AEF\u8F6C\u6362\u4E3A PDF/HTML\u3002"
|
|
10620
|
-
)
|
|
10621
|
-
);
|
|
10764
|
+
format.append(strong, document.createTextNode(" "), document.createTextNode(messages.officeLegacyBinaryNotice));
|
|
10622
10765
|
const meta = document.createElement("dl");
|
|
10623
10766
|
meta.className = "ofv-office-binary-meta";
|
|
10624
|
-
appendOfficeBinaryMeta(meta,
|
|
10625
|
-
appendOfficeBinaryMeta(
|
|
10626
|
-
|
|
10767
|
+
appendOfficeBinaryMeta(meta, messages.officeLegacyMetaFormatType, legacyOfficeFormatLabel(extension));
|
|
10768
|
+
appendOfficeBinaryMeta(
|
|
10769
|
+
meta,
|
|
10770
|
+
messages.officeLegacyMetaFileStructure,
|
|
10771
|
+
hasOleSignature(arrayBuffer) ? messages.officeLegacyOleDetected : messages.officeLegacyOleMissing
|
|
10772
|
+
);
|
|
10773
|
+
appendOfficeBinaryMeta(
|
|
10774
|
+
meta,
|
|
10775
|
+
messages.officeLegacyMetaTextFragments,
|
|
10776
|
+
formatPreviewMessage(messages.officeLegacyTextFragmentCount, { count: fragments.length.toLocaleString() })
|
|
10777
|
+
);
|
|
10627
10778
|
if (parseError) {
|
|
10628
|
-
appendOfficeBinaryMeta(meta,
|
|
10779
|
+
appendOfficeBinaryMeta(meta, messages.officeLegacyMetaParseStatus, parseError);
|
|
10629
10780
|
}
|
|
10630
10781
|
section.append(format, meta);
|
|
10631
10782
|
if (fragments.length > 0) {
|
|
10632
10783
|
const article = document.createElement("article");
|
|
10633
10784
|
article.className = "ofv-document ofv-office-binary-fragments";
|
|
10634
10785
|
const heading = document.createElement("h4");
|
|
10635
|
-
heading.textContent =
|
|
10786
|
+
heading.textContent = messages.officeLegacyReadableFragments;
|
|
10636
10787
|
article.append(heading);
|
|
10637
10788
|
for (const fragment of fragments.slice(0, 80)) {
|
|
10638
10789
|
const paragraph = document.createElement("p");
|
|
@@ -10643,7 +10794,7 @@ function renderLegacyOfficeBinary(panel, extension, arrayBuffer, parseError) {
|
|
|
10643
10794
|
} else {
|
|
10644
10795
|
const empty = document.createElement("p");
|
|
10645
10796
|
empty.className = "ofv-office-binary-empty";
|
|
10646
|
-
empty.textContent =
|
|
10797
|
+
empty.textContent = messages.officeLegacyNoText;
|
|
10647
10798
|
section.append(empty);
|
|
10648
10799
|
}
|
|
10649
10800
|
panel.append(section);
|
|
@@ -10655,23 +10806,27 @@ function appendOfficeBinaryMeta(list, label, value) {
|
|
|
10655
10806
|
detail.textContent = value;
|
|
10656
10807
|
list.append(term, detail);
|
|
10657
10808
|
}
|
|
10658
|
-
function renderUnsupportedOffice(panel, extension) {
|
|
10809
|
+
function renderUnsupportedOffice(panel, extension, messages) {
|
|
10659
10810
|
const legacyBinary = /* @__PURE__ */ new Set(["doc", "dot", "wps", "ppt", "pps", "key", "dps"]);
|
|
10660
|
-
const message = legacyBinary.has(extension) ?
|
|
10811
|
+
const message = legacyBinary.has(extension) ? messages.officeUnsupportedLegacyMessage : messages.officeUnsupportedGenericMessage;
|
|
10661
10812
|
panel.replaceChildren();
|
|
10662
|
-
const section = createSection(
|
|
10813
|
+
const section = createSection(messages.officeUnsupportedTitle);
|
|
10663
10814
|
const format = document.createElement("p");
|
|
10664
10815
|
const strong = document.createElement("strong");
|
|
10665
10816
|
strong.textContent = `.${extension}`;
|
|
10666
|
-
format.append(
|
|
10817
|
+
format.append(
|
|
10818
|
+
strong,
|
|
10819
|
+
document.createTextNode(" "),
|
|
10820
|
+
document.createTextNode(formatPreviewMessage(messages.officeUnsupportedIntro, { message }))
|
|
10821
|
+
);
|
|
10667
10822
|
const support = document.createElement("p");
|
|
10668
|
-
support.textContent =
|
|
10823
|
+
support.textContent = messages.officeUnsupportedSupportedFormats;
|
|
10669
10824
|
section.append(format, support);
|
|
10670
10825
|
panel.append(section);
|
|
10671
10826
|
}
|
|
10672
|
-
function normalizeOfficeError(error) {
|
|
10827
|
+
function normalizeOfficeError(error, messages) {
|
|
10673
10828
|
const message = error instanceof Error ? error.message : String(error || "");
|
|
10674
|
-
return message ?
|
|
10829
|
+
return message ? formatPreviewMessage(messages.officeErrorWithMessage, { message }) : messages.officeErrorWithoutMessage;
|
|
10675
10830
|
}
|
|
10676
10831
|
function extractLegacyOfficeText(arrayBuffer) {
|
|
10677
10832
|
const bytes = new Uint8Array(arrayBuffer);
|
|
@@ -11913,11 +12068,13 @@ function archivePlugin() {
|
|
|
11913
12068
|
sidebarToggle.addEventListener("click", () => {
|
|
11914
12069
|
setSidebarCollapsed(!layout.classList.contains("is-sidebar-collapsed"));
|
|
11915
12070
|
});
|
|
11916
|
-
const showDefaultSummary = () => {
|
|
12071
|
+
const showDefaultSummary = (isSupplemental = true) => {
|
|
11917
12072
|
mainPanel.replaceChildren();
|
|
11918
12073
|
const summary = document.createElement("div");
|
|
11919
12074
|
summary.className = "ofv-archive-info";
|
|
11920
|
-
|
|
12075
|
+
if (isSupplemental) {
|
|
12076
|
+
hideSupplementalInfo4(summary);
|
|
12077
|
+
}
|
|
11921
12078
|
const heading = document.createElement("h3");
|
|
11922
12079
|
heading.textContent = ctx.file.name;
|
|
11923
12080
|
const info = document.createElement("div");
|
|
@@ -11927,12 +12084,16 @@ function archivePlugin() {
|
|
|
11927
12084
|
appendArchiveInfo(info, "\u683C\u5F0F\u7C7B\u578B", `.${ext.toUpperCase()} \u538B\u7F29\u6587\u4EF6`);
|
|
11928
12085
|
appendArchiveInfo(info, "\u5305\u542B\u6587\u4EF6\u6570", `${fileCount} \u4E2A`);
|
|
11929
12086
|
appendArchiveInfo(info, "\u5305\u542B\u76EE\u5F55\u6570", `${dirCount} \u4E2A`);
|
|
11930
|
-
appendArchiveInfo(
|
|
12087
|
+
appendArchiveInfo(
|
|
12088
|
+
info,
|
|
12089
|
+
"\u64CD\u4F5C\u63D0\u793A",
|
|
12090
|
+
fileCount === 0 ? "\u538B\u7F29\u5305\u5185\u6CA1\u6709\u53EF\u9884\u89C8\u7684\u6587\u4EF6\u3002" : "\u8BF7\u70B9\u51FB\u5DE6\u4FA7\u680F\u4E2D\u7684\u6587\u4EF6\u8FDB\u884C\u8054\u52A8\u9884\u89C8\u3002"
|
|
12091
|
+
);
|
|
11931
12092
|
summary.append(heading, info, createArchiveSummary(archiveEntries));
|
|
11932
12093
|
mainPanel.append(summary);
|
|
11933
12094
|
};
|
|
11934
|
-
showDefaultSummary();
|
|
11935
12095
|
const visibleEntries = archiveEntries.filter((e) => !e.dir).slice(0, 500);
|
|
12096
|
+
showDefaultSummary(visibleEntries.length > 0);
|
|
11936
12097
|
let destroyed = false;
|
|
11937
12098
|
let renderToken = 0;
|
|
11938
12099
|
const openArchiveEntry = async (entry, item) => {
|