@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.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");
|
|
@@ -686,12 +756,17 @@ function createViewer(options) {
|
|
|
686
756
|
currentIndex = clampIndex(index, queue.length);
|
|
687
757
|
await renderQueueItem(currentIndex);
|
|
688
758
|
};
|
|
689
|
-
const toolbar = createToolbar(
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
759
|
+
const toolbar = createToolbar(
|
|
760
|
+
options.toolbar,
|
|
761
|
+
viewport,
|
|
762
|
+
{
|
|
763
|
+
getLength: () => queue.length,
|
|
764
|
+
next: () => goTo(currentIndex + 1),
|
|
765
|
+
previous: () => goTo(currentIndex - 1),
|
|
766
|
+
command: (command) => currentInstance?.command?.(command)
|
|
767
|
+
},
|
|
768
|
+
options.locale || "en-US"
|
|
769
|
+
);
|
|
695
770
|
if (toolbar) {
|
|
696
771
|
host.append(toolbar.element);
|
|
697
772
|
}
|
|
@@ -810,12 +885,15 @@ function createViewer(options) {
|
|
|
810
885
|
theme.destroy();
|
|
811
886
|
container.replaceChildren();
|
|
812
887
|
container.classList.remove("ofv-root");
|
|
813
|
-
if (
|
|
814
|
-
container.classList.remove(
|
|
888
|
+
if (customClassNames.length > 0) {
|
|
889
|
+
container.classList.remove(...customClassNames);
|
|
815
890
|
}
|
|
816
891
|
}
|
|
817
892
|
};
|
|
818
893
|
}
|
|
894
|
+
function parseClassNameTokens(className) {
|
|
895
|
+
return className?.trim().split(/\s+/).filter(Boolean) ?? [];
|
|
896
|
+
}
|
|
819
897
|
function destroyPreviewInstance(instance) {
|
|
820
898
|
if (!instance) {
|
|
821
899
|
return;
|
|
@@ -925,7 +1003,7 @@ function removeMediaListener(media, listener) {
|
|
|
925
1003
|
}
|
|
926
1004
|
media.removeListener?.(listener);
|
|
927
1005
|
}
|
|
928
|
-
function createToolbar(toolbar, viewport, queue) {
|
|
1006
|
+
function createToolbar(toolbar, viewport, queue, locale) {
|
|
929
1007
|
if (!toolbar) {
|
|
930
1008
|
return void 0;
|
|
931
1009
|
}
|
|
@@ -933,7 +1011,7 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
933
1011
|
const element = document.createElement("div");
|
|
934
1012
|
element.className = "ofv-toolbar";
|
|
935
1013
|
element.setAttribute("role", "toolbar");
|
|
936
|
-
element.setAttribute("aria-label",
|
|
1014
|
+
element.setAttribute("aria-label", defaultToolbarText[locale].ariaLabel);
|
|
937
1015
|
let file;
|
|
938
1016
|
let currentIndex = 0;
|
|
939
1017
|
let currentLength = queue.getLength();
|
|
@@ -941,6 +1019,7 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
941
1019
|
let previousButton;
|
|
942
1020
|
let nextButton;
|
|
943
1021
|
let zoomResetButton;
|
|
1022
|
+
let fullscreenButton;
|
|
944
1023
|
let currentZoom;
|
|
945
1024
|
const commandButtons = [];
|
|
946
1025
|
const customButtons = [];
|
|
@@ -993,8 +1072,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
993
1072
|
}
|
|
994
1073
|
if (id === "previous" && queue.getLength() > 1) {
|
|
995
1074
|
previousButton = addButton(
|
|
996
|
-
getToolbarLabel(options, "previous"),
|
|
997
|
-
getToolbarTitle(options, "previous"),
|
|
1075
|
+
getToolbarLabel(options, locale, "previous"),
|
|
1076
|
+
getToolbarTitle(options, locale, "previous"),
|
|
998
1077
|
() => void queue.previous(),
|
|
999
1078
|
void 0,
|
|
1000
1079
|
options.icons?.previous
|
|
@@ -1003,8 +1082,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1003
1082
|
}
|
|
1004
1083
|
if (id === "next" && queue.getLength() > 1) {
|
|
1005
1084
|
nextButton = addButton(
|
|
1006
|
-
getToolbarLabel(options, "next"),
|
|
1007
|
-
getToolbarTitle(options, "next"),
|
|
1085
|
+
getToolbarLabel(options, locale, "next"),
|
|
1086
|
+
getToolbarTitle(options, locale, "next"),
|
|
1008
1087
|
() => void queue.next(),
|
|
1009
1088
|
void 0,
|
|
1010
1089
|
options.icons?.next
|
|
@@ -1018,27 +1097,27 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1018
1097
|
return;
|
|
1019
1098
|
}
|
|
1020
1099
|
if (id === "zoom-out" && options.zoom) {
|
|
1021
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "zoom-out");
|
|
1100
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "zoom-out");
|
|
1022
1101
|
return;
|
|
1023
1102
|
}
|
|
1024
1103
|
if (id === "zoom-in" && options.zoom) {
|
|
1025
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "zoom-in");
|
|
1104
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "zoom-in");
|
|
1026
1105
|
return;
|
|
1027
1106
|
}
|
|
1028
1107
|
if (id === "zoom-reset" && options.zoom) {
|
|
1029
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "zoom-reset");
|
|
1108
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "zoom-reset");
|
|
1030
1109
|
zoomResetButton = commandButtons[commandButtons.length - 1]?.button;
|
|
1031
1110
|
updateZoomLabel();
|
|
1032
1111
|
return;
|
|
1033
1112
|
}
|
|
1034
1113
|
if (id === "rotate-right" && options.rotate) {
|
|
1035
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "rotate-right");
|
|
1114
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "rotate-right");
|
|
1036
1115
|
return;
|
|
1037
1116
|
}
|
|
1038
1117
|
if (id === "download" && options.download !== false) {
|
|
1039
1118
|
addButton(
|
|
1040
|
-
getToolbarLabel(options, id),
|
|
1041
|
-
getToolbarTitle(options, id),
|
|
1119
|
+
getToolbarLabel(options, locale, id),
|
|
1120
|
+
getToolbarTitle(options, locale, id),
|
|
1042
1121
|
() => getContext().download(),
|
|
1043
1122
|
void 0,
|
|
1044
1123
|
options.icons?.download
|
|
@@ -1046,19 +1125,20 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1046
1125
|
return;
|
|
1047
1126
|
}
|
|
1048
1127
|
if (id === "fullscreen" && options.fullscreen !== false) {
|
|
1049
|
-
addButton(
|
|
1050
|
-
getToolbarLabel(options, id),
|
|
1051
|
-
getToolbarTitle(options, id),
|
|
1128
|
+
fullscreenButton = addButton(
|
|
1129
|
+
getToolbarLabel(options, locale, id),
|
|
1130
|
+
getToolbarTitle(options, locale, id),
|
|
1052
1131
|
() => getContext().fullscreen(),
|
|
1053
1132
|
void 0,
|
|
1054
1133
|
options.icons?.fullscreen
|
|
1055
1134
|
);
|
|
1135
|
+
updateFullscreenButton();
|
|
1056
1136
|
return;
|
|
1057
1137
|
}
|
|
1058
1138
|
if (id === "print" && options.print) {
|
|
1059
1139
|
addButton(
|
|
1060
|
-
getToolbarLabel(options, id),
|
|
1061
|
-
getToolbarTitle(options, id),
|
|
1140
|
+
getToolbarLabel(options, locale, id),
|
|
1141
|
+
getToolbarTitle(options, locale, id),
|
|
1062
1142
|
() => getContext().print(),
|
|
1063
1143
|
void 0,
|
|
1064
1144
|
options.icons?.print
|
|
@@ -1084,11 +1164,11 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1084
1164
|
const renderSearchControl = () => {
|
|
1085
1165
|
const searchGroup = document.createElement("div");
|
|
1086
1166
|
searchGroup.className = "ofv-toolbar-search";
|
|
1087
|
-
searchGroup.title = getToolbarTitle(options, "search");
|
|
1167
|
+
searchGroup.title = getToolbarTitle(options, locale, "search");
|
|
1088
1168
|
const nextSearchInput = document.createElement("input");
|
|
1089
1169
|
nextSearchInput.type = "search";
|
|
1090
|
-
nextSearchInput.placeholder = getToolbarLabel(options, "search");
|
|
1091
|
-
nextSearchInput.setAttribute("aria-label", getToolbarTitle(options, "search"));
|
|
1170
|
+
nextSearchInput.placeholder = getToolbarLabel(options, locale, "search");
|
|
1171
|
+
nextSearchInput.setAttribute("aria-label", getToolbarTitle(options, locale, "search"));
|
|
1092
1172
|
const nextSearchCount = document.createElement("span");
|
|
1093
1173
|
nextSearchCount.className = "ofv-toolbar-search-count";
|
|
1094
1174
|
searchInput = nextSearchInput;
|
|
@@ -1143,7 +1223,7 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1143
1223
|
}
|
|
1144
1224
|
setToolbarButtonContent(
|
|
1145
1225
|
zoomResetButton,
|
|
1146
|
-
currentZoom === void 0 ? getToolbarLabel(options, "zoom-reset") : formatToolbarZoom(currentZoom),
|
|
1226
|
+
currentZoom === void 0 ? getToolbarLabel(options, locale, "zoom-reset") : formatToolbarZoom(currentZoom),
|
|
1147
1227
|
options.icons?.["zoom-reset"]
|
|
1148
1228
|
);
|
|
1149
1229
|
}
|
|
@@ -1154,6 +1234,32 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1154
1234
|
updateCustomButtons();
|
|
1155
1235
|
refreshCustomRender();
|
|
1156
1236
|
}
|
|
1237
|
+
function isFullscreenActive() {
|
|
1238
|
+
return Boolean(
|
|
1239
|
+
typeof document !== "undefined" && element.parentElement && document.fullscreenElement === element.parentElement
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
function updateFullscreenButton() {
|
|
1243
|
+
if (!fullscreenButton) {
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
const active = isFullscreenActive();
|
|
1247
|
+
const id = active ? "exit-fullscreen" : "fullscreen";
|
|
1248
|
+
const icon = active ? options.icons?.["exit-fullscreen"] ?? options.icons?.fullscreen : options.icons?.fullscreen;
|
|
1249
|
+
setToolbarButtonContent(fullscreenButton, getToolbarLabel(options, locale, id), icon);
|
|
1250
|
+
const title = getToolbarTitle(options, locale, id);
|
|
1251
|
+
fullscreenButton.title = title;
|
|
1252
|
+
fullscreenButton.setAttribute("aria-label", title);
|
|
1253
|
+
fullscreenButton.setAttribute("aria-pressed", String(active));
|
|
1254
|
+
}
|
|
1255
|
+
const handleFullscreenChange = () => {
|
|
1256
|
+
updateFullscreenButton();
|
|
1257
|
+
refreshCustomRender();
|
|
1258
|
+
};
|
|
1259
|
+
if (typeof document !== "undefined") {
|
|
1260
|
+
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
1261
|
+
disposers.push(() => document.removeEventListener("fullscreenchange", handleFullscreenChange));
|
|
1262
|
+
}
|
|
1157
1263
|
const refreshCustomRender = () => {
|
|
1158
1264
|
if (!options.render) {
|
|
1159
1265
|
return;
|
|
@@ -1227,6 +1333,9 @@ function createToolbarContext({
|
|
|
1227
1333
|
viewport,
|
|
1228
1334
|
canPrevious: index > 0,
|
|
1229
1335
|
canNext: index < length - 1,
|
|
1336
|
+
isFullscreen: Boolean(
|
|
1337
|
+
typeof document !== "undefined" && element.parentElement && document.fullscreenElement === element.parentElement
|
|
1338
|
+
),
|
|
1230
1339
|
zoom,
|
|
1231
1340
|
zoomLabel: zoom === void 0 ? void 0 : formatToolbarZoom(zoom),
|
|
1232
1341
|
async previous() {
|
|
@@ -1245,7 +1354,15 @@ function createToolbarContext({
|
|
|
1245
1354
|
}
|
|
1246
1355
|
},
|
|
1247
1356
|
fullscreen() {
|
|
1248
|
-
|
|
1357
|
+
const target = element.parentElement;
|
|
1358
|
+
if (!target) {
|
|
1359
|
+
return;
|
|
1360
|
+
}
|
|
1361
|
+
if (typeof document !== "undefined" && document.fullscreenElement === target) {
|
|
1362
|
+
void document.exitFullscreen?.();
|
|
1363
|
+
} else {
|
|
1364
|
+
void target.requestFullscreen?.();
|
|
1365
|
+
}
|
|
1249
1366
|
},
|
|
1250
1367
|
print() {
|
|
1251
1368
|
printPreview(viewport);
|
|
@@ -1254,37 +1371,75 @@ function createToolbarContext({
|
|
|
1254
1371
|
clearSearch: search.clear
|
|
1255
1372
|
};
|
|
1256
1373
|
}
|
|
1257
|
-
var
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1374
|
+
var defaultToolbarText = {
|
|
1375
|
+
"zh-CN": {
|
|
1376
|
+
ariaLabel: "\u6587\u4EF6\u9884\u89C8\u5DE5\u5177\u680F",
|
|
1377
|
+
labels: {
|
|
1378
|
+
previous: "\u4E0A\u4E00\u4E2A",
|
|
1379
|
+
next: "\u4E0B\u4E00\u4E2A",
|
|
1380
|
+
queue: "",
|
|
1381
|
+
"zoom-out": "-",
|
|
1382
|
+
"zoom-in": "+",
|
|
1383
|
+
"zoom-reset": "100%",
|
|
1384
|
+
"rotate-right": "\u65CB\u8F6C",
|
|
1385
|
+
download: "\u4E0B\u8F7D",
|
|
1386
|
+
fullscreen: "\u5168\u5C4F",
|
|
1387
|
+
"exit-fullscreen": "\u9000\u51FA\u5168\u5C4F",
|
|
1388
|
+
print: "\u6253\u5370",
|
|
1389
|
+
search: "\u641C\u7D22"
|
|
1390
|
+
},
|
|
1391
|
+
titles: {
|
|
1392
|
+
previous: "\u4E0A\u4E00\u4E2A\u6587\u4EF6",
|
|
1393
|
+
next: "\u4E0B\u4E00\u4E2A\u6587\u4EF6",
|
|
1394
|
+
queue: "\u5F53\u524D\u6587\u4EF6\u4F4D\u7F6E",
|
|
1395
|
+
"zoom-out": "\u7F29\u5C0F",
|
|
1396
|
+
"zoom-in": "\u653E\u5927",
|
|
1397
|
+
"zoom-reset": "\u91CD\u7F6E\u7F29\u653E",
|
|
1398
|
+
"rotate-right": "\u5411\u53F3\u65CB\u8F6C",
|
|
1399
|
+
download: "\u4E0B\u8F7D\u6587\u4EF6",
|
|
1400
|
+
fullscreen: "\u5168\u5C4F\u67E5\u770B\u9884\u89C8",
|
|
1401
|
+
"exit-fullscreen": "\u9000\u51FA\u5168\u5C4F",
|
|
1402
|
+
print: "\u6253\u5370\u9884\u89C8",
|
|
1403
|
+
search: "\u641C\u7D22\u9884\u89C8\u6587\u672C"
|
|
1404
|
+
}
|
|
1405
|
+
},
|
|
1406
|
+
"en-US": {
|
|
1407
|
+
ariaLabel: "File preview toolbar",
|
|
1408
|
+
labels: {
|
|
1409
|
+
previous: "Prev",
|
|
1410
|
+
next: "Next",
|
|
1411
|
+
queue: "",
|
|
1412
|
+
"zoom-out": "-",
|
|
1413
|
+
"zoom-in": "+",
|
|
1414
|
+
"zoom-reset": "100%",
|
|
1415
|
+
"rotate-right": "Rotate",
|
|
1416
|
+
download: "Download",
|
|
1417
|
+
fullscreen: "Fullscreen",
|
|
1418
|
+
"exit-fullscreen": "Exit fullscreen",
|
|
1419
|
+
print: "Print",
|
|
1420
|
+
search: "Search"
|
|
1421
|
+
},
|
|
1422
|
+
titles: {
|
|
1423
|
+
previous: "Previous file",
|
|
1424
|
+
next: "Next file",
|
|
1425
|
+
queue: "Current file position",
|
|
1426
|
+
"zoom-out": "Zoom out",
|
|
1427
|
+
"zoom-in": "Zoom in",
|
|
1428
|
+
"zoom-reset": "Reset zoom",
|
|
1429
|
+
"rotate-right": "Rotate right",
|
|
1430
|
+
download: "Download file",
|
|
1431
|
+
fullscreen: "Open preview fullscreen",
|
|
1432
|
+
"exit-fullscreen": "Exit fullscreen",
|
|
1433
|
+
print: "Print preview",
|
|
1434
|
+
search: "Search preview text"
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1282
1437
|
};
|
|
1283
|
-
function getToolbarLabel(options, id) {
|
|
1284
|
-
return options.labels?.[id] ??
|
|
1438
|
+
function getToolbarLabel(options, locale, id) {
|
|
1439
|
+
return options.labels?.[id] ?? defaultToolbarText[locale].labels[id];
|
|
1285
1440
|
}
|
|
1286
|
-
function getToolbarTitle(options, id) {
|
|
1287
|
-
return options.titles?.[id] ?? options.labels?.[id] ??
|
|
1441
|
+
function getToolbarTitle(options, locale, id) {
|
|
1442
|
+
return options.titles?.[id] ?? options.labels?.[id] ?? defaultToolbarText[locale].titles[id];
|
|
1288
1443
|
}
|
|
1289
1444
|
function formatToolbarZoom(zoom) {
|
|
1290
1445
|
return `${Math.round(zoom * 100)}%`;
|
|
@@ -1436,7 +1591,7 @@ function isSafeToolbarIconAttribute(name, value) {
|
|
|
1436
1591
|
return !/^\s*(?:javascript|data:text\/html|vbscript):/i.test(value);
|
|
1437
1592
|
}
|
|
1438
1593
|
function isBuiltInToolbarAction(id) {
|
|
1439
|
-
return id in
|
|
1594
|
+
return id in defaultToolbarText["en-US"].labels;
|
|
1440
1595
|
}
|
|
1441
1596
|
function createSearchController(root) {
|
|
1442
1597
|
const markerClass = "ofv-search-match";
|
|
@@ -1515,6 +1670,9 @@ function collectSearchableTextNodes(root) {
|
|
|
1515
1670
|
if (["SCRIPT", "STYLE", "TEXTAREA", "INPUT", "BUTTON"].includes(parent.tagName)) {
|
|
1516
1671
|
return NodeFilter.FILTER_REJECT;
|
|
1517
1672
|
}
|
|
1673
|
+
if (hasHiddenSearchAncestor(parent, root)) {
|
|
1674
|
+
return NodeFilter.FILTER_REJECT;
|
|
1675
|
+
}
|
|
1518
1676
|
return NodeFilter.FILTER_ACCEPT;
|
|
1519
1677
|
}
|
|
1520
1678
|
});
|
|
@@ -1525,6 +1683,19 @@ function collectSearchableTextNodes(root) {
|
|
|
1525
1683
|
}
|
|
1526
1684
|
return nodes;
|
|
1527
1685
|
}
|
|
1686
|
+
function hasHiddenSearchAncestor(element, root) {
|
|
1687
|
+
let current = element;
|
|
1688
|
+
while (current) {
|
|
1689
|
+
if (current.hidden || current.getAttribute("aria-hidden") === "true" || current.style.display === "none" || current.style.visibility === "hidden") {
|
|
1690
|
+
return true;
|
|
1691
|
+
}
|
|
1692
|
+
if (current === root) {
|
|
1693
|
+
break;
|
|
1694
|
+
}
|
|
1695
|
+
current = current.parentElement;
|
|
1696
|
+
}
|
|
1697
|
+
return false;
|
|
1698
|
+
}
|
|
1528
1699
|
function printPreview(viewport) {
|
|
1529
1700
|
const frame = document.createElement("iframe");
|
|
1530
1701
|
frame.className = "ofv-print-frame";
|
|
@@ -4022,7 +4193,7 @@ function textPlugin() {
|
|
|
4022
4193
|
const isMarkdown = lang === "markdown";
|
|
4023
4194
|
const text = await readText(ctx.file.source).catch((error) => void 0);
|
|
4024
4195
|
if (text === void 0) {
|
|
4025
|
-
const fallback = createTextFallback(ctx.file.name, ctx.file.url);
|
|
4196
|
+
const fallback = createTextFallback(ctx.file.name, ctx.options.messages, ctx.file.url);
|
|
4026
4197
|
ctx.viewport.classList.add("ofv-center");
|
|
4027
4198
|
ctx.viewport.append(fallback);
|
|
4028
4199
|
return {
|
|
@@ -4194,10 +4365,11 @@ function textPlugin() {
|
|
|
4194
4365
|
title.className = "ofv-code-title";
|
|
4195
4366
|
const fileName = document.createElement("strong");
|
|
4196
4367
|
fileName.textContent = ctx.file.name;
|
|
4368
|
+
const messages = ctx.options.messages;
|
|
4197
4369
|
const meta = document.createElement("span");
|
|
4198
4370
|
meta.textContent = [
|
|
4199
|
-
lang === "none" ?
|
|
4200
|
-
|
|
4371
|
+
lang === "none" ? messages.textPlainLanguage : lang,
|
|
4372
|
+
formatPreviewMessage(messages.textLineCount, { count: totalLines.toLocaleString() }),
|
|
4201
4373
|
formatBytes(ctx.file.size ?? (ctx.file.source instanceof Blob ? ctx.file.source.size : text.length))
|
|
4202
4374
|
].join(" \xB7 ");
|
|
4203
4375
|
title.append(fileName, meta);
|
|
@@ -4209,7 +4381,7 @@ function textPlugin() {
|
|
|
4209
4381
|
const wrapButton = document.createElement("button");
|
|
4210
4382
|
wrapButton.type = "button";
|
|
4211
4383
|
wrapButton.className = "ofv-code-action";
|
|
4212
|
-
wrapButton.textContent =
|
|
4384
|
+
wrapButton.textContent = messages.textWrap;
|
|
4213
4385
|
wrapButton.setAttribute("aria-pressed", String(defaultWrapped));
|
|
4214
4386
|
wrapButton.addEventListener("click", () => {
|
|
4215
4387
|
const wrapped = wrapper.classList.toggle("is-wrapped");
|
|
@@ -4218,14 +4390,14 @@ function textPlugin() {
|
|
|
4218
4390
|
const copyButton = document.createElement("button");
|
|
4219
4391
|
copyButton.type = "button";
|
|
4220
4392
|
copyButton.className = "ofv-code-action";
|
|
4221
|
-
copyButton.textContent =
|
|
4393
|
+
copyButton.textContent = messages.textCopy;
|
|
4222
4394
|
copyButton.addEventListener("click", async () => {
|
|
4223
4395
|
copyButton.disabled = true;
|
|
4224
4396
|
try {
|
|
4225
4397
|
await copyToClipboard(text);
|
|
4226
|
-
status.textContent =
|
|
4398
|
+
status.textContent = messages.textCopied;
|
|
4227
4399
|
} catch {
|
|
4228
|
-
status.textContent =
|
|
4400
|
+
status.textContent = messages.textCopyFailed;
|
|
4229
4401
|
} finally {
|
|
4230
4402
|
copyButton.disabled = false;
|
|
4231
4403
|
}
|
|
@@ -4233,10 +4405,10 @@ function textPlugin() {
|
|
|
4233
4405
|
const downloadButton = document.createElement("button");
|
|
4234
4406
|
downloadButton.type = "button";
|
|
4235
4407
|
downloadButton.className = "ofv-code-action";
|
|
4236
|
-
downloadButton.textContent =
|
|
4408
|
+
downloadButton.textContent = messages.textDownload;
|
|
4237
4409
|
downloadButton.addEventListener("click", () => {
|
|
4238
4410
|
downloadText(ctx.file.name, text);
|
|
4239
|
-
status.textContent =
|
|
4411
|
+
status.textContent = messages.textDownloadReady;
|
|
4240
4412
|
});
|
|
4241
4413
|
actions.append(wrapButton, copyButton, downloadButton, status);
|
|
4242
4414
|
header.append(title, actions);
|
|
@@ -4261,13 +4433,13 @@ function textPlugin() {
|
|
|
4261
4433
|
if (truncated) {
|
|
4262
4434
|
const notice = document.createElement("div");
|
|
4263
4435
|
notice.className = "ofv-code-notice";
|
|
4264
|
-
notice.textContent =
|
|
4436
|
+
notice.textContent = formatPreviewMessage(messages.textLargeFileNotice, { size: formatBytes(codeText.length) });
|
|
4265
4437
|
wrapper.append(notice);
|
|
4266
4438
|
}
|
|
4267
4439
|
if (!shouldHighlight) {
|
|
4268
4440
|
const notice = document.createElement("div");
|
|
4269
4441
|
notice.className = "ofv-code-notice";
|
|
4270
|
-
notice.textContent =
|
|
4442
|
+
notice.textContent = messages.textHighlightSkipped;
|
|
4271
4443
|
wrapper.append(notice);
|
|
4272
4444
|
}
|
|
4273
4445
|
wrapper.appendChild(body);
|
|
@@ -4334,19 +4506,19 @@ function normalizeFileName2(name) {
|
|
|
4334
4506
|
const baseName = name.split(/[\\/]/).pop() || name;
|
|
4335
4507
|
return baseName.toLowerCase();
|
|
4336
4508
|
}
|
|
4337
|
-
function createTextFallback(fileName, url) {
|
|
4509
|
+
function createTextFallback(fileName, messages, url) {
|
|
4338
4510
|
const fallback = document.createElement("div");
|
|
4339
4511
|
fallback.className = "ofv-fallback";
|
|
4340
4512
|
const title = document.createElement("strong");
|
|
4341
|
-
title.textContent =
|
|
4513
|
+
title.textContent = messages.textPreviewFailedTitle;
|
|
4342
4514
|
const meta = document.createElement("span");
|
|
4343
|
-
meta.textContent =
|
|
4515
|
+
meta.textContent = messages.textPreviewFailedMessage;
|
|
4344
4516
|
fallback.append(title, meta);
|
|
4345
4517
|
if (url) {
|
|
4346
4518
|
const download = document.createElement("a");
|
|
4347
4519
|
download.href = url;
|
|
4348
4520
|
download.download = fileName;
|
|
4349
|
-
download.textContent =
|
|
4521
|
+
download.textContent = messages.textOpenOriginal;
|
|
4350
4522
|
fallback.append(download);
|
|
4351
4523
|
}
|
|
4352
4524
|
return fallback;
|
|
@@ -7408,7 +7580,7 @@ function officePlugin(options = {}) {
|
|
|
7408
7580
|
} else if (packageFormat === "docx" && !fileIsDocx(extension)) {
|
|
7409
7581
|
disposeDocxFit = await renderDocx(panel, arrayBuffer, ctx.options.fit);
|
|
7410
7582
|
} else if (packageFormat === "xlsx" && !sheetExtensions.has(extension)) {
|
|
7411
|
-
await renderSheet(panel, arrayBuffer, "xlsx");
|
|
7583
|
+
await renderSheet(panel, arrayBuffer, "xlsx", ctx.options.messages);
|
|
7412
7584
|
} else if (packageFormat === "pptx" && !["pptx", "pptm", "ppsx", "ppsm", "potx", "potm"].includes(extension)) {
|
|
7413
7585
|
await renderPptx(panel, arrayBuffer);
|
|
7414
7586
|
} else if (fileIsDocx(extension)) {
|
|
@@ -7421,9 +7593,9 @@ function officePlugin(options = {}) {
|
|
|
7421
7593
|
renderOpenDocumentXml(panel, "FODT \u6587\u6863", await readTextFromBuffer(arrayBuffer));
|
|
7422
7594
|
} else if (extension === "fods") {
|
|
7423
7595
|
renderFlatOds(panel, await readTextFromBuffer(arrayBuffer));
|
|
7424
|
-
} else if (packagedOfficeCandidates.has(extension) && await renderPackagedOfficePreview(panel, arrayBuffer, extension, ctx.options.fit)) {
|
|
7596
|
+
} else if (packagedOfficeCandidates.has(extension) && await renderPackagedOfficePreview(panel, arrayBuffer, extension, ctx.options.fit, ctx.options.messages)) {
|
|
7425
7597
|
} else if (sheetExtensions.has(extension)) {
|
|
7426
|
-
await renderSheet(panel, arrayBuffer, extension);
|
|
7598
|
+
await renderSheet(panel, arrayBuffer, extension, ctx.options.messages);
|
|
7427
7599
|
} else if (["pptx", "pptm", "ppsx", "ppsm", "potx", "potm"].includes(extension)) {
|
|
7428
7600
|
await renderPptx(panel, arrayBuffer);
|
|
7429
7601
|
} else if (extension === "odp") {
|
|
@@ -7431,11 +7603,11 @@ function officePlugin(options = {}) {
|
|
|
7431
7603
|
} else if (extension === "fodp") {
|
|
7432
7604
|
renderOpenDocumentPresentationXml(panel, await readTextFromBuffer(arrayBuffer));
|
|
7433
7605
|
} else if (extension === "doc" || extension === "dot") {
|
|
7434
|
-
renderLegacyWordBinary(panel, extension, arrayBuffer);
|
|
7606
|
+
renderLegacyWordBinary(panel, extension, arrayBuffer, ctx.options.messages);
|
|
7435
7607
|
} else if (isLegacyOfficeBinary(extension)) {
|
|
7436
|
-
renderLegacyOfficeBinary(panel, extension, arrayBuffer);
|
|
7608
|
+
renderLegacyOfficeBinary(panel, extension, arrayBuffer, ctx.options.messages);
|
|
7437
7609
|
} else {
|
|
7438
|
-
renderUnsupportedOffice(panel, extension || ctx.file.extension || "office");
|
|
7610
|
+
renderUnsupportedOffice(panel, extension || ctx.file.extension || "office", ctx.options.messages);
|
|
7439
7611
|
}
|
|
7440
7612
|
const controller = createOfficeZoomController(panel, ctx);
|
|
7441
7613
|
ctx.toolbar?.refreshCommandSupport();
|
|
@@ -8780,7 +8952,7 @@ function renderPlainDocument(panel, title, text) {
|
|
|
8780
8952
|
section.append(pre);
|
|
8781
8953
|
panel.append(section);
|
|
8782
8954
|
}
|
|
8783
|
-
async function renderSheet(panel, arrayBuffer, extension) {
|
|
8955
|
+
async function renderSheet(panel, arrayBuffer, extension, messages) {
|
|
8784
8956
|
const xlsx = await import("xlsx");
|
|
8785
8957
|
let workbook;
|
|
8786
8958
|
try {
|
|
@@ -8793,10 +8965,16 @@ async function renderSheet(panel, arrayBuffer, extension) {
|
|
|
8793
8965
|
}) : xlsx.read(arrayBuffer, { type: "array", cellDates: true, cellNF: true, cellStyles: true });
|
|
8794
8966
|
} catch (error) {
|
|
8795
8967
|
if (isLegacyOfficeBinary(extension)) {
|
|
8796
|
-
renderLegacyOfficeBinary(
|
|
8968
|
+
renderLegacyOfficeBinary(
|
|
8969
|
+
panel,
|
|
8970
|
+
extension,
|
|
8971
|
+
arrayBuffer,
|
|
8972
|
+
messages,
|
|
8973
|
+
formatPreviewMessage(messages.officeSheetParseFailed, { message: normalizeOfficeError(error, messages) })
|
|
8974
|
+
);
|
|
8797
8975
|
return;
|
|
8798
8976
|
}
|
|
8799
|
-
renderSheetFallback(panel, extension, normalizeOfficeError(error));
|
|
8977
|
+
renderSheetFallback(panel, extension, normalizeOfficeError(error, messages));
|
|
8800
8978
|
return;
|
|
8801
8979
|
}
|
|
8802
8980
|
const chartPreviews = await readWorkbookCharts(arrayBuffer).catch(() => []);
|
|
@@ -9277,6 +9455,9 @@ function renderChartCard(chart) {
|
|
|
9277
9455
|
function renderChartSvg(chart) {
|
|
9278
9456
|
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
9279
9457
|
svg.setAttribute("viewBox", "0 0 640 380");
|
|
9458
|
+
svg.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
|
9459
|
+
svg.setAttribute("text-rendering", "geometricPrecision");
|
|
9460
|
+
svg.setAttribute("shape-rendering", "geometricPrecision");
|
|
9280
9461
|
svg.setAttribute("role", "img");
|
|
9281
9462
|
svg.setAttribute("aria-label", chart.title);
|
|
9282
9463
|
svg.classList.add("ofv-chart-svg");
|
|
@@ -9322,16 +9503,7 @@ function renderChartSvg(chart) {
|
|
|
9322
9503
|
const clusterWidth = groupWidth * 0.58;
|
|
9323
9504
|
const barWidth = Math.max(5, Math.min(28, clusterWidth / Math.max(1, chart.series.length)));
|
|
9324
9505
|
const zeroY = plot.y + plot.height - (0 - axisMin) / (axisMax - axisMin || 1) * plot.height;
|
|
9325
|
-
|
|
9326
|
-
const x = plot.x + groupWidth * (index + 0.5);
|
|
9327
|
-
const label = appendSvg(svg, "text", {
|
|
9328
|
-
x: Number(x.toFixed(1)),
|
|
9329
|
-
y: plot.y + plot.height + 22,
|
|
9330
|
-
class: "ofv-chart-label",
|
|
9331
|
-
"text-anchor": "middle"
|
|
9332
|
-
});
|
|
9333
|
-
label.textContent = truncateChartLabel(category);
|
|
9334
|
-
});
|
|
9506
|
+
appendChartCategoryLabels(svg, categories, plot, (index) => plot.x + groupWidth * (index + 0.5));
|
|
9335
9507
|
chart.series.forEach((series, seriesIndex) => {
|
|
9336
9508
|
const color = series.color || colors[seriesIndex % colors.length];
|
|
9337
9509
|
series.values.forEach((value, index) => {
|
|
@@ -9349,6 +9521,8 @@ function renderChartSvg(chart) {
|
|
|
9349
9521
|
});
|
|
9350
9522
|
});
|
|
9351
9523
|
} else {
|
|
9524
|
+
const categoryStep = categories.length > 1 ? plot.width / (categories.length - 1) : plot.width;
|
|
9525
|
+
appendChartCategoryLabels(svg, categories, plot, (index) => plot.x + index * categoryStep);
|
|
9352
9526
|
chart.series.forEach((series, seriesIndex) => {
|
|
9353
9527
|
const color = series.color || colors[seriesIndex % colors.length];
|
|
9354
9528
|
const step = series.values.length > 1 ? plot.width / (series.values.length - 1) : plot.width;
|
|
@@ -9373,6 +9547,22 @@ function renderChartSvg(chart) {
|
|
|
9373
9547
|
appendChartLegend(svg, chart, colors, 348);
|
|
9374
9548
|
return svg;
|
|
9375
9549
|
}
|
|
9550
|
+
function appendChartCategoryLabels(svg, categories, plot, getX) {
|
|
9551
|
+
const interval = Math.max(1, Math.ceil(categories.length / 14));
|
|
9552
|
+
categories.forEach((category, index) => {
|
|
9553
|
+
if (index % interval !== 0 && index !== categories.length - 1) {
|
|
9554
|
+
return;
|
|
9555
|
+
}
|
|
9556
|
+
const label = appendSvg(svg, "text", {
|
|
9557
|
+
x: Number(getX(index).toFixed(1)),
|
|
9558
|
+
y: plot.y + plot.height + 22,
|
|
9559
|
+
class: "ofv-chart-label ofv-chart-category-label",
|
|
9560
|
+
"data-axis": "category",
|
|
9561
|
+
"text-anchor": "middle"
|
|
9562
|
+
});
|
|
9563
|
+
label.textContent = truncateChartLabel(category);
|
|
9564
|
+
});
|
|
9565
|
+
}
|
|
9376
9566
|
function appendChartLegend(svg, chart, colors, y) {
|
|
9377
9567
|
const itemWidth = 86;
|
|
9378
9568
|
const startX = 320 - chart.series.length * itemWidth / 2;
|
|
@@ -10057,10 +10247,15 @@ function pptxRenderTimeoutMs() {
|
|
|
10057
10247
|
function normalizePptxLayout(container) {
|
|
10058
10248
|
const slideCanvases = findPptxSlideCanvases(container);
|
|
10059
10249
|
for (const slide of slideCanvases) {
|
|
10060
|
-
slide
|
|
10250
|
+
if (!hasInlineBackground(slide)) {
|
|
10251
|
+
slide.style.backgroundColor = "#FFFFFF";
|
|
10252
|
+
}
|
|
10061
10253
|
}
|
|
10062
10254
|
normalizePptxMirroredText(container);
|
|
10063
10255
|
}
|
|
10256
|
+
function hasInlineBackground(element) {
|
|
10257
|
+
return Boolean(element.style.background || element.style.backgroundColor || element.style.backgroundImage);
|
|
10258
|
+
}
|
|
10064
10259
|
function normalizePptxMirroredText(container) {
|
|
10065
10260
|
const mirroredContainers = Array.from(container.querySelectorAll("div")).filter((element) => {
|
|
10066
10261
|
const text = element.textContent?.trim();
|
|
@@ -10152,7 +10347,7 @@ function renderOpenDocumentPresentationXml(panel, xml) {
|
|
|
10152
10347
|
renderPresentationInsight(panel, inspectOpenDocumentPresentation("FODP \u6F14\u793A\u6587\u7A3F", xml, 0));
|
|
10153
10348
|
renderOpenDocumentPresentation(panel, "FODP \u6F14\u793A\u6587\u7A3F", xml, []);
|
|
10154
10349
|
}
|
|
10155
|
-
async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit) {
|
|
10350
|
+
async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit, messages) {
|
|
10156
10351
|
let zip;
|
|
10157
10352
|
try {
|
|
10158
10353
|
zip = await JSZip3.loadAsync(arrayBuffer);
|
|
@@ -10167,7 +10362,7 @@ async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit) {
|
|
|
10167
10362
|
return true;
|
|
10168
10363
|
}
|
|
10169
10364
|
if (hasEntry("xl/workbook.xml")) {
|
|
10170
|
-
await renderSheet(panel, arrayBuffer, extension);
|
|
10365
|
+
await renderSheet(panel, arrayBuffer, extension, messages);
|
|
10171
10366
|
return true;
|
|
10172
10367
|
}
|
|
10173
10368
|
if (hasEntry("ppt/presentation.xml")) {
|
|
@@ -10598,41 +10793,50 @@ function legacyOfficeFormatLabel(extension) {
|
|
|
10598
10793
|
}
|
|
10599
10794
|
return "PowerPoint Binary File Format";
|
|
10600
10795
|
}
|
|
10601
|
-
function renderLegacyWordBinary(panel, extension, arrayBuffer) {
|
|
10796
|
+
function renderLegacyWordBinary(panel, extension, arrayBuffer, messages) {
|
|
10602
10797
|
try {
|
|
10603
10798
|
renderLegacyWordDocument(panel, parseLegacyWordDocument(arrayBuffer));
|
|
10604
10799
|
} catch (error) {
|
|
10605
|
-
renderLegacyOfficeBinary(
|
|
10800
|
+
renderLegacyOfficeBinary(
|
|
10801
|
+
panel,
|
|
10802
|
+
extension,
|
|
10803
|
+
arrayBuffer,
|
|
10804
|
+
messages,
|
|
10805
|
+
formatPreviewMessage(messages.officeLegacyWordParseFailed, { message: normalizeOfficeError(error, messages) })
|
|
10806
|
+
);
|
|
10606
10807
|
}
|
|
10607
10808
|
}
|
|
10608
|
-
function renderLegacyOfficeBinary(panel, extension, arrayBuffer, parseError) {
|
|
10809
|
+
function renderLegacyOfficeBinary(panel, extension, arrayBuffer, messages, parseError) {
|
|
10609
10810
|
const fragments = extractLegacyOfficeText(arrayBuffer);
|
|
10610
10811
|
panel.replaceChildren();
|
|
10611
|
-
const section = createSection(
|
|
10812
|
+
const section = createSection(messages.officeLegacyConversionTitle);
|
|
10612
10813
|
section.classList.add("ofv-office-conversion");
|
|
10613
10814
|
const format = document.createElement("p");
|
|
10614
10815
|
const strong = document.createElement("strong");
|
|
10615
10816
|
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
|
-
);
|
|
10817
|
+
format.append(strong, document.createTextNode(" "), document.createTextNode(messages.officeLegacyBinaryNotice));
|
|
10622
10818
|
const meta = document.createElement("dl");
|
|
10623
10819
|
meta.className = "ofv-office-binary-meta";
|
|
10624
|
-
appendOfficeBinaryMeta(meta,
|
|
10625
|
-
appendOfficeBinaryMeta(
|
|
10626
|
-
|
|
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
|
+
);
|
|
10627
10831
|
if (parseError) {
|
|
10628
|
-
appendOfficeBinaryMeta(meta,
|
|
10832
|
+
appendOfficeBinaryMeta(meta, messages.officeLegacyMetaParseStatus, parseError);
|
|
10629
10833
|
}
|
|
10630
10834
|
section.append(format, meta);
|
|
10631
10835
|
if (fragments.length > 0) {
|
|
10632
10836
|
const article = document.createElement("article");
|
|
10633
10837
|
article.className = "ofv-document ofv-office-binary-fragments";
|
|
10634
10838
|
const heading = document.createElement("h4");
|
|
10635
|
-
heading.textContent =
|
|
10839
|
+
heading.textContent = messages.officeLegacyReadableFragments;
|
|
10636
10840
|
article.append(heading);
|
|
10637
10841
|
for (const fragment of fragments.slice(0, 80)) {
|
|
10638
10842
|
const paragraph = document.createElement("p");
|
|
@@ -10643,7 +10847,7 @@ function renderLegacyOfficeBinary(panel, extension, arrayBuffer, parseError) {
|
|
|
10643
10847
|
} else {
|
|
10644
10848
|
const empty = document.createElement("p");
|
|
10645
10849
|
empty.className = "ofv-office-binary-empty";
|
|
10646
|
-
empty.textContent =
|
|
10850
|
+
empty.textContent = messages.officeLegacyNoText;
|
|
10647
10851
|
section.append(empty);
|
|
10648
10852
|
}
|
|
10649
10853
|
panel.append(section);
|
|
@@ -10655,23 +10859,27 @@ function appendOfficeBinaryMeta(list, label, value) {
|
|
|
10655
10859
|
detail.textContent = value;
|
|
10656
10860
|
list.append(term, detail);
|
|
10657
10861
|
}
|
|
10658
|
-
function renderUnsupportedOffice(panel, extension) {
|
|
10862
|
+
function renderUnsupportedOffice(panel, extension, messages) {
|
|
10659
10863
|
const legacyBinary = /* @__PURE__ */ new Set(["doc", "dot", "wps", "ppt", "pps", "key", "dps"]);
|
|
10660
|
-
const message = legacyBinary.has(extension) ?
|
|
10864
|
+
const message = legacyBinary.has(extension) ? messages.officeUnsupportedLegacyMessage : messages.officeUnsupportedGenericMessage;
|
|
10661
10865
|
panel.replaceChildren();
|
|
10662
|
-
const section = createSection(
|
|
10866
|
+
const section = createSection(messages.officeUnsupportedTitle);
|
|
10663
10867
|
const format = document.createElement("p");
|
|
10664
10868
|
const strong = document.createElement("strong");
|
|
10665
10869
|
strong.textContent = `.${extension}`;
|
|
10666
|
-
format.append(
|
|
10870
|
+
format.append(
|
|
10871
|
+
strong,
|
|
10872
|
+
document.createTextNode(" "),
|
|
10873
|
+
document.createTextNode(formatPreviewMessage(messages.officeUnsupportedIntro, { message }))
|
|
10874
|
+
);
|
|
10667
10875
|
const support = document.createElement("p");
|
|
10668
|
-
support.textContent =
|
|
10876
|
+
support.textContent = messages.officeUnsupportedSupportedFormats;
|
|
10669
10877
|
section.append(format, support);
|
|
10670
10878
|
panel.append(section);
|
|
10671
10879
|
}
|
|
10672
|
-
function normalizeOfficeError(error) {
|
|
10880
|
+
function normalizeOfficeError(error, messages) {
|
|
10673
10881
|
const message = error instanceof Error ? error.message : String(error || "");
|
|
10674
|
-
return message ?
|
|
10882
|
+
return message ? formatPreviewMessage(messages.officeErrorWithMessage, { message }) : messages.officeErrorWithoutMessage;
|
|
10675
10883
|
}
|
|
10676
10884
|
function extractLegacyOfficeText(arrayBuffer) {
|
|
10677
10885
|
const bytes = new Uint8Array(arrayBuffer);
|
|
@@ -11913,11 +12121,13 @@ function archivePlugin() {
|
|
|
11913
12121
|
sidebarToggle.addEventListener("click", () => {
|
|
11914
12122
|
setSidebarCollapsed(!layout.classList.contains("is-sidebar-collapsed"));
|
|
11915
12123
|
});
|
|
11916
|
-
const showDefaultSummary = () => {
|
|
12124
|
+
const showDefaultSummary = (isSupplemental = true) => {
|
|
11917
12125
|
mainPanel.replaceChildren();
|
|
11918
12126
|
const summary = document.createElement("div");
|
|
11919
12127
|
summary.className = "ofv-archive-info";
|
|
11920
|
-
|
|
12128
|
+
if (isSupplemental) {
|
|
12129
|
+
hideSupplementalInfo4(summary);
|
|
12130
|
+
}
|
|
11921
12131
|
const heading = document.createElement("h3");
|
|
11922
12132
|
heading.textContent = ctx.file.name;
|
|
11923
12133
|
const info = document.createElement("div");
|
|
@@ -11927,12 +12137,16 @@ function archivePlugin() {
|
|
|
11927
12137
|
appendArchiveInfo(info, "\u683C\u5F0F\u7C7B\u578B", `.${ext.toUpperCase()} \u538B\u7F29\u6587\u4EF6`);
|
|
11928
12138
|
appendArchiveInfo(info, "\u5305\u542B\u6587\u4EF6\u6570", `${fileCount} \u4E2A`);
|
|
11929
12139
|
appendArchiveInfo(info, "\u5305\u542B\u76EE\u5F55\u6570", `${dirCount} \u4E2A`);
|
|
11930
|
-
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
|
+
);
|
|
11931
12145
|
summary.append(heading, info, createArchiveSummary(archiveEntries));
|
|
11932
12146
|
mainPanel.append(summary);
|
|
11933
12147
|
};
|
|
11934
|
-
showDefaultSummary();
|
|
11935
12148
|
const visibleEntries = archiveEntries.filter((e) => !e.dir).slice(0, 500);
|
|
12149
|
+
showDefaultSummary(visibleEntries.length > 0);
|
|
11936
12150
|
let destroyed = false;
|
|
11937
12151
|
let renderToken = 0;
|
|
11938
12152
|
const openArchiveEntry = async (entry, item) => {
|