@open-file-viewer/core 0.1.21 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -2
- package/dist/index.cjs +350 -108
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +350 -108
- package/dist/index.js.map +1 -1
- package/dist/style.css +60 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -655,7 +655,36 @@ var defaultMessages = {
|
|
|
655
655
|
officeUnsupportedIntro: "\u5DF2\u8FDB\u5165 Office \u63D2\u4EF6\u3002{message}",
|
|
656
656
|
officeUnsupportedSupportedFormats: "\u5F53\u524D\u7248\u672C\u4F18\u5148\u652F\u6301 docx\u3001rtf\u3001odt/fodt\u3001xlsx/xls/csv/ods\u3001pptx/ppsx\u3001odp/fodp \u7684\u57FA\u7840\u5185\u5BB9\u9884\u89C8\u3002",
|
|
657
657
|
officeErrorWithMessage: "\u89E3\u6790\u5668\u8FD4\u56DE\uFF1A{message}",
|
|
658
|
-
officeErrorWithoutMessage: "\u89E3\u6790\u5668\u672A\u8FD4\u56DE\u5177\u4F53\u9519\u8BEF\u4FE1\u606F\u3002"
|
|
658
|
+
officeErrorWithoutMessage: "\u89E3\u6790\u5668\u672A\u8FD4\u56DE\u5177\u4F53\u9519\u8BEF\u4FE1\u606F\u3002",
|
|
659
|
+
officeConvertedTitle: "Office \u9AD8\u4FDD\u771F\u8F6C\u6362\u9884\u89C8",
|
|
660
|
+
officeConvertedPdfFailed: "Office \u8F6C\u6362\u540E\u7684 PDF \u65E0\u6CD5\u9884\u89C8",
|
|
661
|
+
pdfEncryptedTitle: "PDF \u5DF2\u52A0\u5BC6\uFF0C\u65E0\u6CD5\u5728\u7EBF\u9884\u89C8",
|
|
662
|
+
pdfEncryptedMessage: "\u8BF7\u4E0B\u8F7D\u540E\u4F7F\u7528\u5BC6\u7801\u6253\u5F00\uFF0C\u6216\u4E0A\u4F20\u89E3\u5BC6\u540E\u7684 PDF \u6587\u4EF6\u3002",
|
|
663
|
+
pdfPreviewFailedTitle: "PDF \u9884\u89C8\u5931\u8D25",
|
|
664
|
+
pdfCorruptedMessage: "\u8BE5 PDF \u6587\u4EF6\u53EF\u80FD\u5DF2\u635F\u574F\u6216\u683C\u5F0F\u65E0\u6548\u3002",
|
|
665
|
+
pdfCannotLoadMessage: "\u5F53\u524D\u6D4F\u89C8\u5668\u65E0\u6CD5\u52A0\u8F7D\u8BE5 PDF\u3002",
|
|
666
|
+
pdfDownload: "\u4E0B\u8F7D PDF",
|
|
667
|
+
pdfPageLoading: "\u9875\u9762 {page} \u52A0\u8F7D\u4E2D...",
|
|
668
|
+
pdfPageEmpty: "\u8BE5\u9875\u6CA1\u6709\u68C0\u6D4B\u5230\u53EF\u663E\u793A\u7684 PDF \u517C\u5BB9\u5185\u5BB9\u3002\u82E5\u8FD9\u662F Illustrator/AI \u6587\u4EF6\uFF0C\u53EF\u80FD\u53EA\u5305\u542B\u79C1\u6709\u7F16\u8F91\u6570\u636E\uFF0C\u5EFA\u8BAE\u5BFC\u51FA\u4E3A PDF/SVG/PNG \u540E\u9884\u89C8\u3002",
|
|
669
|
+
pdfPageRenderFailed: "\u65E0\u6CD5\u6E32\u67D3\u8BE5\u9875\u9762\u3002\u8BE5\u9875\u53EF\u80FD\u5305\u542B\u6D4F\u89C8\u5668 PDF \u5F15\u64CE\u6682\u4E0D\u652F\u6301\u7684\u56FE\u5F62\u3001\u5B57\u4F53\u6216\u538B\u7F29\u7279\u6027\u3002",
|
|
670
|
+
pdfPreviousPage: "\u4E0A\u4E00\u9875",
|
|
671
|
+
pdfNextPage: "\u4E0B\u4E00\u9875",
|
|
672
|
+
pdfPageInput: "\u5F53\u524D\u9875\u7801",
|
|
673
|
+
pdfPagePosition: "/ {total}",
|
|
674
|
+
pdfPageLabel: "\u7B2C {page} \u9875",
|
|
675
|
+
pdfSummaryPages: "\u9875\u6570",
|
|
676
|
+
pdfSummaryPageSizes: "\u9875\u9762\u5C3A\u5BF8",
|
|
677
|
+
pdfSummaryFit: "\u9002\u914D",
|
|
678
|
+
pdfSummaryActualSize: "\u539F\u59CB\u5927\u5C0F",
|
|
679
|
+
pdfSummaryFitWidth: "\u9002\u5408\u5BBD\u5EA6",
|
|
680
|
+
pdfSummaryZoom: "\u7F29\u653E",
|
|
681
|
+
imagePreviewFailedTitle: "\u56FE\u7247\u9884\u89C8\u5931\u8D25",
|
|
682
|
+
imagePreviewFailedMessage: "\u5F53\u524D\u6D4F\u89C8\u5668\u65E0\u6CD5\u76F4\u63A5\u663E\u793A\u8BE5\u56FE\u7247\uFF0C\u6587\u4EF6\u53EF\u80FD\u5DF2\u635F\u574F\u6216\u7F16\u7801\u6682\u4E0D\u53D7\u652F\u6301\u3002",
|
|
683
|
+
imageDownload: "\u4E0B\u8F7D\u56FE\u7247",
|
|
684
|
+
imageZoomOut: "\u7F29\u5C0F",
|
|
685
|
+
imageZoomIn: "\u653E\u5927",
|
|
686
|
+
imageRotate: "\u65CB\u8F6C\u56FE\u7247",
|
|
687
|
+
imageReset: "\u91CD\u7F6E\u56FE\u7247\u89C6\u56FE"
|
|
659
688
|
},
|
|
660
689
|
"en-US": {
|
|
661
690
|
loading: "Loading preview...",
|
|
@@ -704,7 +733,36 @@ var defaultMessages = {
|
|
|
704
733
|
officeUnsupportedIntro: "is handled by the Office plugin. {message}",
|
|
705
734
|
officeUnsupportedSupportedFormats: "This version prioritizes basic previews for docx, rtf, odt/fodt, xlsx/xls/csv/ods, pptx/ppsx, and odp/fodp files.",
|
|
706
735
|
officeErrorWithMessage: "Parser returned: {message}",
|
|
707
|
-
officeErrorWithoutMessage: "Parser did not return a specific error."
|
|
736
|
+
officeErrorWithoutMessage: "Parser did not return a specific error.",
|
|
737
|
+
officeConvertedTitle: "High-fidelity Office conversion preview",
|
|
738
|
+
officeConvertedPdfFailed: "The converted Office PDF could not be previewed",
|
|
739
|
+
pdfEncryptedTitle: "This PDF is encrypted and cannot be previewed online",
|
|
740
|
+
pdfEncryptedMessage: "Download and open it with the password, or upload a decrypted PDF file.",
|
|
741
|
+
pdfPreviewFailedTitle: "PDF preview failed",
|
|
742
|
+
pdfCorruptedMessage: "The PDF may be corrupted or use an invalid format.",
|
|
743
|
+
pdfCannotLoadMessage: "This browser could not load the PDF.",
|
|
744
|
+
pdfDownload: "Download PDF",
|
|
745
|
+
pdfPageLoading: "Loading page {page}...",
|
|
746
|
+
pdfPageEmpty: "No displayable PDF-compatible content was detected on this page. If this is an Illustrator/AI file, export it as PDF, SVG, or PNG before previewing.",
|
|
747
|
+
pdfPageRenderFailed: "This page could not be rendered. It may contain graphics, fonts, or compression features that the browser PDF engine does not support.",
|
|
748
|
+
pdfPreviousPage: "Previous page",
|
|
749
|
+
pdfNextPage: "Next page",
|
|
750
|
+
pdfPageInput: "Current page",
|
|
751
|
+
pdfPagePosition: "/ {total}",
|
|
752
|
+
pdfPageLabel: "Page {page}",
|
|
753
|
+
pdfSummaryPages: "Pages",
|
|
754
|
+
pdfSummaryPageSizes: "Page sizes",
|
|
755
|
+
pdfSummaryFit: "Fit",
|
|
756
|
+
pdfSummaryActualSize: "Actual size",
|
|
757
|
+
pdfSummaryFitWidth: "Fit width",
|
|
758
|
+
pdfSummaryZoom: "Zoom",
|
|
759
|
+
imagePreviewFailedTitle: "Image preview failed",
|
|
760
|
+
imagePreviewFailedMessage: "This browser cannot display the image. The file may be corrupted or use an unsupported encoding.",
|
|
761
|
+
imageDownload: "Download image",
|
|
762
|
+
imageZoomOut: "Zoom out",
|
|
763
|
+
imageZoomIn: "Zoom in",
|
|
764
|
+
imageRotate: "Rotate image",
|
|
765
|
+
imageReset: "Reset image view"
|
|
708
766
|
}
|
|
709
767
|
};
|
|
710
768
|
function resolveMessages(options) {
|
|
@@ -809,12 +867,17 @@ function createViewer(options) {
|
|
|
809
867
|
currentIndex = clampIndex(index, queue.length);
|
|
810
868
|
await renderQueueItem(currentIndex);
|
|
811
869
|
};
|
|
812
|
-
const toolbar = createToolbar(
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
870
|
+
const toolbar = createToolbar(
|
|
871
|
+
options.toolbar,
|
|
872
|
+
viewport,
|
|
873
|
+
{
|
|
874
|
+
getLength: () => queue.length,
|
|
875
|
+
next: () => goTo(currentIndex + 1),
|
|
876
|
+
previous: () => goTo(currentIndex - 1),
|
|
877
|
+
command: (command) => currentInstance?.command?.(command)
|
|
878
|
+
},
|
|
879
|
+
options.locale || "en-US"
|
|
880
|
+
);
|
|
818
881
|
if (toolbar) {
|
|
819
882
|
host.append(toolbar.element);
|
|
820
883
|
}
|
|
@@ -1051,7 +1114,7 @@ function removeMediaListener(media, listener) {
|
|
|
1051
1114
|
}
|
|
1052
1115
|
media.removeListener?.(listener);
|
|
1053
1116
|
}
|
|
1054
|
-
function createToolbar(toolbar, viewport, queue) {
|
|
1117
|
+
function createToolbar(toolbar, viewport, queue, locale) {
|
|
1055
1118
|
if (!toolbar) {
|
|
1056
1119
|
return void 0;
|
|
1057
1120
|
}
|
|
@@ -1059,7 +1122,7 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1059
1122
|
const element = document.createElement("div");
|
|
1060
1123
|
element.className = "ofv-toolbar";
|
|
1061
1124
|
element.setAttribute("role", "toolbar");
|
|
1062
|
-
element.setAttribute("aria-label",
|
|
1125
|
+
element.setAttribute("aria-label", defaultToolbarText[locale].ariaLabel);
|
|
1063
1126
|
let file;
|
|
1064
1127
|
let currentIndex = 0;
|
|
1065
1128
|
let currentLength = queue.getLength();
|
|
@@ -1120,8 +1183,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1120
1183
|
}
|
|
1121
1184
|
if (id === "previous" && queue.getLength() > 1) {
|
|
1122
1185
|
previousButton = addButton(
|
|
1123
|
-
getToolbarLabel(options, "previous"),
|
|
1124
|
-
getToolbarTitle(options, "previous"),
|
|
1186
|
+
getToolbarLabel(options, locale, "previous"),
|
|
1187
|
+
getToolbarTitle(options, locale, "previous"),
|
|
1125
1188
|
() => void queue.previous(),
|
|
1126
1189
|
void 0,
|
|
1127
1190
|
options.icons?.previous
|
|
@@ -1130,8 +1193,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1130
1193
|
}
|
|
1131
1194
|
if (id === "next" && queue.getLength() > 1) {
|
|
1132
1195
|
nextButton = addButton(
|
|
1133
|
-
getToolbarLabel(options, "next"),
|
|
1134
|
-
getToolbarTitle(options, "next"),
|
|
1196
|
+
getToolbarLabel(options, locale, "next"),
|
|
1197
|
+
getToolbarTitle(options, locale, "next"),
|
|
1135
1198
|
() => void queue.next(),
|
|
1136
1199
|
void 0,
|
|
1137
1200
|
options.icons?.next
|
|
@@ -1145,27 +1208,27 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1145
1208
|
return;
|
|
1146
1209
|
}
|
|
1147
1210
|
if (id === "zoom-out" && options.zoom) {
|
|
1148
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "zoom-out");
|
|
1211
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "zoom-out");
|
|
1149
1212
|
return;
|
|
1150
1213
|
}
|
|
1151
1214
|
if (id === "zoom-in" && options.zoom) {
|
|
1152
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "zoom-in");
|
|
1215
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "zoom-in");
|
|
1153
1216
|
return;
|
|
1154
1217
|
}
|
|
1155
1218
|
if (id === "zoom-reset" && options.zoom) {
|
|
1156
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "zoom-reset");
|
|
1219
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "zoom-reset");
|
|
1157
1220
|
zoomResetButton = commandButtons[commandButtons.length - 1]?.button;
|
|
1158
1221
|
updateZoomLabel();
|
|
1159
1222
|
return;
|
|
1160
1223
|
}
|
|
1161
1224
|
if (id === "rotate-right" && options.rotate) {
|
|
1162
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "rotate-right");
|
|
1225
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "rotate-right");
|
|
1163
1226
|
return;
|
|
1164
1227
|
}
|
|
1165
1228
|
if (id === "download" && options.download !== false) {
|
|
1166
1229
|
addButton(
|
|
1167
|
-
getToolbarLabel(options, id),
|
|
1168
|
-
getToolbarTitle(options, id),
|
|
1230
|
+
getToolbarLabel(options, locale, id),
|
|
1231
|
+
getToolbarTitle(options, locale, id),
|
|
1169
1232
|
() => getContext().download(),
|
|
1170
1233
|
void 0,
|
|
1171
1234
|
options.icons?.download
|
|
@@ -1174,8 +1237,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1174
1237
|
}
|
|
1175
1238
|
if (id === "fullscreen" && options.fullscreen !== false) {
|
|
1176
1239
|
fullscreenButton = addButton(
|
|
1177
|
-
getToolbarLabel(options, id),
|
|
1178
|
-
getToolbarTitle(options, id),
|
|
1240
|
+
getToolbarLabel(options, locale, id),
|
|
1241
|
+
getToolbarTitle(options, locale, id),
|
|
1179
1242
|
() => getContext().fullscreen(),
|
|
1180
1243
|
void 0,
|
|
1181
1244
|
options.icons?.fullscreen
|
|
@@ -1185,8 +1248,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1185
1248
|
}
|
|
1186
1249
|
if (id === "print" && options.print) {
|
|
1187
1250
|
addButton(
|
|
1188
|
-
getToolbarLabel(options, id),
|
|
1189
|
-
getToolbarTitle(options, id),
|
|
1251
|
+
getToolbarLabel(options, locale, id),
|
|
1252
|
+
getToolbarTitle(options, locale, id),
|
|
1190
1253
|
() => getContext().print(),
|
|
1191
1254
|
void 0,
|
|
1192
1255
|
options.icons?.print
|
|
@@ -1212,11 +1275,11 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1212
1275
|
const renderSearchControl = () => {
|
|
1213
1276
|
const searchGroup = document.createElement("div");
|
|
1214
1277
|
searchGroup.className = "ofv-toolbar-search";
|
|
1215
|
-
searchGroup.title = getToolbarTitle(options, "search");
|
|
1278
|
+
searchGroup.title = getToolbarTitle(options, locale, "search");
|
|
1216
1279
|
const nextSearchInput = document.createElement("input");
|
|
1217
1280
|
nextSearchInput.type = "search";
|
|
1218
|
-
nextSearchInput.placeholder = getToolbarLabel(options, "search");
|
|
1219
|
-
nextSearchInput.setAttribute("aria-label", getToolbarTitle(options, "search"));
|
|
1281
|
+
nextSearchInput.placeholder = getToolbarLabel(options, locale, "search");
|
|
1282
|
+
nextSearchInput.setAttribute("aria-label", getToolbarTitle(options, locale, "search"));
|
|
1220
1283
|
const nextSearchCount = document.createElement("span");
|
|
1221
1284
|
nextSearchCount.className = "ofv-toolbar-search-count";
|
|
1222
1285
|
searchInput = nextSearchInput;
|
|
@@ -1271,7 +1334,7 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1271
1334
|
}
|
|
1272
1335
|
setToolbarButtonContent(
|
|
1273
1336
|
zoomResetButton,
|
|
1274
|
-
currentZoom === void 0 ? getToolbarLabel(options, "zoom-reset") : formatToolbarZoom(currentZoom),
|
|
1337
|
+
currentZoom === void 0 ? getToolbarLabel(options, locale, "zoom-reset") : formatToolbarZoom(currentZoom),
|
|
1275
1338
|
options.icons?.["zoom-reset"]
|
|
1276
1339
|
);
|
|
1277
1340
|
}
|
|
@@ -1294,8 +1357,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1294
1357
|
const active = isFullscreenActive();
|
|
1295
1358
|
const id = active ? "exit-fullscreen" : "fullscreen";
|
|
1296
1359
|
const icon = active ? options.icons?.["exit-fullscreen"] ?? options.icons?.fullscreen : options.icons?.fullscreen;
|
|
1297
|
-
setToolbarButtonContent(fullscreenButton, getToolbarLabel(options, id), icon);
|
|
1298
|
-
const title = getToolbarTitle(options, id);
|
|
1360
|
+
setToolbarButtonContent(fullscreenButton, getToolbarLabel(options, locale, id), icon);
|
|
1361
|
+
const title = getToolbarTitle(options, locale, id);
|
|
1299
1362
|
fullscreenButton.title = title;
|
|
1300
1363
|
fullscreenButton.setAttribute("aria-label", title);
|
|
1301
1364
|
fullscreenButton.setAttribute("aria-pressed", String(active));
|
|
@@ -1419,39 +1482,75 @@ function createToolbarContext({
|
|
|
1419
1482
|
clearSearch: search.clear
|
|
1420
1483
|
};
|
|
1421
1484
|
}
|
|
1422
|
-
var
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1485
|
+
var defaultToolbarText = {
|
|
1486
|
+
"zh-CN": {
|
|
1487
|
+
ariaLabel: "\u6587\u4EF6\u9884\u89C8\u5DE5\u5177\u680F",
|
|
1488
|
+
labels: {
|
|
1489
|
+
previous: "\u4E0A\u4E00\u4E2A",
|
|
1490
|
+
next: "\u4E0B\u4E00\u4E2A",
|
|
1491
|
+
queue: "",
|
|
1492
|
+
"zoom-out": "-",
|
|
1493
|
+
"zoom-in": "+",
|
|
1494
|
+
"zoom-reset": "100%",
|
|
1495
|
+
"rotate-right": "\u65CB\u8F6C",
|
|
1496
|
+
download: "\u4E0B\u8F7D",
|
|
1497
|
+
fullscreen: "\u5168\u5C4F",
|
|
1498
|
+
"exit-fullscreen": "\u9000\u51FA\u5168\u5C4F",
|
|
1499
|
+
print: "\u6253\u5370",
|
|
1500
|
+
search: "\u641C\u7D22"
|
|
1501
|
+
},
|
|
1502
|
+
titles: {
|
|
1503
|
+
previous: "\u4E0A\u4E00\u4E2A\u6587\u4EF6",
|
|
1504
|
+
next: "\u4E0B\u4E00\u4E2A\u6587\u4EF6",
|
|
1505
|
+
queue: "\u5F53\u524D\u6587\u4EF6\u4F4D\u7F6E",
|
|
1506
|
+
"zoom-out": "\u7F29\u5C0F",
|
|
1507
|
+
"zoom-in": "\u653E\u5927",
|
|
1508
|
+
"zoom-reset": "\u91CD\u7F6E\u7F29\u653E",
|
|
1509
|
+
"rotate-right": "\u5411\u53F3\u65CB\u8F6C",
|
|
1510
|
+
download: "\u4E0B\u8F7D\u6587\u4EF6",
|
|
1511
|
+
fullscreen: "\u5168\u5C4F\u67E5\u770B\u9884\u89C8",
|
|
1512
|
+
"exit-fullscreen": "\u9000\u51FA\u5168\u5C4F",
|
|
1513
|
+
print: "\u6253\u5370\u9884\u89C8",
|
|
1514
|
+
search: "\u641C\u7D22\u9884\u89C8\u6587\u672C"
|
|
1515
|
+
}
|
|
1516
|
+
},
|
|
1517
|
+
"en-US": {
|
|
1518
|
+
ariaLabel: "File preview toolbar",
|
|
1519
|
+
labels: {
|
|
1520
|
+
previous: "Prev",
|
|
1521
|
+
next: "Next",
|
|
1522
|
+
queue: "",
|
|
1523
|
+
"zoom-out": "-",
|
|
1524
|
+
"zoom-in": "+",
|
|
1525
|
+
"zoom-reset": "100%",
|
|
1526
|
+
"rotate-right": "Rotate",
|
|
1527
|
+
download: "Download",
|
|
1528
|
+
fullscreen: "Fullscreen",
|
|
1529
|
+
"exit-fullscreen": "Exit fullscreen",
|
|
1530
|
+
print: "Print",
|
|
1531
|
+
search: "Search"
|
|
1532
|
+
},
|
|
1533
|
+
titles: {
|
|
1534
|
+
previous: "Previous file",
|
|
1535
|
+
next: "Next file",
|
|
1536
|
+
queue: "Current file position",
|
|
1537
|
+
"zoom-out": "Zoom out",
|
|
1538
|
+
"zoom-in": "Zoom in",
|
|
1539
|
+
"zoom-reset": "Reset zoom",
|
|
1540
|
+
"rotate-right": "Rotate right",
|
|
1541
|
+
download: "Download file",
|
|
1542
|
+
fullscreen: "Open preview fullscreen",
|
|
1543
|
+
"exit-fullscreen": "Exit fullscreen",
|
|
1544
|
+
print: "Print preview",
|
|
1545
|
+
search: "Search preview text"
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1449
1548
|
};
|
|
1450
|
-
function getToolbarLabel(options, id) {
|
|
1451
|
-
return options.labels?.[id] ??
|
|
1549
|
+
function getToolbarLabel(options, locale, id) {
|
|
1550
|
+
return options.labels?.[id] ?? defaultToolbarText[locale].labels[id];
|
|
1452
1551
|
}
|
|
1453
|
-
function getToolbarTitle(options, id) {
|
|
1454
|
-
return options.titles?.[id] ?? options.labels?.[id] ??
|
|
1552
|
+
function getToolbarTitle(options, locale, id) {
|
|
1553
|
+
return options.titles?.[id] ?? options.labels?.[id] ?? defaultToolbarText[locale].titles[id];
|
|
1455
1554
|
}
|
|
1456
1555
|
function formatToolbarZoom(zoom) {
|
|
1457
1556
|
return `${Math.round(zoom * 100)}%`;
|
|
@@ -1603,7 +1702,7 @@ function isSafeToolbarIconAttribute(name, value) {
|
|
|
1603
1702
|
return !/^\s*(?:javascript|data:text\/html|vbscript):/i.test(value);
|
|
1604
1703
|
}
|
|
1605
1704
|
function isBuiltInToolbarAction(id) {
|
|
1606
|
-
return id in
|
|
1705
|
+
return id in defaultToolbarText["en-US"].labels;
|
|
1607
1706
|
}
|
|
1608
1707
|
function createSearchController(root) {
|
|
1609
1708
|
const markerClass = "ofv-search-match";
|
|
@@ -2174,7 +2273,7 @@ function imagePlugin() {
|
|
|
2174
2273
|
infoBar.hidden = false;
|
|
2175
2274
|
infoBar.removeAttribute("aria-hidden");
|
|
2176
2275
|
infoBar.style.removeProperty("display");
|
|
2177
|
-
stage.replaceChildren(createImageFallback(ctx.file.name, url));
|
|
2276
|
+
stage.replaceChildren(createImageFallback(ctx.file.name, url, ctx.options.messages));
|
|
2178
2277
|
ctx.toolbar?.refreshCommandSupport();
|
|
2179
2278
|
};
|
|
2180
2279
|
const setScale = (nextScale) => {
|
|
@@ -2199,13 +2298,13 @@ function imagePlugin() {
|
|
|
2199
2298
|
return () => button.removeEventListener("click", action);
|
|
2200
2299
|
};
|
|
2201
2300
|
const disposers = showInlineControls ? [
|
|
2202
|
-
addButton("-",
|
|
2203
|
-
addButton("+",
|
|
2204
|
-
addButton(
|
|
2301
|
+
addButton("-", ctx.options.messages.imageZoomOut, () => setScale(scale - 0.25)),
|
|
2302
|
+
addButton("+", ctx.options.messages.imageZoomIn, () => setScale(scale + 0.25)),
|
|
2303
|
+
addButton(ctx.options.messages.imageRotate, ctx.options.messages.imageRotate, () => {
|
|
2205
2304
|
rotation += 90;
|
|
2206
2305
|
updateTransform();
|
|
2207
2306
|
}),
|
|
2208
|
-
addButton(
|
|
2307
|
+
addButton(ctx.options.messages.imageReset, ctx.options.messages.imageReset, reset)
|
|
2209
2308
|
] : [];
|
|
2210
2309
|
if (showInlineControls) {
|
|
2211
2310
|
controls.append(zoomLabel);
|
|
@@ -2420,17 +2519,17 @@ function getTiffDimensions(ifd) {
|
|
|
2420
2519
|
height: Number(ifd.height || ifd.t257 || 0)
|
|
2421
2520
|
};
|
|
2422
2521
|
}
|
|
2423
|
-
function createImageFallback(fileName, url) {
|
|
2522
|
+
function createImageFallback(fileName, url, messages) {
|
|
2424
2523
|
const fallback = document.createElement("div");
|
|
2425
2524
|
fallback.className = "ofv-fallback";
|
|
2426
2525
|
const title = document.createElement("strong");
|
|
2427
|
-
title.textContent =
|
|
2526
|
+
title.textContent = messages.imagePreviewFailedTitle;
|
|
2428
2527
|
const meta = document.createElement("span");
|
|
2429
|
-
meta.textContent =
|
|
2528
|
+
meta.textContent = messages.imagePreviewFailedMessage;
|
|
2430
2529
|
const download = document.createElement("a");
|
|
2431
2530
|
download.href = url;
|
|
2432
2531
|
download.download = fileName;
|
|
2433
|
-
download.textContent =
|
|
2532
|
+
download.textContent = messages.imageDownload;
|
|
2434
2533
|
fallback.append(title, meta, download);
|
|
2435
2534
|
return fallback;
|
|
2436
2535
|
}
|
|
@@ -4791,17 +4890,20 @@ function pdfPlugin(options = {}) {
|
|
|
4791
4890
|
fit: ctx.options.fit,
|
|
4792
4891
|
zoom: ctx.options.zoom,
|
|
4793
4892
|
toolbar: ctx.toolbar,
|
|
4794
|
-
|
|
4795
|
-
encryptedMessage: "\u8BF7\u4E0B\u8F7D\u540E\u4F7F\u7528\u5BC6\u7801\u6253\u5F00\uFF0C\u6216\u4E0A\u4F20\u89E3\u5BC6\u540E\u7684 PDF \u6587\u4EF6\u3002",
|
|
4796
|
-
encryptedAction: "\u4E0B\u8F7D PDF",
|
|
4893
|
+
messages: ctx.options.messages,
|
|
4797
4894
|
revokeUrlOnDestroy: true
|
|
4798
4895
|
});
|
|
4799
4896
|
}
|
|
4800
4897
|
};
|
|
4801
4898
|
}
|
|
4802
4899
|
async function renderPdfDocumentPreview(options) {
|
|
4900
|
+
const useLegacyCompatibility = shouldUseLegacyPdfCompatibility(options.compatibilityMode);
|
|
4901
|
+
if (useLegacyCompatibility) {
|
|
4902
|
+
installPromiseWithResolversPolyfill();
|
|
4903
|
+
}
|
|
4803
4904
|
const pdf = options.pdfjs || await import("pdfjs-dist");
|
|
4804
|
-
|
|
4905
|
+
const messages = { ...defaultMessages["en-US"], ...options.messages };
|
|
4906
|
+
configurePdfWorker(pdf, options.workerSrc, useLegacyCompatibility);
|
|
4805
4907
|
const viewer = document.createElement("div");
|
|
4806
4908
|
viewer.className = "ofv-pdf-viewer";
|
|
4807
4909
|
if (options.title) {
|
|
@@ -4830,10 +4932,10 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4830
4932
|
url: options.fileUrl
|
|
4831
4933
|
};
|
|
4832
4934
|
const fallback = isEncryptedError(error) ? createEncryptedFallback(fileLike, options.fileUrl, {
|
|
4833
|
-
title: options.encryptedTitle ||
|
|
4834
|
-
message: options.encryptedMessage ||
|
|
4835
|
-
action: options.encryptedAction ||
|
|
4836
|
-
}) : createPdfFallback(options.fileName, options.fileUrl, normalizePdfError(error), options.fallbackTitle);
|
|
4935
|
+
title: options.encryptedTitle || messages.pdfEncryptedTitle,
|
|
4936
|
+
message: options.encryptedMessage || messages.pdfEncryptedMessage,
|
|
4937
|
+
action: options.encryptedAction || messages.pdfDownload
|
|
4938
|
+
}) : createPdfFallback(options.fileName, options.fileUrl, normalizePdfError(error, messages), messages, options.fallbackTitle);
|
|
4837
4939
|
if (!fallback.classList.contains("ofv-pdf-web-fallback")) {
|
|
4838
4940
|
options.viewport.classList.add("ofv-center");
|
|
4839
4941
|
}
|
|
@@ -4900,8 +5002,43 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4900
5002
|
let currentSize = options.size;
|
|
4901
5003
|
let zoomFactor = getInitialZoom({ options: { zoom: options.zoom ?? 1 } }, 0.25, 4);
|
|
4902
5004
|
let rotation = 0;
|
|
5005
|
+
let currentPage = 1;
|
|
5006
|
+
const goToPage = (page, scroll = true) => {
|
|
5007
|
+
currentPage = Math.min(pdfDocument.numPages, Math.max(1, Math.round(page) || 1));
|
|
5008
|
+
pageNavigator.setCurrent(currentPage);
|
|
5009
|
+
const wrapper = pageStates[currentPage - 1]?.wrapper;
|
|
5010
|
+
if (!scroll || !wrapper) {
|
|
5011
|
+
return;
|
|
5012
|
+
}
|
|
5013
|
+
const top = Math.max(0, wrapper.offsetTop - 16);
|
|
5014
|
+
if (typeof scroller.scrollTo === "function") {
|
|
5015
|
+
scroller.scrollTo({ top, behavior: "smooth" });
|
|
5016
|
+
} else {
|
|
5017
|
+
scroller.scrollTop = top;
|
|
5018
|
+
}
|
|
5019
|
+
};
|
|
5020
|
+
const pageNavigator = createPdfPageNavigator(pdfDocument.numPages, messages, (page) => goToPage(page));
|
|
5021
|
+
viewer.insertBefore(pageNavigator.element, summary);
|
|
5022
|
+
const handleScrollerScroll = () => {
|
|
5023
|
+
const scrollerRect = scroller.getBoundingClientRect();
|
|
5024
|
+
const targetY = scrollerRect.top + Math.min(Math.max(scroller.clientHeight * 0.25, 40), 180);
|
|
5025
|
+
let nearestPage = currentPage;
|
|
5026
|
+
let nearestDistance = Number.POSITIVE_INFINITY;
|
|
5027
|
+
pageStates.forEach((state, index) => {
|
|
5028
|
+
const distance = Math.abs(state.wrapper.getBoundingClientRect().top - targetY);
|
|
5029
|
+
if (distance < nearestDistance) {
|
|
5030
|
+
nearestDistance = distance;
|
|
5031
|
+
nearestPage = index + 1;
|
|
5032
|
+
}
|
|
5033
|
+
});
|
|
5034
|
+
if (nearestPage !== currentPage) {
|
|
5035
|
+
currentPage = nearestPage;
|
|
5036
|
+
pageNavigator.setCurrent(currentPage);
|
|
5037
|
+
}
|
|
5038
|
+
};
|
|
5039
|
+
scroller.addEventListener("scroll", handleScrollerScroll, { passive: true });
|
|
4903
5040
|
const updateSummary = () => {
|
|
4904
|
-
renderPdfSummary(summary, pdfDocument.numPages, pagesMeta, options.fit, zoomFactor);
|
|
5041
|
+
renderPdfSummary(summary, pdfDocument.numPages, pagesMeta, options.fit, zoomFactor, messages);
|
|
4905
5042
|
options.toolbar?.setZoom(zoomFactor);
|
|
4906
5043
|
};
|
|
4907
5044
|
const clearPage = (pageIdx) => {
|
|
@@ -4917,7 +5054,9 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4917
5054
|
state.canvas = null;
|
|
4918
5055
|
state.rendered = false;
|
|
4919
5056
|
state.wrapper.replaceChildren();
|
|
4920
|
-
state.wrapper.append(
|
|
5057
|
+
state.wrapper.append(
|
|
5058
|
+
createPageStatus("ofv-pdf-skeleton", formatPreviewMessage(messages.pdfPageLoading, { page: pageIdx + 1 }))
|
|
5059
|
+
);
|
|
4921
5060
|
};
|
|
4922
5061
|
const renderPage = async (pageIdx, size) => {
|
|
4923
5062
|
const state = pageStates[pageIdx];
|
|
@@ -4985,7 +5124,7 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4985
5124
|
state.wrapper.appendChild(
|
|
4986
5125
|
createPageStatus(
|
|
4987
5126
|
"ofv-pdf-empty",
|
|
4988
|
-
|
|
5127
|
+
messages.pdfPageEmpty
|
|
4989
5128
|
)
|
|
4990
5129
|
);
|
|
4991
5130
|
}
|
|
@@ -4993,7 +5132,7 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4993
5132
|
console.error(`Failed to render PDF page ${pageIdx + 1}:`, err);
|
|
4994
5133
|
state.rendered = false;
|
|
4995
5134
|
state.wrapper.replaceChildren(
|
|
4996
|
-
createPageStatus("ofv-pdf-error",
|
|
5135
|
+
createPageStatus("ofv-pdf-error", messages.pdfPageRenderFailed)
|
|
4997
5136
|
);
|
|
4998
5137
|
}
|
|
4999
5138
|
};
|
|
@@ -5034,9 +5173,10 @@ async function renderPdfDocumentPreview(options) {
|
|
|
5034
5173
|
const wrapper = document.createElement("div");
|
|
5035
5174
|
wrapper.className = "ofv-pdf-page-wrapper";
|
|
5036
5175
|
wrapper.setAttribute("data-page-index", String(i));
|
|
5176
|
+
wrapper.setAttribute("aria-label", formatPreviewMessage(messages.pdfPageLabel, { page: i + 1 }));
|
|
5037
5177
|
wrapper.style.width = `${w}px`;
|
|
5038
5178
|
wrapper.style.height = `${h}px`;
|
|
5039
|
-
wrapper.append(createPageStatus("ofv-pdf-skeleton",
|
|
5179
|
+
wrapper.append(createPageStatus("ofv-pdf-skeleton", formatPreviewMessage(messages.pdfPageLoading, { page: i + 1 })));
|
|
5040
5180
|
scroller.appendChild(wrapper);
|
|
5041
5181
|
pageStates.push({
|
|
5042
5182
|
wrapper,
|
|
@@ -5058,6 +5198,7 @@ async function renderPdfDocumentPreview(options) {
|
|
|
5058
5198
|
}
|
|
5059
5199
|
}, 0);
|
|
5060
5200
|
}
|
|
5201
|
+
goToPage(currentPage, false);
|
|
5061
5202
|
};
|
|
5062
5203
|
renderLayout(options.size);
|
|
5063
5204
|
let resizeTimer;
|
|
@@ -5098,6 +5239,8 @@ async function renderPdfDocumentPreview(options) {
|
|
|
5098
5239
|
},
|
|
5099
5240
|
destroy() {
|
|
5100
5241
|
options.toolbar?.setZoom(void 0);
|
|
5242
|
+
pageNavigator.destroy();
|
|
5243
|
+
scroller.removeEventListener("scroll", handleScrollerScroll);
|
|
5101
5244
|
window.clearTimeout(resizeTimer);
|
|
5102
5245
|
observer?.disconnect();
|
|
5103
5246
|
pageStates.forEach((state) => {
|
|
@@ -5143,15 +5286,15 @@ function getPdfAvailableWidth(width) {
|
|
|
5143
5286
|
const gutter = width < 160 ? 16 : 32;
|
|
5144
5287
|
return Math.max(1, width - gutter);
|
|
5145
5288
|
}
|
|
5146
|
-
function renderPdfSummary(summary, pages, pagesMeta, fit, zoomFactor) {
|
|
5289
|
+
function renderPdfSummary(summary, pages, pagesMeta, fit, zoomFactor, messages) {
|
|
5147
5290
|
summary.replaceChildren();
|
|
5148
|
-
appendPdfSummary(summary,
|
|
5291
|
+
appendPdfSummary(summary, messages.pdfSummaryPages, String(pages));
|
|
5149
5292
|
const pageSizes = formatPdfPageSizes(pagesMeta);
|
|
5150
5293
|
if (pageSizes) {
|
|
5151
|
-
appendPdfSummary(summary,
|
|
5294
|
+
appendPdfSummary(summary, messages.pdfSummaryPageSizes, pageSizes);
|
|
5152
5295
|
}
|
|
5153
|
-
appendPdfSummary(summary,
|
|
5154
|
-
appendPdfSummary(summary,
|
|
5296
|
+
appendPdfSummary(summary, messages.pdfSummaryFit, fit === "actual" ? messages.pdfSummaryActualSize : messages.pdfSummaryFitWidth);
|
|
5297
|
+
appendPdfSummary(summary, messages.pdfSummaryZoom, `${Math.round(zoomFactor * 100)}%`);
|
|
5155
5298
|
}
|
|
5156
5299
|
function appendPdfSummary(parent, label, value) {
|
|
5157
5300
|
const item = document.createElement("span");
|
|
@@ -5241,7 +5384,7 @@ function createPageStatus(className, text) {
|
|
|
5241
5384
|
status.textContent = text;
|
|
5242
5385
|
return status;
|
|
5243
5386
|
}
|
|
5244
|
-
function createPdfFallback(fileName, url, message, titleText =
|
|
5387
|
+
function createPdfFallback(fileName, url, message, messages, titleText = messages.pdfPreviewFailedTitle) {
|
|
5245
5388
|
if (isEmbeddableRemoteUrl(url)) {
|
|
5246
5389
|
return createPdfWebFallback(fileName, url);
|
|
5247
5390
|
}
|
|
@@ -5254,7 +5397,7 @@ function createPdfFallback(fileName, url, message, titleText = "PDF \u9884\u89C8
|
|
|
5254
5397
|
const download = document.createElement("a");
|
|
5255
5398
|
download.href = url;
|
|
5256
5399
|
download.download = fileName;
|
|
5257
|
-
download.textContent =
|
|
5400
|
+
download.textContent = messages.pdfDownload;
|
|
5258
5401
|
fallback.append(title, meta, download);
|
|
5259
5402
|
return fallback;
|
|
5260
5403
|
}
|
|
@@ -5273,23 +5416,109 @@ function createPdfWebFallback(fileName, url) {
|
|
|
5273
5416
|
function isEmbeddableRemoteUrl(url) {
|
|
5274
5417
|
return /^https?:\/\//i.test(url);
|
|
5275
5418
|
}
|
|
5276
|
-
function normalizePdfError(error) {
|
|
5419
|
+
function normalizePdfError(error, messages) {
|
|
5277
5420
|
const message = error instanceof Error ? error.message : String(error || "");
|
|
5278
5421
|
const name = typeof error === "object" && error !== null && "name" in error ? String(error.name) : "";
|
|
5279
5422
|
const lower = `${name} ${message}`.toLowerCase();
|
|
5280
5423
|
if (lower.includes("invalid") || lower.includes("missing") || lower.includes("corrupt")) {
|
|
5281
|
-
return
|
|
5424
|
+
return messages.pdfCorruptedMessage;
|
|
5282
5425
|
}
|
|
5283
|
-
return
|
|
5426
|
+
return messages.pdfCannotLoadMessage;
|
|
5427
|
+
}
|
|
5428
|
+
function createPdfPageNavigator(total, messages, onChange) {
|
|
5429
|
+
const element = document.createElement("div");
|
|
5430
|
+
element.className = "ofv-pdf-page-navigator";
|
|
5431
|
+
const previous = document.createElement("button");
|
|
5432
|
+
previous.type = "button";
|
|
5433
|
+
previous.textContent = "\u2039";
|
|
5434
|
+
previous.title = messages.pdfPreviousPage;
|
|
5435
|
+
previous.setAttribute("aria-label", messages.pdfPreviousPage);
|
|
5436
|
+
const input = document.createElement("input");
|
|
5437
|
+
input.type = "number";
|
|
5438
|
+
input.min = "1";
|
|
5439
|
+
input.max = String(total);
|
|
5440
|
+
input.value = "1";
|
|
5441
|
+
input.inputMode = "numeric";
|
|
5442
|
+
input.setAttribute("aria-label", messages.pdfPageInput);
|
|
5443
|
+
const position = document.createElement("span");
|
|
5444
|
+
position.textContent = formatPreviewMessage(messages.pdfPagePosition, { total });
|
|
5445
|
+
const next = document.createElement("button");
|
|
5446
|
+
next.type = "button";
|
|
5447
|
+
next.textContent = "\u203A";
|
|
5448
|
+
next.title = messages.pdfNextPage;
|
|
5449
|
+
next.setAttribute("aria-label", messages.pdfNextPage);
|
|
5450
|
+
const commit = () => onChange(Number(input.value));
|
|
5451
|
+
const handleKeydown = (event) => {
|
|
5452
|
+
if (event.key === "Enter") {
|
|
5453
|
+
commit();
|
|
5454
|
+
}
|
|
5455
|
+
};
|
|
5456
|
+
const handlePrevious = () => onChange(Number(input.value) - 1);
|
|
5457
|
+
const handleNext = () => onChange(Number(input.value) + 1);
|
|
5458
|
+
input.addEventListener("change", commit);
|
|
5459
|
+
input.addEventListener("keydown", handleKeydown);
|
|
5460
|
+
previous.addEventListener("click", handlePrevious);
|
|
5461
|
+
next.addEventListener("click", handleNext);
|
|
5462
|
+
element.append(previous, input, position, next);
|
|
5463
|
+
return {
|
|
5464
|
+
element,
|
|
5465
|
+
setCurrent(page) {
|
|
5466
|
+
input.value = String(page);
|
|
5467
|
+
previous.disabled = page <= 1;
|
|
5468
|
+
next.disabled = page >= total;
|
|
5469
|
+
},
|
|
5470
|
+
destroy() {
|
|
5471
|
+
input.removeEventListener("change", commit);
|
|
5472
|
+
input.removeEventListener("keydown", handleKeydown);
|
|
5473
|
+
previous.removeEventListener("click", handlePrevious);
|
|
5474
|
+
next.removeEventListener("click", handleNext);
|
|
5475
|
+
}
|
|
5476
|
+
};
|
|
5284
5477
|
}
|
|
5285
|
-
function configurePdfWorker(pdf, workerSrc) {
|
|
5478
|
+
function configurePdfWorker(pdf, workerSrc, legacy = false) {
|
|
5286
5479
|
if (workerSrc) {
|
|
5287
5480
|
pdf.GlobalWorkerOptions.workerSrc = workerSrc;
|
|
5288
5481
|
return;
|
|
5289
5482
|
}
|
|
5290
5483
|
if (!pdf.GlobalWorkerOptions.workerSrc && typeof window !== "undefined") {
|
|
5291
|
-
|
|
5484
|
+
const build = legacy ? "legacy/build" : "build";
|
|
5485
|
+
pdf.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdf.version}/${build}/pdf.worker.mjs`;
|
|
5486
|
+
}
|
|
5487
|
+
}
|
|
5488
|
+
function shouldUseLegacyPdfCompatibility(mode = "auto") {
|
|
5489
|
+
if (mode === "legacy") {
|
|
5490
|
+
return true;
|
|
5491
|
+
}
|
|
5492
|
+
if (mode === "modern") {
|
|
5493
|
+
return false;
|
|
5494
|
+
}
|
|
5495
|
+
const promise = Promise;
|
|
5496
|
+
if (typeof promise.withResolvers !== "function") {
|
|
5497
|
+
return true;
|
|
5498
|
+
}
|
|
5499
|
+
if (typeof navigator === "undefined") {
|
|
5500
|
+
return false;
|
|
5292
5501
|
}
|
|
5502
|
+
return /(?:QIHU|360SE|360EE)/i.test(navigator.userAgent);
|
|
5503
|
+
}
|
|
5504
|
+
function installPromiseWithResolversPolyfill() {
|
|
5505
|
+
const promise = Promise;
|
|
5506
|
+
if (typeof promise.withResolvers === "function") {
|
|
5507
|
+
return;
|
|
5508
|
+
}
|
|
5509
|
+
Object.defineProperty(promise, "withResolvers", {
|
|
5510
|
+
configurable: true,
|
|
5511
|
+
writable: true,
|
|
5512
|
+
value: () => {
|
|
5513
|
+
let resolve;
|
|
5514
|
+
let reject;
|
|
5515
|
+
const pending = new Promise((resolvePromise, rejectPromise) => {
|
|
5516
|
+
resolve = resolvePromise;
|
|
5517
|
+
reject = rejectPromise;
|
|
5518
|
+
});
|
|
5519
|
+
return { promise: pending, resolve, reject };
|
|
5520
|
+
}
|
|
5521
|
+
});
|
|
5293
5522
|
}
|
|
5294
5523
|
|
|
5295
5524
|
// src/plugins/epub.ts
|
|
@@ -7684,8 +7913,9 @@ async function renderConvertedOfficePreview(panel, ctx, options, conversionConte
|
|
|
7684
7913
|
fit: ctx.options.fit,
|
|
7685
7914
|
zoom: ctx.options.zoom,
|
|
7686
7915
|
toolbar: ctx.toolbar,
|
|
7687
|
-
|
|
7688
|
-
|
|
7916
|
+
messages: ctx.options.messages,
|
|
7917
|
+
title: ctx.options.messages.officeConvertedTitle,
|
|
7918
|
+
fallbackTitle: ctx.options.messages.officeConvertedPdfFailed,
|
|
7689
7919
|
revokeUrlOnDestroy: converted.revokeUrlOnDestroy
|
|
7690
7920
|
});
|
|
7691
7921
|
}
|
|
@@ -9467,6 +9697,9 @@ function renderChartCard(chart) {
|
|
|
9467
9697
|
function renderChartSvg(chart) {
|
|
9468
9698
|
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
9469
9699
|
svg.setAttribute("viewBox", "0 0 640 380");
|
|
9700
|
+
svg.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
|
9701
|
+
svg.setAttribute("text-rendering", "geometricPrecision");
|
|
9702
|
+
svg.setAttribute("shape-rendering", "geometricPrecision");
|
|
9470
9703
|
svg.setAttribute("role", "img");
|
|
9471
9704
|
svg.setAttribute("aria-label", chart.title);
|
|
9472
9705
|
svg.classList.add("ofv-chart-svg");
|
|
@@ -9512,16 +9745,7 @@ function renderChartSvg(chart) {
|
|
|
9512
9745
|
const clusterWidth = groupWidth * 0.58;
|
|
9513
9746
|
const barWidth = Math.max(5, Math.min(28, clusterWidth / Math.max(1, chart.series.length)));
|
|
9514
9747
|
const zeroY = plot.y + plot.height - (0 - axisMin) / (axisMax - axisMin || 1) * plot.height;
|
|
9515
|
-
|
|
9516
|
-
const x = plot.x + groupWidth * (index + 0.5);
|
|
9517
|
-
const label = appendSvg(svg, "text", {
|
|
9518
|
-
x: Number(x.toFixed(1)),
|
|
9519
|
-
y: plot.y + plot.height + 22,
|
|
9520
|
-
class: "ofv-chart-label",
|
|
9521
|
-
"text-anchor": "middle"
|
|
9522
|
-
});
|
|
9523
|
-
label.textContent = truncateChartLabel(category);
|
|
9524
|
-
});
|
|
9748
|
+
appendChartCategoryLabels(svg, categories, plot, (index) => plot.x + groupWidth * (index + 0.5));
|
|
9525
9749
|
chart.series.forEach((series, seriesIndex) => {
|
|
9526
9750
|
const color = series.color || colors[seriesIndex % colors.length];
|
|
9527
9751
|
series.values.forEach((value, index) => {
|
|
@@ -9539,6 +9763,8 @@ function renderChartSvg(chart) {
|
|
|
9539
9763
|
});
|
|
9540
9764
|
});
|
|
9541
9765
|
} else {
|
|
9766
|
+
const categoryStep = categories.length > 1 ? plot.width / (categories.length - 1) : plot.width;
|
|
9767
|
+
appendChartCategoryLabels(svg, categories, plot, (index) => plot.x + index * categoryStep);
|
|
9542
9768
|
chart.series.forEach((series, seriesIndex) => {
|
|
9543
9769
|
const color = series.color || colors[seriesIndex % colors.length];
|
|
9544
9770
|
const step = series.values.length > 1 ? plot.width / (series.values.length - 1) : plot.width;
|
|
@@ -9563,6 +9789,22 @@ function renderChartSvg(chart) {
|
|
|
9563
9789
|
appendChartLegend(svg, chart, colors, 348);
|
|
9564
9790
|
return svg;
|
|
9565
9791
|
}
|
|
9792
|
+
function appendChartCategoryLabels(svg, categories, plot, getX) {
|
|
9793
|
+
const interval = Math.max(1, Math.ceil(categories.length / 14));
|
|
9794
|
+
categories.forEach((category, index) => {
|
|
9795
|
+
if (index % interval !== 0 && index !== categories.length - 1) {
|
|
9796
|
+
return;
|
|
9797
|
+
}
|
|
9798
|
+
const label = appendSvg(svg, "text", {
|
|
9799
|
+
x: Number(getX(index).toFixed(1)),
|
|
9800
|
+
y: plot.y + plot.height + 22,
|
|
9801
|
+
class: "ofv-chart-label ofv-chart-category-label",
|
|
9802
|
+
"data-axis": "category",
|
|
9803
|
+
"text-anchor": "middle"
|
|
9804
|
+
});
|
|
9805
|
+
label.textContent = truncateChartLabel(category);
|
|
9806
|
+
});
|
|
9807
|
+
}
|
|
9566
9808
|
function appendChartLegend(svg, chart, colors, y) {
|
|
9567
9809
|
const itemWidth = 86;
|
|
9568
9810
|
const startX = 320 - chart.series.length * itemWidth / 2;
|