@files-preview-app/preview-file 1.2.4 → 1.2.5
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/angular.cjs +645 -158
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.js +644 -158
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +645 -158
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +644 -158
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +645 -158
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +644 -158
- package/dist/react.js.map +1 -1
- package/dist/vue.cjs +645 -158
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +644 -158
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var DOMPurify2 = require('dompurify');
|
|
4
|
+
var pdfjsLib = require('pdfjs-dist');
|
|
4
5
|
var docx = require('docx-preview');
|
|
5
6
|
var fflate = require('fflate');
|
|
6
7
|
var XLSX = require('xlsx');
|
|
@@ -34,6 +35,7 @@ function _interopNamespace(e) {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
var DOMPurify2__default = /*#__PURE__*/_interopDefault(DOMPurify2);
|
|
38
|
+
var pdfjsLib__namespace = /*#__PURE__*/_interopNamespace(pdfjsLib);
|
|
37
39
|
var docx__namespace = /*#__PURE__*/_interopNamespace(docx);
|
|
38
40
|
var XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
|
|
39
41
|
var hljs__default = /*#__PURE__*/_interopDefault(hljs);
|
|
@@ -551,11 +553,21 @@ var ToolbarController = class {
|
|
|
551
553
|
el;
|
|
552
554
|
toolbarEl;
|
|
553
555
|
actions = [];
|
|
556
|
+
pageInputEl = null;
|
|
557
|
+
pageLabelEl = null;
|
|
554
558
|
constructor(container) {
|
|
555
559
|
this.el = container;
|
|
556
560
|
this.toolbarEl = createElement("div", { className: "fp-toolbar" });
|
|
557
561
|
this.el.appendChild(this.toolbarEl);
|
|
558
562
|
}
|
|
563
|
+
setPage(page, max) {
|
|
564
|
+
if (this.pageInputEl) {
|
|
565
|
+
this.pageInputEl.value = page.toString();
|
|
566
|
+
}
|
|
567
|
+
if (max !== void 0 && this.pageLabelEl) {
|
|
568
|
+
this.pageLabelEl.textContent = ` / ${max}`;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
559
571
|
update(actions) {
|
|
560
572
|
this.actions = actions;
|
|
561
573
|
this.render();
|
|
@@ -598,6 +610,7 @@ var ToolbarController = class {
|
|
|
598
610
|
if (action.type === "separator") {
|
|
599
611
|
groupEl.appendChild(createElement("div", { className: "fp-toolbar-separator" }));
|
|
600
612
|
} else if (action.type === "page-nav") {
|
|
613
|
+
const max = action.max ?? 1;
|
|
601
614
|
const prevBtn = this.createButton(
|
|
602
615
|
"prev",
|
|
603
616
|
ICON_PAGE_PREV,
|
|
@@ -616,7 +629,6 @@ var ToolbarController = class {
|
|
|
616
629
|
"Next Page",
|
|
617
630
|
() => {
|
|
618
631
|
const cur = parseInt(input.value, 10) || 1;
|
|
619
|
-
const max = action.max ?? 1;
|
|
620
632
|
if (cur < max) {
|
|
621
633
|
input.value = (cur + 1).toString();
|
|
622
634
|
action.execute("next", cur + 1);
|
|
@@ -628,15 +640,18 @@ var ToolbarController = class {
|
|
|
628
640
|
type: "number",
|
|
629
641
|
value: (action.value ?? 1).toString(),
|
|
630
642
|
min: "1",
|
|
631
|
-
max:
|
|
643
|
+
max: max.toString()
|
|
632
644
|
});
|
|
633
645
|
input.addEventListener("change", () => {
|
|
634
|
-
|
|
635
|
-
if (
|
|
636
|
-
|
|
637
|
-
|
|
646
|
+
let val = parseInt(input.value, 10);
|
|
647
|
+
if (isNaN(val)) val = 1;
|
|
648
|
+
val = Math.max(1, Math.min(max, val));
|
|
649
|
+
input.value = val.toString();
|
|
650
|
+
action.execute("go", val);
|
|
638
651
|
});
|
|
639
|
-
const label = createElement("span", { className: "fp-toolbar-label" }, ` / ${
|
|
652
|
+
const label = createElement("span", { className: "fp-toolbar-label" }, ` / ${max}`);
|
|
653
|
+
this.pageInputEl = input;
|
|
654
|
+
this.pageLabelEl = label;
|
|
640
655
|
groupEl.appendChild(prevBtn);
|
|
641
656
|
groupEl.appendChild(input);
|
|
642
657
|
groupEl.appendChild(label);
|
|
@@ -814,7 +829,13 @@ var FilePreviewViewer = class {
|
|
|
814
829
|
buffer,
|
|
815
830
|
options,
|
|
816
831
|
signal,
|
|
817
|
-
emit: (event, payload) =>
|
|
832
|
+
emit: (event, payload) => {
|
|
833
|
+
if (event === "page-change" && payload && typeof payload.page === "number") {
|
|
834
|
+
const total = payload.total ?? payload.totalPages;
|
|
835
|
+
this.toolbar?.setPage(payload.page, total);
|
|
836
|
+
}
|
|
837
|
+
this.eventEmitter.emit(event, payload);
|
|
838
|
+
}
|
|
818
839
|
});
|
|
819
840
|
this.activeInstance = instance;
|
|
820
841
|
this.hideLoading();
|
|
@@ -848,6 +869,7 @@ var FilePreviewViewer = class {
|
|
|
848
869
|
if (thumbnails && thumbnails.length > 0 && this.thumbnailPanel) {
|
|
849
870
|
this.thumbnailPanel.update(thumbnails, (index) => {
|
|
850
871
|
instance.goToPage?.(index + 1);
|
|
872
|
+
this.toolbar?.setPage(index + 1);
|
|
851
873
|
});
|
|
852
874
|
if (options.showThumbnails) {
|
|
853
875
|
this.thumbnailPanel.show();
|
|
@@ -973,9 +995,13 @@ var FilePreviewViewer = class {
|
|
|
973
995
|
if (e.key === "ArrowRight" || e.key === "PageDown") {
|
|
974
996
|
const cur = this.activeInstance.getCurrentPage?.() ?? 1;
|
|
975
997
|
this.activeInstance.goToPage?.(cur + 1);
|
|
998
|
+
const nextCur = this.activeInstance.getCurrentPage?.() ?? cur + 1;
|
|
999
|
+
this.toolbar?.setPage(nextCur);
|
|
976
1000
|
} else if (e.key === "ArrowLeft" || e.key === "PageUp") {
|
|
977
1001
|
const cur = this.activeInstance.getCurrentPage?.() ?? 1;
|
|
978
1002
|
this.activeInstance.goToPage?.(Math.max(1, cur - 1));
|
|
1003
|
+
const prevCur = this.activeInstance.getCurrentPage?.() ?? Math.max(1, cur - 1);
|
|
1004
|
+
this.toolbar?.setPage(prevCur);
|
|
979
1005
|
} else if (e.key === "+" || e.key === "=") {
|
|
980
1006
|
this.activeInstance.zoomIn?.();
|
|
981
1007
|
} else if (e.key === "-" || e.key === "_") {
|
|
@@ -1241,30 +1267,62 @@ var CfbfReader = class {
|
|
|
1241
1267
|
return result.subarray(0, targetSize);
|
|
1242
1268
|
}
|
|
1243
1269
|
};
|
|
1244
|
-
|
|
1245
|
-
|
|
1270
|
+
if (typeof window !== "undefined" && pdfjsLib__namespace.GlobalWorkerOptions) {
|
|
1271
|
+
if (!pdfjsLib__namespace.GlobalWorkerOptions.workerSrc) {
|
|
1272
|
+
pdfjsLib__namespace.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjsLib__namespace.version || "4.10.38"}/build/pdf.worker.min.mjs`;
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1246
1275
|
var PdfPlugin = class {
|
|
1247
1276
|
id = "pdf";
|
|
1248
|
-
name = "PDF Preview";
|
|
1277
|
+
name = "PDF Document Preview";
|
|
1249
1278
|
extensions = [".pdf"];
|
|
1250
1279
|
mimeTypes = ["application/pdf"];
|
|
1251
1280
|
weight = 100;
|
|
1252
1281
|
supports(file) {
|
|
1253
1282
|
const ext = file.metadata.extension?.toLowerCase();
|
|
1254
1283
|
const mime = file.metadata.mimeType?.toLowerCase();
|
|
1255
|
-
|
|
1284
|
+
if (ext) return this.extensions.includes(ext);
|
|
1285
|
+
return this.mimeTypes.includes(mime || "");
|
|
1256
1286
|
}
|
|
1257
1287
|
getToolbarActions(instance) {
|
|
1288
|
+
const totalPages = instance.getPageCount?.() ?? 1;
|
|
1289
|
+
const curPage = instance.getCurrentPage?.() ?? 1;
|
|
1258
1290
|
return [
|
|
1291
|
+
{
|
|
1292
|
+
id: "thumbnails",
|
|
1293
|
+
icon: "thumbnails",
|
|
1294
|
+
label: "Page Thumbnails",
|
|
1295
|
+
type: "button",
|
|
1296
|
+
group: "navigation",
|
|
1297
|
+
execute: () => instance.toggleThumbnails?.()
|
|
1298
|
+
},
|
|
1299
|
+
{
|
|
1300
|
+
id: "page-nav",
|
|
1301
|
+
icon: "",
|
|
1302
|
+
label: "Page Navigation",
|
|
1303
|
+
type: "page-nav",
|
|
1304
|
+
group: "navigation",
|
|
1305
|
+
value: curPage,
|
|
1306
|
+
max: totalPages,
|
|
1307
|
+
execute: (action, page) => {
|
|
1308
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
1309
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
1310
|
+
if (action === "prev") {
|
|
1311
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
1312
|
+
} else if (action === "next") {
|
|
1313
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
1314
|
+
} else if (typeof page === "number") {
|
|
1315
|
+
instance.goToPage?.(page);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
},
|
|
1259
1319
|
{
|
|
1260
1320
|
id: "zoom-out",
|
|
1261
1321
|
icon: "zoom-out",
|
|
1262
1322
|
label: "Zoom Out",
|
|
1263
1323
|
type: "button",
|
|
1264
1324
|
group: "zoom",
|
|
1265
|
-
execute: () =>
|
|
1266
|
-
instance.zoomOut?.();
|
|
1267
|
-
}
|
|
1325
|
+
execute: () => instance.zoomOut?.()
|
|
1268
1326
|
},
|
|
1269
1327
|
{
|
|
1270
1328
|
id: "zoom-in",
|
|
@@ -1272,9 +1330,7 @@ var PdfPlugin = class {
|
|
|
1272
1330
|
label: "Zoom In",
|
|
1273
1331
|
type: "button",
|
|
1274
1332
|
group: "zoom",
|
|
1275
|
-
execute: () =>
|
|
1276
|
-
instance.zoomIn?.();
|
|
1277
|
-
}
|
|
1333
|
+
execute: () => instance.zoomIn?.()
|
|
1278
1334
|
},
|
|
1279
1335
|
{
|
|
1280
1336
|
id: "fit-page",
|
|
@@ -1282,39 +1338,23 @@ var PdfPlugin = class {
|
|
|
1282
1338
|
label: "Fit to Page",
|
|
1283
1339
|
type: "button",
|
|
1284
1340
|
group: "zoom",
|
|
1285
|
-
execute: () =>
|
|
1286
|
-
instance.fitToPage?.();
|
|
1287
|
-
}
|
|
1341
|
+
execute: () => instance.fitToPage?.()
|
|
1288
1342
|
},
|
|
1289
1343
|
{
|
|
1290
1344
|
id: "rotate-cw",
|
|
1291
1345
|
icon: "rotate-cw",
|
|
1292
|
-
label: "Rotate",
|
|
1346
|
+
label: "Rotate Clockwise",
|
|
1293
1347
|
type: "button",
|
|
1294
1348
|
group: "view",
|
|
1295
|
-
execute: () =>
|
|
1296
|
-
instance.rotateCW?.();
|
|
1297
|
-
}
|
|
1298
|
-
},
|
|
1299
|
-
{
|
|
1300
|
-
id: "page-nav",
|
|
1301
|
-
icon: "page-nav",
|
|
1302
|
-
label: "Page Navigation",
|
|
1303
|
-
type: "page-nav",
|
|
1304
|
-
group: "navigation",
|
|
1305
|
-
execute: (page) => {
|
|
1306
|
-
if (typeof page === "number") instance.goToPage?.(page);
|
|
1307
|
-
}
|
|
1349
|
+
execute: () => instance.rotateCW?.()
|
|
1308
1350
|
},
|
|
1309
1351
|
{
|
|
1310
1352
|
id: "download",
|
|
1311
1353
|
icon: "download",
|
|
1312
|
-
label: "Download",
|
|
1354
|
+
label: "Download PDF",
|
|
1313
1355
|
type: "button",
|
|
1314
1356
|
group: "actions",
|
|
1315
|
-
execute: () =>
|
|
1316
|
-
instance.download?.();
|
|
1317
|
-
}
|
|
1357
|
+
execute: () => instance.download?.()
|
|
1318
1358
|
},
|
|
1319
1359
|
{
|
|
1320
1360
|
id: "print",
|
|
@@ -1322,99 +1362,213 @@ var PdfPlugin = class {
|
|
|
1322
1362
|
label: "Print",
|
|
1323
1363
|
type: "button",
|
|
1324
1364
|
group: "actions",
|
|
1325
|
-
execute: () =>
|
|
1326
|
-
instance.print?.();
|
|
1327
|
-
}
|
|
1365
|
+
execute: () => instance.print?.()
|
|
1328
1366
|
}
|
|
1329
1367
|
];
|
|
1330
1368
|
}
|
|
1331
1369
|
async render(ctx) {
|
|
1332
|
-
const
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1370
|
+
const container = document.createElement("div");
|
|
1371
|
+
container.className = "fp-pdf-container";
|
|
1372
|
+
container.style.width = "100%";
|
|
1373
|
+
container.style.height = "100%";
|
|
1374
|
+
container.style.overflow = "auto";
|
|
1375
|
+
container.style.display = "flex";
|
|
1376
|
+
container.style.flexDirection = "column";
|
|
1377
|
+
container.style.alignItems = "center";
|
|
1378
|
+
container.style.padding = "24px 16px";
|
|
1379
|
+
container.style.backgroundColor = "#0f172a";
|
|
1380
|
+
container.style.boxSizing = "border-box";
|
|
1381
|
+
container.style.position = "relative";
|
|
1382
|
+
const pageCard = document.createElement("div");
|
|
1383
|
+
pageCard.className = "fp-pdf-page-card";
|
|
1384
|
+
pageCard.style.boxShadow = "0 10px 35px rgba(0, 0, 0, 0.5)";
|
|
1385
|
+
pageCard.style.backgroundColor = "#ffffff";
|
|
1386
|
+
pageCard.style.borderRadius = "4px";
|
|
1387
|
+
pageCard.style.overflow = "hidden";
|
|
1388
|
+
pageCard.style.lineHeight = "0";
|
|
1389
|
+
pageCard.style.transition = "transform 0.15s ease";
|
|
1390
|
+
pageCard.style.position = "relative";
|
|
1391
|
+
const canvas = document.createElement("canvas");
|
|
1392
|
+
pageCard.appendChild(canvas);
|
|
1393
|
+
container.appendChild(pageCard);
|
|
1394
|
+
const indicator = document.createElement("div");
|
|
1395
|
+
indicator.className = "fp-pdf-page-indicator";
|
|
1396
|
+
indicator.style.position = "sticky";
|
|
1397
|
+
indicator.style.bottom = "16px";
|
|
1398
|
+
indicator.style.marginTop = "16px";
|
|
1399
|
+
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
1400
|
+
indicator.style.backdropFilter = "blur(8px)";
|
|
1401
|
+
indicator.style.color = "#f8fafc";
|
|
1402
|
+
indicator.style.fontSize = "12px";
|
|
1403
|
+
indicator.style.fontWeight = "600";
|
|
1404
|
+
indicator.style.padding = "5px 14px";
|
|
1405
|
+
indicator.style.borderRadius = "20px";
|
|
1406
|
+
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
1407
|
+
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
1408
|
+
indicator.style.zIndex = "10";
|
|
1409
|
+
indicator.style.userSelect = "none";
|
|
1410
|
+
indicator.style.pointerEvents = "none";
|
|
1411
|
+
container.appendChild(indicator);
|
|
1412
|
+
ctx.container.appendChild(container);
|
|
1413
|
+
const loadingTask = pdfjsLib__namespace.getDocument({
|
|
1414
|
+
data: new Uint8Array(ctx.buffer),
|
|
1415
|
+
cMapUrl: `https://unpkg.com/pdfjs-dist@${pdfjsLib__namespace.version || "4.10.38"}/cmaps/`,
|
|
1416
|
+
cMapPacked: true,
|
|
1417
|
+
standardFontDataUrl: `https://unpkg.com/pdfjs-dist@${pdfjsLib__namespace.version || "4.10.38"}/standard_fonts/`
|
|
1418
|
+
});
|
|
1419
|
+
const pdfDoc = await loadingTask.promise;
|
|
1420
|
+
const totalPages = Math.max(1, pdfDoc.numPages);
|
|
1348
1421
|
let currentPage = 1;
|
|
1349
|
-
let
|
|
1422
|
+
let zoomScale = 1;
|
|
1350
1423
|
let rotation = 0;
|
|
1424
|
+
let currentRenderTask = null;
|
|
1425
|
+
const renderPage = async (pageNum) => {
|
|
1426
|
+
if (currentRenderTask) {
|
|
1427
|
+
try {
|
|
1428
|
+
currentRenderTask.cancel();
|
|
1429
|
+
} catch {
|
|
1430
|
+
}
|
|
1431
|
+
currentRenderTask = null;
|
|
1432
|
+
}
|
|
1433
|
+
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
1434
|
+
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
1435
|
+
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
1436
|
+
const page = await pdfDoc.getPage(currentPage);
|
|
1437
|
+
const containerWidth = container.clientWidth || 900;
|
|
1438
|
+
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1439
|
+
const baseScale = Math.min((containerWidth - 64) / unscaledVp.width, 1.6);
|
|
1440
|
+
const effectiveScale = (baseScale > 0 ? baseScale : 1) * zoomScale;
|
|
1441
|
+
const pixelRatio = window.devicePixelRatio || 1;
|
|
1442
|
+
const viewport = page.getViewport({ scale: effectiveScale, rotation });
|
|
1443
|
+
canvas.width = Math.floor(viewport.width * pixelRatio);
|
|
1444
|
+
canvas.height = Math.floor(viewport.height * pixelRatio);
|
|
1445
|
+
canvas.style.width = `${Math.floor(viewport.width)}px`;
|
|
1446
|
+
canvas.style.height = `${Math.floor(viewport.height)}px`;
|
|
1447
|
+
const canvasCtx = canvas.getContext("2d");
|
|
1448
|
+
if (!canvasCtx) return;
|
|
1449
|
+
canvasCtx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
|
|
1450
|
+
currentRenderTask = page.render({
|
|
1451
|
+
canvasContext: canvasCtx,
|
|
1452
|
+
viewport
|
|
1453
|
+
});
|
|
1454
|
+
try {
|
|
1455
|
+
await currentRenderTask.promise;
|
|
1456
|
+
} catch (err) {
|
|
1457
|
+
if (err?.name !== "RenderingCancelledException") {
|
|
1458
|
+
console.warn("[PdfPlugin] Page render warning:", err);
|
|
1459
|
+
}
|
|
1460
|
+
} finally {
|
|
1461
|
+
currentRenderTask = null;
|
|
1462
|
+
}
|
|
1463
|
+
};
|
|
1464
|
+
await renderPage(1);
|
|
1351
1465
|
const cleanup = () => {
|
|
1352
|
-
|
|
1353
|
-
|
|
1466
|
+
if (currentRenderTask) {
|
|
1467
|
+
try {
|
|
1468
|
+
currentRenderTask.cancel();
|
|
1469
|
+
} catch {
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
try {
|
|
1473
|
+
pdfDoc.destroy();
|
|
1474
|
+
} catch {
|
|
1475
|
+
}
|
|
1476
|
+
container.remove();
|
|
1354
1477
|
ctx.container.innerHTML = "";
|
|
1355
1478
|
};
|
|
1356
1479
|
ctx.signal.addEventListener("abort", cleanup);
|
|
1357
|
-
|
|
1480
|
+
const instance = {
|
|
1358
1481
|
destroy: cleanup,
|
|
1359
1482
|
zoomIn: () => {
|
|
1360
|
-
|
|
1361
|
-
|
|
1483
|
+
zoomScale = Math.min(3.5, zoomScale + 0.2);
|
|
1484
|
+
renderPage(currentPage);
|
|
1362
1485
|
},
|
|
1363
1486
|
zoomOut: () => {
|
|
1364
|
-
|
|
1365
|
-
|
|
1487
|
+
zoomScale = Math.max(0.3, zoomScale - 0.2);
|
|
1488
|
+
renderPage(currentPage);
|
|
1366
1489
|
},
|
|
1367
|
-
getZoom: () =>
|
|
1490
|
+
getZoom: () => zoomScale,
|
|
1368
1491
|
setZoom: (level) => {
|
|
1369
|
-
|
|
1370
|
-
|
|
1492
|
+
zoomScale = Math.max(0.3, Math.min(3.5, level));
|
|
1493
|
+
renderPage(currentPage);
|
|
1371
1494
|
},
|
|
1372
1495
|
fitToPage: () => {
|
|
1373
|
-
|
|
1374
|
-
|
|
1496
|
+
zoomScale = 1;
|
|
1497
|
+
renderPage(currentPage);
|
|
1375
1498
|
},
|
|
1376
1499
|
rotateCW: () => {
|
|
1377
1500
|
rotation = (rotation + 90) % 360;
|
|
1378
|
-
|
|
1501
|
+
renderPage(currentPage);
|
|
1379
1502
|
},
|
|
1380
1503
|
rotateCCW: () => {
|
|
1381
1504
|
rotation = (rotation - 90 + 360) % 360;
|
|
1382
|
-
|
|
1505
|
+
renderPage(currentPage);
|
|
1383
1506
|
},
|
|
1384
1507
|
getRotation: () => rotation,
|
|
1508
|
+
getPageCount: () => totalPages,
|
|
1509
|
+
getCurrentPage: () => currentPage,
|
|
1385
1510
|
goToPage: (page) => {
|
|
1386
|
-
|
|
1387
|
-
iframe.src = `${url}#page=${page}`;
|
|
1511
|
+
renderPage(page);
|
|
1388
1512
|
},
|
|
1389
|
-
getCurrentPage: () => currentPage,
|
|
1390
1513
|
download: () => {
|
|
1514
|
+
const blob = new Blob([ctx.buffer], { type: "application/pdf" });
|
|
1515
|
+
const url = URL.createObjectURL(blob);
|
|
1391
1516
|
const a = document.createElement("a");
|
|
1392
1517
|
a.href = url;
|
|
1393
1518
|
a.download = ctx.metadata.name || "document.pdf";
|
|
1394
1519
|
a.click();
|
|
1520
|
+
URL.revokeObjectURL(url);
|
|
1395
1521
|
},
|
|
1396
1522
|
print: () => {
|
|
1397
|
-
|
|
1523
|
+
const blob = new Blob([ctx.buffer], { type: "application/pdf" });
|
|
1524
|
+
const url = URL.createObjectURL(blob);
|
|
1525
|
+
const hiddenIframe = document.createElement("iframe");
|
|
1526
|
+
hiddenIframe.style.position = "fixed";
|
|
1527
|
+
hiddenIframe.style.right = "0";
|
|
1528
|
+
hiddenIframe.style.bottom = "0";
|
|
1529
|
+
hiddenIframe.style.width = "0";
|
|
1530
|
+
hiddenIframe.style.height = "0";
|
|
1531
|
+
hiddenIframe.style.border = "0";
|
|
1532
|
+
document.body.appendChild(hiddenIframe);
|
|
1533
|
+
hiddenIframe.src = url;
|
|
1534
|
+
hiddenIframe.onload = () => {
|
|
1535
|
+
setTimeout(() => {
|
|
1536
|
+
hiddenIframe.contentWindow?.print();
|
|
1537
|
+
setTimeout(() => {
|
|
1538
|
+
hiddenIframe.remove();
|
|
1539
|
+
URL.revokeObjectURL(url);
|
|
1540
|
+
}, 1e3);
|
|
1541
|
+
}, 300);
|
|
1542
|
+
};
|
|
1398
1543
|
},
|
|
1399
1544
|
getThumbnails: async () => {
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1545
|
+
const thumbnails = [];
|
|
1546
|
+
const count = Math.min(totalPages, 50);
|
|
1547
|
+
for (let i = 1; i <= count; i++) {
|
|
1548
|
+
thumbnails.push({
|
|
1549
|
+
index: i,
|
|
1550
|
+
label: `Page ${i}`,
|
|
1551
|
+
render: async (thumbCanvas) => {
|
|
1552
|
+
try {
|
|
1553
|
+
const p = await pdfDoc.getPage(i);
|
|
1554
|
+
const baseVp = p.getViewport({ scale: 1 });
|
|
1555
|
+
const thumbScale = (thumbCanvas.width || 120) / baseVp.width;
|
|
1556
|
+
const thumbVp = p.getViewport({ scale: thumbScale });
|
|
1557
|
+
thumbCanvas.height = Math.floor(thumbVp.height);
|
|
1558
|
+
const tCtx = thumbCanvas.getContext("2d");
|
|
1559
|
+
if (tCtx) {
|
|
1560
|
+
await p.render({ canvasContext: tCtx, viewport: thumbVp }).promise;
|
|
1561
|
+
}
|
|
1562
|
+
} catch (e) {
|
|
1563
|
+
console.warn(`[PdfPlugin] Error generating thumbnail for page ${i}:`, e);
|
|
1412
1564
|
}
|
|
1413
1565
|
}
|
|
1414
|
-
}
|
|
1415
|
-
|
|
1566
|
+
});
|
|
1567
|
+
}
|
|
1568
|
+
return thumbnails;
|
|
1416
1569
|
}
|
|
1417
1570
|
};
|
|
1571
|
+
return instance;
|
|
1418
1572
|
}
|
|
1419
1573
|
};
|
|
1420
1574
|
function pdfPlugin() {
|
|
@@ -1741,7 +1895,31 @@ var DocxPlugin = class {
|
|
|
1741
1895
|
return this.mimeTypes.includes(mime || "");
|
|
1742
1896
|
}
|
|
1743
1897
|
getToolbarActions(instance) {
|
|
1744
|
-
|
|
1898
|
+
const totalPages = instance.getPageCount?.() ?? 1;
|
|
1899
|
+
const actions = [];
|
|
1900
|
+
if (totalPages > 1) {
|
|
1901
|
+
actions.push({
|
|
1902
|
+
id: "page-nav",
|
|
1903
|
+
icon: "",
|
|
1904
|
+
label: "Page Navigation",
|
|
1905
|
+
type: "page-nav",
|
|
1906
|
+
group: "navigation",
|
|
1907
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
1908
|
+
max: totalPages,
|
|
1909
|
+
execute: (action, page) => {
|
|
1910
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
1911
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
1912
|
+
if (action === "prev") {
|
|
1913
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
1914
|
+
} else if (action === "next") {
|
|
1915
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
1916
|
+
} else if (typeof page === "number") {
|
|
1917
|
+
instance.goToPage?.(page);
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
});
|
|
1921
|
+
}
|
|
1922
|
+
actions.push(
|
|
1745
1923
|
{
|
|
1746
1924
|
id: "zoom-out",
|
|
1747
1925
|
icon: "zoom-out",
|
|
@@ -1782,7 +1960,8 @@ var DocxPlugin = class {
|
|
|
1782
1960
|
group: "actions",
|
|
1783
1961
|
execute: () => instance.print?.()
|
|
1784
1962
|
}
|
|
1785
|
-
|
|
1963
|
+
);
|
|
1964
|
+
return actions;
|
|
1786
1965
|
}
|
|
1787
1966
|
async render(ctx) {
|
|
1788
1967
|
const wrapper = document.createElement("div");
|
|
@@ -1858,7 +2037,51 @@ var DocxPlugin = class {
|
|
|
1858
2037
|
}
|
|
1859
2038
|
}
|
|
1860
2039
|
}
|
|
2040
|
+
const sections = wrapper.querySelectorAll("section.docx");
|
|
2041
|
+
const cards = wrapper.querySelectorAll(".fp-docx-page-card");
|
|
2042
|
+
const pageElements = sections.length > 0 ? sections : cards;
|
|
2043
|
+
const totalPages = Math.max(1, pageElements.length);
|
|
2044
|
+
let currentPage = 1;
|
|
2045
|
+
let indicator = null;
|
|
2046
|
+
if (totalPages > 1) {
|
|
2047
|
+
indicator = document.createElement("div");
|
|
2048
|
+
indicator.className = "fp-docx-page-indicator";
|
|
2049
|
+
indicator.style.position = "sticky";
|
|
2050
|
+
indicator.style.bottom = "16px";
|
|
2051
|
+
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
2052
|
+
indicator.style.backdropFilter = "blur(8px)";
|
|
2053
|
+
indicator.style.color = "#f8fafc";
|
|
2054
|
+
indicator.style.fontSize = "12px";
|
|
2055
|
+
indicator.style.fontWeight = "600";
|
|
2056
|
+
indicator.style.padding = "5px 14px";
|
|
2057
|
+
indicator.style.borderRadius = "20px";
|
|
2058
|
+
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
2059
|
+
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
2060
|
+
indicator.style.zIndex = "10";
|
|
2061
|
+
indicator.style.userSelect = "none";
|
|
2062
|
+
indicator.style.pointerEvents = "none";
|
|
2063
|
+
indicator.style.textAlign = "center";
|
|
2064
|
+
indicator.style.width = "fit-content";
|
|
2065
|
+
indicator.style.margin = "16px auto 0";
|
|
2066
|
+
ctx.container.appendChild(indicator);
|
|
2067
|
+
}
|
|
2068
|
+
const showPage = (pageNum) => {
|
|
2069
|
+
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
2070
|
+
if (pageElements.length > 1) {
|
|
2071
|
+
pageElements.forEach((sec, idx) => {
|
|
2072
|
+
sec.style.display = idx + 1 === currentPage ? "block" : "none";
|
|
2073
|
+
});
|
|
2074
|
+
}
|
|
2075
|
+
if (indicator) {
|
|
2076
|
+
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
2077
|
+
}
|
|
2078
|
+
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
2079
|
+
};
|
|
2080
|
+
if (totalPages > 1) {
|
|
2081
|
+
showPage(1);
|
|
2082
|
+
}
|
|
1861
2083
|
const cleanup = () => {
|
|
2084
|
+
indicator?.remove();
|
|
1862
2085
|
for (const url of createdBlobUrls) {
|
|
1863
2086
|
URL.revokeObjectURL(url);
|
|
1864
2087
|
}
|
|
@@ -1869,6 +2092,11 @@ var DocxPlugin = class {
|
|
|
1869
2092
|
ctx.signal.addEventListener("abort", cleanup);
|
|
1870
2093
|
return {
|
|
1871
2094
|
destroy: cleanup,
|
|
2095
|
+
getPageCount: () => totalPages,
|
|
2096
|
+
getCurrentPage: () => currentPage,
|
|
2097
|
+
goToPage: (page) => {
|
|
2098
|
+
showPage(page);
|
|
2099
|
+
},
|
|
1872
2100
|
zoomIn: () => {
|
|
1873
2101
|
scale += 0.1;
|
|
1874
2102
|
wrapper.style.transform = `scale(${scale})`;
|
|
@@ -2133,7 +2361,31 @@ var ExcelPlugin = class {
|
|
|
2133
2361
|
return this.mimeTypes.includes(mime || "");
|
|
2134
2362
|
}
|
|
2135
2363
|
getToolbarActions(instance) {
|
|
2136
|
-
|
|
2364
|
+
const totalSheets = instance.getPageCount?.() ?? 1;
|
|
2365
|
+
const actions = [];
|
|
2366
|
+
if (totalSheets > 1) {
|
|
2367
|
+
actions.push({
|
|
2368
|
+
id: "page-nav",
|
|
2369
|
+
icon: "",
|
|
2370
|
+
label: "Sheet Navigation",
|
|
2371
|
+
type: "page-nav",
|
|
2372
|
+
group: "navigation",
|
|
2373
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
2374
|
+
max: totalSheets,
|
|
2375
|
+
execute: (action, sheet) => {
|
|
2376
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2377
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
2378
|
+
if (action === "prev") {
|
|
2379
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
2380
|
+
} else if (action === "next") {
|
|
2381
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
2382
|
+
} else if (typeof sheet === "number") {
|
|
2383
|
+
instance.goToPage?.(sheet);
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
});
|
|
2387
|
+
}
|
|
2388
|
+
actions.push(
|
|
2137
2389
|
{
|
|
2138
2390
|
id: "zoom-out",
|
|
2139
2391
|
icon: "zoom-out",
|
|
@@ -2154,16 +2406,6 @@ var ExcelPlugin = class {
|
|
|
2154
2406
|
instance.zoomIn?.();
|
|
2155
2407
|
}
|
|
2156
2408
|
},
|
|
2157
|
-
{
|
|
2158
|
-
id: "page-nav",
|
|
2159
|
-
icon: "page-nav",
|
|
2160
|
-
label: "Sheet Navigation",
|
|
2161
|
-
type: "page-nav",
|
|
2162
|
-
group: "navigation",
|
|
2163
|
-
execute: (sheet) => {
|
|
2164
|
-
if (typeof sheet === "number") instance.goToPage?.(sheet);
|
|
2165
|
-
}
|
|
2166
|
-
},
|
|
2167
2409
|
{
|
|
2168
2410
|
id: "download",
|
|
2169
2411
|
icon: "download",
|
|
@@ -2184,7 +2426,8 @@ var ExcelPlugin = class {
|
|
|
2184
2426
|
instance.print?.();
|
|
2185
2427
|
}
|
|
2186
2428
|
}
|
|
2187
|
-
|
|
2429
|
+
);
|
|
2430
|
+
return actions;
|
|
2188
2431
|
}
|
|
2189
2432
|
async render(ctx) {
|
|
2190
2433
|
const container = document.createElement("div");
|
|
@@ -2268,6 +2511,7 @@ var ExcelPlugin = class {
|
|
|
2268
2511
|
b.style.fontWeight = "normal";
|
|
2269
2512
|
}
|
|
2270
2513
|
});
|
|
2514
|
+
ctx.emit("page-change", { page: currentSheetIndex, total: sheetNames.length });
|
|
2271
2515
|
};
|
|
2272
2516
|
if (sheetNames.length > 0) {
|
|
2273
2517
|
sheetNames.forEach((name, idx) => {
|
|
@@ -2517,7 +2761,31 @@ var CodePlugin = class {
|
|
|
2517
2761
|
return false;
|
|
2518
2762
|
}
|
|
2519
2763
|
getToolbarActions(instance) {
|
|
2520
|
-
|
|
2764
|
+
const totalPages = instance.getPageCount?.() ?? 1;
|
|
2765
|
+
const actions = [];
|
|
2766
|
+
if (totalPages > 1) {
|
|
2767
|
+
actions.push({
|
|
2768
|
+
id: "page-nav",
|
|
2769
|
+
icon: "",
|
|
2770
|
+
label: "Page Navigation",
|
|
2771
|
+
type: "page-nav",
|
|
2772
|
+
group: "navigation",
|
|
2773
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
2774
|
+
max: totalPages,
|
|
2775
|
+
execute: (action, page) => {
|
|
2776
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2777
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
2778
|
+
if (action === "prev") {
|
|
2779
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
2780
|
+
} else if (action === "next") {
|
|
2781
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
2782
|
+
} else if (typeof page === "number") {
|
|
2783
|
+
instance.goToPage?.(page);
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
});
|
|
2787
|
+
}
|
|
2788
|
+
actions.push(
|
|
2521
2789
|
{
|
|
2522
2790
|
id: "zoom-out",
|
|
2523
2791
|
icon: "zoom-out",
|
|
@@ -2568,11 +2836,16 @@ var CodePlugin = class {
|
|
|
2568
2836
|
instance.print?.();
|
|
2569
2837
|
}
|
|
2570
2838
|
}
|
|
2571
|
-
|
|
2839
|
+
);
|
|
2840
|
+
return actions;
|
|
2572
2841
|
}
|
|
2573
2842
|
async render(ctx) {
|
|
2574
2843
|
const decoder = new TextDecoder("utf-8");
|
|
2575
|
-
const
|
|
2844
|
+
const fullText = decoder.decode(ctx.buffer);
|
|
2845
|
+
const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
|
|
2846
|
+
const rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
2847
|
+
const totalPages = Math.max(1, rawPages.length);
|
|
2848
|
+
let currentPage = 1;
|
|
2576
2849
|
const container = document.createElement("div");
|
|
2577
2850
|
container.style.width = "100%";
|
|
2578
2851
|
container.style.height = "100%";
|
|
@@ -2591,25 +2864,66 @@ var CodePlugin = class {
|
|
|
2591
2864
|
pre.style.wordBreak = "break-all";
|
|
2592
2865
|
const code = document.createElement("code");
|
|
2593
2866
|
const ext = (ctx.metadata.extension || "").replace(".", "");
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2867
|
+
const renderCodePage = (text) => {
|
|
2868
|
+
try {
|
|
2869
|
+
if (ext && hljs__default.default.getLanguage(ext)) {
|
|
2870
|
+
code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
|
|
2871
|
+
} else {
|
|
2872
|
+
code.innerHTML = hljs__default.default.highlightAuto(text).value;
|
|
2873
|
+
}
|
|
2874
|
+
} catch {
|
|
2875
|
+
code.textContent = text;
|
|
2599
2876
|
}
|
|
2600
|
-
}
|
|
2601
|
-
|
|
2602
|
-
}
|
|
2877
|
+
};
|
|
2878
|
+
renderCodePage(rawPages[0] || fullText);
|
|
2603
2879
|
pre.appendChild(code);
|
|
2604
2880
|
container.appendChild(pre);
|
|
2881
|
+
let indicator = null;
|
|
2882
|
+
if (totalPages > 1) {
|
|
2883
|
+
indicator = document.createElement("div");
|
|
2884
|
+
indicator.className = "fp-code-page-indicator";
|
|
2885
|
+
indicator.style.position = "sticky";
|
|
2886
|
+
indicator.style.bottom = "16px";
|
|
2887
|
+
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
2888
|
+
indicator.style.backdropFilter = "blur(8px)";
|
|
2889
|
+
indicator.style.color = "#f8fafc";
|
|
2890
|
+
indicator.style.fontSize = "12px";
|
|
2891
|
+
indicator.style.fontWeight = "600";
|
|
2892
|
+
indicator.style.padding = "5px 14px";
|
|
2893
|
+
indicator.style.borderRadius = "20px";
|
|
2894
|
+
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
2895
|
+
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
2896
|
+
indicator.style.zIndex = "10";
|
|
2897
|
+
indicator.style.userSelect = "none";
|
|
2898
|
+
indicator.style.pointerEvents = "none";
|
|
2899
|
+
indicator.style.textAlign = "center";
|
|
2900
|
+
indicator.style.width = "fit-content";
|
|
2901
|
+
indicator.style.margin = "16px auto 0";
|
|
2902
|
+
container.appendChild(indicator);
|
|
2903
|
+
}
|
|
2904
|
+
const showPage = (pageNum) => {
|
|
2905
|
+
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
2906
|
+
renderCodePage(rawPages[currentPage - 1] || fullText);
|
|
2907
|
+
if (indicator) {
|
|
2908
|
+
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
2909
|
+
}
|
|
2910
|
+
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
2911
|
+
};
|
|
2912
|
+
if (totalPages > 1) {
|
|
2913
|
+
showPage(1);
|
|
2914
|
+
}
|
|
2605
2915
|
ctx.container.appendChild(container);
|
|
2606
2916
|
const cleanup = () => {
|
|
2917
|
+
indicator?.remove();
|
|
2607
2918
|
container.remove();
|
|
2608
2919
|
ctx.container.innerHTML = "";
|
|
2609
2920
|
};
|
|
2610
2921
|
ctx.signal.addEventListener("abort", cleanup);
|
|
2611
2922
|
return {
|
|
2612
2923
|
destroy: cleanup,
|
|
2924
|
+
getPageCount: () => totalPages,
|
|
2925
|
+
getCurrentPage: () => currentPage,
|
|
2926
|
+
goToPage: (page) => showPage(page),
|
|
2613
2927
|
zoomIn: () => {
|
|
2614
2928
|
fontSize = Math.min(32, fontSize + 2);
|
|
2615
2929
|
pre.style.fontSize = `${fontSize}px`;
|
|
@@ -2637,7 +2951,7 @@ var CodePlugin = class {
|
|
|
2637
2951
|
window.print();
|
|
2638
2952
|
},
|
|
2639
2953
|
copy: () => {
|
|
2640
|
-
navigator.clipboard?.writeText(
|
|
2954
|
+
navigator.clipboard?.writeText(fullText);
|
|
2641
2955
|
}
|
|
2642
2956
|
};
|
|
2643
2957
|
}
|
|
@@ -3459,7 +3773,31 @@ var RtfPlugin = class {
|
|
|
3459
3773
|
return this.extensions.includes(ext || "") || this.mimeTypes.includes(mime || "");
|
|
3460
3774
|
}
|
|
3461
3775
|
getToolbarActions(instance) {
|
|
3462
|
-
|
|
3776
|
+
const totalPages = instance.getPageCount?.() ?? 1;
|
|
3777
|
+
const actions = [];
|
|
3778
|
+
if (totalPages > 1) {
|
|
3779
|
+
actions.push({
|
|
3780
|
+
id: "page-nav",
|
|
3781
|
+
icon: "",
|
|
3782
|
+
label: "Page Navigation",
|
|
3783
|
+
type: "page-nav",
|
|
3784
|
+
group: "navigation",
|
|
3785
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
3786
|
+
max: totalPages,
|
|
3787
|
+
execute: (action, page) => {
|
|
3788
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3789
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
3790
|
+
if (action === "prev") {
|
|
3791
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3792
|
+
} else if (action === "next") {
|
|
3793
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
3794
|
+
} else if (typeof page === "number") {
|
|
3795
|
+
instance.goToPage?.(page);
|
|
3796
|
+
}
|
|
3797
|
+
}
|
|
3798
|
+
});
|
|
3799
|
+
}
|
|
3800
|
+
actions.push(
|
|
3463
3801
|
{
|
|
3464
3802
|
id: "zoom-out",
|
|
3465
3803
|
icon: "zoom-out",
|
|
@@ -3500,7 +3838,8 @@ var RtfPlugin = class {
|
|
|
3500
3838
|
group: "actions",
|
|
3501
3839
|
execute: () => instance.print?.()
|
|
3502
3840
|
}
|
|
3503
|
-
|
|
3841
|
+
);
|
|
3842
|
+
return actions;
|
|
3504
3843
|
}
|
|
3505
3844
|
async render(ctx) {
|
|
3506
3845
|
const wrapper = document.createElement("div");
|
|
@@ -3519,28 +3858,82 @@ var RtfPlugin = class {
|
|
|
3519
3858
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
3520
3859
|
ctx.container.appendChild(wrapper);
|
|
3521
3860
|
let scale = 1;
|
|
3861
|
+
let pageElements = [];
|
|
3522
3862
|
try {
|
|
3523
3863
|
if (typeof RTFJS__namespace.loggingEnabled === "function") {
|
|
3524
3864
|
RTFJS__namespace.loggingEnabled(false);
|
|
3525
3865
|
}
|
|
3526
3866
|
const doc = new RTFJS__namespace.Document(ctx.buffer, {});
|
|
3527
3867
|
const htmlElements = await doc.render();
|
|
3528
|
-
|
|
3868
|
+
pageElements = htmlElements;
|
|
3869
|
+
for (let i = 0; i < htmlElements.length; i++) {
|
|
3870
|
+
const el = htmlElements[i];
|
|
3871
|
+
el.style.display = i === 0 ? "block" : "none";
|
|
3529
3872
|
wrapper.appendChild(el);
|
|
3530
3873
|
}
|
|
3531
3874
|
} catch (err) {
|
|
3532
3875
|
console.warn("[RtfPlugin] RTF render error, fallback text:", err);
|
|
3533
3876
|
const text = new TextDecoder("latin1").decode(ctx.buffer);
|
|
3534
3877
|
const clean = text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "");
|
|
3535
|
-
|
|
3878
|
+
const pre = document.createElement("pre");
|
|
3879
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3880
|
+
pre.style.fontFamily = "serif";
|
|
3881
|
+
pre.style.color = "#333";
|
|
3882
|
+
pre.textContent = clean;
|
|
3883
|
+
wrapper.appendChild(pre);
|
|
3884
|
+
pageElements = [pre];
|
|
3885
|
+
}
|
|
3886
|
+
const totalPages = Math.max(1, pageElements.length);
|
|
3887
|
+
let currentPage = 1;
|
|
3888
|
+
let indicator = null;
|
|
3889
|
+
if (totalPages > 1) {
|
|
3890
|
+
indicator = document.createElement("div");
|
|
3891
|
+
indicator.className = "fp-rtf-page-indicator";
|
|
3892
|
+
indicator.style.position = "sticky";
|
|
3893
|
+
indicator.style.bottom = "16px";
|
|
3894
|
+
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3895
|
+
indicator.style.backdropFilter = "blur(8px)";
|
|
3896
|
+
indicator.style.color = "#f8fafc";
|
|
3897
|
+
indicator.style.fontSize = "12px";
|
|
3898
|
+
indicator.style.fontWeight = "600";
|
|
3899
|
+
indicator.style.padding = "5px 14px";
|
|
3900
|
+
indicator.style.borderRadius = "20px";
|
|
3901
|
+
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3902
|
+
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3903
|
+
indicator.style.zIndex = "10";
|
|
3904
|
+
indicator.style.userSelect = "none";
|
|
3905
|
+
indicator.style.pointerEvents = "none";
|
|
3906
|
+
indicator.style.textAlign = "center";
|
|
3907
|
+
indicator.style.width = "fit-content";
|
|
3908
|
+
indicator.style.margin = "16px auto 0";
|
|
3909
|
+
ctx.container.appendChild(indicator);
|
|
3910
|
+
}
|
|
3911
|
+
const showPage = (pageNum) => {
|
|
3912
|
+
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3913
|
+
if (totalPages > 1) {
|
|
3914
|
+
pageElements.forEach((el, idx) => {
|
|
3915
|
+
el.style.display = idx + 1 === currentPage ? "block" : "none";
|
|
3916
|
+
});
|
|
3917
|
+
}
|
|
3918
|
+
if (indicator) {
|
|
3919
|
+
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
3920
|
+
}
|
|
3921
|
+
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
3922
|
+
};
|
|
3923
|
+
if (totalPages > 1) {
|
|
3924
|
+
showPage(1);
|
|
3536
3925
|
}
|
|
3537
3926
|
const cleanup = () => {
|
|
3927
|
+
indicator?.remove();
|
|
3538
3928
|
wrapper.remove();
|
|
3539
3929
|
ctx.container.innerHTML = "";
|
|
3540
3930
|
};
|
|
3541
3931
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3542
3932
|
return {
|
|
3543
3933
|
destroy: cleanup,
|
|
3934
|
+
getPageCount: () => totalPages,
|
|
3935
|
+
getCurrentPage: () => currentPage,
|
|
3936
|
+
goToPage: (page) => showPage(page),
|
|
3544
3937
|
zoomIn: () => {
|
|
3545
3938
|
scale += 0.1;
|
|
3546
3939
|
wrapper.style.transform = `scale(${scale})`;
|
|
@@ -3728,41 +4121,41 @@ var OpenDocumentPlugin = class {
|
|
|
3728
4121
|
}
|
|
3729
4122
|
getToolbarActions(instance) {
|
|
3730
4123
|
const isPresentation = instance.isPresentation;
|
|
4124
|
+
const totalPages = instance.getPageCount?.() ?? 1;
|
|
3731
4125
|
const actions = [];
|
|
3732
|
-
if (isPresentation) {
|
|
3733
|
-
|
|
3734
|
-
{
|
|
4126
|
+
if (isPresentation || totalPages > 1) {
|
|
4127
|
+
if (isPresentation) {
|
|
4128
|
+
actions.push({
|
|
3735
4129
|
id: "thumbnails",
|
|
3736
4130
|
icon: "thumbnails",
|
|
3737
4131
|
label: "Slide Thumbnails",
|
|
3738
4132
|
type: "button",
|
|
3739
4133
|
group: "navigation",
|
|
3740
4134
|
execute: () => instance.toggleThumbnails?.()
|
|
3741
|
-
}
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
}
|
|
4135
|
+
});
|
|
4136
|
+
}
|
|
4137
|
+
actions.push({
|
|
4138
|
+
id: "page-nav",
|
|
4139
|
+
icon: "",
|
|
4140
|
+
label: isPresentation ? "Slide Navigation" : "Page Navigation",
|
|
4141
|
+
type: "page-nav",
|
|
4142
|
+
group: "navigation",
|
|
4143
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
4144
|
+
max: totalPages,
|
|
4145
|
+
execute: (action, page) => {
|
|
4146
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4147
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
4148
|
+
if (action === "prev") {
|
|
4149
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
4150
|
+
} else if (action === "next") {
|
|
4151
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
4152
|
+
} else if (typeof page === "number") {
|
|
4153
|
+
instance.goToPage?.(page);
|
|
4154
|
+
} else if (typeof action === "number") {
|
|
4155
|
+
instance.goToPage?.(action);
|
|
3763
4156
|
}
|
|
3764
4157
|
}
|
|
3765
|
-
);
|
|
4158
|
+
});
|
|
3766
4159
|
}
|
|
3767
4160
|
actions.push(
|
|
3768
4161
|
{
|
|
@@ -4145,7 +4538,31 @@ var DocPlugin = class {
|
|
|
4145
4538
|
return this.mimeTypes.includes(mime || "");
|
|
4146
4539
|
}
|
|
4147
4540
|
getToolbarActions(instance) {
|
|
4148
|
-
|
|
4541
|
+
const totalPages = instance.getPageCount?.() ?? 1;
|
|
4542
|
+
const actions = [];
|
|
4543
|
+
if (totalPages > 1) {
|
|
4544
|
+
actions.push({
|
|
4545
|
+
id: "page-nav",
|
|
4546
|
+
icon: "",
|
|
4547
|
+
label: "Page Navigation",
|
|
4548
|
+
type: "page-nav",
|
|
4549
|
+
group: "navigation",
|
|
4550
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
4551
|
+
max: totalPages,
|
|
4552
|
+
execute: (action, page) => {
|
|
4553
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4554
|
+
const max = instance.getPageCount?.() ?? 1;
|
|
4555
|
+
if (action === "prev") {
|
|
4556
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
4557
|
+
} else if (action === "next") {
|
|
4558
|
+
if (cur < max) instance.goToPage?.(cur + 1);
|
|
4559
|
+
} else if (typeof page === "number") {
|
|
4560
|
+
instance.goToPage?.(page);
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4563
|
+
});
|
|
4564
|
+
}
|
|
4565
|
+
actions.push(
|
|
4149
4566
|
{
|
|
4150
4567
|
id: "zoom-out",
|
|
4151
4568
|
icon: "zoom-out",
|
|
@@ -4194,7 +4611,8 @@ var DocPlugin = class {
|
|
|
4194
4611
|
group: "actions",
|
|
4195
4612
|
execute: () => instance.print?.()
|
|
4196
4613
|
}
|
|
4197
|
-
|
|
4614
|
+
);
|
|
4615
|
+
return actions;
|
|
4198
4616
|
}
|
|
4199
4617
|
async render(ctx) {
|
|
4200
4618
|
const container = document.createElement("div");
|
|
@@ -4221,6 +4639,7 @@ var DocPlugin = class {
|
|
|
4221
4639
|
ctx.container.appendChild(container);
|
|
4222
4640
|
let scale = 1;
|
|
4223
4641
|
let extractedRawText = "";
|
|
4642
|
+
let isFallback = false;
|
|
4224
4643
|
try {
|
|
4225
4644
|
const cfbf = new CfbfReader(ctx.buffer);
|
|
4226
4645
|
const wordDocStream = cfbf.readStream("WordDocument");
|
|
@@ -4234,26 +4653,89 @@ var DocPlugin = class {
|
|
|
4234
4653
|
const tableStream = cfbf.readStream(tableName);
|
|
4235
4654
|
const text = this.extractDocText(wordDocStream, tableStream);
|
|
4236
4655
|
extractedRawText = text;
|
|
4237
|
-
wrapper.innerHTML = this.formatDocToHtml(text, ctx.metadata.name || "Document");
|
|
4238
4656
|
} catch (err) {
|
|
4239
4657
|
console.warn("[DocPlugin] Binary parsing error, fallback text:", err);
|
|
4240
4658
|
const fallback = this.heuristicTextExtraction(ctx.buffer);
|
|
4241
4659
|
extractedRawText = fallback;
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4660
|
+
isFallback = true;
|
|
4661
|
+
}
|
|
4662
|
+
const rawPages = this.splitIntoPages(extractedRawText);
|
|
4663
|
+
const totalPages = Math.max(1, rawPages.length);
|
|
4664
|
+
let currentPage = 1;
|
|
4665
|
+
wrapper.innerHTML = "";
|
|
4666
|
+
const pageCards = [];
|
|
4667
|
+
for (let i = 0; i < totalPages; i++) {
|
|
4668
|
+
const pageCard = document.createElement("div");
|
|
4669
|
+
pageCard.className = "fp-doc-page-card";
|
|
4670
|
+
pageCard.style.backgroundColor = "#ffffff";
|
|
4671
|
+
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4672
|
+
pageCard.style.borderRadius = "4px";
|
|
4673
|
+
pageCard.style.padding = "56px 48px";
|
|
4674
|
+
pageCard.style.minHeight = "100%";
|
|
4675
|
+
pageCard.style.display = i === 0 ? "block" : "none";
|
|
4676
|
+
if (isFallback && i === 0) {
|
|
4677
|
+
pageCard.innerHTML = `
|
|
4678
|
+
<div style="border-bottom: 1px solid #e2e8f0; padding-bottom: 12px; margin-bottom: 24px;">
|
|
4679
|
+
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify2__default.default.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
|
|
4680
|
+
<span style="font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 4px;">Legacy Word 97-2003 Binary Preview</span>
|
|
4681
|
+
</div>
|
|
4682
|
+
${this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document")}
|
|
4683
|
+
`;
|
|
4684
|
+
} else {
|
|
4685
|
+
pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
|
|
4686
|
+
}
|
|
4687
|
+
wrapper.appendChild(pageCard);
|
|
4688
|
+
pageCards.push(pageCard);
|
|
4689
|
+
}
|
|
4690
|
+
let indicator = null;
|
|
4691
|
+
if (totalPages > 1) {
|
|
4692
|
+
indicator = document.createElement("div");
|
|
4693
|
+
indicator.className = "fp-doc-page-indicator";
|
|
4694
|
+
indicator.style.position = "sticky";
|
|
4695
|
+
indicator.style.bottom = "16px";
|
|
4696
|
+
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4697
|
+
indicator.style.backdropFilter = "blur(8px)";
|
|
4698
|
+
indicator.style.color = "#f8fafc";
|
|
4699
|
+
indicator.style.fontSize = "12px";
|
|
4700
|
+
indicator.style.fontWeight = "600";
|
|
4701
|
+
indicator.style.padding = "5px 14px";
|
|
4702
|
+
indicator.style.borderRadius = "20px";
|
|
4703
|
+
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
4704
|
+
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
4705
|
+
indicator.style.zIndex = "10";
|
|
4706
|
+
indicator.style.userSelect = "none";
|
|
4707
|
+
indicator.style.pointerEvents = "none";
|
|
4708
|
+
indicator.style.textAlign = "center";
|
|
4709
|
+
indicator.style.width = "fit-content";
|
|
4710
|
+
indicator.style.margin = "16px auto 0";
|
|
4711
|
+
container.appendChild(indicator);
|
|
4712
|
+
}
|
|
4713
|
+
const showPage = (pageNum) => {
|
|
4714
|
+
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
4715
|
+
if (totalPages > 1) {
|
|
4716
|
+
pageCards.forEach((card, idx) => {
|
|
4717
|
+
card.style.display = idx + 1 === currentPage ? "block" : "none";
|
|
4718
|
+
});
|
|
4719
|
+
}
|
|
4720
|
+
if (indicator) {
|
|
4721
|
+
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4722
|
+
}
|
|
4723
|
+
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4724
|
+
};
|
|
4725
|
+
if (totalPages > 1) {
|
|
4726
|
+
showPage(1);
|
|
4249
4727
|
}
|
|
4250
4728
|
const cleanup = () => {
|
|
4729
|
+
indicator?.remove();
|
|
4251
4730
|
container.remove();
|
|
4252
4731
|
ctx.container.innerHTML = "";
|
|
4253
4732
|
};
|
|
4254
4733
|
ctx.signal.addEventListener("abort", cleanup);
|
|
4255
4734
|
return {
|
|
4256
4735
|
destroy: cleanup,
|
|
4736
|
+
getPageCount: () => totalPages,
|
|
4737
|
+
getCurrentPage: () => currentPage,
|
|
4738
|
+
goToPage: (page) => showPage(page),
|
|
4257
4739
|
zoomIn: () => {
|
|
4258
4740
|
scale += 0.1;
|
|
4259
4741
|
wrapper.style.transform = `scale(${scale})`;
|
|
@@ -4385,11 +4867,16 @@ var DocPlugin = class {
|
|
|
4385
4867
|
heuristicTextExtraction(buffer) {
|
|
4386
4868
|
return this.extractStringsFromBytes(new Uint8Array(buffer));
|
|
4387
4869
|
}
|
|
4870
|
+
splitIntoPages(text) {
|
|
4871
|
+
if (!text) return [""];
|
|
4872
|
+
const parts = text.split(/[\x0C\f]|\r?\n\s*[-=_]{3,}\s*(?:PAGE|Page|page break)[\s\d\w-]*[-=_]{3,}\s*\r?\n/i).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
4873
|
+
return parts.length > 0 ? parts : [text];
|
|
4874
|
+
}
|
|
4388
4875
|
/**
|
|
4389
4876
|
* Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
|
|
4390
4877
|
*/
|
|
4391
4878
|
formatDocToHtml(text, filename) {
|
|
4392
|
-
const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").
|
|
4879
|
+
const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
|
|
4393
4880
|
let html = "";
|
|
4394
4881
|
let inList = false;
|
|
4395
4882
|
for (const rawLine of lines) {
|