@open-file-viewer/core 0.1.20 → 0.1.22
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 +342 -128
- 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 +342 -128
- package/dist/index.js.map +1 -1
- package/dist/style.css +17 -2
- 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");
|
|
@@ -739,12 +809,17 @@ function createViewer(options) {
|
|
|
739
809
|
currentIndex = clampIndex(index, queue.length);
|
|
740
810
|
await renderQueueItem(currentIndex);
|
|
741
811
|
};
|
|
742
|
-
const toolbar = createToolbar(
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
812
|
+
const toolbar = createToolbar(
|
|
813
|
+
options.toolbar,
|
|
814
|
+
viewport,
|
|
815
|
+
{
|
|
816
|
+
getLength: () => queue.length,
|
|
817
|
+
next: () => goTo(currentIndex + 1),
|
|
818
|
+
previous: () => goTo(currentIndex - 1),
|
|
819
|
+
command: (command) => currentInstance?.command?.(command)
|
|
820
|
+
},
|
|
821
|
+
options.locale || "en-US"
|
|
822
|
+
);
|
|
748
823
|
if (toolbar) {
|
|
749
824
|
host.append(toolbar.element);
|
|
750
825
|
}
|
|
@@ -863,12 +938,15 @@ function createViewer(options) {
|
|
|
863
938
|
theme.destroy();
|
|
864
939
|
container.replaceChildren();
|
|
865
940
|
container.classList.remove("ofv-root");
|
|
866
|
-
if (
|
|
867
|
-
container.classList.remove(
|
|
941
|
+
if (customClassNames.length > 0) {
|
|
942
|
+
container.classList.remove(...customClassNames);
|
|
868
943
|
}
|
|
869
944
|
}
|
|
870
945
|
};
|
|
871
946
|
}
|
|
947
|
+
function parseClassNameTokens(className) {
|
|
948
|
+
return className?.trim().split(/\s+/).filter(Boolean) ?? [];
|
|
949
|
+
}
|
|
872
950
|
function destroyPreviewInstance(instance) {
|
|
873
951
|
if (!instance) {
|
|
874
952
|
return;
|
|
@@ -978,7 +1056,7 @@ function removeMediaListener(media, listener) {
|
|
|
978
1056
|
}
|
|
979
1057
|
media.removeListener?.(listener);
|
|
980
1058
|
}
|
|
981
|
-
function createToolbar(toolbar, viewport, queue) {
|
|
1059
|
+
function createToolbar(toolbar, viewport, queue, locale) {
|
|
982
1060
|
if (!toolbar) {
|
|
983
1061
|
return void 0;
|
|
984
1062
|
}
|
|
@@ -986,7 +1064,7 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
986
1064
|
const element = document.createElement("div");
|
|
987
1065
|
element.className = "ofv-toolbar";
|
|
988
1066
|
element.setAttribute("role", "toolbar");
|
|
989
|
-
element.setAttribute("aria-label",
|
|
1067
|
+
element.setAttribute("aria-label", defaultToolbarText[locale].ariaLabel);
|
|
990
1068
|
let file;
|
|
991
1069
|
let currentIndex = 0;
|
|
992
1070
|
let currentLength = queue.getLength();
|
|
@@ -994,6 +1072,7 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
994
1072
|
let previousButton;
|
|
995
1073
|
let nextButton;
|
|
996
1074
|
let zoomResetButton;
|
|
1075
|
+
let fullscreenButton;
|
|
997
1076
|
let currentZoom;
|
|
998
1077
|
const commandButtons = [];
|
|
999
1078
|
const customButtons = [];
|
|
@@ -1046,8 +1125,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1046
1125
|
}
|
|
1047
1126
|
if (id === "previous" && queue.getLength() > 1) {
|
|
1048
1127
|
previousButton = addButton(
|
|
1049
|
-
getToolbarLabel(options, "previous"),
|
|
1050
|
-
getToolbarTitle(options, "previous"),
|
|
1128
|
+
getToolbarLabel(options, locale, "previous"),
|
|
1129
|
+
getToolbarTitle(options, locale, "previous"),
|
|
1051
1130
|
() => void queue.previous(),
|
|
1052
1131
|
void 0,
|
|
1053
1132
|
options.icons?.previous
|
|
@@ -1056,8 +1135,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1056
1135
|
}
|
|
1057
1136
|
if (id === "next" && queue.getLength() > 1) {
|
|
1058
1137
|
nextButton = addButton(
|
|
1059
|
-
getToolbarLabel(options, "next"),
|
|
1060
|
-
getToolbarTitle(options, "next"),
|
|
1138
|
+
getToolbarLabel(options, locale, "next"),
|
|
1139
|
+
getToolbarTitle(options, locale, "next"),
|
|
1061
1140
|
() => void queue.next(),
|
|
1062
1141
|
void 0,
|
|
1063
1142
|
options.icons?.next
|
|
@@ -1071,27 +1150,27 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1071
1150
|
return;
|
|
1072
1151
|
}
|
|
1073
1152
|
if (id === "zoom-out" && options.zoom) {
|
|
1074
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "zoom-out");
|
|
1153
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "zoom-out");
|
|
1075
1154
|
return;
|
|
1076
1155
|
}
|
|
1077
1156
|
if (id === "zoom-in" && options.zoom) {
|
|
1078
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "zoom-in");
|
|
1157
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "zoom-in");
|
|
1079
1158
|
return;
|
|
1080
1159
|
}
|
|
1081
1160
|
if (id === "zoom-reset" && options.zoom) {
|
|
1082
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "zoom-reset");
|
|
1161
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "zoom-reset");
|
|
1083
1162
|
zoomResetButton = commandButtons[commandButtons.length - 1]?.button;
|
|
1084
1163
|
updateZoomLabel();
|
|
1085
1164
|
return;
|
|
1086
1165
|
}
|
|
1087
1166
|
if (id === "rotate-right" && options.rotate) {
|
|
1088
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "rotate-right");
|
|
1167
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "rotate-right");
|
|
1089
1168
|
return;
|
|
1090
1169
|
}
|
|
1091
1170
|
if (id === "download" && options.download !== false) {
|
|
1092
1171
|
addButton(
|
|
1093
|
-
getToolbarLabel(options, id),
|
|
1094
|
-
getToolbarTitle(options, id),
|
|
1172
|
+
getToolbarLabel(options, locale, id),
|
|
1173
|
+
getToolbarTitle(options, locale, id),
|
|
1095
1174
|
() => getContext().download(),
|
|
1096
1175
|
void 0,
|
|
1097
1176
|
options.icons?.download
|
|
@@ -1099,19 +1178,20 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1099
1178
|
return;
|
|
1100
1179
|
}
|
|
1101
1180
|
if (id === "fullscreen" && options.fullscreen !== false) {
|
|
1102
|
-
addButton(
|
|
1103
|
-
getToolbarLabel(options, id),
|
|
1104
|
-
getToolbarTitle(options, id),
|
|
1181
|
+
fullscreenButton = addButton(
|
|
1182
|
+
getToolbarLabel(options, locale, id),
|
|
1183
|
+
getToolbarTitle(options, locale, id),
|
|
1105
1184
|
() => getContext().fullscreen(),
|
|
1106
1185
|
void 0,
|
|
1107
1186
|
options.icons?.fullscreen
|
|
1108
1187
|
);
|
|
1188
|
+
updateFullscreenButton();
|
|
1109
1189
|
return;
|
|
1110
1190
|
}
|
|
1111
1191
|
if (id === "print" && options.print) {
|
|
1112
1192
|
addButton(
|
|
1113
|
-
getToolbarLabel(options, id),
|
|
1114
|
-
getToolbarTitle(options, id),
|
|
1193
|
+
getToolbarLabel(options, locale, id),
|
|
1194
|
+
getToolbarTitle(options, locale, id),
|
|
1115
1195
|
() => getContext().print(),
|
|
1116
1196
|
void 0,
|
|
1117
1197
|
options.icons?.print
|
|
@@ -1137,11 +1217,11 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1137
1217
|
const renderSearchControl = () => {
|
|
1138
1218
|
const searchGroup = document.createElement("div");
|
|
1139
1219
|
searchGroup.className = "ofv-toolbar-search";
|
|
1140
|
-
searchGroup.title = getToolbarTitle(options, "search");
|
|
1220
|
+
searchGroup.title = getToolbarTitle(options, locale, "search");
|
|
1141
1221
|
const nextSearchInput = document.createElement("input");
|
|
1142
1222
|
nextSearchInput.type = "search";
|
|
1143
|
-
nextSearchInput.placeholder = getToolbarLabel(options, "search");
|
|
1144
|
-
nextSearchInput.setAttribute("aria-label", getToolbarTitle(options, "search"));
|
|
1223
|
+
nextSearchInput.placeholder = getToolbarLabel(options, locale, "search");
|
|
1224
|
+
nextSearchInput.setAttribute("aria-label", getToolbarTitle(options, locale, "search"));
|
|
1145
1225
|
const nextSearchCount = document.createElement("span");
|
|
1146
1226
|
nextSearchCount.className = "ofv-toolbar-search-count";
|
|
1147
1227
|
searchInput = nextSearchInput;
|
|
@@ -1196,7 +1276,7 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1196
1276
|
}
|
|
1197
1277
|
setToolbarButtonContent(
|
|
1198
1278
|
zoomResetButton,
|
|
1199
|
-
currentZoom === void 0 ? getToolbarLabel(options, "zoom-reset") : formatToolbarZoom(currentZoom),
|
|
1279
|
+
currentZoom === void 0 ? getToolbarLabel(options, locale, "zoom-reset") : formatToolbarZoom(currentZoom),
|
|
1200
1280
|
options.icons?.["zoom-reset"]
|
|
1201
1281
|
);
|
|
1202
1282
|
}
|
|
@@ -1207,6 +1287,32 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1207
1287
|
updateCustomButtons();
|
|
1208
1288
|
refreshCustomRender();
|
|
1209
1289
|
}
|
|
1290
|
+
function isFullscreenActive() {
|
|
1291
|
+
return Boolean(
|
|
1292
|
+
typeof document !== "undefined" && element.parentElement && document.fullscreenElement === element.parentElement
|
|
1293
|
+
);
|
|
1294
|
+
}
|
|
1295
|
+
function updateFullscreenButton() {
|
|
1296
|
+
if (!fullscreenButton) {
|
|
1297
|
+
return;
|
|
1298
|
+
}
|
|
1299
|
+
const active = isFullscreenActive();
|
|
1300
|
+
const id = active ? "exit-fullscreen" : "fullscreen";
|
|
1301
|
+
const icon = active ? options.icons?.["exit-fullscreen"] ?? options.icons?.fullscreen : options.icons?.fullscreen;
|
|
1302
|
+
setToolbarButtonContent(fullscreenButton, getToolbarLabel(options, locale, id), icon);
|
|
1303
|
+
const title = getToolbarTitle(options, locale, id);
|
|
1304
|
+
fullscreenButton.title = title;
|
|
1305
|
+
fullscreenButton.setAttribute("aria-label", title);
|
|
1306
|
+
fullscreenButton.setAttribute("aria-pressed", String(active));
|
|
1307
|
+
}
|
|
1308
|
+
const handleFullscreenChange = () => {
|
|
1309
|
+
updateFullscreenButton();
|
|
1310
|
+
refreshCustomRender();
|
|
1311
|
+
};
|
|
1312
|
+
if (typeof document !== "undefined") {
|
|
1313
|
+
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
1314
|
+
disposers.push(() => document.removeEventListener("fullscreenchange", handleFullscreenChange));
|
|
1315
|
+
}
|
|
1210
1316
|
const refreshCustomRender = () => {
|
|
1211
1317
|
if (!options.render) {
|
|
1212
1318
|
return;
|
|
@@ -1280,6 +1386,9 @@ function createToolbarContext({
|
|
|
1280
1386
|
viewport,
|
|
1281
1387
|
canPrevious: index > 0,
|
|
1282
1388
|
canNext: index < length - 1,
|
|
1389
|
+
isFullscreen: Boolean(
|
|
1390
|
+
typeof document !== "undefined" && element.parentElement && document.fullscreenElement === element.parentElement
|
|
1391
|
+
),
|
|
1283
1392
|
zoom,
|
|
1284
1393
|
zoomLabel: zoom === void 0 ? void 0 : formatToolbarZoom(zoom),
|
|
1285
1394
|
async previous() {
|
|
@@ -1298,7 +1407,15 @@ function createToolbarContext({
|
|
|
1298
1407
|
}
|
|
1299
1408
|
},
|
|
1300
1409
|
fullscreen() {
|
|
1301
|
-
|
|
1410
|
+
const target = element.parentElement;
|
|
1411
|
+
if (!target) {
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1414
|
+
if (typeof document !== "undefined" && document.fullscreenElement === target) {
|
|
1415
|
+
void document.exitFullscreen?.();
|
|
1416
|
+
} else {
|
|
1417
|
+
void target.requestFullscreen?.();
|
|
1418
|
+
}
|
|
1302
1419
|
},
|
|
1303
1420
|
print() {
|
|
1304
1421
|
printPreview(viewport);
|
|
@@ -1307,37 +1424,75 @@ function createToolbarContext({
|
|
|
1307
1424
|
clearSearch: search.clear
|
|
1308
1425
|
};
|
|
1309
1426
|
}
|
|
1310
|
-
var
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1427
|
+
var defaultToolbarText = {
|
|
1428
|
+
"zh-CN": {
|
|
1429
|
+
ariaLabel: "\u6587\u4EF6\u9884\u89C8\u5DE5\u5177\u680F",
|
|
1430
|
+
labels: {
|
|
1431
|
+
previous: "\u4E0A\u4E00\u4E2A",
|
|
1432
|
+
next: "\u4E0B\u4E00\u4E2A",
|
|
1433
|
+
queue: "",
|
|
1434
|
+
"zoom-out": "-",
|
|
1435
|
+
"zoom-in": "+",
|
|
1436
|
+
"zoom-reset": "100%",
|
|
1437
|
+
"rotate-right": "\u65CB\u8F6C",
|
|
1438
|
+
download: "\u4E0B\u8F7D",
|
|
1439
|
+
fullscreen: "\u5168\u5C4F",
|
|
1440
|
+
"exit-fullscreen": "\u9000\u51FA\u5168\u5C4F",
|
|
1441
|
+
print: "\u6253\u5370",
|
|
1442
|
+
search: "\u641C\u7D22"
|
|
1443
|
+
},
|
|
1444
|
+
titles: {
|
|
1445
|
+
previous: "\u4E0A\u4E00\u4E2A\u6587\u4EF6",
|
|
1446
|
+
next: "\u4E0B\u4E00\u4E2A\u6587\u4EF6",
|
|
1447
|
+
queue: "\u5F53\u524D\u6587\u4EF6\u4F4D\u7F6E",
|
|
1448
|
+
"zoom-out": "\u7F29\u5C0F",
|
|
1449
|
+
"zoom-in": "\u653E\u5927",
|
|
1450
|
+
"zoom-reset": "\u91CD\u7F6E\u7F29\u653E",
|
|
1451
|
+
"rotate-right": "\u5411\u53F3\u65CB\u8F6C",
|
|
1452
|
+
download: "\u4E0B\u8F7D\u6587\u4EF6",
|
|
1453
|
+
fullscreen: "\u5168\u5C4F\u67E5\u770B\u9884\u89C8",
|
|
1454
|
+
"exit-fullscreen": "\u9000\u51FA\u5168\u5C4F",
|
|
1455
|
+
print: "\u6253\u5370\u9884\u89C8",
|
|
1456
|
+
search: "\u641C\u7D22\u9884\u89C8\u6587\u672C"
|
|
1457
|
+
}
|
|
1458
|
+
},
|
|
1459
|
+
"en-US": {
|
|
1460
|
+
ariaLabel: "File preview toolbar",
|
|
1461
|
+
labels: {
|
|
1462
|
+
previous: "Prev",
|
|
1463
|
+
next: "Next",
|
|
1464
|
+
queue: "",
|
|
1465
|
+
"zoom-out": "-",
|
|
1466
|
+
"zoom-in": "+",
|
|
1467
|
+
"zoom-reset": "100%",
|
|
1468
|
+
"rotate-right": "Rotate",
|
|
1469
|
+
download: "Download",
|
|
1470
|
+
fullscreen: "Fullscreen",
|
|
1471
|
+
"exit-fullscreen": "Exit fullscreen",
|
|
1472
|
+
print: "Print",
|
|
1473
|
+
search: "Search"
|
|
1474
|
+
},
|
|
1475
|
+
titles: {
|
|
1476
|
+
previous: "Previous file",
|
|
1477
|
+
next: "Next file",
|
|
1478
|
+
queue: "Current file position",
|
|
1479
|
+
"zoom-out": "Zoom out",
|
|
1480
|
+
"zoom-in": "Zoom in",
|
|
1481
|
+
"zoom-reset": "Reset zoom",
|
|
1482
|
+
"rotate-right": "Rotate right",
|
|
1483
|
+
download: "Download file",
|
|
1484
|
+
fullscreen: "Open preview fullscreen",
|
|
1485
|
+
"exit-fullscreen": "Exit fullscreen",
|
|
1486
|
+
print: "Print preview",
|
|
1487
|
+
search: "Search preview text"
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1335
1490
|
};
|
|
1336
|
-
function getToolbarLabel(options, id) {
|
|
1337
|
-
return options.labels?.[id] ??
|
|
1491
|
+
function getToolbarLabel(options, locale, id) {
|
|
1492
|
+
return options.labels?.[id] ?? defaultToolbarText[locale].labels[id];
|
|
1338
1493
|
}
|
|
1339
|
-
function getToolbarTitle(options, id) {
|
|
1340
|
-
return options.titles?.[id] ?? options.labels?.[id] ??
|
|
1494
|
+
function getToolbarTitle(options, locale, id) {
|
|
1495
|
+
return options.titles?.[id] ?? options.labels?.[id] ?? defaultToolbarText[locale].titles[id];
|
|
1341
1496
|
}
|
|
1342
1497
|
function formatToolbarZoom(zoom) {
|
|
1343
1498
|
return `${Math.round(zoom * 100)}%`;
|
|
@@ -1489,7 +1644,7 @@ function isSafeToolbarIconAttribute(name, value) {
|
|
|
1489
1644
|
return !/^\s*(?:javascript|data:text\/html|vbscript):/i.test(value);
|
|
1490
1645
|
}
|
|
1491
1646
|
function isBuiltInToolbarAction(id) {
|
|
1492
|
-
return id in
|
|
1647
|
+
return id in defaultToolbarText["en-US"].labels;
|
|
1493
1648
|
}
|
|
1494
1649
|
function createSearchController(root) {
|
|
1495
1650
|
const markerClass = "ofv-search-match";
|
|
@@ -1568,6 +1723,9 @@ function collectSearchableTextNodes(root) {
|
|
|
1568
1723
|
if (["SCRIPT", "STYLE", "TEXTAREA", "INPUT", "BUTTON"].includes(parent.tagName)) {
|
|
1569
1724
|
return NodeFilter.FILTER_REJECT;
|
|
1570
1725
|
}
|
|
1726
|
+
if (hasHiddenSearchAncestor(parent, root)) {
|
|
1727
|
+
return NodeFilter.FILTER_REJECT;
|
|
1728
|
+
}
|
|
1571
1729
|
return NodeFilter.FILTER_ACCEPT;
|
|
1572
1730
|
}
|
|
1573
1731
|
});
|
|
@@ -1578,6 +1736,19 @@ function collectSearchableTextNodes(root) {
|
|
|
1578
1736
|
}
|
|
1579
1737
|
return nodes;
|
|
1580
1738
|
}
|
|
1739
|
+
function hasHiddenSearchAncestor(element, root) {
|
|
1740
|
+
let current = element;
|
|
1741
|
+
while (current) {
|
|
1742
|
+
if (current.hidden || current.getAttribute("aria-hidden") === "true" || current.style.display === "none" || current.style.visibility === "hidden") {
|
|
1743
|
+
return true;
|
|
1744
|
+
}
|
|
1745
|
+
if (current === root) {
|
|
1746
|
+
break;
|
|
1747
|
+
}
|
|
1748
|
+
current = current.parentElement;
|
|
1749
|
+
}
|
|
1750
|
+
return false;
|
|
1751
|
+
}
|
|
1581
1752
|
function printPreview(viewport) {
|
|
1582
1753
|
const frame = document.createElement("iframe");
|
|
1583
1754
|
frame.className = "ofv-print-frame";
|
|
@@ -4075,7 +4246,7 @@ function textPlugin() {
|
|
|
4075
4246
|
const isMarkdown = lang === "markdown";
|
|
4076
4247
|
const text = await readText(ctx.file.source).catch((error) => void 0);
|
|
4077
4248
|
if (text === void 0) {
|
|
4078
|
-
const fallback = createTextFallback(ctx.file.name, ctx.file.url);
|
|
4249
|
+
const fallback = createTextFallback(ctx.file.name, ctx.options.messages, ctx.file.url);
|
|
4079
4250
|
ctx.viewport.classList.add("ofv-center");
|
|
4080
4251
|
ctx.viewport.append(fallback);
|
|
4081
4252
|
return {
|
|
@@ -4247,10 +4418,11 @@ function textPlugin() {
|
|
|
4247
4418
|
title.className = "ofv-code-title";
|
|
4248
4419
|
const fileName = document.createElement("strong");
|
|
4249
4420
|
fileName.textContent = ctx.file.name;
|
|
4421
|
+
const messages = ctx.options.messages;
|
|
4250
4422
|
const meta = document.createElement("span");
|
|
4251
4423
|
meta.textContent = [
|
|
4252
|
-
lang === "none" ?
|
|
4253
|
-
|
|
4424
|
+
lang === "none" ? messages.textPlainLanguage : lang,
|
|
4425
|
+
formatPreviewMessage(messages.textLineCount, { count: totalLines.toLocaleString() }),
|
|
4254
4426
|
formatBytes(ctx.file.size ?? (ctx.file.source instanceof Blob ? ctx.file.source.size : text.length))
|
|
4255
4427
|
].join(" \xB7 ");
|
|
4256
4428
|
title.append(fileName, meta);
|
|
@@ -4262,7 +4434,7 @@ function textPlugin() {
|
|
|
4262
4434
|
const wrapButton = document.createElement("button");
|
|
4263
4435
|
wrapButton.type = "button";
|
|
4264
4436
|
wrapButton.className = "ofv-code-action";
|
|
4265
|
-
wrapButton.textContent =
|
|
4437
|
+
wrapButton.textContent = messages.textWrap;
|
|
4266
4438
|
wrapButton.setAttribute("aria-pressed", String(defaultWrapped));
|
|
4267
4439
|
wrapButton.addEventListener("click", () => {
|
|
4268
4440
|
const wrapped = wrapper.classList.toggle("is-wrapped");
|
|
@@ -4271,14 +4443,14 @@ function textPlugin() {
|
|
|
4271
4443
|
const copyButton = document.createElement("button");
|
|
4272
4444
|
copyButton.type = "button";
|
|
4273
4445
|
copyButton.className = "ofv-code-action";
|
|
4274
|
-
copyButton.textContent =
|
|
4446
|
+
copyButton.textContent = messages.textCopy;
|
|
4275
4447
|
copyButton.addEventListener("click", async () => {
|
|
4276
4448
|
copyButton.disabled = true;
|
|
4277
4449
|
try {
|
|
4278
4450
|
await copyToClipboard(text);
|
|
4279
|
-
status.textContent =
|
|
4451
|
+
status.textContent = messages.textCopied;
|
|
4280
4452
|
} catch {
|
|
4281
|
-
status.textContent =
|
|
4453
|
+
status.textContent = messages.textCopyFailed;
|
|
4282
4454
|
} finally {
|
|
4283
4455
|
copyButton.disabled = false;
|
|
4284
4456
|
}
|
|
@@ -4286,10 +4458,10 @@ function textPlugin() {
|
|
|
4286
4458
|
const downloadButton = document.createElement("button");
|
|
4287
4459
|
downloadButton.type = "button";
|
|
4288
4460
|
downloadButton.className = "ofv-code-action";
|
|
4289
|
-
downloadButton.textContent =
|
|
4461
|
+
downloadButton.textContent = messages.textDownload;
|
|
4290
4462
|
downloadButton.addEventListener("click", () => {
|
|
4291
4463
|
downloadText(ctx.file.name, text);
|
|
4292
|
-
status.textContent =
|
|
4464
|
+
status.textContent = messages.textDownloadReady;
|
|
4293
4465
|
});
|
|
4294
4466
|
actions.append(wrapButton, copyButton, downloadButton, status);
|
|
4295
4467
|
header.append(title, actions);
|
|
@@ -4314,13 +4486,13 @@ function textPlugin() {
|
|
|
4314
4486
|
if (truncated) {
|
|
4315
4487
|
const notice = document.createElement("div");
|
|
4316
4488
|
notice.className = "ofv-code-notice";
|
|
4317
|
-
notice.textContent =
|
|
4489
|
+
notice.textContent = formatPreviewMessage(messages.textLargeFileNotice, { size: formatBytes(codeText.length) });
|
|
4318
4490
|
wrapper.append(notice);
|
|
4319
4491
|
}
|
|
4320
4492
|
if (!shouldHighlight) {
|
|
4321
4493
|
const notice = document.createElement("div");
|
|
4322
4494
|
notice.className = "ofv-code-notice";
|
|
4323
|
-
notice.textContent =
|
|
4495
|
+
notice.textContent = messages.textHighlightSkipped;
|
|
4324
4496
|
wrapper.append(notice);
|
|
4325
4497
|
}
|
|
4326
4498
|
wrapper.appendChild(body);
|
|
@@ -4387,19 +4559,19 @@ function normalizeFileName2(name) {
|
|
|
4387
4559
|
const baseName = name.split(/[\\/]/).pop() || name;
|
|
4388
4560
|
return baseName.toLowerCase();
|
|
4389
4561
|
}
|
|
4390
|
-
function createTextFallback(fileName, url) {
|
|
4562
|
+
function createTextFallback(fileName, messages, url) {
|
|
4391
4563
|
const fallback = document.createElement("div");
|
|
4392
4564
|
fallback.className = "ofv-fallback";
|
|
4393
4565
|
const title = document.createElement("strong");
|
|
4394
|
-
title.textContent =
|
|
4566
|
+
title.textContent = messages.textPreviewFailedTitle;
|
|
4395
4567
|
const meta = document.createElement("span");
|
|
4396
|
-
meta.textContent =
|
|
4568
|
+
meta.textContent = messages.textPreviewFailedMessage;
|
|
4397
4569
|
fallback.append(title, meta);
|
|
4398
4570
|
if (url) {
|
|
4399
4571
|
const download = document.createElement("a");
|
|
4400
4572
|
download.href = url;
|
|
4401
4573
|
download.download = fileName;
|
|
4402
|
-
download.textContent =
|
|
4574
|
+
download.textContent = messages.textOpenOriginal;
|
|
4403
4575
|
fallback.append(download);
|
|
4404
4576
|
}
|
|
4405
4577
|
return fallback;
|
|
@@ -7461,7 +7633,7 @@ function officePlugin(options = {}) {
|
|
|
7461
7633
|
} else if (packageFormat === "docx" && !fileIsDocx(extension)) {
|
|
7462
7634
|
disposeDocxFit = await renderDocx(panel, arrayBuffer, ctx.options.fit);
|
|
7463
7635
|
} else if (packageFormat === "xlsx" && !sheetExtensions.has(extension)) {
|
|
7464
|
-
await renderSheet(panel, arrayBuffer, "xlsx");
|
|
7636
|
+
await renderSheet(panel, arrayBuffer, "xlsx", ctx.options.messages);
|
|
7465
7637
|
} else if (packageFormat === "pptx" && !["pptx", "pptm", "ppsx", "ppsm", "potx", "potm"].includes(extension)) {
|
|
7466
7638
|
await renderPptx(panel, arrayBuffer);
|
|
7467
7639
|
} else if (fileIsDocx(extension)) {
|
|
@@ -7474,9 +7646,9 @@ function officePlugin(options = {}) {
|
|
|
7474
7646
|
renderOpenDocumentXml(panel, "FODT \u6587\u6863", await readTextFromBuffer(arrayBuffer));
|
|
7475
7647
|
} else if (extension === "fods") {
|
|
7476
7648
|
renderFlatOds(panel, await readTextFromBuffer(arrayBuffer));
|
|
7477
|
-
} else if (packagedOfficeCandidates.has(extension) && await renderPackagedOfficePreview(panel, arrayBuffer, extension, ctx.options.fit)) {
|
|
7649
|
+
} else if (packagedOfficeCandidates.has(extension) && await renderPackagedOfficePreview(panel, arrayBuffer, extension, ctx.options.fit, ctx.options.messages)) {
|
|
7478
7650
|
} else if (sheetExtensions.has(extension)) {
|
|
7479
|
-
await renderSheet(panel, arrayBuffer, extension);
|
|
7651
|
+
await renderSheet(panel, arrayBuffer, extension, ctx.options.messages);
|
|
7480
7652
|
} else if (["pptx", "pptm", "ppsx", "ppsm", "potx", "potm"].includes(extension)) {
|
|
7481
7653
|
await renderPptx(panel, arrayBuffer);
|
|
7482
7654
|
} else if (extension === "odp") {
|
|
@@ -7484,11 +7656,11 @@ function officePlugin(options = {}) {
|
|
|
7484
7656
|
} else if (extension === "fodp") {
|
|
7485
7657
|
renderOpenDocumentPresentationXml(panel, await readTextFromBuffer(arrayBuffer));
|
|
7486
7658
|
} else if (extension === "doc" || extension === "dot") {
|
|
7487
|
-
renderLegacyWordBinary(panel, extension, arrayBuffer);
|
|
7659
|
+
renderLegacyWordBinary(panel, extension, arrayBuffer, ctx.options.messages);
|
|
7488
7660
|
} else if (isLegacyOfficeBinary(extension)) {
|
|
7489
|
-
renderLegacyOfficeBinary(panel, extension, arrayBuffer);
|
|
7661
|
+
renderLegacyOfficeBinary(panel, extension, arrayBuffer, ctx.options.messages);
|
|
7490
7662
|
} else {
|
|
7491
|
-
renderUnsupportedOffice(panel, extension || ctx.file.extension || "office");
|
|
7663
|
+
renderUnsupportedOffice(panel, extension || ctx.file.extension || "office", ctx.options.messages);
|
|
7492
7664
|
}
|
|
7493
7665
|
const controller = createOfficeZoomController(panel, ctx);
|
|
7494
7666
|
ctx.toolbar?.refreshCommandSupport();
|
|
@@ -8833,7 +9005,7 @@ function renderPlainDocument(panel, title, text) {
|
|
|
8833
9005
|
section.append(pre);
|
|
8834
9006
|
panel.append(section);
|
|
8835
9007
|
}
|
|
8836
|
-
async function renderSheet(panel, arrayBuffer, extension) {
|
|
9008
|
+
async function renderSheet(panel, arrayBuffer, extension, messages) {
|
|
8837
9009
|
const xlsx = await import("xlsx");
|
|
8838
9010
|
let workbook;
|
|
8839
9011
|
try {
|
|
@@ -8846,10 +9018,16 @@ async function renderSheet(panel, arrayBuffer, extension) {
|
|
|
8846
9018
|
}) : xlsx.read(arrayBuffer, { type: "array", cellDates: true, cellNF: true, cellStyles: true });
|
|
8847
9019
|
} catch (error) {
|
|
8848
9020
|
if (isLegacyOfficeBinary(extension)) {
|
|
8849
|
-
renderLegacyOfficeBinary(
|
|
9021
|
+
renderLegacyOfficeBinary(
|
|
9022
|
+
panel,
|
|
9023
|
+
extension,
|
|
9024
|
+
arrayBuffer,
|
|
9025
|
+
messages,
|
|
9026
|
+
formatPreviewMessage(messages.officeSheetParseFailed, { message: normalizeOfficeError(error, messages) })
|
|
9027
|
+
);
|
|
8850
9028
|
return;
|
|
8851
9029
|
}
|
|
8852
|
-
renderSheetFallback(panel, extension, normalizeOfficeError(error));
|
|
9030
|
+
renderSheetFallback(panel, extension, normalizeOfficeError(error, messages));
|
|
8853
9031
|
return;
|
|
8854
9032
|
}
|
|
8855
9033
|
const chartPreviews = await readWorkbookCharts(arrayBuffer).catch(() => []);
|
|
@@ -9330,6 +9508,9 @@ function renderChartCard(chart) {
|
|
|
9330
9508
|
function renderChartSvg(chart) {
|
|
9331
9509
|
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
9332
9510
|
svg.setAttribute("viewBox", "0 0 640 380");
|
|
9511
|
+
svg.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
|
9512
|
+
svg.setAttribute("text-rendering", "geometricPrecision");
|
|
9513
|
+
svg.setAttribute("shape-rendering", "geometricPrecision");
|
|
9333
9514
|
svg.setAttribute("role", "img");
|
|
9334
9515
|
svg.setAttribute("aria-label", chart.title);
|
|
9335
9516
|
svg.classList.add("ofv-chart-svg");
|
|
@@ -9375,16 +9556,7 @@ function renderChartSvg(chart) {
|
|
|
9375
9556
|
const clusterWidth = groupWidth * 0.58;
|
|
9376
9557
|
const barWidth = Math.max(5, Math.min(28, clusterWidth / Math.max(1, chart.series.length)));
|
|
9377
9558
|
const zeroY = plot.y + plot.height - (0 - axisMin) / (axisMax - axisMin || 1) * plot.height;
|
|
9378
|
-
|
|
9379
|
-
const x = plot.x + groupWidth * (index + 0.5);
|
|
9380
|
-
const label = appendSvg(svg, "text", {
|
|
9381
|
-
x: Number(x.toFixed(1)),
|
|
9382
|
-
y: plot.y + plot.height + 22,
|
|
9383
|
-
class: "ofv-chart-label",
|
|
9384
|
-
"text-anchor": "middle"
|
|
9385
|
-
});
|
|
9386
|
-
label.textContent = truncateChartLabel(category);
|
|
9387
|
-
});
|
|
9559
|
+
appendChartCategoryLabels(svg, categories, plot, (index) => plot.x + groupWidth * (index + 0.5));
|
|
9388
9560
|
chart.series.forEach((series, seriesIndex) => {
|
|
9389
9561
|
const color = series.color || colors[seriesIndex % colors.length];
|
|
9390
9562
|
series.values.forEach((value, index) => {
|
|
@@ -9402,6 +9574,8 @@ function renderChartSvg(chart) {
|
|
|
9402
9574
|
});
|
|
9403
9575
|
});
|
|
9404
9576
|
} else {
|
|
9577
|
+
const categoryStep = categories.length > 1 ? plot.width / (categories.length - 1) : plot.width;
|
|
9578
|
+
appendChartCategoryLabels(svg, categories, plot, (index) => plot.x + index * categoryStep);
|
|
9405
9579
|
chart.series.forEach((series, seriesIndex) => {
|
|
9406
9580
|
const color = series.color || colors[seriesIndex % colors.length];
|
|
9407
9581
|
const step = series.values.length > 1 ? plot.width / (series.values.length - 1) : plot.width;
|
|
@@ -9426,6 +9600,22 @@ function renderChartSvg(chart) {
|
|
|
9426
9600
|
appendChartLegend(svg, chart, colors, 348);
|
|
9427
9601
|
return svg;
|
|
9428
9602
|
}
|
|
9603
|
+
function appendChartCategoryLabels(svg, categories, plot, getX) {
|
|
9604
|
+
const interval = Math.max(1, Math.ceil(categories.length / 14));
|
|
9605
|
+
categories.forEach((category, index) => {
|
|
9606
|
+
if (index % interval !== 0 && index !== categories.length - 1) {
|
|
9607
|
+
return;
|
|
9608
|
+
}
|
|
9609
|
+
const label = appendSvg(svg, "text", {
|
|
9610
|
+
x: Number(getX(index).toFixed(1)),
|
|
9611
|
+
y: plot.y + plot.height + 22,
|
|
9612
|
+
class: "ofv-chart-label ofv-chart-category-label",
|
|
9613
|
+
"data-axis": "category",
|
|
9614
|
+
"text-anchor": "middle"
|
|
9615
|
+
});
|
|
9616
|
+
label.textContent = truncateChartLabel(category);
|
|
9617
|
+
});
|
|
9618
|
+
}
|
|
9429
9619
|
function appendChartLegend(svg, chart, colors, y) {
|
|
9430
9620
|
const itemWidth = 86;
|
|
9431
9621
|
const startX = 320 - chart.series.length * itemWidth / 2;
|
|
@@ -10110,10 +10300,15 @@ function pptxRenderTimeoutMs() {
|
|
|
10110
10300
|
function normalizePptxLayout(container) {
|
|
10111
10301
|
const slideCanvases = findPptxSlideCanvases(container);
|
|
10112
10302
|
for (const slide of slideCanvases) {
|
|
10113
|
-
slide
|
|
10303
|
+
if (!hasInlineBackground(slide)) {
|
|
10304
|
+
slide.style.backgroundColor = "#FFFFFF";
|
|
10305
|
+
}
|
|
10114
10306
|
}
|
|
10115
10307
|
normalizePptxMirroredText(container);
|
|
10116
10308
|
}
|
|
10309
|
+
function hasInlineBackground(element) {
|
|
10310
|
+
return Boolean(element.style.background || element.style.backgroundColor || element.style.backgroundImage);
|
|
10311
|
+
}
|
|
10117
10312
|
function normalizePptxMirroredText(container) {
|
|
10118
10313
|
const mirroredContainers = Array.from(container.querySelectorAll("div")).filter((element) => {
|
|
10119
10314
|
const text = element.textContent?.trim();
|
|
@@ -10205,7 +10400,7 @@ function renderOpenDocumentPresentationXml(panel, xml) {
|
|
|
10205
10400
|
renderPresentationInsight(panel, inspectOpenDocumentPresentation("FODP \u6F14\u793A\u6587\u7A3F", xml, 0));
|
|
10206
10401
|
renderOpenDocumentPresentation(panel, "FODP \u6F14\u793A\u6587\u7A3F", xml, []);
|
|
10207
10402
|
}
|
|
10208
|
-
async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit) {
|
|
10403
|
+
async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit, messages) {
|
|
10209
10404
|
let zip;
|
|
10210
10405
|
try {
|
|
10211
10406
|
zip = await import_jszip3.default.loadAsync(arrayBuffer);
|
|
@@ -10220,7 +10415,7 @@ async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit) {
|
|
|
10220
10415
|
return true;
|
|
10221
10416
|
}
|
|
10222
10417
|
if (hasEntry("xl/workbook.xml")) {
|
|
10223
|
-
await renderSheet(panel, arrayBuffer, extension);
|
|
10418
|
+
await renderSheet(panel, arrayBuffer, extension, messages);
|
|
10224
10419
|
return true;
|
|
10225
10420
|
}
|
|
10226
10421
|
if (hasEntry("ppt/presentation.xml")) {
|
|
@@ -10651,41 +10846,50 @@ function legacyOfficeFormatLabel(extension) {
|
|
|
10651
10846
|
}
|
|
10652
10847
|
return "PowerPoint Binary File Format";
|
|
10653
10848
|
}
|
|
10654
|
-
function renderLegacyWordBinary(panel, extension, arrayBuffer) {
|
|
10849
|
+
function renderLegacyWordBinary(panel, extension, arrayBuffer, messages) {
|
|
10655
10850
|
try {
|
|
10656
10851
|
renderLegacyWordDocument(panel, parseLegacyWordDocument(arrayBuffer));
|
|
10657
10852
|
} catch (error) {
|
|
10658
|
-
renderLegacyOfficeBinary(
|
|
10853
|
+
renderLegacyOfficeBinary(
|
|
10854
|
+
panel,
|
|
10855
|
+
extension,
|
|
10856
|
+
arrayBuffer,
|
|
10857
|
+
messages,
|
|
10858
|
+
formatPreviewMessage(messages.officeLegacyWordParseFailed, { message: normalizeOfficeError(error, messages) })
|
|
10859
|
+
);
|
|
10659
10860
|
}
|
|
10660
10861
|
}
|
|
10661
|
-
function renderLegacyOfficeBinary(panel, extension, arrayBuffer, parseError) {
|
|
10862
|
+
function renderLegacyOfficeBinary(panel, extension, arrayBuffer, messages, parseError) {
|
|
10662
10863
|
const fragments = extractLegacyOfficeText(arrayBuffer);
|
|
10663
10864
|
panel.replaceChildren();
|
|
10664
|
-
const section = createSection(
|
|
10865
|
+
const section = createSection(messages.officeLegacyConversionTitle);
|
|
10665
10866
|
section.classList.add("ofv-office-conversion");
|
|
10666
10867
|
const format = document.createElement("p");
|
|
10667
10868
|
const strong = document.createElement("strong");
|
|
10668
10869
|
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
|
-
);
|
|
10870
|
+
format.append(strong, document.createTextNode(" "), document.createTextNode(messages.officeLegacyBinaryNotice));
|
|
10675
10871
|
const meta = document.createElement("dl");
|
|
10676
10872
|
meta.className = "ofv-office-binary-meta";
|
|
10677
|
-
appendOfficeBinaryMeta(meta,
|
|
10678
|
-
appendOfficeBinaryMeta(
|
|
10679
|
-
|
|
10873
|
+
appendOfficeBinaryMeta(meta, messages.officeLegacyMetaFormatType, legacyOfficeFormatLabel(extension));
|
|
10874
|
+
appendOfficeBinaryMeta(
|
|
10875
|
+
meta,
|
|
10876
|
+
messages.officeLegacyMetaFileStructure,
|
|
10877
|
+
hasOleSignature(arrayBuffer) ? messages.officeLegacyOleDetected : messages.officeLegacyOleMissing
|
|
10878
|
+
);
|
|
10879
|
+
appendOfficeBinaryMeta(
|
|
10880
|
+
meta,
|
|
10881
|
+
messages.officeLegacyMetaTextFragments,
|
|
10882
|
+
formatPreviewMessage(messages.officeLegacyTextFragmentCount, { count: fragments.length.toLocaleString() })
|
|
10883
|
+
);
|
|
10680
10884
|
if (parseError) {
|
|
10681
|
-
appendOfficeBinaryMeta(meta,
|
|
10885
|
+
appendOfficeBinaryMeta(meta, messages.officeLegacyMetaParseStatus, parseError);
|
|
10682
10886
|
}
|
|
10683
10887
|
section.append(format, meta);
|
|
10684
10888
|
if (fragments.length > 0) {
|
|
10685
10889
|
const article = document.createElement("article");
|
|
10686
10890
|
article.className = "ofv-document ofv-office-binary-fragments";
|
|
10687
10891
|
const heading = document.createElement("h4");
|
|
10688
|
-
heading.textContent =
|
|
10892
|
+
heading.textContent = messages.officeLegacyReadableFragments;
|
|
10689
10893
|
article.append(heading);
|
|
10690
10894
|
for (const fragment of fragments.slice(0, 80)) {
|
|
10691
10895
|
const paragraph = document.createElement("p");
|
|
@@ -10696,7 +10900,7 @@ function renderLegacyOfficeBinary(panel, extension, arrayBuffer, parseError) {
|
|
|
10696
10900
|
} else {
|
|
10697
10901
|
const empty = document.createElement("p");
|
|
10698
10902
|
empty.className = "ofv-office-binary-empty";
|
|
10699
|
-
empty.textContent =
|
|
10903
|
+
empty.textContent = messages.officeLegacyNoText;
|
|
10700
10904
|
section.append(empty);
|
|
10701
10905
|
}
|
|
10702
10906
|
panel.append(section);
|
|
@@ -10708,23 +10912,27 @@ function appendOfficeBinaryMeta(list, label, value) {
|
|
|
10708
10912
|
detail.textContent = value;
|
|
10709
10913
|
list.append(term, detail);
|
|
10710
10914
|
}
|
|
10711
|
-
function renderUnsupportedOffice(panel, extension) {
|
|
10915
|
+
function renderUnsupportedOffice(panel, extension, messages) {
|
|
10712
10916
|
const legacyBinary = /* @__PURE__ */ new Set(["doc", "dot", "wps", "ppt", "pps", "key", "dps"]);
|
|
10713
|
-
const message = legacyBinary.has(extension) ?
|
|
10917
|
+
const message = legacyBinary.has(extension) ? messages.officeUnsupportedLegacyMessage : messages.officeUnsupportedGenericMessage;
|
|
10714
10918
|
panel.replaceChildren();
|
|
10715
|
-
const section = createSection(
|
|
10919
|
+
const section = createSection(messages.officeUnsupportedTitle);
|
|
10716
10920
|
const format = document.createElement("p");
|
|
10717
10921
|
const strong = document.createElement("strong");
|
|
10718
10922
|
strong.textContent = `.${extension}`;
|
|
10719
|
-
format.append(
|
|
10923
|
+
format.append(
|
|
10924
|
+
strong,
|
|
10925
|
+
document.createTextNode(" "),
|
|
10926
|
+
document.createTextNode(formatPreviewMessage(messages.officeUnsupportedIntro, { message }))
|
|
10927
|
+
);
|
|
10720
10928
|
const support = document.createElement("p");
|
|
10721
|
-
support.textContent =
|
|
10929
|
+
support.textContent = messages.officeUnsupportedSupportedFormats;
|
|
10722
10930
|
section.append(format, support);
|
|
10723
10931
|
panel.append(section);
|
|
10724
10932
|
}
|
|
10725
|
-
function normalizeOfficeError(error) {
|
|
10933
|
+
function normalizeOfficeError(error, messages) {
|
|
10726
10934
|
const message = error instanceof Error ? error.message : String(error || "");
|
|
10727
|
-
return message ?
|
|
10935
|
+
return message ? formatPreviewMessage(messages.officeErrorWithMessage, { message }) : messages.officeErrorWithoutMessage;
|
|
10728
10936
|
}
|
|
10729
10937
|
function extractLegacyOfficeText(arrayBuffer) {
|
|
10730
10938
|
const bytes = new Uint8Array(arrayBuffer);
|
|
@@ -11966,11 +12174,13 @@ function archivePlugin() {
|
|
|
11966
12174
|
sidebarToggle.addEventListener("click", () => {
|
|
11967
12175
|
setSidebarCollapsed(!layout.classList.contains("is-sidebar-collapsed"));
|
|
11968
12176
|
});
|
|
11969
|
-
const showDefaultSummary = () => {
|
|
12177
|
+
const showDefaultSummary = (isSupplemental = true) => {
|
|
11970
12178
|
mainPanel.replaceChildren();
|
|
11971
12179
|
const summary = document.createElement("div");
|
|
11972
12180
|
summary.className = "ofv-archive-info";
|
|
11973
|
-
|
|
12181
|
+
if (isSupplemental) {
|
|
12182
|
+
hideSupplementalInfo4(summary);
|
|
12183
|
+
}
|
|
11974
12184
|
const heading = document.createElement("h3");
|
|
11975
12185
|
heading.textContent = ctx.file.name;
|
|
11976
12186
|
const info = document.createElement("div");
|
|
@@ -11980,12 +12190,16 @@ function archivePlugin() {
|
|
|
11980
12190
|
appendArchiveInfo(info, "\u683C\u5F0F\u7C7B\u578B", `.${ext.toUpperCase()} \u538B\u7F29\u6587\u4EF6`);
|
|
11981
12191
|
appendArchiveInfo(info, "\u5305\u542B\u6587\u4EF6\u6570", `${fileCount} \u4E2A`);
|
|
11982
12192
|
appendArchiveInfo(info, "\u5305\u542B\u76EE\u5F55\u6570", `${dirCount} \u4E2A`);
|
|
11983
|
-
appendArchiveInfo(
|
|
12193
|
+
appendArchiveInfo(
|
|
12194
|
+
info,
|
|
12195
|
+
"\u64CD\u4F5C\u63D0\u793A",
|
|
12196
|
+
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"
|
|
12197
|
+
);
|
|
11984
12198
|
summary.append(heading, info, createArchiveSummary(archiveEntries));
|
|
11985
12199
|
mainPanel.append(summary);
|
|
11986
12200
|
};
|
|
11987
|
-
showDefaultSummary();
|
|
11988
12201
|
const visibleEntries = archiveEntries.filter((e) => !e.dir).slice(0, 500);
|
|
12202
|
+
showDefaultSummary(visibleEntries.length > 0);
|
|
11989
12203
|
let destroyed = false;
|
|
11990
12204
|
let renderToken = 0;
|
|
11991
12205
|
const openArchiveEntry = async (entry, item) => {
|