@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.js
CHANGED
|
@@ -602,7 +602,36 @@ var defaultMessages = {
|
|
|
602
602
|
officeUnsupportedIntro: "\u5DF2\u8FDB\u5165 Office \u63D2\u4EF6\u3002{message}",
|
|
603
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
604
|
officeErrorWithMessage: "\u89E3\u6790\u5668\u8FD4\u56DE\uFF1A{message}",
|
|
605
|
-
officeErrorWithoutMessage: "\u89E3\u6790\u5668\u672A\u8FD4\u56DE\u5177\u4F53\u9519\u8BEF\u4FE1\u606F\u3002"
|
|
605
|
+
officeErrorWithoutMessage: "\u89E3\u6790\u5668\u672A\u8FD4\u56DE\u5177\u4F53\u9519\u8BEF\u4FE1\u606F\u3002",
|
|
606
|
+
officeConvertedTitle: "Office \u9AD8\u4FDD\u771F\u8F6C\u6362\u9884\u89C8",
|
|
607
|
+
officeConvertedPdfFailed: "Office \u8F6C\u6362\u540E\u7684 PDF \u65E0\u6CD5\u9884\u89C8",
|
|
608
|
+
pdfEncryptedTitle: "PDF \u5DF2\u52A0\u5BC6\uFF0C\u65E0\u6CD5\u5728\u7EBF\u9884\u89C8",
|
|
609
|
+
pdfEncryptedMessage: "\u8BF7\u4E0B\u8F7D\u540E\u4F7F\u7528\u5BC6\u7801\u6253\u5F00\uFF0C\u6216\u4E0A\u4F20\u89E3\u5BC6\u540E\u7684 PDF \u6587\u4EF6\u3002",
|
|
610
|
+
pdfPreviewFailedTitle: "PDF \u9884\u89C8\u5931\u8D25",
|
|
611
|
+
pdfCorruptedMessage: "\u8BE5 PDF \u6587\u4EF6\u53EF\u80FD\u5DF2\u635F\u574F\u6216\u683C\u5F0F\u65E0\u6548\u3002",
|
|
612
|
+
pdfCannotLoadMessage: "\u5F53\u524D\u6D4F\u89C8\u5668\u65E0\u6CD5\u52A0\u8F7D\u8BE5 PDF\u3002",
|
|
613
|
+
pdfDownload: "\u4E0B\u8F7D PDF",
|
|
614
|
+
pdfPageLoading: "\u9875\u9762 {page} \u52A0\u8F7D\u4E2D...",
|
|
615
|
+
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",
|
|
616
|
+
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",
|
|
617
|
+
pdfPreviousPage: "\u4E0A\u4E00\u9875",
|
|
618
|
+
pdfNextPage: "\u4E0B\u4E00\u9875",
|
|
619
|
+
pdfPageInput: "\u5F53\u524D\u9875\u7801",
|
|
620
|
+
pdfPagePosition: "/ {total}",
|
|
621
|
+
pdfPageLabel: "\u7B2C {page} \u9875",
|
|
622
|
+
pdfSummaryPages: "\u9875\u6570",
|
|
623
|
+
pdfSummaryPageSizes: "\u9875\u9762\u5C3A\u5BF8",
|
|
624
|
+
pdfSummaryFit: "\u9002\u914D",
|
|
625
|
+
pdfSummaryActualSize: "\u539F\u59CB\u5927\u5C0F",
|
|
626
|
+
pdfSummaryFitWidth: "\u9002\u5408\u5BBD\u5EA6",
|
|
627
|
+
pdfSummaryZoom: "\u7F29\u653E",
|
|
628
|
+
imagePreviewFailedTitle: "\u56FE\u7247\u9884\u89C8\u5931\u8D25",
|
|
629
|
+
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",
|
|
630
|
+
imageDownload: "\u4E0B\u8F7D\u56FE\u7247",
|
|
631
|
+
imageZoomOut: "\u7F29\u5C0F",
|
|
632
|
+
imageZoomIn: "\u653E\u5927",
|
|
633
|
+
imageRotate: "\u65CB\u8F6C\u56FE\u7247",
|
|
634
|
+
imageReset: "\u91CD\u7F6E\u56FE\u7247\u89C6\u56FE"
|
|
606
635
|
},
|
|
607
636
|
"en-US": {
|
|
608
637
|
loading: "Loading preview...",
|
|
@@ -651,7 +680,36 @@ var defaultMessages = {
|
|
|
651
680
|
officeUnsupportedIntro: "is handled by the Office plugin. {message}",
|
|
652
681
|
officeUnsupportedSupportedFormats: "This version prioritizes basic previews for docx, rtf, odt/fodt, xlsx/xls/csv/ods, pptx/ppsx, and odp/fodp files.",
|
|
653
682
|
officeErrorWithMessage: "Parser returned: {message}",
|
|
654
|
-
officeErrorWithoutMessage: "Parser did not return a specific error."
|
|
683
|
+
officeErrorWithoutMessage: "Parser did not return a specific error.",
|
|
684
|
+
officeConvertedTitle: "High-fidelity Office conversion preview",
|
|
685
|
+
officeConvertedPdfFailed: "The converted Office PDF could not be previewed",
|
|
686
|
+
pdfEncryptedTitle: "This PDF is encrypted and cannot be previewed online",
|
|
687
|
+
pdfEncryptedMessage: "Download and open it with the password, or upload a decrypted PDF file.",
|
|
688
|
+
pdfPreviewFailedTitle: "PDF preview failed",
|
|
689
|
+
pdfCorruptedMessage: "The PDF may be corrupted or use an invalid format.",
|
|
690
|
+
pdfCannotLoadMessage: "This browser could not load the PDF.",
|
|
691
|
+
pdfDownload: "Download PDF",
|
|
692
|
+
pdfPageLoading: "Loading page {page}...",
|
|
693
|
+
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.",
|
|
694
|
+
pdfPageRenderFailed: "This page could not be rendered. It may contain graphics, fonts, or compression features that the browser PDF engine does not support.",
|
|
695
|
+
pdfPreviousPage: "Previous page",
|
|
696
|
+
pdfNextPage: "Next page",
|
|
697
|
+
pdfPageInput: "Current page",
|
|
698
|
+
pdfPagePosition: "/ {total}",
|
|
699
|
+
pdfPageLabel: "Page {page}",
|
|
700
|
+
pdfSummaryPages: "Pages",
|
|
701
|
+
pdfSummaryPageSizes: "Page sizes",
|
|
702
|
+
pdfSummaryFit: "Fit",
|
|
703
|
+
pdfSummaryActualSize: "Actual size",
|
|
704
|
+
pdfSummaryFitWidth: "Fit width",
|
|
705
|
+
pdfSummaryZoom: "Zoom",
|
|
706
|
+
imagePreviewFailedTitle: "Image preview failed",
|
|
707
|
+
imagePreviewFailedMessage: "This browser cannot display the image. The file may be corrupted or use an unsupported encoding.",
|
|
708
|
+
imageDownload: "Download image",
|
|
709
|
+
imageZoomOut: "Zoom out",
|
|
710
|
+
imageZoomIn: "Zoom in",
|
|
711
|
+
imageRotate: "Rotate image",
|
|
712
|
+
imageReset: "Reset image view"
|
|
655
713
|
}
|
|
656
714
|
};
|
|
657
715
|
function resolveMessages(options) {
|
|
@@ -756,12 +814,17 @@ function createViewer(options) {
|
|
|
756
814
|
currentIndex = clampIndex(index, queue.length);
|
|
757
815
|
await renderQueueItem(currentIndex);
|
|
758
816
|
};
|
|
759
|
-
const toolbar = createToolbar(
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
817
|
+
const toolbar = createToolbar(
|
|
818
|
+
options.toolbar,
|
|
819
|
+
viewport,
|
|
820
|
+
{
|
|
821
|
+
getLength: () => queue.length,
|
|
822
|
+
next: () => goTo(currentIndex + 1),
|
|
823
|
+
previous: () => goTo(currentIndex - 1),
|
|
824
|
+
command: (command) => currentInstance?.command?.(command)
|
|
825
|
+
},
|
|
826
|
+
options.locale || "en-US"
|
|
827
|
+
);
|
|
765
828
|
if (toolbar) {
|
|
766
829
|
host.append(toolbar.element);
|
|
767
830
|
}
|
|
@@ -998,7 +1061,7 @@ function removeMediaListener(media, listener) {
|
|
|
998
1061
|
}
|
|
999
1062
|
media.removeListener?.(listener);
|
|
1000
1063
|
}
|
|
1001
|
-
function createToolbar(toolbar, viewport, queue) {
|
|
1064
|
+
function createToolbar(toolbar, viewport, queue, locale) {
|
|
1002
1065
|
if (!toolbar) {
|
|
1003
1066
|
return void 0;
|
|
1004
1067
|
}
|
|
@@ -1006,7 +1069,7 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1006
1069
|
const element = document.createElement("div");
|
|
1007
1070
|
element.className = "ofv-toolbar";
|
|
1008
1071
|
element.setAttribute("role", "toolbar");
|
|
1009
|
-
element.setAttribute("aria-label",
|
|
1072
|
+
element.setAttribute("aria-label", defaultToolbarText[locale].ariaLabel);
|
|
1010
1073
|
let file;
|
|
1011
1074
|
let currentIndex = 0;
|
|
1012
1075
|
let currentLength = queue.getLength();
|
|
@@ -1067,8 +1130,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1067
1130
|
}
|
|
1068
1131
|
if (id === "previous" && queue.getLength() > 1) {
|
|
1069
1132
|
previousButton = addButton(
|
|
1070
|
-
getToolbarLabel(options, "previous"),
|
|
1071
|
-
getToolbarTitle(options, "previous"),
|
|
1133
|
+
getToolbarLabel(options, locale, "previous"),
|
|
1134
|
+
getToolbarTitle(options, locale, "previous"),
|
|
1072
1135
|
() => void queue.previous(),
|
|
1073
1136
|
void 0,
|
|
1074
1137
|
options.icons?.previous
|
|
@@ -1077,8 +1140,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1077
1140
|
}
|
|
1078
1141
|
if (id === "next" && queue.getLength() > 1) {
|
|
1079
1142
|
nextButton = addButton(
|
|
1080
|
-
getToolbarLabel(options, "next"),
|
|
1081
|
-
getToolbarTitle(options, "next"),
|
|
1143
|
+
getToolbarLabel(options, locale, "next"),
|
|
1144
|
+
getToolbarTitle(options, locale, "next"),
|
|
1082
1145
|
() => void queue.next(),
|
|
1083
1146
|
void 0,
|
|
1084
1147
|
options.icons?.next
|
|
@@ -1092,27 +1155,27 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1092
1155
|
return;
|
|
1093
1156
|
}
|
|
1094
1157
|
if (id === "zoom-out" && options.zoom) {
|
|
1095
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "zoom-out");
|
|
1158
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "zoom-out");
|
|
1096
1159
|
return;
|
|
1097
1160
|
}
|
|
1098
1161
|
if (id === "zoom-in" && options.zoom) {
|
|
1099
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "zoom-in");
|
|
1162
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "zoom-in");
|
|
1100
1163
|
return;
|
|
1101
1164
|
}
|
|
1102
1165
|
if (id === "zoom-reset" && options.zoom) {
|
|
1103
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "zoom-reset");
|
|
1166
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "zoom-reset");
|
|
1104
1167
|
zoomResetButton = commandButtons[commandButtons.length - 1]?.button;
|
|
1105
1168
|
updateZoomLabel();
|
|
1106
1169
|
return;
|
|
1107
1170
|
}
|
|
1108
1171
|
if (id === "rotate-right" && options.rotate) {
|
|
1109
|
-
addCommandButton(id, getToolbarLabel(options, id), getToolbarTitle(options, id), "rotate-right");
|
|
1172
|
+
addCommandButton(id, getToolbarLabel(options, locale, id), getToolbarTitle(options, locale, id), "rotate-right");
|
|
1110
1173
|
return;
|
|
1111
1174
|
}
|
|
1112
1175
|
if (id === "download" && options.download !== false) {
|
|
1113
1176
|
addButton(
|
|
1114
|
-
getToolbarLabel(options, id),
|
|
1115
|
-
getToolbarTitle(options, id),
|
|
1177
|
+
getToolbarLabel(options, locale, id),
|
|
1178
|
+
getToolbarTitle(options, locale, id),
|
|
1116
1179
|
() => getContext().download(),
|
|
1117
1180
|
void 0,
|
|
1118
1181
|
options.icons?.download
|
|
@@ -1121,8 +1184,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1121
1184
|
}
|
|
1122
1185
|
if (id === "fullscreen" && options.fullscreen !== false) {
|
|
1123
1186
|
fullscreenButton = addButton(
|
|
1124
|
-
getToolbarLabel(options, id),
|
|
1125
|
-
getToolbarTitle(options, id),
|
|
1187
|
+
getToolbarLabel(options, locale, id),
|
|
1188
|
+
getToolbarTitle(options, locale, id),
|
|
1126
1189
|
() => getContext().fullscreen(),
|
|
1127
1190
|
void 0,
|
|
1128
1191
|
options.icons?.fullscreen
|
|
@@ -1132,8 +1195,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1132
1195
|
}
|
|
1133
1196
|
if (id === "print" && options.print) {
|
|
1134
1197
|
addButton(
|
|
1135
|
-
getToolbarLabel(options, id),
|
|
1136
|
-
getToolbarTitle(options, id),
|
|
1198
|
+
getToolbarLabel(options, locale, id),
|
|
1199
|
+
getToolbarTitle(options, locale, id),
|
|
1137
1200
|
() => getContext().print(),
|
|
1138
1201
|
void 0,
|
|
1139
1202
|
options.icons?.print
|
|
@@ -1159,11 +1222,11 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1159
1222
|
const renderSearchControl = () => {
|
|
1160
1223
|
const searchGroup = document.createElement("div");
|
|
1161
1224
|
searchGroup.className = "ofv-toolbar-search";
|
|
1162
|
-
searchGroup.title = getToolbarTitle(options, "search");
|
|
1225
|
+
searchGroup.title = getToolbarTitle(options, locale, "search");
|
|
1163
1226
|
const nextSearchInput = document.createElement("input");
|
|
1164
1227
|
nextSearchInput.type = "search";
|
|
1165
|
-
nextSearchInput.placeholder = getToolbarLabel(options, "search");
|
|
1166
|
-
nextSearchInput.setAttribute("aria-label", getToolbarTitle(options, "search"));
|
|
1228
|
+
nextSearchInput.placeholder = getToolbarLabel(options, locale, "search");
|
|
1229
|
+
nextSearchInput.setAttribute("aria-label", getToolbarTitle(options, locale, "search"));
|
|
1167
1230
|
const nextSearchCount = document.createElement("span");
|
|
1168
1231
|
nextSearchCount.className = "ofv-toolbar-search-count";
|
|
1169
1232
|
searchInput = nextSearchInput;
|
|
@@ -1218,7 +1281,7 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1218
1281
|
}
|
|
1219
1282
|
setToolbarButtonContent(
|
|
1220
1283
|
zoomResetButton,
|
|
1221
|
-
currentZoom === void 0 ? getToolbarLabel(options, "zoom-reset") : formatToolbarZoom(currentZoom),
|
|
1284
|
+
currentZoom === void 0 ? getToolbarLabel(options, locale, "zoom-reset") : formatToolbarZoom(currentZoom),
|
|
1222
1285
|
options.icons?.["zoom-reset"]
|
|
1223
1286
|
);
|
|
1224
1287
|
}
|
|
@@ -1241,8 +1304,8 @@ function createToolbar(toolbar, viewport, queue) {
|
|
|
1241
1304
|
const active = isFullscreenActive();
|
|
1242
1305
|
const id = active ? "exit-fullscreen" : "fullscreen";
|
|
1243
1306
|
const icon = active ? options.icons?.["exit-fullscreen"] ?? options.icons?.fullscreen : options.icons?.fullscreen;
|
|
1244
|
-
setToolbarButtonContent(fullscreenButton, getToolbarLabel(options, id), icon);
|
|
1245
|
-
const title = getToolbarTitle(options, id);
|
|
1307
|
+
setToolbarButtonContent(fullscreenButton, getToolbarLabel(options, locale, id), icon);
|
|
1308
|
+
const title = getToolbarTitle(options, locale, id);
|
|
1246
1309
|
fullscreenButton.title = title;
|
|
1247
1310
|
fullscreenButton.setAttribute("aria-label", title);
|
|
1248
1311
|
fullscreenButton.setAttribute("aria-pressed", String(active));
|
|
@@ -1366,39 +1429,75 @@ function createToolbarContext({
|
|
|
1366
1429
|
clearSearch: search.clear
|
|
1367
1430
|
};
|
|
1368
1431
|
}
|
|
1369
|
-
var
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1432
|
+
var defaultToolbarText = {
|
|
1433
|
+
"zh-CN": {
|
|
1434
|
+
ariaLabel: "\u6587\u4EF6\u9884\u89C8\u5DE5\u5177\u680F",
|
|
1435
|
+
labels: {
|
|
1436
|
+
previous: "\u4E0A\u4E00\u4E2A",
|
|
1437
|
+
next: "\u4E0B\u4E00\u4E2A",
|
|
1438
|
+
queue: "",
|
|
1439
|
+
"zoom-out": "-",
|
|
1440
|
+
"zoom-in": "+",
|
|
1441
|
+
"zoom-reset": "100%",
|
|
1442
|
+
"rotate-right": "\u65CB\u8F6C",
|
|
1443
|
+
download: "\u4E0B\u8F7D",
|
|
1444
|
+
fullscreen: "\u5168\u5C4F",
|
|
1445
|
+
"exit-fullscreen": "\u9000\u51FA\u5168\u5C4F",
|
|
1446
|
+
print: "\u6253\u5370",
|
|
1447
|
+
search: "\u641C\u7D22"
|
|
1448
|
+
},
|
|
1449
|
+
titles: {
|
|
1450
|
+
previous: "\u4E0A\u4E00\u4E2A\u6587\u4EF6",
|
|
1451
|
+
next: "\u4E0B\u4E00\u4E2A\u6587\u4EF6",
|
|
1452
|
+
queue: "\u5F53\u524D\u6587\u4EF6\u4F4D\u7F6E",
|
|
1453
|
+
"zoom-out": "\u7F29\u5C0F",
|
|
1454
|
+
"zoom-in": "\u653E\u5927",
|
|
1455
|
+
"zoom-reset": "\u91CD\u7F6E\u7F29\u653E",
|
|
1456
|
+
"rotate-right": "\u5411\u53F3\u65CB\u8F6C",
|
|
1457
|
+
download: "\u4E0B\u8F7D\u6587\u4EF6",
|
|
1458
|
+
fullscreen: "\u5168\u5C4F\u67E5\u770B\u9884\u89C8",
|
|
1459
|
+
"exit-fullscreen": "\u9000\u51FA\u5168\u5C4F",
|
|
1460
|
+
print: "\u6253\u5370\u9884\u89C8",
|
|
1461
|
+
search: "\u641C\u7D22\u9884\u89C8\u6587\u672C"
|
|
1462
|
+
}
|
|
1463
|
+
},
|
|
1464
|
+
"en-US": {
|
|
1465
|
+
ariaLabel: "File preview toolbar",
|
|
1466
|
+
labels: {
|
|
1467
|
+
previous: "Prev",
|
|
1468
|
+
next: "Next",
|
|
1469
|
+
queue: "",
|
|
1470
|
+
"zoom-out": "-",
|
|
1471
|
+
"zoom-in": "+",
|
|
1472
|
+
"zoom-reset": "100%",
|
|
1473
|
+
"rotate-right": "Rotate",
|
|
1474
|
+
download: "Download",
|
|
1475
|
+
fullscreen: "Fullscreen",
|
|
1476
|
+
"exit-fullscreen": "Exit fullscreen",
|
|
1477
|
+
print: "Print",
|
|
1478
|
+
search: "Search"
|
|
1479
|
+
},
|
|
1480
|
+
titles: {
|
|
1481
|
+
previous: "Previous file",
|
|
1482
|
+
next: "Next file",
|
|
1483
|
+
queue: "Current file position",
|
|
1484
|
+
"zoom-out": "Zoom out",
|
|
1485
|
+
"zoom-in": "Zoom in",
|
|
1486
|
+
"zoom-reset": "Reset zoom",
|
|
1487
|
+
"rotate-right": "Rotate right",
|
|
1488
|
+
download: "Download file",
|
|
1489
|
+
fullscreen: "Open preview fullscreen",
|
|
1490
|
+
"exit-fullscreen": "Exit fullscreen",
|
|
1491
|
+
print: "Print preview",
|
|
1492
|
+
search: "Search preview text"
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1396
1495
|
};
|
|
1397
|
-
function getToolbarLabel(options, id) {
|
|
1398
|
-
return options.labels?.[id] ??
|
|
1496
|
+
function getToolbarLabel(options, locale, id) {
|
|
1497
|
+
return options.labels?.[id] ?? defaultToolbarText[locale].labels[id];
|
|
1399
1498
|
}
|
|
1400
|
-
function getToolbarTitle(options, id) {
|
|
1401
|
-
return options.titles?.[id] ?? options.labels?.[id] ??
|
|
1499
|
+
function getToolbarTitle(options, locale, id) {
|
|
1500
|
+
return options.titles?.[id] ?? options.labels?.[id] ?? defaultToolbarText[locale].titles[id];
|
|
1402
1501
|
}
|
|
1403
1502
|
function formatToolbarZoom(zoom) {
|
|
1404
1503
|
return `${Math.round(zoom * 100)}%`;
|
|
@@ -1550,7 +1649,7 @@ function isSafeToolbarIconAttribute(name, value) {
|
|
|
1550
1649
|
return !/^\s*(?:javascript|data:text\/html|vbscript):/i.test(value);
|
|
1551
1650
|
}
|
|
1552
1651
|
function isBuiltInToolbarAction(id) {
|
|
1553
|
-
return id in
|
|
1652
|
+
return id in defaultToolbarText["en-US"].labels;
|
|
1554
1653
|
}
|
|
1555
1654
|
function createSearchController(root) {
|
|
1556
1655
|
const markerClass = "ofv-search-match";
|
|
@@ -2121,7 +2220,7 @@ function imagePlugin() {
|
|
|
2121
2220
|
infoBar.hidden = false;
|
|
2122
2221
|
infoBar.removeAttribute("aria-hidden");
|
|
2123
2222
|
infoBar.style.removeProperty("display");
|
|
2124
|
-
stage.replaceChildren(createImageFallback(ctx.file.name, url));
|
|
2223
|
+
stage.replaceChildren(createImageFallback(ctx.file.name, url, ctx.options.messages));
|
|
2125
2224
|
ctx.toolbar?.refreshCommandSupport();
|
|
2126
2225
|
};
|
|
2127
2226
|
const setScale = (nextScale) => {
|
|
@@ -2146,13 +2245,13 @@ function imagePlugin() {
|
|
|
2146
2245
|
return () => button.removeEventListener("click", action);
|
|
2147
2246
|
};
|
|
2148
2247
|
const disposers = showInlineControls ? [
|
|
2149
|
-
addButton("-",
|
|
2150
|
-
addButton("+",
|
|
2151
|
-
addButton(
|
|
2248
|
+
addButton("-", ctx.options.messages.imageZoomOut, () => setScale(scale - 0.25)),
|
|
2249
|
+
addButton("+", ctx.options.messages.imageZoomIn, () => setScale(scale + 0.25)),
|
|
2250
|
+
addButton(ctx.options.messages.imageRotate, ctx.options.messages.imageRotate, () => {
|
|
2152
2251
|
rotation += 90;
|
|
2153
2252
|
updateTransform();
|
|
2154
2253
|
}),
|
|
2155
|
-
addButton(
|
|
2254
|
+
addButton(ctx.options.messages.imageReset, ctx.options.messages.imageReset, reset)
|
|
2156
2255
|
] : [];
|
|
2157
2256
|
if (showInlineControls) {
|
|
2158
2257
|
controls.append(zoomLabel);
|
|
@@ -2367,17 +2466,17 @@ function getTiffDimensions(ifd) {
|
|
|
2367
2466
|
height: Number(ifd.height || ifd.t257 || 0)
|
|
2368
2467
|
};
|
|
2369
2468
|
}
|
|
2370
|
-
function createImageFallback(fileName, url) {
|
|
2469
|
+
function createImageFallback(fileName, url, messages) {
|
|
2371
2470
|
const fallback = document.createElement("div");
|
|
2372
2471
|
fallback.className = "ofv-fallback";
|
|
2373
2472
|
const title = document.createElement("strong");
|
|
2374
|
-
title.textContent =
|
|
2473
|
+
title.textContent = messages.imagePreviewFailedTitle;
|
|
2375
2474
|
const meta = document.createElement("span");
|
|
2376
|
-
meta.textContent =
|
|
2475
|
+
meta.textContent = messages.imagePreviewFailedMessage;
|
|
2377
2476
|
const download = document.createElement("a");
|
|
2378
2477
|
download.href = url;
|
|
2379
2478
|
download.download = fileName;
|
|
2380
|
-
download.textContent =
|
|
2479
|
+
download.textContent = messages.imageDownload;
|
|
2381
2480
|
fallback.append(title, meta, download);
|
|
2382
2481
|
return fallback;
|
|
2383
2482
|
}
|
|
@@ -4738,17 +4837,20 @@ function pdfPlugin(options = {}) {
|
|
|
4738
4837
|
fit: ctx.options.fit,
|
|
4739
4838
|
zoom: ctx.options.zoom,
|
|
4740
4839
|
toolbar: ctx.toolbar,
|
|
4741
|
-
|
|
4742
|
-
encryptedMessage: "\u8BF7\u4E0B\u8F7D\u540E\u4F7F\u7528\u5BC6\u7801\u6253\u5F00\uFF0C\u6216\u4E0A\u4F20\u89E3\u5BC6\u540E\u7684 PDF \u6587\u4EF6\u3002",
|
|
4743
|
-
encryptedAction: "\u4E0B\u8F7D PDF",
|
|
4840
|
+
messages: ctx.options.messages,
|
|
4744
4841
|
revokeUrlOnDestroy: true
|
|
4745
4842
|
});
|
|
4746
4843
|
}
|
|
4747
4844
|
};
|
|
4748
4845
|
}
|
|
4749
4846
|
async function renderPdfDocumentPreview(options) {
|
|
4847
|
+
const useLegacyCompatibility = shouldUseLegacyPdfCompatibility(options.compatibilityMode);
|
|
4848
|
+
if (useLegacyCompatibility) {
|
|
4849
|
+
installPromiseWithResolversPolyfill();
|
|
4850
|
+
}
|
|
4750
4851
|
const pdf = options.pdfjs || await import("pdfjs-dist");
|
|
4751
|
-
|
|
4852
|
+
const messages = { ...defaultMessages["en-US"], ...options.messages };
|
|
4853
|
+
configurePdfWorker(pdf, options.workerSrc, useLegacyCompatibility);
|
|
4752
4854
|
const viewer = document.createElement("div");
|
|
4753
4855
|
viewer.className = "ofv-pdf-viewer";
|
|
4754
4856
|
if (options.title) {
|
|
@@ -4777,10 +4879,10 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4777
4879
|
url: options.fileUrl
|
|
4778
4880
|
};
|
|
4779
4881
|
const fallback = isEncryptedError(error) ? createEncryptedFallback(fileLike, options.fileUrl, {
|
|
4780
|
-
title: options.encryptedTitle ||
|
|
4781
|
-
message: options.encryptedMessage ||
|
|
4782
|
-
action: options.encryptedAction ||
|
|
4783
|
-
}) : createPdfFallback(options.fileName, options.fileUrl, normalizePdfError(error), options.fallbackTitle);
|
|
4882
|
+
title: options.encryptedTitle || messages.pdfEncryptedTitle,
|
|
4883
|
+
message: options.encryptedMessage || messages.pdfEncryptedMessage,
|
|
4884
|
+
action: options.encryptedAction || messages.pdfDownload
|
|
4885
|
+
}) : createPdfFallback(options.fileName, options.fileUrl, normalizePdfError(error, messages), messages, options.fallbackTitle);
|
|
4784
4886
|
if (!fallback.classList.contains("ofv-pdf-web-fallback")) {
|
|
4785
4887
|
options.viewport.classList.add("ofv-center");
|
|
4786
4888
|
}
|
|
@@ -4847,8 +4949,43 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4847
4949
|
let currentSize = options.size;
|
|
4848
4950
|
let zoomFactor = getInitialZoom({ options: { zoom: options.zoom ?? 1 } }, 0.25, 4);
|
|
4849
4951
|
let rotation = 0;
|
|
4952
|
+
let currentPage = 1;
|
|
4953
|
+
const goToPage = (page, scroll = true) => {
|
|
4954
|
+
currentPage = Math.min(pdfDocument.numPages, Math.max(1, Math.round(page) || 1));
|
|
4955
|
+
pageNavigator.setCurrent(currentPage);
|
|
4956
|
+
const wrapper = pageStates[currentPage - 1]?.wrapper;
|
|
4957
|
+
if (!scroll || !wrapper) {
|
|
4958
|
+
return;
|
|
4959
|
+
}
|
|
4960
|
+
const top = Math.max(0, wrapper.offsetTop - 16);
|
|
4961
|
+
if (typeof scroller.scrollTo === "function") {
|
|
4962
|
+
scroller.scrollTo({ top, behavior: "smooth" });
|
|
4963
|
+
} else {
|
|
4964
|
+
scroller.scrollTop = top;
|
|
4965
|
+
}
|
|
4966
|
+
};
|
|
4967
|
+
const pageNavigator = createPdfPageNavigator(pdfDocument.numPages, messages, (page) => goToPage(page));
|
|
4968
|
+
viewer.insertBefore(pageNavigator.element, summary);
|
|
4969
|
+
const handleScrollerScroll = () => {
|
|
4970
|
+
const scrollerRect = scroller.getBoundingClientRect();
|
|
4971
|
+
const targetY = scrollerRect.top + Math.min(Math.max(scroller.clientHeight * 0.25, 40), 180);
|
|
4972
|
+
let nearestPage = currentPage;
|
|
4973
|
+
let nearestDistance = Number.POSITIVE_INFINITY;
|
|
4974
|
+
pageStates.forEach((state, index) => {
|
|
4975
|
+
const distance = Math.abs(state.wrapper.getBoundingClientRect().top - targetY);
|
|
4976
|
+
if (distance < nearestDistance) {
|
|
4977
|
+
nearestDistance = distance;
|
|
4978
|
+
nearestPage = index + 1;
|
|
4979
|
+
}
|
|
4980
|
+
});
|
|
4981
|
+
if (nearestPage !== currentPage) {
|
|
4982
|
+
currentPage = nearestPage;
|
|
4983
|
+
pageNavigator.setCurrent(currentPage);
|
|
4984
|
+
}
|
|
4985
|
+
};
|
|
4986
|
+
scroller.addEventListener("scroll", handleScrollerScroll, { passive: true });
|
|
4850
4987
|
const updateSummary = () => {
|
|
4851
|
-
renderPdfSummary(summary, pdfDocument.numPages, pagesMeta, options.fit, zoomFactor);
|
|
4988
|
+
renderPdfSummary(summary, pdfDocument.numPages, pagesMeta, options.fit, zoomFactor, messages);
|
|
4852
4989
|
options.toolbar?.setZoom(zoomFactor);
|
|
4853
4990
|
};
|
|
4854
4991
|
const clearPage = (pageIdx) => {
|
|
@@ -4864,7 +5001,9 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4864
5001
|
state.canvas = null;
|
|
4865
5002
|
state.rendered = false;
|
|
4866
5003
|
state.wrapper.replaceChildren();
|
|
4867
|
-
state.wrapper.append(
|
|
5004
|
+
state.wrapper.append(
|
|
5005
|
+
createPageStatus("ofv-pdf-skeleton", formatPreviewMessage(messages.pdfPageLoading, { page: pageIdx + 1 }))
|
|
5006
|
+
);
|
|
4868
5007
|
};
|
|
4869
5008
|
const renderPage = async (pageIdx, size) => {
|
|
4870
5009
|
const state = pageStates[pageIdx];
|
|
@@ -4932,7 +5071,7 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4932
5071
|
state.wrapper.appendChild(
|
|
4933
5072
|
createPageStatus(
|
|
4934
5073
|
"ofv-pdf-empty",
|
|
4935
|
-
|
|
5074
|
+
messages.pdfPageEmpty
|
|
4936
5075
|
)
|
|
4937
5076
|
);
|
|
4938
5077
|
}
|
|
@@ -4940,7 +5079,7 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4940
5079
|
console.error(`Failed to render PDF page ${pageIdx + 1}:`, err);
|
|
4941
5080
|
state.rendered = false;
|
|
4942
5081
|
state.wrapper.replaceChildren(
|
|
4943
|
-
createPageStatus("ofv-pdf-error",
|
|
5082
|
+
createPageStatus("ofv-pdf-error", messages.pdfPageRenderFailed)
|
|
4944
5083
|
);
|
|
4945
5084
|
}
|
|
4946
5085
|
};
|
|
@@ -4981,9 +5120,10 @@ async function renderPdfDocumentPreview(options) {
|
|
|
4981
5120
|
const wrapper = document.createElement("div");
|
|
4982
5121
|
wrapper.className = "ofv-pdf-page-wrapper";
|
|
4983
5122
|
wrapper.setAttribute("data-page-index", String(i));
|
|
5123
|
+
wrapper.setAttribute("aria-label", formatPreviewMessage(messages.pdfPageLabel, { page: i + 1 }));
|
|
4984
5124
|
wrapper.style.width = `${w}px`;
|
|
4985
5125
|
wrapper.style.height = `${h}px`;
|
|
4986
|
-
wrapper.append(createPageStatus("ofv-pdf-skeleton",
|
|
5126
|
+
wrapper.append(createPageStatus("ofv-pdf-skeleton", formatPreviewMessage(messages.pdfPageLoading, { page: i + 1 })));
|
|
4987
5127
|
scroller.appendChild(wrapper);
|
|
4988
5128
|
pageStates.push({
|
|
4989
5129
|
wrapper,
|
|
@@ -5005,6 +5145,7 @@ async function renderPdfDocumentPreview(options) {
|
|
|
5005
5145
|
}
|
|
5006
5146
|
}, 0);
|
|
5007
5147
|
}
|
|
5148
|
+
goToPage(currentPage, false);
|
|
5008
5149
|
};
|
|
5009
5150
|
renderLayout(options.size);
|
|
5010
5151
|
let resizeTimer;
|
|
@@ -5045,6 +5186,8 @@ async function renderPdfDocumentPreview(options) {
|
|
|
5045
5186
|
},
|
|
5046
5187
|
destroy() {
|
|
5047
5188
|
options.toolbar?.setZoom(void 0);
|
|
5189
|
+
pageNavigator.destroy();
|
|
5190
|
+
scroller.removeEventListener("scroll", handleScrollerScroll);
|
|
5048
5191
|
window.clearTimeout(resizeTimer);
|
|
5049
5192
|
observer?.disconnect();
|
|
5050
5193
|
pageStates.forEach((state) => {
|
|
@@ -5090,15 +5233,15 @@ function getPdfAvailableWidth(width) {
|
|
|
5090
5233
|
const gutter = width < 160 ? 16 : 32;
|
|
5091
5234
|
return Math.max(1, width - gutter);
|
|
5092
5235
|
}
|
|
5093
|
-
function renderPdfSummary(summary, pages, pagesMeta, fit, zoomFactor) {
|
|
5236
|
+
function renderPdfSummary(summary, pages, pagesMeta, fit, zoomFactor, messages) {
|
|
5094
5237
|
summary.replaceChildren();
|
|
5095
|
-
appendPdfSummary(summary,
|
|
5238
|
+
appendPdfSummary(summary, messages.pdfSummaryPages, String(pages));
|
|
5096
5239
|
const pageSizes = formatPdfPageSizes(pagesMeta);
|
|
5097
5240
|
if (pageSizes) {
|
|
5098
|
-
appendPdfSummary(summary,
|
|
5241
|
+
appendPdfSummary(summary, messages.pdfSummaryPageSizes, pageSizes);
|
|
5099
5242
|
}
|
|
5100
|
-
appendPdfSummary(summary,
|
|
5101
|
-
appendPdfSummary(summary,
|
|
5243
|
+
appendPdfSummary(summary, messages.pdfSummaryFit, fit === "actual" ? messages.pdfSummaryActualSize : messages.pdfSummaryFitWidth);
|
|
5244
|
+
appendPdfSummary(summary, messages.pdfSummaryZoom, `${Math.round(zoomFactor * 100)}%`);
|
|
5102
5245
|
}
|
|
5103
5246
|
function appendPdfSummary(parent, label, value) {
|
|
5104
5247
|
const item = document.createElement("span");
|
|
@@ -5188,7 +5331,7 @@ function createPageStatus(className, text) {
|
|
|
5188
5331
|
status.textContent = text;
|
|
5189
5332
|
return status;
|
|
5190
5333
|
}
|
|
5191
|
-
function createPdfFallback(fileName, url, message, titleText =
|
|
5334
|
+
function createPdfFallback(fileName, url, message, messages, titleText = messages.pdfPreviewFailedTitle) {
|
|
5192
5335
|
if (isEmbeddableRemoteUrl(url)) {
|
|
5193
5336
|
return createPdfWebFallback(fileName, url);
|
|
5194
5337
|
}
|
|
@@ -5201,7 +5344,7 @@ function createPdfFallback(fileName, url, message, titleText = "PDF \u9884\u89C8
|
|
|
5201
5344
|
const download = document.createElement("a");
|
|
5202
5345
|
download.href = url;
|
|
5203
5346
|
download.download = fileName;
|
|
5204
|
-
download.textContent =
|
|
5347
|
+
download.textContent = messages.pdfDownload;
|
|
5205
5348
|
fallback.append(title, meta, download);
|
|
5206
5349
|
return fallback;
|
|
5207
5350
|
}
|
|
@@ -5220,23 +5363,109 @@ function createPdfWebFallback(fileName, url) {
|
|
|
5220
5363
|
function isEmbeddableRemoteUrl(url) {
|
|
5221
5364
|
return /^https?:\/\//i.test(url);
|
|
5222
5365
|
}
|
|
5223
|
-
function normalizePdfError(error) {
|
|
5366
|
+
function normalizePdfError(error, messages) {
|
|
5224
5367
|
const message = error instanceof Error ? error.message : String(error || "");
|
|
5225
5368
|
const name = typeof error === "object" && error !== null && "name" in error ? String(error.name) : "";
|
|
5226
5369
|
const lower = `${name} ${message}`.toLowerCase();
|
|
5227
5370
|
if (lower.includes("invalid") || lower.includes("missing") || lower.includes("corrupt")) {
|
|
5228
|
-
return
|
|
5371
|
+
return messages.pdfCorruptedMessage;
|
|
5229
5372
|
}
|
|
5230
|
-
return
|
|
5373
|
+
return messages.pdfCannotLoadMessage;
|
|
5374
|
+
}
|
|
5375
|
+
function createPdfPageNavigator(total, messages, onChange) {
|
|
5376
|
+
const element = document.createElement("div");
|
|
5377
|
+
element.className = "ofv-pdf-page-navigator";
|
|
5378
|
+
const previous = document.createElement("button");
|
|
5379
|
+
previous.type = "button";
|
|
5380
|
+
previous.textContent = "\u2039";
|
|
5381
|
+
previous.title = messages.pdfPreviousPage;
|
|
5382
|
+
previous.setAttribute("aria-label", messages.pdfPreviousPage);
|
|
5383
|
+
const input = document.createElement("input");
|
|
5384
|
+
input.type = "number";
|
|
5385
|
+
input.min = "1";
|
|
5386
|
+
input.max = String(total);
|
|
5387
|
+
input.value = "1";
|
|
5388
|
+
input.inputMode = "numeric";
|
|
5389
|
+
input.setAttribute("aria-label", messages.pdfPageInput);
|
|
5390
|
+
const position = document.createElement("span");
|
|
5391
|
+
position.textContent = formatPreviewMessage(messages.pdfPagePosition, { total });
|
|
5392
|
+
const next = document.createElement("button");
|
|
5393
|
+
next.type = "button";
|
|
5394
|
+
next.textContent = "\u203A";
|
|
5395
|
+
next.title = messages.pdfNextPage;
|
|
5396
|
+
next.setAttribute("aria-label", messages.pdfNextPage);
|
|
5397
|
+
const commit = () => onChange(Number(input.value));
|
|
5398
|
+
const handleKeydown = (event) => {
|
|
5399
|
+
if (event.key === "Enter") {
|
|
5400
|
+
commit();
|
|
5401
|
+
}
|
|
5402
|
+
};
|
|
5403
|
+
const handlePrevious = () => onChange(Number(input.value) - 1);
|
|
5404
|
+
const handleNext = () => onChange(Number(input.value) + 1);
|
|
5405
|
+
input.addEventListener("change", commit);
|
|
5406
|
+
input.addEventListener("keydown", handleKeydown);
|
|
5407
|
+
previous.addEventListener("click", handlePrevious);
|
|
5408
|
+
next.addEventListener("click", handleNext);
|
|
5409
|
+
element.append(previous, input, position, next);
|
|
5410
|
+
return {
|
|
5411
|
+
element,
|
|
5412
|
+
setCurrent(page) {
|
|
5413
|
+
input.value = String(page);
|
|
5414
|
+
previous.disabled = page <= 1;
|
|
5415
|
+
next.disabled = page >= total;
|
|
5416
|
+
},
|
|
5417
|
+
destroy() {
|
|
5418
|
+
input.removeEventListener("change", commit);
|
|
5419
|
+
input.removeEventListener("keydown", handleKeydown);
|
|
5420
|
+
previous.removeEventListener("click", handlePrevious);
|
|
5421
|
+
next.removeEventListener("click", handleNext);
|
|
5422
|
+
}
|
|
5423
|
+
};
|
|
5231
5424
|
}
|
|
5232
|
-
function configurePdfWorker(pdf, workerSrc) {
|
|
5425
|
+
function configurePdfWorker(pdf, workerSrc, legacy = false) {
|
|
5233
5426
|
if (workerSrc) {
|
|
5234
5427
|
pdf.GlobalWorkerOptions.workerSrc = workerSrc;
|
|
5235
5428
|
return;
|
|
5236
5429
|
}
|
|
5237
5430
|
if (!pdf.GlobalWorkerOptions.workerSrc && typeof window !== "undefined") {
|
|
5238
|
-
|
|
5431
|
+
const build = legacy ? "legacy/build" : "build";
|
|
5432
|
+
pdf.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdf.version}/${build}/pdf.worker.mjs`;
|
|
5433
|
+
}
|
|
5434
|
+
}
|
|
5435
|
+
function shouldUseLegacyPdfCompatibility(mode = "auto") {
|
|
5436
|
+
if (mode === "legacy") {
|
|
5437
|
+
return true;
|
|
5438
|
+
}
|
|
5439
|
+
if (mode === "modern") {
|
|
5440
|
+
return false;
|
|
5441
|
+
}
|
|
5442
|
+
const promise = Promise;
|
|
5443
|
+
if (typeof promise.withResolvers !== "function") {
|
|
5444
|
+
return true;
|
|
5445
|
+
}
|
|
5446
|
+
if (typeof navigator === "undefined") {
|
|
5447
|
+
return false;
|
|
5239
5448
|
}
|
|
5449
|
+
return /(?:QIHU|360SE|360EE)/i.test(navigator.userAgent);
|
|
5450
|
+
}
|
|
5451
|
+
function installPromiseWithResolversPolyfill() {
|
|
5452
|
+
const promise = Promise;
|
|
5453
|
+
if (typeof promise.withResolvers === "function") {
|
|
5454
|
+
return;
|
|
5455
|
+
}
|
|
5456
|
+
Object.defineProperty(promise, "withResolvers", {
|
|
5457
|
+
configurable: true,
|
|
5458
|
+
writable: true,
|
|
5459
|
+
value: () => {
|
|
5460
|
+
let resolve;
|
|
5461
|
+
let reject;
|
|
5462
|
+
const pending = new Promise((resolvePromise, rejectPromise) => {
|
|
5463
|
+
resolve = resolvePromise;
|
|
5464
|
+
reject = rejectPromise;
|
|
5465
|
+
});
|
|
5466
|
+
return { promise: pending, resolve, reject };
|
|
5467
|
+
}
|
|
5468
|
+
});
|
|
5240
5469
|
}
|
|
5241
5470
|
|
|
5242
5471
|
// src/plugins/epub.ts
|
|
@@ -7631,8 +7860,9 @@ async function renderConvertedOfficePreview(panel, ctx, options, conversionConte
|
|
|
7631
7860
|
fit: ctx.options.fit,
|
|
7632
7861
|
zoom: ctx.options.zoom,
|
|
7633
7862
|
toolbar: ctx.toolbar,
|
|
7634
|
-
|
|
7635
|
-
|
|
7863
|
+
messages: ctx.options.messages,
|
|
7864
|
+
title: ctx.options.messages.officeConvertedTitle,
|
|
7865
|
+
fallbackTitle: ctx.options.messages.officeConvertedPdfFailed,
|
|
7636
7866
|
revokeUrlOnDestroy: converted.revokeUrlOnDestroy
|
|
7637
7867
|
});
|
|
7638
7868
|
}
|
|
@@ -9414,6 +9644,9 @@ function renderChartCard(chart) {
|
|
|
9414
9644
|
function renderChartSvg(chart) {
|
|
9415
9645
|
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
9416
9646
|
svg.setAttribute("viewBox", "0 0 640 380");
|
|
9647
|
+
svg.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
|
9648
|
+
svg.setAttribute("text-rendering", "geometricPrecision");
|
|
9649
|
+
svg.setAttribute("shape-rendering", "geometricPrecision");
|
|
9417
9650
|
svg.setAttribute("role", "img");
|
|
9418
9651
|
svg.setAttribute("aria-label", chart.title);
|
|
9419
9652
|
svg.classList.add("ofv-chart-svg");
|
|
@@ -9459,16 +9692,7 @@ function renderChartSvg(chart) {
|
|
|
9459
9692
|
const clusterWidth = groupWidth * 0.58;
|
|
9460
9693
|
const barWidth = Math.max(5, Math.min(28, clusterWidth / Math.max(1, chart.series.length)));
|
|
9461
9694
|
const zeroY = plot.y + plot.height - (0 - axisMin) / (axisMax - axisMin || 1) * plot.height;
|
|
9462
|
-
|
|
9463
|
-
const x = plot.x + groupWidth * (index + 0.5);
|
|
9464
|
-
const label = appendSvg(svg, "text", {
|
|
9465
|
-
x: Number(x.toFixed(1)),
|
|
9466
|
-
y: plot.y + plot.height + 22,
|
|
9467
|
-
class: "ofv-chart-label",
|
|
9468
|
-
"text-anchor": "middle"
|
|
9469
|
-
});
|
|
9470
|
-
label.textContent = truncateChartLabel(category);
|
|
9471
|
-
});
|
|
9695
|
+
appendChartCategoryLabels(svg, categories, plot, (index) => plot.x + groupWidth * (index + 0.5));
|
|
9472
9696
|
chart.series.forEach((series, seriesIndex) => {
|
|
9473
9697
|
const color = series.color || colors[seriesIndex % colors.length];
|
|
9474
9698
|
series.values.forEach((value, index) => {
|
|
@@ -9486,6 +9710,8 @@ function renderChartSvg(chart) {
|
|
|
9486
9710
|
});
|
|
9487
9711
|
});
|
|
9488
9712
|
} else {
|
|
9713
|
+
const categoryStep = categories.length > 1 ? plot.width / (categories.length - 1) : plot.width;
|
|
9714
|
+
appendChartCategoryLabels(svg, categories, plot, (index) => plot.x + index * categoryStep);
|
|
9489
9715
|
chart.series.forEach((series, seriesIndex) => {
|
|
9490
9716
|
const color = series.color || colors[seriesIndex % colors.length];
|
|
9491
9717
|
const step = series.values.length > 1 ? plot.width / (series.values.length - 1) : plot.width;
|
|
@@ -9510,6 +9736,22 @@ function renderChartSvg(chart) {
|
|
|
9510
9736
|
appendChartLegend(svg, chart, colors, 348);
|
|
9511
9737
|
return svg;
|
|
9512
9738
|
}
|
|
9739
|
+
function appendChartCategoryLabels(svg, categories, plot, getX) {
|
|
9740
|
+
const interval = Math.max(1, Math.ceil(categories.length / 14));
|
|
9741
|
+
categories.forEach((category, index) => {
|
|
9742
|
+
if (index % interval !== 0 && index !== categories.length - 1) {
|
|
9743
|
+
return;
|
|
9744
|
+
}
|
|
9745
|
+
const label = appendSvg(svg, "text", {
|
|
9746
|
+
x: Number(getX(index).toFixed(1)),
|
|
9747
|
+
y: plot.y + plot.height + 22,
|
|
9748
|
+
class: "ofv-chart-label ofv-chart-category-label",
|
|
9749
|
+
"data-axis": "category",
|
|
9750
|
+
"text-anchor": "middle"
|
|
9751
|
+
});
|
|
9752
|
+
label.textContent = truncateChartLabel(category);
|
|
9753
|
+
});
|
|
9754
|
+
}
|
|
9513
9755
|
function appendChartLegend(svg, chart, colors, y) {
|
|
9514
9756
|
const itemWidth = 86;
|
|
9515
9757
|
const startX = 320 - chart.series.length * itemWidth / 2;
|