@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.cjs
CHANGED
|
@@ -622,7 +622,40 @@ var defaultMessages = {
|
|
|
622
622
|
size: "\u5927\u5C0F",
|
|
623
623
|
source: "\u6765\u6E90",
|
|
624
624
|
remoteUrl: "\u8FDC\u7A0B URL",
|
|
625
|
-
localFile: "\u672C\u5730/\u5185\u5B58\u6587\u4EF6"
|
|
625
|
+
localFile: "\u672C\u5730/\u5185\u5B58\u6587\u4EF6",
|
|
626
|
+
textPlainLanguage: "\u7EAF\u6587\u672C",
|
|
627
|
+
textLineCount: "{count} \u884C",
|
|
628
|
+
textWrap: "\u6362\u884C",
|
|
629
|
+
textCopy: "\u590D\u5236",
|
|
630
|
+
textCopied: "\u5DF2\u590D\u5236",
|
|
631
|
+
textCopyFailed: "\u590D\u5236\u5931\u8D25",
|
|
632
|
+
textDownload: "\u4E0B\u8F7D",
|
|
633
|
+
textDownloadReady: "\u4E0B\u8F7D\u5DF2\u51C6\u5907",
|
|
634
|
+
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",
|
|
635
|
+
textHighlightSkipped: "\u5185\u5BB9\u8F83\u5927\uFF0C\u5DF2\u8DF3\u8FC7\u8BED\u6CD5\u9AD8\u4EAE\u4EE5\u4FDD\u6301\u6EDA\u52A8\u6D41\u7545\u3002",
|
|
636
|
+
textPreviewFailedTitle: "\u6587\u672C\u9884\u89C8\u5931\u8D25",
|
|
637
|
+
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",
|
|
638
|
+
textOpenOriginal: "\u6253\u5F00\u539F\u6587\u4EF6",
|
|
639
|
+
officeLegacyConversionTitle: "Office \u8F6C\u6362\u63D0\u793A",
|
|
640
|
+
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",
|
|
641
|
+
officeLegacyMetaFormatType: "\u683C\u5F0F\u7C7B\u578B",
|
|
642
|
+
officeLegacyMetaFileStructure: "\u6587\u4EF6\u7ED3\u6784",
|
|
643
|
+
officeLegacyOleDetected: "\u68C0\u6D4B\u5230 OLE Compound File \u7B7E\u540D",
|
|
644
|
+
officeLegacyOleMissing: "\u672A\u68C0\u6D4B\u5230\u6807\u51C6 OLE \u7B7E\u540D\uFF0C\u6309\u539F\u59CB\u4E8C\u8FDB\u5236\u5C1D\u8BD5\u63D0\u53D6",
|
|
645
|
+
officeLegacyMetaTextFragments: "\u6587\u672C\u7247\u6BB5",
|
|
646
|
+
officeLegacyTextFragmentCount: "{count} \u6BB5",
|
|
647
|
+
officeLegacyMetaParseStatus: "\u89E3\u6790\u72B6\u6001",
|
|
648
|
+
officeLegacyReadableFragments: "\u53EF\u8BFB\u6587\u672C\u7247\u6BB5",
|
|
649
|
+
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",
|
|
650
|
+
officeLegacyWordParseFailed: "Word \u4E8C\u8FDB\u5236\u89E3\u6790\u5931\u8D25\uFF1A{message}",
|
|
651
|
+
officeSheetParseFailed: "\u8868\u683C\u89E3\u6790\u5931\u8D25\uFF1A{message}",
|
|
652
|
+
officeUnsupportedTitle: "Office \u57FA\u7840\u9884\u89C8",
|
|
653
|
+
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",
|
|
654
|
+
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",
|
|
655
|
+
officeUnsupportedIntro: "\u5DF2\u8FDB\u5165 Office \u63D2\u4EF6\u3002{message}",
|
|
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
|
+
officeErrorWithMessage: "\u89E3\u6790\u5668\u8FD4\u56DE\uFF1A{message}",
|
|
658
|
+
officeErrorWithoutMessage: "\u89E3\u6790\u5668\u672A\u8FD4\u56DE\u5177\u4F53\u9519\u8BEF\u4FE1\u606F\u3002"
|
|
626
659
|
},
|
|
627
660
|
"en-US": {
|
|
628
661
|
loading: "Loading preview...",
|
|
@@ -638,7 +671,40 @@ var defaultMessages = {
|
|
|
638
671
|
size: "Size",
|
|
639
672
|
source: "Source",
|
|
640
673
|
remoteUrl: "Remote URL",
|
|
641
|
-
localFile: "Local or in-memory file"
|
|
674
|
+
localFile: "Local or in-memory file",
|
|
675
|
+
textPlainLanguage: "plain text",
|
|
676
|
+
textLineCount: "{count} lines",
|
|
677
|
+
textWrap: "Wrap",
|
|
678
|
+
textCopy: "Copy",
|
|
679
|
+
textCopied: "Copied",
|
|
680
|
+
textCopyFailed: "Copy failed",
|
|
681
|
+
textDownload: "Download",
|
|
682
|
+
textDownloadReady: "Download ready",
|
|
683
|
+
textLargeFileNotice: "Large file, showing the first {size}. Copy and download still use the full content.",
|
|
684
|
+
textHighlightSkipped: "Large content, syntax highlighting was skipped to keep scrolling smooth.",
|
|
685
|
+
textPreviewFailedTitle: "Text preview failed",
|
|
686
|
+
textPreviewFailedMessage: "Unable to read this text content. The remote file may be unreachable or returned an invalid response.",
|
|
687
|
+
textOpenOriginal: "Open original file",
|
|
688
|
+
officeLegacyConversionTitle: "Office conversion guidance",
|
|
689
|
+
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.",
|
|
690
|
+
officeLegacyMetaFormatType: "Format type",
|
|
691
|
+
officeLegacyMetaFileStructure: "File structure",
|
|
692
|
+
officeLegacyOleDetected: "OLE Compound File signature detected",
|
|
693
|
+
officeLegacyOleMissing: "No standard OLE signature detected; extracting from raw binary data",
|
|
694
|
+
officeLegacyMetaTextFragments: "Text fragments",
|
|
695
|
+
officeLegacyTextFragmentCount: "{count} fragments",
|
|
696
|
+
officeLegacyMetaParseStatus: "Parse status",
|
|
697
|
+
officeLegacyReadableFragments: "Readable text fragments",
|
|
698
|
+
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.",
|
|
699
|
+
officeLegacyWordParseFailed: "Word binary parse failed: {message}",
|
|
700
|
+
officeSheetParseFailed: "Spreadsheet parse failed: {message}",
|
|
701
|
+
officeUnsupportedTitle: "Office basic preview",
|
|
702
|
+
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.",
|
|
703
|
+
officeUnsupportedGenericMessage: "This format usually needs server-side conversion or a dedicated parser for high-fidelity preview.",
|
|
704
|
+
officeUnsupportedIntro: "is handled by the Office plugin. {message}",
|
|
705
|
+
officeUnsupportedSupportedFormats: "This version prioritizes basic previews for docx, rtf, odt/fodt, xlsx/xls/csv/ods, pptx/ppsx, and odp/fodp files.",
|
|
706
|
+
officeErrorWithMessage: "Parser returned: {message}",
|
|
707
|
+
officeErrorWithoutMessage: "Parser did not return a specific error."
|
|
642
708
|
}
|
|
643
709
|
};
|
|
644
710
|
function resolveMessages(options) {
|
|
@@ -647,6 +713,9 @@ function resolveMessages(options) {
|
|
|
647
713
|
...options.messages
|
|
648
714
|
};
|
|
649
715
|
}
|
|
716
|
+
function formatPreviewMessage(template, values) {
|
|
717
|
+
return template.replace(/\{(\w+)\}/g, (match, key) => String(values[key] ?? match));
|
|
718
|
+
}
|
|
650
719
|
|
|
651
720
|
// src/plugins/fallback.ts
|
|
652
721
|
function fallbackPlugin() {
|
|
@@ -717,9 +786,10 @@ function formatFallbackBytes(bytes) {
|
|
|
717
786
|
function createViewer(options) {
|
|
718
787
|
const container = resolveContainer(options.container);
|
|
719
788
|
applyBoxSize(container, options.width, options.height);
|
|
789
|
+
const customClassNames = parseClassNameTokens(options.className);
|
|
720
790
|
container.classList.add("ofv-root");
|
|
721
|
-
if (
|
|
722
|
-
container.classList.add(
|
|
791
|
+
if (customClassNames.length > 0) {
|
|
792
|
+
container.classList.add(...customClassNames);
|
|
723
793
|
}
|
|
724
794
|
const theme = applyTheme(container, options.theme || "light");
|
|
725
795
|
const host = document.createElement("div");
|
|
@@ -863,12 +933,15 @@ function createViewer(options) {
|
|
|
863
933
|
theme.destroy();
|
|
864
934
|
container.replaceChildren();
|
|
865
935
|
container.classList.remove("ofv-root");
|
|
866
|
-
if (
|
|
867
|
-
container.classList.remove(
|
|
936
|
+
if (customClassNames.length > 0) {
|
|
937
|
+
container.classList.remove(...customClassNames);
|
|
868
938
|
}
|
|
869
939
|
}
|
|
870
940
|
};
|
|
871
941
|
}
|
|
942
|
+
function parseClassNameTokens(className) {
|
|
943
|
+
return className?.trim().split(/\s+/).filter(Boolean) ?? [];
|
|
944
|
+
}
|
|
872
945
|
function destroyPreviewInstance(instance) {
|
|
873
946
|
if (!instance) {
|
|
874
947
|
return;
|
|
@@ -994,6 +1067,7 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
994
1067
|
let previousButton;
|
|
995
1068
|
let nextButton;
|
|
996
1069
|
let zoomResetButton;
|
|
1070
|
+
let fullscreenButton;
|
|
997
1071
|
let currentZoom;
|
|
998
1072
|
const commandButtons = [];
|
|
999
1073
|
const customButtons = [];
|
|
@@ -1099,13 +1173,14 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1099
1173
|
return;
|
|
1100
1174
|
}
|
|
1101
1175
|
if (id === "fullscreen" && options.fullscreen !== false) {
|
|
1102
|
-
addButton(
|
|
1176
|
+
fullscreenButton = addButton(
|
|
1103
1177
|
getToolbarLabel(options, id),
|
|
1104
1178
|
getToolbarTitle(options, id),
|
|
1105
1179
|
() => getContext().fullscreen(),
|
|
1106
1180
|
void 0,
|
|
1107
1181
|
options.icons?.fullscreen
|
|
1108
1182
|
);
|
|
1183
|
+
updateFullscreenButton();
|
|
1109
1184
|
return;
|
|
1110
1185
|
}
|
|
1111
1186
|
if (id === "print" && options.print) {
|
|
@@ -1207,6 +1282,32 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1207
1282
|
updateCustomButtons();
|
|
1208
1283
|
refreshCustomRender();
|
|
1209
1284
|
}
|
|
1285
|
+
function isFullscreenActive() {
|
|
1286
|
+
return Boolean(
|
|
1287
|
+
typeof document !== "undefined" && element.parentElement && document.fullscreenElement === element.parentElement
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1290
|
+
function updateFullscreenButton() {
|
|
1291
|
+
if (!fullscreenButton) {
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
const active = isFullscreenActive();
|
|
1295
|
+
const id = active ? "exit-fullscreen" : "fullscreen";
|
|
1296
|
+
const icon = active ? options.icons?.["exit-fullscreen"] ?? options.icons?.fullscreen : options.icons?.fullscreen;
|
|
1297
|
+
setToolbarButtonContent(fullscreenButton, getToolbarLabel(options, id), icon);
|
|
1298
|
+
const title = getToolbarTitle(options, id);
|
|
1299
|
+
fullscreenButton.title = title;
|
|
1300
|
+
fullscreenButton.setAttribute("aria-label", title);
|
|
1301
|
+
fullscreenButton.setAttribute("aria-pressed", String(active));
|
|
1302
|
+
}
|
|
1303
|
+
const handleFullscreenChange = () => {
|
|
1304
|
+
updateFullscreenButton();
|
|
1305
|
+
refreshCustomRender();
|
|
1306
|
+
};
|
|
1307
|
+
if (typeof document !== "undefined") {
|
|
1308
|
+
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
1309
|
+
disposers.push(() => document.removeEventListener("fullscreenchange", handleFullscreenChange));
|
|
1310
|
+
}
|
|
1210
1311
|
const refreshCustomRender = () => {
|
|
1211
1312
|
if (!options.render) {
|
|
1212
1313
|
return;
|
|
@@ -1280,6 +1381,9 @@ function createToolbarContext({
|
|
|
1280
1381
|
viewport,
|
|
1281
1382
|
canPrevious: index > 0,
|
|
1282
1383
|
canNext: index < length - 1,
|
|
1384
|
+
isFullscreen: Boolean(
|
|
1385
|
+
typeof document !== "undefined" && element.parentElement && document.fullscreenElement === element.parentElement
|
|
1386
|
+
),
|
|
1283
1387
|
zoom,
|
|
1284
1388
|
zoomLabel: zoom === void 0 ? void 0 : formatToolbarZoom(zoom),
|
|
1285
1389
|
async previous() {
|
|
@@ -1298,7 +1402,15 @@ function createToolbarContext({
|
|
|
1298
1402
|
}
|
|
1299
1403
|
},
|
|
1300
1404
|
fullscreen() {
|
|
1301
|
-
|
|
1405
|
+
const target = element.parentElement;
|
|
1406
|
+
if (!target) {
|
|
1407
|
+
return;
|
|
1408
|
+
}
|
|
1409
|
+
if (typeof document !== "undefined" && document.fullscreenElement === target) {
|
|
1410
|
+
void document.exitFullscreen?.();
|
|
1411
|
+
} else {
|
|
1412
|
+
void target.requestFullscreen?.();
|
|
1413
|
+
}
|
|
1302
1414
|
},
|
|
1303
1415
|
print() {
|
|
1304
1416
|
printPreview(viewport);
|
|
@@ -1317,6 +1429,7 @@ var defaultToolbarLabels = {
|
|
|
1317
1429
|
"rotate-right": "Rotate",
|
|
1318
1430
|
download: "Download",
|
|
1319
1431
|
fullscreen: "Fullscreen",
|
|
1432
|
+
"exit-fullscreen": "Exit fullscreen",
|
|
1320
1433
|
print: "Print",
|
|
1321
1434
|
search: "Search"
|
|
1322
1435
|
};
|
|
@@ -1330,6 +1443,7 @@ var defaultToolbarTitles = {
|
|
|
1330
1443
|
"rotate-right": "Rotate right",
|
|
1331
1444
|
download: "Download file",
|
|
1332
1445
|
fullscreen: "Open preview fullscreen",
|
|
1446
|
+
"exit-fullscreen": "Exit fullscreen",
|
|
1333
1447
|
print: "Print preview",
|
|
1334
1448
|
search: "Search preview text"
|
|
1335
1449
|
};
|
|
@@ -1568,6 +1682,9 @@ function collectSearchableTextNodes(root) {
|
|
|
1568
1682
|
if (["SCRIPT", "STYLE", "TEXTAREA", "INPUT", "BUTTON"].includes(parent.tagName)) {
|
|
1569
1683
|
return NodeFilter.FILTER_REJECT;
|
|
1570
1684
|
}
|
|
1685
|
+
if (hasHiddenSearchAncestor(parent, root)) {
|
|
1686
|
+
return NodeFilter.FILTER_REJECT;
|
|
1687
|
+
}
|
|
1571
1688
|
return NodeFilter.FILTER_ACCEPT;
|
|
1572
1689
|
}
|
|
1573
1690
|
});
|
|
@@ -1578,6 +1695,19 @@ function collectSearchableTextNodes(root) {
|
|
|
1578
1695
|
}
|
|
1579
1696
|
return nodes;
|
|
1580
1697
|
}
|
|
1698
|
+
function hasHiddenSearchAncestor(element, root) {
|
|
1699
|
+
let current = element;
|
|
1700
|
+
while (current) {
|
|
1701
|
+
if (current.hidden || current.getAttribute("aria-hidden") === "true" || current.style.display === "none" || current.style.visibility === "hidden") {
|
|
1702
|
+
return true;
|
|
1703
|
+
}
|
|
1704
|
+
if (current === root) {
|
|
1705
|
+
break;
|
|
1706
|
+
}
|
|
1707
|
+
current = current.parentElement;
|
|
1708
|
+
}
|
|
1709
|
+
return false;
|
|
1710
|
+
}
|
|
1581
1711
|
function printPreview(viewport) {
|
|
1582
1712
|
const frame = document.createElement("iframe");
|
|
1583
1713
|
frame.className = "ofv-print-frame";
|
|
@@ -4075,7 +4205,7 @@ function textPlugin() {
|
|
|
4075
4205
|
const isMarkdown = lang === "markdown";
|
|
4076
4206
|
const text = await readText(ctx.file.source).catch((error) => void 0);
|
|
4077
4207
|
if (text === void 0) {
|
|
4078
|
-
const fallback = createTextFallback(ctx.file.name, ctx.file.url);
|
|
4208
|
+
const fallback = createTextFallback(ctx.file.name, ctx.options.messages, ctx.file.url);
|
|
4079
4209
|
ctx.viewport.classList.add("ofv-center");
|
|
4080
4210
|
ctx.viewport.append(fallback);
|
|
4081
4211
|
return {
|
|
@@ -4247,10 +4377,11 @@ function textPlugin() {
|
|
|
4247
4377
|
title.className = "ofv-code-title";
|
|
4248
4378
|
const fileName = document.createElement("strong");
|
|
4249
4379
|
fileName.textContent = ctx.file.name;
|
|
4380
|
+
const messages = ctx.options.messages;
|
|
4250
4381
|
const meta = document.createElement("span");
|
|
4251
4382
|
meta.textContent = [
|
|
4252
|
-
lang === "none" ?
|
|
4253
|
-
|
|
4383
|
+
lang === "none" ? messages.textPlainLanguage : lang,
|
|
4384
|
+
formatPreviewMessage(messages.textLineCount, { count: totalLines.toLocaleString() }),
|
|
4254
4385
|
formatBytes(ctx.file.size ?? (ctx.file.source instanceof Blob ? ctx.file.source.size : text.length))
|
|
4255
4386
|
].join(" \xB7 ");
|
|
4256
4387
|
title.append(fileName, meta);
|
|
@@ -4262,7 +4393,7 @@ function textPlugin() {
|
|
|
4262
4393
|
const wrapButton = document.createElement("button");
|
|
4263
4394
|
wrapButton.type = "button";
|
|
4264
4395
|
wrapButton.className = "ofv-code-action";
|
|
4265
|
-
wrapButton.textContent =
|
|
4396
|
+
wrapButton.textContent = messages.textWrap;
|
|
4266
4397
|
wrapButton.setAttribute("aria-pressed", String(defaultWrapped));
|
|
4267
4398
|
wrapButton.addEventListener("click", () => {
|
|
4268
4399
|
const wrapped = wrapper.classList.toggle("is-wrapped");
|
|
@@ -4271,14 +4402,14 @@ function textPlugin() {
|
|
|
4271
4402
|
const copyButton = document.createElement("button");
|
|
4272
4403
|
copyButton.type = "button";
|
|
4273
4404
|
copyButton.className = "ofv-code-action";
|
|
4274
|
-
copyButton.textContent =
|
|
4405
|
+
copyButton.textContent = messages.textCopy;
|
|
4275
4406
|
copyButton.addEventListener("click", async () => {
|
|
4276
4407
|
copyButton.disabled = true;
|
|
4277
4408
|
try {
|
|
4278
4409
|
await copyToClipboard(text);
|
|
4279
|
-
status.textContent =
|
|
4410
|
+
status.textContent = messages.textCopied;
|
|
4280
4411
|
} catch {
|
|
4281
|
-
status.textContent =
|
|
4412
|
+
status.textContent = messages.textCopyFailed;
|
|
4282
4413
|
} finally {
|
|
4283
4414
|
copyButton.disabled = false;
|
|
4284
4415
|
}
|
|
@@ -4286,10 +4417,10 @@ function textPlugin() {
|
|
|
4286
4417
|
const downloadButton = document.createElement("button");
|
|
4287
4418
|
downloadButton.type = "button";
|
|
4288
4419
|
downloadButton.className = "ofv-code-action";
|
|
4289
|
-
downloadButton.textContent =
|
|
4420
|
+
downloadButton.textContent = messages.textDownload;
|
|
4290
4421
|
downloadButton.addEventListener("click", () => {
|
|
4291
4422
|
downloadText(ctx.file.name, text);
|
|
4292
|
-
status.textContent =
|
|
4423
|
+
status.textContent = messages.textDownloadReady;
|
|
4293
4424
|
});
|
|
4294
4425
|
actions.append(wrapButton, copyButton, downloadButton, status);
|
|
4295
4426
|
header.append(title, actions);
|
|
@@ -4314,13 +4445,13 @@ function textPlugin() {
|
|
|
4314
4445
|
if (truncated) {
|
|
4315
4446
|
const notice = document.createElement("div");
|
|
4316
4447
|
notice.className = "ofv-code-notice";
|
|
4317
|
-
notice.textContent =
|
|
4448
|
+
notice.textContent = formatPreviewMessage(messages.textLargeFileNotice, { size: formatBytes(codeText.length) });
|
|
4318
4449
|
wrapper.append(notice);
|
|
4319
4450
|
}
|
|
4320
4451
|
if (!shouldHighlight) {
|
|
4321
4452
|
const notice = document.createElement("div");
|
|
4322
4453
|
notice.className = "ofv-code-notice";
|
|
4323
|
-
notice.textContent =
|
|
4454
|
+
notice.textContent = messages.textHighlightSkipped;
|
|
4324
4455
|
wrapper.append(notice);
|
|
4325
4456
|
}
|
|
4326
4457
|
wrapper.appendChild(body);
|
|
@@ -4387,19 +4518,19 @@ function normalizeFileName2(name) {
|
|
|
4387
4518
|
const baseName = name.split(/[\\/]/).pop() || name;
|
|
4388
4519
|
return baseName.toLowerCase();
|
|
4389
4520
|
}
|
|
4390
|
-
function createTextFallback(fileName, url) {
|
|
4521
|
+
function createTextFallback(fileName, messages, url) {
|
|
4391
4522
|
const fallback = document.createElement("div");
|
|
4392
4523
|
fallback.className = "ofv-fallback";
|
|
4393
4524
|
const title = document.createElement("strong");
|
|
4394
|
-
title.textContent =
|
|
4525
|
+
title.textContent = messages.textPreviewFailedTitle;
|
|
4395
4526
|
const meta = document.createElement("span");
|
|
4396
|
-
meta.textContent =
|
|
4527
|
+
meta.textContent = messages.textPreviewFailedMessage;
|
|
4397
4528
|
fallback.append(title, meta);
|
|
4398
4529
|
if (url) {
|
|
4399
4530
|
const download = document.createElement("a");
|
|
4400
4531
|
download.href = url;
|
|
4401
4532
|
download.download = fileName;
|
|
4402
|
-
download.textContent =
|
|
4533
|
+
download.textContent = messages.textOpenOriginal;
|
|
4403
4534
|
fallback.append(download);
|
|
4404
4535
|
}
|
|
4405
4536
|
return fallback;
|
|
@@ -7461,7 +7592,7 @@ function officePlugin(options = {}) {
|
|
|
7461
7592
|
} else if (packageFormat === "docx" && !fileIsDocx(extension)) {
|
|
7462
7593
|
disposeDocxFit = await renderDocx(panel, arrayBuffer, ctx.options.fit);
|
|
7463
7594
|
} else if (packageFormat === "xlsx" && !sheetExtensions.has(extension)) {
|
|
7464
|
-
await renderSheet(panel, arrayBuffer, "xlsx");
|
|
7595
|
+
await renderSheet(panel, arrayBuffer, "xlsx", ctx.options.messages);
|
|
7465
7596
|
} else if (packageFormat === "pptx" && !["pptx", "pptm", "ppsx", "ppsm", "potx", "potm"].includes(extension)) {
|
|
7466
7597
|
await renderPptx(panel, arrayBuffer);
|
|
7467
7598
|
} else if (fileIsDocx(extension)) {
|
|
@@ -7474,9 +7605,9 @@ function officePlugin(options = {}) {
|
|
|
7474
7605
|
renderOpenDocumentXml(panel, "FODT \u6587\u6863", await readTextFromBuffer(arrayBuffer));
|
|
7475
7606
|
} else if (extension === "fods") {
|
|
7476
7607
|
renderFlatOds(panel, await readTextFromBuffer(arrayBuffer));
|
|
7477
|
-
} else if (packagedOfficeCandidates.has(extension) && await renderPackagedOfficePreview(panel, arrayBuffer, extension, ctx.options.fit)) {
|
|
7608
|
+
} else if (packagedOfficeCandidates.has(extension) && await renderPackagedOfficePreview(panel, arrayBuffer, extension, ctx.options.fit, ctx.options.messages)) {
|
|
7478
7609
|
} else if (sheetExtensions.has(extension)) {
|
|
7479
|
-
await renderSheet(panel, arrayBuffer, extension);
|
|
7610
|
+
await renderSheet(panel, arrayBuffer, extension, ctx.options.messages);
|
|
7480
7611
|
} else if (["pptx", "pptm", "ppsx", "ppsm", "potx", "potm"].includes(extension)) {
|
|
7481
7612
|
await renderPptx(panel, arrayBuffer);
|
|
7482
7613
|
} else if (extension === "odp") {
|
|
@@ -7484,11 +7615,11 @@ function officePlugin(options = {}) {
|
|
|
7484
7615
|
} else if (extension === "fodp") {
|
|
7485
7616
|
renderOpenDocumentPresentationXml(panel, await readTextFromBuffer(arrayBuffer));
|
|
7486
7617
|
} else if (extension === "doc" || extension === "dot") {
|
|
7487
|
-
renderLegacyWordBinary(panel, extension, arrayBuffer);
|
|
7618
|
+
renderLegacyWordBinary(panel, extension, arrayBuffer, ctx.options.messages);
|
|
7488
7619
|
} else if (isLegacyOfficeBinary(extension)) {
|
|
7489
|
-
renderLegacyOfficeBinary(panel, extension, arrayBuffer);
|
|
7620
|
+
renderLegacyOfficeBinary(panel, extension, arrayBuffer, ctx.options.messages);
|
|
7490
7621
|
} else {
|
|
7491
|
-
renderUnsupportedOffice(panel, extension || ctx.file.extension || "office");
|
|
7622
|
+
renderUnsupportedOffice(panel, extension || ctx.file.extension || "office", ctx.options.messages);
|
|
7492
7623
|
}
|
|
7493
7624
|
const controller = createOfficeZoomController(panel, ctx);
|
|
7494
7625
|
ctx.toolbar?.refreshCommandSupport();
|
|
@@ -8833,7 +8964,7 @@ function renderPlainDocument(panel, title, text) {
|
|
|
8833
8964
|
section.append(pre);
|
|
8834
8965
|
panel.append(section);
|
|
8835
8966
|
}
|
|
8836
|
-
async function renderSheet(panel, arrayBuffer, extension) {
|
|
8967
|
+
async function renderSheet(panel, arrayBuffer, extension, messages) {
|
|
8837
8968
|
const xlsx = await import("xlsx");
|
|
8838
8969
|
let workbook;
|
|
8839
8970
|
try {
|
|
@@ -8846,10 +8977,16 @@ async function renderSheet(panel, arrayBuffer, extension) {
|
|
|
8846
8977
|
}) : xlsx.read(arrayBuffer, { type: "array", cellDates: true, cellNF: true, cellStyles: true });
|
|
8847
8978
|
} catch (error) {
|
|
8848
8979
|
if (isLegacyOfficeBinary(extension)) {
|
|
8849
|
-
renderLegacyOfficeBinary(
|
|
8980
|
+
renderLegacyOfficeBinary(
|
|
8981
|
+
panel,
|
|
8982
|
+
extension,
|
|
8983
|
+
arrayBuffer,
|
|
8984
|
+
messages,
|
|
8985
|
+
formatPreviewMessage(messages.officeSheetParseFailed, { message: normalizeOfficeError(error, messages) })
|
|
8986
|
+
);
|
|
8850
8987
|
return;
|
|
8851
8988
|
}
|
|
8852
|
-
renderSheetFallback(panel, extension, normalizeOfficeError(error));
|
|
8989
|
+
renderSheetFallback(panel, extension, normalizeOfficeError(error, messages));
|
|
8853
8990
|
return;
|
|
8854
8991
|
}
|
|
8855
8992
|
const chartPreviews = await readWorkbookCharts(arrayBuffer).catch(() => []);
|
|
@@ -10110,10 +10247,15 @@ function pptxRenderTimeoutMs() {
|
|
|
10110
10247
|
function normalizePptxLayout(container) {
|
|
10111
10248
|
const slideCanvases = findPptxSlideCanvases(container);
|
|
10112
10249
|
for (const slide of slideCanvases) {
|
|
10113
|
-
slide
|
|
10250
|
+
if (!hasInlineBackground(slide)) {
|
|
10251
|
+
slide.style.backgroundColor = "#FFFFFF";
|
|
10252
|
+
}
|
|
10114
10253
|
}
|
|
10115
10254
|
normalizePptxMirroredText(container);
|
|
10116
10255
|
}
|
|
10256
|
+
function hasInlineBackground(element) {
|
|
10257
|
+
return Boolean(element.style.background || element.style.backgroundColor || element.style.backgroundImage);
|
|
10258
|
+
}
|
|
10117
10259
|
function normalizePptxMirroredText(container) {
|
|
10118
10260
|
const mirroredContainers = Array.from(container.querySelectorAll("div")).filter((element) => {
|
|
10119
10261
|
const text = element.textContent?.trim();
|
|
@@ -10205,7 +10347,7 @@ function renderOpenDocumentPresentationXml(panel, xml) {
|
|
|
10205
10347
|
renderPresentationInsight(panel, inspectOpenDocumentPresentation("FODP \u6F14\u793A\u6587\u7A3F", xml, 0));
|
|
10206
10348
|
renderOpenDocumentPresentation(panel, "FODP \u6F14\u793A\u6587\u7A3F", xml, []);
|
|
10207
10349
|
}
|
|
10208
|
-
async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit) {
|
|
10350
|
+
async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit, messages) {
|
|
10209
10351
|
let zip;
|
|
10210
10352
|
try {
|
|
10211
10353
|
zip = await import_jszip3.default.loadAsync(arrayBuffer);
|
|
@@ -10220,7 +10362,7 @@ async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit) {
|
|
|
10220
10362
|
return true;
|
|
10221
10363
|
}
|
|
10222
10364
|
if (hasEntry("xl/workbook.xml")) {
|
|
10223
|
-
await renderSheet(panel, arrayBuffer, extension);
|
|
10365
|
+
await renderSheet(panel, arrayBuffer, extension, messages);
|
|
10224
10366
|
return true;
|
|
10225
10367
|
}
|
|
10226
10368
|
if (hasEntry("ppt/presentation.xml")) {
|
|
@@ -10651,41 +10793,50 @@ function legacyOfficeFormatLabel(extension) {
|
|
|
10651
10793
|
}
|
|
10652
10794
|
return "PowerPoint Binary File Format";
|
|
10653
10795
|
}
|
|
10654
|
-
function renderLegacyWordBinary(panel, extension, arrayBuffer) {
|
|
10796
|
+
function renderLegacyWordBinary(panel, extension, arrayBuffer, messages) {
|
|
10655
10797
|
try {
|
|
10656
10798
|
renderLegacyWordDocument(panel, parseLegacyWordDocument(arrayBuffer));
|
|
10657
10799
|
} catch (error) {
|
|
10658
|
-
renderLegacyOfficeBinary(
|
|
10800
|
+
renderLegacyOfficeBinary(
|
|
10801
|
+
panel,
|
|
10802
|
+
extension,
|
|
10803
|
+
arrayBuffer,
|
|
10804
|
+
messages,
|
|
10805
|
+
formatPreviewMessage(messages.officeLegacyWordParseFailed, { message: normalizeOfficeError(error, messages) })
|
|
10806
|
+
);
|
|
10659
10807
|
}
|
|
10660
10808
|
}
|
|
10661
|
-
function renderLegacyOfficeBinary(panel, extension, arrayBuffer, parseError) {
|
|
10809
|
+
function renderLegacyOfficeBinary(panel, extension, arrayBuffer, messages, parseError) {
|
|
10662
10810
|
const fragments = extractLegacyOfficeText(arrayBuffer);
|
|
10663
10811
|
panel.replaceChildren();
|
|
10664
|
-
const section = createSection(
|
|
10812
|
+
const section = createSection(messages.officeLegacyConversionTitle);
|
|
10665
10813
|
section.classList.add("ofv-office-conversion");
|
|
10666
10814
|
const format = document.createElement("p");
|
|
10667
10815
|
const strong = document.createElement("strong");
|
|
10668
10816
|
strong.textContent = `.${extension}`;
|
|
10669
|
-
format.append(
|
|
10670
|
-
strong,
|
|
10671
|
-
document.createTextNode(
|
|
10672
|
-
" \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"
|
|
10673
|
-
)
|
|
10674
|
-
);
|
|
10817
|
+
format.append(strong, document.createTextNode(" "), document.createTextNode(messages.officeLegacyBinaryNotice));
|
|
10675
10818
|
const meta = document.createElement("dl");
|
|
10676
10819
|
meta.className = "ofv-office-binary-meta";
|
|
10677
|
-
appendOfficeBinaryMeta(meta,
|
|
10678
|
-
appendOfficeBinaryMeta(
|
|
10679
|
-
|
|
10820
|
+
appendOfficeBinaryMeta(meta, messages.officeLegacyMetaFormatType, legacyOfficeFormatLabel(extension));
|
|
10821
|
+
appendOfficeBinaryMeta(
|
|
10822
|
+
meta,
|
|
10823
|
+
messages.officeLegacyMetaFileStructure,
|
|
10824
|
+
hasOleSignature(arrayBuffer) ? messages.officeLegacyOleDetected : messages.officeLegacyOleMissing
|
|
10825
|
+
);
|
|
10826
|
+
appendOfficeBinaryMeta(
|
|
10827
|
+
meta,
|
|
10828
|
+
messages.officeLegacyMetaTextFragments,
|
|
10829
|
+
formatPreviewMessage(messages.officeLegacyTextFragmentCount, { count: fragments.length.toLocaleString() })
|
|
10830
|
+
);
|
|
10680
10831
|
if (parseError) {
|
|
10681
|
-
appendOfficeBinaryMeta(meta,
|
|
10832
|
+
appendOfficeBinaryMeta(meta, messages.officeLegacyMetaParseStatus, parseError);
|
|
10682
10833
|
}
|
|
10683
10834
|
section.append(format, meta);
|
|
10684
10835
|
if (fragments.length > 0) {
|
|
10685
10836
|
const article = document.createElement("article");
|
|
10686
10837
|
article.className = "ofv-document ofv-office-binary-fragments";
|
|
10687
10838
|
const heading = document.createElement("h4");
|
|
10688
|
-
heading.textContent =
|
|
10839
|
+
heading.textContent = messages.officeLegacyReadableFragments;
|
|
10689
10840
|
article.append(heading);
|
|
10690
10841
|
for (const fragment of fragments.slice(0, 80)) {
|
|
10691
10842
|
const paragraph = document.createElement("p");
|
|
@@ -10696,7 +10847,7 @@ function renderLegacyOfficeBinary(panel, extension, arrayBuffer, parseError) {
|
|
|
10696
10847
|
} else {
|
|
10697
10848
|
const empty = document.createElement("p");
|
|
10698
10849
|
empty.className = "ofv-office-binary-empty";
|
|
10699
|
-
empty.textContent =
|
|
10850
|
+
empty.textContent = messages.officeLegacyNoText;
|
|
10700
10851
|
section.append(empty);
|
|
10701
10852
|
}
|
|
10702
10853
|
panel.append(section);
|
|
@@ -10708,23 +10859,27 @@ function appendOfficeBinaryMeta(list, label, value) {
|
|
|
10708
10859
|
detail.textContent = value;
|
|
10709
10860
|
list.append(term, detail);
|
|
10710
10861
|
}
|
|
10711
|
-
function renderUnsupportedOffice(panel, extension) {
|
|
10862
|
+
function renderUnsupportedOffice(panel, extension, messages) {
|
|
10712
10863
|
const legacyBinary = /* @__PURE__ */ new Set(["doc", "dot", "wps", "ppt", "pps", "key", "dps"]);
|
|
10713
|
-
const message = legacyBinary.has(extension) ?
|
|
10864
|
+
const message = legacyBinary.has(extension) ? messages.officeUnsupportedLegacyMessage : messages.officeUnsupportedGenericMessage;
|
|
10714
10865
|
panel.replaceChildren();
|
|
10715
|
-
const section = createSection(
|
|
10866
|
+
const section = createSection(messages.officeUnsupportedTitle);
|
|
10716
10867
|
const format = document.createElement("p");
|
|
10717
10868
|
const strong = document.createElement("strong");
|
|
10718
10869
|
strong.textContent = `.${extension}`;
|
|
10719
|
-
format.append(
|
|
10870
|
+
format.append(
|
|
10871
|
+
strong,
|
|
10872
|
+
document.createTextNode(" "),
|
|
10873
|
+
document.createTextNode(formatPreviewMessage(messages.officeUnsupportedIntro, { message }))
|
|
10874
|
+
);
|
|
10720
10875
|
const support = document.createElement("p");
|
|
10721
|
-
support.textContent =
|
|
10876
|
+
support.textContent = messages.officeUnsupportedSupportedFormats;
|
|
10722
10877
|
section.append(format, support);
|
|
10723
10878
|
panel.append(section);
|
|
10724
10879
|
}
|
|
10725
|
-
function normalizeOfficeError(error) {
|
|
10880
|
+
function normalizeOfficeError(error, messages) {
|
|
10726
10881
|
const message = error instanceof Error ? error.message : String(error || "");
|
|
10727
|
-
return message ?
|
|
10882
|
+
return message ? formatPreviewMessage(messages.officeErrorWithMessage, { message }) : messages.officeErrorWithoutMessage;
|
|
10728
10883
|
}
|
|
10729
10884
|
function extractLegacyOfficeText(arrayBuffer) {
|
|
10730
10885
|
const bytes = new Uint8Array(arrayBuffer);
|
|
@@ -11966,11 +12121,13 @@ function archivePlugin() {
|
|
|
11966
12121
|
sidebarToggle.addEventListener("click", () => {
|
|
11967
12122
|
setSidebarCollapsed(!layout.classList.contains("is-sidebar-collapsed"));
|
|
11968
12123
|
});
|
|
11969
|
-
const showDefaultSummary = () => {
|
|
12124
|
+
const showDefaultSummary = (isSupplemental = true) => {
|
|
11970
12125
|
mainPanel.replaceChildren();
|
|
11971
12126
|
const summary = document.createElement("div");
|
|
11972
12127
|
summary.className = "ofv-archive-info";
|
|
11973
|
-
|
|
12128
|
+
if (isSupplemental) {
|
|
12129
|
+
hideSupplementalInfo4(summary);
|
|
12130
|
+
}
|
|
11974
12131
|
const heading = document.createElement("h3");
|
|
11975
12132
|
heading.textContent = ctx.file.name;
|
|
11976
12133
|
const info = document.createElement("div");
|
|
@@ -11980,12 +12137,16 @@ function archivePlugin() {
|
|
|
11980
12137
|
appendArchiveInfo(info, "\u683C\u5F0F\u7C7B\u578B", `.${ext.toUpperCase()} \u538B\u7F29\u6587\u4EF6`);
|
|
11981
12138
|
appendArchiveInfo(info, "\u5305\u542B\u6587\u4EF6\u6570", `${fileCount} \u4E2A`);
|
|
11982
12139
|
appendArchiveInfo(info, "\u5305\u542B\u76EE\u5F55\u6570", `${dirCount} \u4E2A`);
|
|
11983
|
-
appendArchiveInfo(
|
|
12140
|
+
appendArchiveInfo(
|
|
12141
|
+
info,
|
|
12142
|
+
"\u64CD\u4F5C\u63D0\u793A",
|
|
12143
|
+
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"
|
|
12144
|
+
);
|
|
11984
12145
|
summary.append(heading, info, createArchiveSummary(archiveEntries));
|
|
11985
12146
|
mainPanel.append(summary);
|
|
11986
12147
|
};
|
|
11987
|
-
showDefaultSummary();
|
|
11988
12148
|
const visibleEntries = archiveEntries.filter((e) => !e.dir).slice(0, 500);
|
|
12149
|
+
showDefaultSummary(visibleEntries.length > 0);
|
|
11989
12150
|
let destroyed = false;
|
|
11990
12151
|
let renderToken = 0;
|
|
11991
12152
|
const openArchiveEntry = async (entry, item) => {
|