@files-preview-app/preview-file 1.2.8 → 1.3.0
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 +563 -111
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.js +562 -111
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +606 -111
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +604 -112
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +563 -111
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +562 -111
- package/dist/react.js.map +1 -1
- package/dist/vue.cjs +563 -111
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +562 -111
- package/dist/vue.js.map +1 -1
- package/package.json +169 -179
package/dist/index.cjs
CHANGED
|
@@ -14,6 +14,7 @@ var OBJLoader_js = require('three/examples/jsm/loaders/OBJLoader.js');
|
|
|
14
14
|
var OrbitControls_js = require('three/examples/jsm/controls/OrbitControls.js');
|
|
15
15
|
var RTFJS = require('rtf.js/dist/RTFJS.bundle.js');
|
|
16
16
|
|
|
17
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
17
18
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
18
19
|
|
|
19
20
|
function _interopNamespace(e) {
|
|
@@ -366,16 +367,21 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
366
367
|
metadata.mimeType = source.type || void 0;
|
|
367
368
|
metadata.extension = extractExtension(source.name);
|
|
368
369
|
buffer = await source.arrayBuffer();
|
|
369
|
-
} else if (source instanceof Blob) {
|
|
370
|
+
} else if (source instanceof Blob || source && typeof source.arrayBuffer === "function" && typeof source.size === "number") {
|
|
370
371
|
metadata.size = source.size;
|
|
371
372
|
metadata.mimeType = source.type || void 0;
|
|
373
|
+
if (source.name) {
|
|
374
|
+
metadata.name = source.name;
|
|
375
|
+
metadata.extension = extractExtension(source.name);
|
|
376
|
+
}
|
|
372
377
|
buffer = await source.arrayBuffer();
|
|
373
|
-
} else if (source instanceof ArrayBuffer) {
|
|
378
|
+
} else if (source instanceof ArrayBuffer || Object.prototype.toString.call(source) === "[object ArrayBuffer]" || source && typeof source.byteLength === "number" && typeof source.slice === "function") {
|
|
374
379
|
buffer = source;
|
|
375
|
-
} else if (source instanceof Uint8Array) {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
380
|
+
} else if (source instanceof Uint8Array || ArrayBuffer.isView(source)) {
|
|
381
|
+
const view = source;
|
|
382
|
+
buffer = view.buffer.slice(
|
|
383
|
+
view.byteOffset,
|
|
384
|
+
view.byteOffset + view.byteLength
|
|
379
385
|
);
|
|
380
386
|
} else {
|
|
381
387
|
throw new Error("Unsupported file source type");
|
|
@@ -504,6 +510,86 @@ function createElement(tag, attrs, ...children) {
|
|
|
504
510
|
}
|
|
505
511
|
return el;
|
|
506
512
|
}
|
|
513
|
+
var DB_NAME = "PreviewFileTransferDB";
|
|
514
|
+
var DB_STORE = "transfers";
|
|
515
|
+
function openDB() {
|
|
516
|
+
return new Promise((resolve, reject) => {
|
|
517
|
+
if (typeof indexedDB === "undefined") {
|
|
518
|
+
return reject(new Error("IndexedDB is not available"));
|
|
519
|
+
}
|
|
520
|
+
const req = indexedDB.open(DB_NAME, 1);
|
|
521
|
+
req.onupgradeneeded = () => {
|
|
522
|
+
const db = req.result;
|
|
523
|
+
if (!db.objectStoreNames.contains(DB_STORE)) {
|
|
524
|
+
db.createObjectStore(DB_STORE, { keyPath: "id" });
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
req.onsuccess = () => resolve(req.result);
|
|
528
|
+
req.onerror = () => reject(req.error);
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
async function saveTransferPayload(id, payload) {
|
|
532
|
+
if (typeof window !== "undefined") {
|
|
533
|
+
try {
|
|
534
|
+
window[id] = payload;
|
|
535
|
+
window.__lastTransfer = payload;
|
|
536
|
+
} catch {
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
try {
|
|
540
|
+
const db = await openDB();
|
|
541
|
+
return new Promise((resolve, reject) => {
|
|
542
|
+
const tx = db.transaction(DB_STORE, "readwrite");
|
|
543
|
+
const store = tx.objectStore(DB_STORE);
|
|
544
|
+
store.put({ id, ...payload, timestamp: Date.now() });
|
|
545
|
+
tx.oncomplete = () => resolve();
|
|
546
|
+
tx.onerror = () => reject(tx.error);
|
|
547
|
+
});
|
|
548
|
+
} catch (e) {
|
|
549
|
+
console.warn("[saveTransferPayload] IndexedDB store warning:", e);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
async function getTransferPayload(id) {
|
|
553
|
+
if (typeof window !== "undefined") {
|
|
554
|
+
try {
|
|
555
|
+
if (window.opener && window.opener[id]) {
|
|
556
|
+
return window.opener[id];
|
|
557
|
+
}
|
|
558
|
+
if (window[id]) {
|
|
559
|
+
return window[id];
|
|
560
|
+
}
|
|
561
|
+
if (window.opener && window.opener.__lastTransfer) {
|
|
562
|
+
return window.opener.__lastTransfer;
|
|
563
|
+
}
|
|
564
|
+
if (window.__lastTransfer) {
|
|
565
|
+
return window.__lastTransfer;
|
|
566
|
+
}
|
|
567
|
+
} catch {
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
try {
|
|
571
|
+
const db = await openDB();
|
|
572
|
+
return new Promise((resolve) => {
|
|
573
|
+
const tx = db.transaction(DB_STORE, "readonly");
|
|
574
|
+
const store = tx.objectStore(DB_STORE);
|
|
575
|
+
const req = store.get(id);
|
|
576
|
+
req.onsuccess = () => {
|
|
577
|
+
if (req.result && req.result.buffer) {
|
|
578
|
+
resolve({
|
|
579
|
+
buffer: req.result.buffer,
|
|
580
|
+
metadata: req.result.metadata,
|
|
581
|
+
options: req.result.options
|
|
582
|
+
});
|
|
583
|
+
} else {
|
|
584
|
+
resolve(null);
|
|
585
|
+
}
|
|
586
|
+
};
|
|
587
|
+
req.onerror = () => resolve(null);
|
|
588
|
+
});
|
|
589
|
+
} catch {
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
507
593
|
var ICON_ZOOM_IN = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><line x1="11" y1="8" x2="11" y2="14"></line><line x1="8" y1="11" x2="14" y2="11"></line></svg>`;
|
|
508
594
|
var ICON_ZOOM_OUT = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><line x1="8" y1="11" x2="14" y2="11"></line></svg>`;
|
|
509
595
|
var ICON_FIT_PAGE = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"></rect><line x1="8" y1="12" x2="16" y2="12"></line><polyline points="11 9 8 12 11 15"></polyline><polyline points="13 9 16 12 13 15"></polyline></svg>`;
|
|
@@ -523,6 +609,7 @@ var ICON_COPY = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" str
|
|
|
523
609
|
var ICON_FAST_FORWARD = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 19 22 12 13 5 13 19"></polygon><polygon points="2 19 11 12 2 5 2 19"></polygon></svg>`;
|
|
524
610
|
var ICON_REWIND = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 19 2 12 11 5 11 19"></polygon><polygon points="22 19 13 12 22 5 22 19"></polygon></svg>`;
|
|
525
611
|
var ICON_SPEED = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>`;
|
|
612
|
+
var ICON_EXTERNAL_WINDOW = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>`;
|
|
526
613
|
var ICON_MAP = {
|
|
527
614
|
"zoom-in": ICON_ZOOM_IN,
|
|
528
615
|
"zoom-out": ICON_ZOOM_OUT,
|
|
@@ -549,7 +636,9 @@ var ICON_MAP = {
|
|
|
549
636
|
"forward-10": ICON_FAST_FORWARD,
|
|
550
637
|
"rewind": ICON_REWIND,
|
|
551
638
|
"replay-10": ICON_REWIND,
|
|
552
|
-
"speed": ICON_SPEED
|
|
639
|
+
"speed": ICON_SPEED,
|
|
640
|
+
"open-window": ICON_EXTERNAL_WINDOW,
|
|
641
|
+
"external-window": ICON_EXTERNAL_WINDOW
|
|
553
642
|
};
|
|
554
643
|
var ToolbarController = class {
|
|
555
644
|
el;
|
|
@@ -766,7 +855,7 @@ var ThumbnailPanel = class {
|
|
|
766
855
|
}
|
|
767
856
|
}
|
|
768
857
|
};
|
|
769
|
-
var FilePreviewViewer = class {
|
|
858
|
+
var FilePreviewViewer = class _FilePreviewViewer {
|
|
770
859
|
plugins = [];
|
|
771
860
|
activeInstance = null;
|
|
772
861
|
abortController = null;
|
|
@@ -803,6 +892,7 @@ var FilePreviewViewer = class {
|
|
|
803
892
|
* Preview a file in the given container element.
|
|
804
893
|
*/
|
|
805
894
|
async preview(container, source, options = {}) {
|
|
895
|
+
this.currentOptions = options;
|
|
806
896
|
this.abort();
|
|
807
897
|
this.abortController = new AbortController();
|
|
808
898
|
const { signal } = this.abortController;
|
|
@@ -812,7 +902,10 @@ var FilePreviewViewer = class {
|
|
|
812
902
|
this.showLoading();
|
|
813
903
|
try {
|
|
814
904
|
const { buffer, metadata } = await sourceToArrayBuffer(source, signal);
|
|
815
|
-
|
|
905
|
+
if (options.metadata) {
|
|
906
|
+
Object.assign(metadata, options.metadata);
|
|
907
|
+
}
|
|
908
|
+
this.currentBuffer = buffer.slice(0);
|
|
816
909
|
this.currentMetadata = metadata;
|
|
817
910
|
if (signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
818
911
|
const fileInfo = { metadata, buffer };
|
|
@@ -842,6 +935,7 @@ var FilePreviewViewer = class {
|
|
|
842
935
|
}
|
|
843
936
|
});
|
|
844
937
|
this.activeInstance = instance;
|
|
938
|
+
instance.openInSeparateWindow = () => this.openInSeparateWindow();
|
|
845
939
|
this.hideLoading();
|
|
846
940
|
this.eventEmitter.emit("loaded", { metadata, plugin: matchedPlugin.id });
|
|
847
941
|
if (options.showToolbar !== false && this.toolbar) {
|
|
@@ -851,26 +945,16 @@ var FilePreviewViewer = class {
|
|
|
851
945
|
actions.push({
|
|
852
946
|
id: "fullscreen",
|
|
853
947
|
icon: "fullscreen",
|
|
854
|
-
label: "
|
|
948
|
+
label: "Fullscreen",
|
|
855
949
|
type: "button",
|
|
856
950
|
group: "view",
|
|
857
|
-
execute:
|
|
951
|
+
execute: () => {
|
|
858
952
|
try {
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
if (this.wrapperEl?.requestFullscreen) {
|
|
863
|
-
await this.wrapperEl.requestFullscreen().catch(() => {
|
|
864
|
-
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
865
|
-
});
|
|
866
|
-
} else {
|
|
867
|
-
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
868
|
-
}
|
|
953
|
+
if (!document.fullscreenElement) {
|
|
954
|
+
this.wrapperEl?.requestFullscreen?.();
|
|
955
|
+
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
869
956
|
} else {
|
|
870
|
-
|
|
871
|
-
await document.exitFullscreen().catch(() => {
|
|
872
|
-
});
|
|
873
|
-
}
|
|
957
|
+
document.exitFullscreen?.();
|
|
874
958
|
this.wrapperEl?.classList.remove("fp-fullscreen-active");
|
|
875
959
|
}
|
|
876
960
|
} catch {
|
|
@@ -882,6 +966,28 @@ var FilePreviewViewer = class {
|
|
|
882
966
|
}
|
|
883
967
|
});
|
|
884
968
|
}
|
|
969
|
+
const openWinAction = actions.find((a) => a.id === "open-window");
|
|
970
|
+
if (openWinAction) {
|
|
971
|
+
if (options?._isSeparateWindow) {
|
|
972
|
+
const idx = actions.indexOf(openWinAction);
|
|
973
|
+
if (idx !== -1) actions.splice(idx, 1);
|
|
974
|
+
} else {
|
|
975
|
+
openWinAction.execute = () => {
|
|
976
|
+
this.openInSeparateWindow();
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
} else if (!options?._isSeparateWindow) {
|
|
980
|
+
actions.push({
|
|
981
|
+
id: "open-window",
|
|
982
|
+
icon: "open-window",
|
|
983
|
+
label: "Open in Separate Full Window",
|
|
984
|
+
type: "button",
|
|
985
|
+
group: "actions",
|
|
986
|
+
execute: () => {
|
|
987
|
+
this.openInSeparateWindow();
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
|
+
}
|
|
885
991
|
this.toolbar.update(actions);
|
|
886
992
|
this.toolbar.show();
|
|
887
993
|
}
|
|
@@ -914,6 +1020,104 @@ var FilePreviewViewer = class {
|
|
|
914
1020
|
throw error;
|
|
915
1021
|
}
|
|
916
1022
|
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Opens the current file preview in a separate full browser window.
|
|
1025
|
+
*/
|
|
1026
|
+
openInSeparateWindow() {
|
|
1027
|
+
if (!this.currentBuffer) {
|
|
1028
|
+
console.warn("[FilePreviewViewer] No active file buffer to open in separate window");
|
|
1029
|
+
return null;
|
|
1030
|
+
}
|
|
1031
|
+
if (this.currentOptions.onOpenSeparateWindow) {
|
|
1032
|
+
return this.currentOptions.onOpenSeparateWindow({
|
|
1033
|
+
buffer: this.currentBuffer,
|
|
1034
|
+
metadata: this.currentMetadata || { name: "Document" },
|
|
1035
|
+
options: this.currentOptions
|
|
1036
|
+
});
|
|
1037
|
+
}
|
|
1038
|
+
const transferId = "fp_win_" + Date.now() + "_" + Math.random().toString(36).slice(2, 8);
|
|
1039
|
+
let clonedBuffer;
|
|
1040
|
+
try {
|
|
1041
|
+
clonedBuffer = this.currentBuffer.slice(0);
|
|
1042
|
+
} catch {
|
|
1043
|
+
clonedBuffer = this.currentBuffer;
|
|
1044
|
+
}
|
|
1045
|
+
const payload = {
|
|
1046
|
+
buffer: clonedBuffer,
|
|
1047
|
+
metadata: this.currentMetadata ? { ...this.currentMetadata } : void 0,
|
|
1048
|
+
options: { ...this.currentOptions, _isSeparateWindow: true }
|
|
1049
|
+
};
|
|
1050
|
+
if (typeof window !== "undefined") {
|
|
1051
|
+
try {
|
|
1052
|
+
window[transferId] = payload;
|
|
1053
|
+
window.__lastTransfer = payload;
|
|
1054
|
+
} catch {
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
saveTransferPayload(transferId, payload).catch((err) => {
|
|
1058
|
+
console.warn("[FilePreviewViewer] Transfer payload save warning:", err);
|
|
1059
|
+
});
|
|
1060
|
+
let targetUrl = null;
|
|
1061
|
+
if (this.currentOptions.standaloneViewerUrl) {
|
|
1062
|
+
const u = new URL(this.currentOptions.standaloneViewerUrl, window.location.href);
|
|
1063
|
+
u.searchParams.set("mode", "fullscreen");
|
|
1064
|
+
u.searchParams.set("transferId", transferId);
|
|
1065
|
+
targetUrl = u.toString();
|
|
1066
|
+
} else if (typeof window !== "undefined" && window.location?.href && !window.location.href.startsWith("about:")) {
|
|
1067
|
+
const u = new URL(window.location.href);
|
|
1068
|
+
u.searchParams.set("mode", "fullscreen");
|
|
1069
|
+
u.searchParams.set("transferId", transferId);
|
|
1070
|
+
targetUrl = u.toString();
|
|
1071
|
+
}
|
|
1072
|
+
if (targetUrl) {
|
|
1073
|
+
const newWin2 = window.open(targetUrl, "_blank");
|
|
1074
|
+
if (!newWin2) {
|
|
1075
|
+
alert("Popup blocker prevented opening the preview in a separate window. Please allow popups for this site.");
|
|
1076
|
+
return null;
|
|
1077
|
+
}
|
|
1078
|
+
return newWin2;
|
|
1079
|
+
}
|
|
1080
|
+
const title = (this.currentMetadata?.name || "Document Preview") + " - Full Preview";
|
|
1081
|
+
const newWin = window.open("", "_blank");
|
|
1082
|
+
if (!newWin) {
|
|
1083
|
+
alert("Popup blocker prevented opening the preview in a separate window. Please allow popups for this site.");
|
|
1084
|
+
return null;
|
|
1085
|
+
}
|
|
1086
|
+
newWin.document.title = title;
|
|
1087
|
+
newWin.document.body.style.margin = "0";
|
|
1088
|
+
newWin.document.body.style.padding = "0";
|
|
1089
|
+
newWin.document.body.style.width = "100vw";
|
|
1090
|
+
newWin.document.body.style.height = "100vh";
|
|
1091
|
+
newWin.document.body.style.overflow = "hidden";
|
|
1092
|
+
newWin.document.body.style.backgroundColor = "#f8fafc";
|
|
1093
|
+
const headNodes = document.querySelectorAll('link[rel="stylesheet"], style');
|
|
1094
|
+
headNodes.forEach((node) => {
|
|
1095
|
+
newWin.document.head.appendChild(node.cloneNode(true));
|
|
1096
|
+
});
|
|
1097
|
+
const root = newWin.document.createElement("div");
|
|
1098
|
+
root.id = "full-window-preview-root";
|
|
1099
|
+
root.style.width = "100%";
|
|
1100
|
+
root.style.height = "100%";
|
|
1101
|
+
root.style.overflow = "hidden";
|
|
1102
|
+
newWin.document.body.appendChild(root);
|
|
1103
|
+
const separateViewer = new _FilePreviewViewer();
|
|
1104
|
+
for (const plugin of this.plugins) {
|
|
1105
|
+
separateViewer.registerPlugin(plugin);
|
|
1106
|
+
}
|
|
1107
|
+
separateViewer.preview(root, this.currentBuffer.slice(0), {
|
|
1108
|
+
...this.currentOptions,
|
|
1109
|
+
showToolbar: true,
|
|
1110
|
+
toolbarPosition: "top",
|
|
1111
|
+
metadata: this.currentMetadata || void 0,
|
|
1112
|
+
_isSeparateWindow: true
|
|
1113
|
+
}).catch((err) => {
|
|
1114
|
+
console.error("[FilePreviewViewer] Error rendering in separate window:", err);
|
|
1115
|
+
});
|
|
1116
|
+
newWin.addEventListener("beforeunload", () => {
|
|
1117
|
+
separateViewer.destroy();
|
|
1118
|
+
});
|
|
1119
|
+
return newWin;
|
|
1120
|
+
}
|
|
917
1121
|
/**
|
|
918
1122
|
* Subscribe to viewer events.
|
|
919
1123
|
*/
|
|
@@ -1319,8 +1523,20 @@ var CfbfReader = class {
|
|
|
1319
1523
|
}
|
|
1320
1524
|
};
|
|
1321
1525
|
if (typeof window !== "undefined" && pdfjsLib__namespace.GlobalWorkerOptions) {
|
|
1322
|
-
if (!pdfjsLib__namespace.GlobalWorkerOptions.workerSrc) {
|
|
1323
|
-
|
|
1526
|
+
if (!pdfjsLib__namespace.GlobalWorkerOptions.workerPort && !pdfjsLib__namespace.GlobalWorkerOptions.workerSrc) {
|
|
1527
|
+
const customWorker = window.__PDF_WORKER_SRC__;
|
|
1528
|
+
if (customWorker) {
|
|
1529
|
+
pdfjsLib__namespace.GlobalWorkerOptions.workerSrc = customWorker;
|
|
1530
|
+
} else {
|
|
1531
|
+
try {
|
|
1532
|
+
pdfjsLib__namespace.GlobalWorkerOptions.workerPort = new Worker(
|
|
1533
|
+
new URL("pdfjs-dist/build/pdf.worker.min.mjs", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))),
|
|
1534
|
+
{ type: "module" }
|
|
1535
|
+
);
|
|
1536
|
+
} catch {
|
|
1537
|
+
pdfjsLib__namespace.GlobalWorkerOptions.workerSrc = "./pdf.worker.min.mjs";
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1324
1540
|
}
|
|
1325
1541
|
}
|
|
1326
1542
|
var PdfPlugin = class {
|
|
@@ -1414,6 +1630,14 @@ var PdfPlugin = class {
|
|
|
1414
1630
|
type: "button",
|
|
1415
1631
|
group: "actions",
|
|
1416
1632
|
execute: () => instance.print?.()
|
|
1633
|
+
},
|
|
1634
|
+
{
|
|
1635
|
+
id: "open-window",
|
|
1636
|
+
icon: "open-window",
|
|
1637
|
+
label: "Open in Separate Full Window",
|
|
1638
|
+
type: "button",
|
|
1639
|
+
group: "actions",
|
|
1640
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
1417
1641
|
}
|
|
1418
1642
|
];
|
|
1419
1643
|
}
|
|
@@ -1463,18 +1687,21 @@ var PdfPlugin = class {
|
|
|
1463
1687
|
indicator.style.pointerEvents = "none";
|
|
1464
1688
|
container.appendChild(indicator);
|
|
1465
1689
|
ctx.container.appendChild(container);
|
|
1690
|
+
const standardFontsUrl = typeof window !== "undefined" && window.__PDF_STANDARD_FONTS_URL__ || "./standard_fonts/";
|
|
1691
|
+
const cmapsUrl = typeof window !== "undefined" && window.__PDF_CMAPS_URL__ || "./cmaps/";
|
|
1466
1692
|
const loadingTask = pdfjsLib__namespace.getDocument({
|
|
1467
|
-
data: new Uint8Array(ctx.buffer),
|
|
1468
|
-
cMapUrl:
|
|
1693
|
+
data: new Uint8Array(ctx.buffer.slice(0)),
|
|
1694
|
+
cMapUrl: cmapsUrl,
|
|
1469
1695
|
cMapPacked: true,
|
|
1470
|
-
standardFontDataUrl:
|
|
1696
|
+
standardFontDataUrl: standardFontsUrl,
|
|
1697
|
+
verbosity: 0
|
|
1471
1698
|
});
|
|
1472
1699
|
const pdfDoc = await loadingTask.promise;
|
|
1473
1700
|
const totalPages = Math.max(1, pdfDoc.numPages);
|
|
1474
1701
|
let currentPage = 1;
|
|
1475
1702
|
let zoomScale = 1;
|
|
1476
1703
|
let rotation = 0;
|
|
1477
|
-
let fitMode = "
|
|
1704
|
+
let fitMode = "page";
|
|
1478
1705
|
let currentRenderTask = null;
|
|
1479
1706
|
const renderPage = async (pageNum) => {
|
|
1480
1707
|
if (currentRenderTask) {
|
|
@@ -1494,15 +1721,15 @@ var PdfPlugin = class {
|
|
|
1494
1721
|
const containerWidth = container.clientWidth || 900;
|
|
1495
1722
|
const containerHeight = container.clientHeight || 700;
|
|
1496
1723
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1497
|
-
const availWidth = Math.max(
|
|
1498
|
-
const availHeight = Math.max(
|
|
1724
|
+
const availWidth = Math.max(320, containerWidth - 48);
|
|
1725
|
+
const availHeight = Math.max(550, containerHeight - 88);
|
|
1499
1726
|
const scaleW = availWidth / unscaledVp.width;
|
|
1500
1727
|
const scaleH = availHeight / unscaledVp.height;
|
|
1501
1728
|
let fitScale;
|
|
1502
1729
|
if (fitMode === "page") {
|
|
1503
|
-
fitScale = Math.max(0.
|
|
1730
|
+
fitScale = Math.max(0.4, Math.min(scaleW, scaleH));
|
|
1504
1731
|
} else {
|
|
1505
|
-
fitScale = Math.max(0.65, Math.min(1.
|
|
1732
|
+
fitScale = Math.max(0.65, Math.min(1.25, scaleW));
|
|
1506
1733
|
}
|
|
1507
1734
|
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1508
1735
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
@@ -1528,7 +1755,7 @@ var PdfPlugin = class {
|
|
|
1528
1755
|
currentRenderTask = null;
|
|
1529
1756
|
}
|
|
1530
1757
|
};
|
|
1531
|
-
|
|
1758
|
+
renderPage(1);
|
|
1532
1759
|
let resizeTimer = null;
|
|
1533
1760
|
const resizeObserver = new ResizeObserver(() => {
|
|
1534
1761
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
@@ -1572,7 +1799,7 @@ var PdfPlugin = class {
|
|
|
1572
1799
|
renderPage(currentPage);
|
|
1573
1800
|
},
|
|
1574
1801
|
fitToPage: () => {
|
|
1575
|
-
fitMode = fitMode === "
|
|
1802
|
+
fitMode = fitMode === "page" ? "width" : "page";
|
|
1576
1803
|
zoomScale = 1;
|
|
1577
1804
|
rotation = 0;
|
|
1578
1805
|
renderPage(currentPage);
|
|
@@ -1589,6 +1816,7 @@ var PdfPlugin = class {
|
|
|
1589
1816
|
getPageCount: () => totalPages,
|
|
1590
1817
|
getCurrentPage: () => currentPage,
|
|
1591
1818
|
goToPage: (page) => {
|
|
1819
|
+
container.scrollTop = 0;
|
|
1592
1820
|
renderPage(page);
|
|
1593
1821
|
},
|
|
1594
1822
|
download: () => {
|
|
@@ -2048,6 +2276,14 @@ var DocxPlugin = class {
|
|
|
2048
2276
|
type: "button",
|
|
2049
2277
|
group: "actions",
|
|
2050
2278
|
execute: () => instance.print?.()
|
|
2279
|
+
},
|
|
2280
|
+
{
|
|
2281
|
+
id: "open-window",
|
|
2282
|
+
icon: "open-window",
|
|
2283
|
+
label: "Open in Separate Full Window",
|
|
2284
|
+
type: "button",
|
|
2285
|
+
group: "actions",
|
|
2286
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
2051
2287
|
}
|
|
2052
2288
|
);
|
|
2053
2289
|
return actions;
|
|
@@ -2093,13 +2329,45 @@ var DocxPlugin = class {
|
|
|
2093
2329
|
ignoreFonts: true,
|
|
2094
2330
|
// Avoid crashes on embedded obfuscated fonts
|
|
2095
2331
|
breakPages: true,
|
|
2096
|
-
experimental: true
|
|
2332
|
+
experimental: true,
|
|
2333
|
+
ignoreLastRenderedPageBreak: false,
|
|
2334
|
+
// Honor Word's exact page breaks!
|
|
2335
|
+
renderHeaders: true,
|
|
2336
|
+
renderFooters: true,
|
|
2337
|
+
renderFootnotes: true,
|
|
2338
|
+
renderEndnotes: true,
|
|
2339
|
+
useBase64URL: true
|
|
2097
2340
|
});
|
|
2098
2341
|
if (!ctx.container.contains(wrapper)) {
|
|
2099
2342
|
ctx.container.appendChild(wrapper);
|
|
2100
2343
|
}
|
|
2101
2344
|
if (wrapper.children.length > 0 && (wrapper.textContent?.trim().length ?? 0) > 0) {
|
|
2102
2345
|
renderedSuccessfully = true;
|
|
2346
|
+
try {
|
|
2347
|
+
const unzipped = fflate.unzipSync(new Uint8Array(ctx.buffer));
|
|
2348
|
+
const chartKeys = Object.keys(unzipped).filter((k) => k.replace(/^[./\\]+/, "").toLowerCase().startsWith("word/charts/chart") && k.endsWith(".xml")).sort();
|
|
2349
|
+
if (chartKeys.length > 0) {
|
|
2350
|
+
const allDivs = Array.from(wrapper.querySelectorAll("div"));
|
|
2351
|
+
const emptyContainers = allDivs.filter((div) => {
|
|
2352
|
+
const st = div.getAttribute("style") || "";
|
|
2353
|
+
return st.includes("width:") && st.includes("height:") && div.children.length === 0 && (div.textContent?.trim().length ?? 0) === 0;
|
|
2354
|
+
});
|
|
2355
|
+
chartKeys.forEach((cKey, idx) => {
|
|
2356
|
+
const target = emptyContainers[idx];
|
|
2357
|
+
if (target) {
|
|
2358
|
+
const xmlStr = fflate.strFromU8(unzipped[cKey]);
|
|
2359
|
+
const svg = this.parseAndRenderChartSvg(xmlStr);
|
|
2360
|
+
if (svg) {
|
|
2361
|
+
target.innerHTML = svg;
|
|
2362
|
+
target.style.display = "block";
|
|
2363
|
+
target.style.margin = "12px auto";
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
});
|
|
2367
|
+
}
|
|
2368
|
+
} catch (chartErr) {
|
|
2369
|
+
console.warn("[DocxPlugin] Non-critical error rendering DrawingML charts:", chartErr);
|
|
2370
|
+
}
|
|
2103
2371
|
}
|
|
2104
2372
|
} catch (err) {
|
|
2105
2373
|
console.warn("[DocxPlugin] docx-preview failed, triggering native fallback:", err);
|
|
@@ -2114,11 +2382,14 @@ var DocxPlugin = class {
|
|
|
2114
2382
|
renderedSuccessfully = true;
|
|
2115
2383
|
} catch (fallbackErr) {
|
|
2116
2384
|
console.error("[DocxPlugin] Native fallback failed:", fallbackErr);
|
|
2385
|
+
const isCorrupt = fallbackErr?.message?.includes("invalid zip") || fallbackErr?.message?.includes("corrupted");
|
|
2117
2386
|
wrapper.innerHTML = `
|
|
2118
|
-
<div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
|
|
2119
|
-
<div style="font-size:48px; margin-bottom: 16px;"
|
|
2120
|
-
<h3 style="margin: 0 0 8px; color: #1e293b;">${ctx.metadata.name || "Word Document"}</h3>
|
|
2121
|
-
<p style="color: #64748b; margin: 0;
|
|
2387
|
+
<div style="text-align:center; padding: 48px 32px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06); max-width: 600px; margin: 40px auto;">
|
|
2388
|
+
<div style="font-size:48px; margin-bottom: 16px;">${isCorrupt ? "\u26A0\uFE0F" : "\u{1F4C4}"}</div>
|
|
2389
|
+
<h3 style="margin: 0 0 8px; color: #1e293b; font-size: 18px;">${ctx.metadata.name || "Word Document"}</h3>
|
|
2390
|
+
<p style="color: #64748b; margin: 0 0 16px; font-size: 14px; line-height: 1.5;">
|
|
2391
|
+
${isCorrupt ? "This document appears to be corrupted or contains invalid archive data and cannot be opened (matches Microsoft Word on Windows)." : "Could not render document content. The file structure may be damaged."}
|
|
2392
|
+
</p>
|
|
2122
2393
|
</div>
|
|
2123
2394
|
`;
|
|
2124
2395
|
if (!ctx.container.contains(wrapper)) {
|
|
@@ -2128,50 +2399,74 @@ var DocxPlugin = class {
|
|
|
2128
2399
|
}
|
|
2129
2400
|
let sections = Array.from(wrapper.querySelectorAll("section.docx"));
|
|
2130
2401
|
const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
|
|
2131
|
-
if (sections.length
|
|
2132
|
-
const
|
|
2133
|
-
const
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
const
|
|
2137
|
-
|
|
2402
|
+
if (sections.length > 0 && cards.length === 0) {
|
|
2403
|
+
const finalSections = [];
|
|
2404
|
+
for (const singleSec of sections) {
|
|
2405
|
+
const contentContainer = singleSec.querySelector("article") || singleSec;
|
|
2406
|
+
const children = Array.from(contentContainer.children);
|
|
2407
|
+
const pageH = singleSec.offsetHeight > 1300 ? 1122 : Math.max(1056, singleSec.offsetHeight);
|
|
2408
|
+
const secH = singleSec.scrollHeight || singleSec.offsetHeight;
|
|
2409
|
+
if (secH > pageH * 1.25 && children.length > 1) {
|
|
2410
|
+
const childHeights = children.map((c) => {
|
|
2411
|
+
const rectH = c.getBoundingClientRect().height;
|
|
2412
|
+
const offH = c.offsetHeight;
|
|
2413
|
+
const textLen = c.textContent?.trim().length || 0;
|
|
2414
|
+
const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
|
|
2415
|
+
return Math.max(rectH, offH, estH);
|
|
2416
|
+
});
|
|
2138
2417
|
const parent = singleSec.parentElement || wrapper;
|
|
2139
|
-
const
|
|
2140
|
-
|
|
2418
|
+
const headerEl = singleSec.querySelector("header");
|
|
2419
|
+
const footerEl = singleSec.querySelector("footer");
|
|
2420
|
+
contentContainer.innerHTML = "";
|
|
2141
2421
|
singleSec.style.minHeight = `${pageH}px`;
|
|
2142
|
-
singleSec.style.maxHeight = `${pageH}px`;
|
|
2143
|
-
singleSec.style.overflow = "hidden";
|
|
2144
2422
|
singleSec.style.boxSizing = "border-box";
|
|
2423
|
+
let curContent = contentContainer;
|
|
2145
2424
|
let curSec = singleSec;
|
|
2146
2425
|
let curH = 0;
|
|
2147
|
-
const maxH = pageH -
|
|
2426
|
+
const maxH = pageH - 140;
|
|
2427
|
+
finalSections.push(singleSec);
|
|
2148
2428
|
for (let i = 0; i < children.length; i++) {
|
|
2149
2429
|
const child = children[i];
|
|
2150
|
-
|
|
2151
|
-
|
|
2430
|
+
const chH = childHeights[i];
|
|
2431
|
+
curContent.appendChild(child);
|
|
2152
2432
|
curH += chH;
|
|
2153
2433
|
if (curH >= maxH && i < children.length - 1) {
|
|
2154
2434
|
const nextSec = document.createElement("section");
|
|
2155
2435
|
nextSec.className = singleSec.className;
|
|
2156
2436
|
nextSec.style.cssText = singleSec.style.cssText;
|
|
2157
|
-
nextSec.style.width = singleSec.style.width || "816px";
|
|
2158
2437
|
nextSec.style.minHeight = `${pageH}px`;
|
|
2159
|
-
nextSec.style.maxHeight = `${pageH}px`;
|
|
2160
|
-
nextSec.style.overflow = "hidden";
|
|
2161
2438
|
nextSec.style.boxSizing = "border-box";
|
|
2162
2439
|
nextSec.style.backgroundColor = "#ffffff";
|
|
2163
2440
|
nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
|
|
2164
2441
|
nextSec.style.borderRadius = "4px";
|
|
2165
2442
|
nextSec.style.marginBottom = "24px";
|
|
2166
|
-
|
|
2167
|
-
|
|
2443
|
+
if (headerEl) {
|
|
2444
|
+
nextSec.appendChild(headerEl.cloneNode(true));
|
|
2445
|
+
}
|
|
2446
|
+
const nextArticle = document.createElement("article");
|
|
2447
|
+
if (contentContainer.tagName.toLowerCase() === "article") {
|
|
2448
|
+
nextArticle.style.cssText = contentContainer.style.cssText;
|
|
2449
|
+
}
|
|
2450
|
+
nextSec.appendChild(nextArticle);
|
|
2451
|
+
if (footerEl) {
|
|
2452
|
+
nextSec.appendChild(footerEl.cloneNode(true));
|
|
2453
|
+
}
|
|
2454
|
+
if (curSec.nextSibling) {
|
|
2455
|
+
parent.insertBefore(nextSec, curSec.nextSibling);
|
|
2456
|
+
} else {
|
|
2457
|
+
parent.appendChild(nextSec);
|
|
2458
|
+
}
|
|
2459
|
+
finalSections.push(nextSec);
|
|
2168
2460
|
curSec = nextSec;
|
|
2461
|
+
curContent = nextArticle;
|
|
2169
2462
|
curH = 0;
|
|
2170
2463
|
}
|
|
2171
2464
|
}
|
|
2172
|
-
|
|
2465
|
+
} else {
|
|
2466
|
+
finalSections.push(singleSec);
|
|
2173
2467
|
}
|
|
2174
2468
|
}
|
|
2469
|
+
sections = finalSections;
|
|
2175
2470
|
}
|
|
2176
2471
|
const pageElements = sections.length > 0 ? sections : cards;
|
|
2177
2472
|
const totalPages = Math.max(1, pageElements.length);
|
|
@@ -2209,6 +2504,7 @@ var DocxPlugin = class {
|
|
|
2209
2504
|
if (indicator) {
|
|
2210
2505
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
2211
2506
|
}
|
|
2507
|
+
ctx.container.scrollTop = 0;
|
|
2212
2508
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
2213
2509
|
};
|
|
2214
2510
|
if (totalPages > 1) {
|
|
@@ -2562,6 +2858,88 @@ var DocxPlugin = class {
|
|
|
2562
2858
|
}
|
|
2563
2859
|
return result;
|
|
2564
2860
|
}
|
|
2861
|
+
parseAndRenderChartSvg(xmlStr, width = 500, height = 260) {
|
|
2862
|
+
const catMatches = [...xmlStr.matchAll(/<c:cat>[\s\S]*?<c:strCache>([\s\S]*?)<\/c:strCache>/g)];
|
|
2863
|
+
let categories = [];
|
|
2864
|
+
if (catMatches.length > 0) {
|
|
2865
|
+
categories = [...catMatches[0][1].matchAll(/<c:v>([^<]+)<\/c:v>/g)].map((m) => m[1]);
|
|
2866
|
+
}
|
|
2867
|
+
if (categories.length === 0) {
|
|
2868
|
+
categories = ["Category 1", "Category 2", "Category 3", "Category 4"];
|
|
2869
|
+
}
|
|
2870
|
+
const defaultColors = ["#004586", "#ff420e", "#ffd320", "#579d1c", "#7e0021", "#83caff"];
|
|
2871
|
+
const sers = [...xmlStr.matchAll(/<c:ser>([\s\S]*?)<\/c:ser>/g)];
|
|
2872
|
+
const series = [];
|
|
2873
|
+
sers.forEach((s, sIdx) => {
|
|
2874
|
+
const titleMatch = s[1].match(/<c:tx>[\s\S]*?<c:v>([^<]+)<\/c:v>/);
|
|
2875
|
+
const title = titleMatch ? titleMatch[1] : `Series ${sIdx + 1}`;
|
|
2876
|
+
const clrMatch = s[1].match(/<a:srgbClr\s+val="([^"]+)"/);
|
|
2877
|
+
const color = clrMatch ? "#" + clrMatch[1] : defaultColors[sIdx % defaultColors.length];
|
|
2878
|
+
const valMatch = s[1].match(/<c:val>[\s\S]*?<c:numCache>([\s\S]*?)<\/c:numCache>/);
|
|
2879
|
+
let values = [];
|
|
2880
|
+
if (valMatch) {
|
|
2881
|
+
values = [...valMatch[1].matchAll(/<c:pt\s+idx="(\d+)">\s*<c:v>([^<]+)<\/c:v>/g)].sort((a, b) => parseInt(a[1], 10) - parseInt(b[1], 10)).map((m) => parseFloat(m[2]) || 0);
|
|
2882
|
+
}
|
|
2883
|
+
series.push({ title, color, values });
|
|
2884
|
+
});
|
|
2885
|
+
if (series.length === 0) return "";
|
|
2886
|
+
let maxVal = 10;
|
|
2887
|
+
series.forEach((s) => s.values.forEach((v) => {
|
|
2888
|
+
if (v > maxVal) maxVal = v;
|
|
2889
|
+
}));
|
|
2890
|
+
maxVal = Math.ceil(maxVal * 1.15);
|
|
2891
|
+
if (maxVal % 2 !== 0) maxVal++;
|
|
2892
|
+
const padLeft = 45;
|
|
2893
|
+
const padBottom = 55;
|
|
2894
|
+
const padTop = 20;
|
|
2895
|
+
const padRight = 20;
|
|
2896
|
+
const plotW = width - padLeft - padRight;
|
|
2897
|
+
const plotH = height - padTop - padBottom;
|
|
2898
|
+
const yTicks = 5;
|
|
2899
|
+
let gridLines = "";
|
|
2900
|
+
for (let i = 0; i <= yTicks; i++) {
|
|
2901
|
+
const val = maxVal / yTicks * i;
|
|
2902
|
+
const y = padTop + plotH - val / maxVal * plotH;
|
|
2903
|
+
gridLines += `<line x1="${padLeft}" y1="${y}" x2="${padLeft + plotW}" y2="${y}" stroke="#e2e8f0" stroke-width="1" />`;
|
|
2904
|
+
gridLines += `<text x="${padLeft - 8}" y="${y + 4}" text-anchor="end" font-size="11" fill="#64748b" font-family="Calibri, sans-serif">${Math.round(val)}</text>`;
|
|
2905
|
+
}
|
|
2906
|
+
const numCats = categories.length;
|
|
2907
|
+
const numSers = series.length;
|
|
2908
|
+
const groupW = plotW / numCats;
|
|
2909
|
+
const barW = Math.max(8, Math.min(28, groupW * 0.7 / numSers));
|
|
2910
|
+
const groupPad = (groupW - barW * numSers) / 2;
|
|
2911
|
+
let bars = "";
|
|
2912
|
+
let catLabels = "";
|
|
2913
|
+
for (let c = 0; c < numCats; c++) {
|
|
2914
|
+
const catX = padLeft + c * groupW;
|
|
2915
|
+
catLabels += `<text x="${catX + groupW / 2}" y="${padTop + plotH + 18}" text-anchor="middle" font-size="11" fill="#334155" font-family="Calibri, sans-serif">${categories[c]}</text>`;
|
|
2916
|
+
for (let s = 0; s < numSers; s++) {
|
|
2917
|
+
const val = series[s].values[c] ?? 0;
|
|
2918
|
+
const bH = Math.max(0, val / maxVal * plotH);
|
|
2919
|
+
const bX = catX + groupPad + s * barW;
|
|
2920
|
+
const bY = padTop + plotH - bH;
|
|
2921
|
+
bars += `<rect x="${bX}" y="${bY}" width="${barW - 2}" height="${bH}" fill="${series[s].color}" rx="1" />`;
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
let legend = "";
|
|
2925
|
+
const legY = height - 12;
|
|
2926
|
+
let legX = padLeft + (plotW - numSers * 100) / 2;
|
|
2927
|
+
series.forEach((s) => {
|
|
2928
|
+
legend += `<rect x="${legX}" y="${legY - 9}" width="10" height="10" fill="${s.color}" rx="2" />`;
|
|
2929
|
+
legend += `<text x="${legX + 15}" y="${legY}" font-size="11" fill="#475569" font-family="Calibri, sans-serif">${s.title}</text>`;
|
|
2930
|
+
legX += 95;
|
|
2931
|
+
});
|
|
2932
|
+
return `
|
|
2933
|
+
<svg viewBox="0 0 ${width} ${height}" width="100%" height="100%" style="background:#ffffff; border-radius:4px; overflow:visible;" xmlns="http://www.w3.org/2000/svg">
|
|
2934
|
+
${gridLines}
|
|
2935
|
+
<line x1="${padLeft}" y1="${padTop + plotH}" x2="${padLeft + plotW}" y2="${padTop + plotH}" stroke="#94a3b8" stroke-width="1.5" />
|
|
2936
|
+
<line x1="${padLeft}" y1="${padTop}" x2="${padLeft}" y2="${padTop + plotH}" stroke="#94a3b8" stroke-width="1.5" />
|
|
2937
|
+
${bars}
|
|
2938
|
+
${catLabels}
|
|
2939
|
+
${legend}
|
|
2940
|
+
</svg>
|
|
2941
|
+
`.trim();
|
|
2942
|
+
}
|
|
2565
2943
|
};
|
|
2566
2944
|
function docxPlugin() {
|
|
2567
2945
|
return new DocxPlugin();
|
|
@@ -3128,6 +3506,16 @@ var CodePlugin = class {
|
|
|
3128
3506
|
execute: () => {
|
|
3129
3507
|
instance.print?.();
|
|
3130
3508
|
}
|
|
3509
|
+
},
|
|
3510
|
+
{
|
|
3511
|
+
id: "open-window",
|
|
3512
|
+
icon: "open-window",
|
|
3513
|
+
label: "Open in Separate Full Window",
|
|
3514
|
+
type: "button",
|
|
3515
|
+
group: "actions",
|
|
3516
|
+
execute: () => {
|
|
3517
|
+
instance.openInSeparateWindow?.();
|
|
3518
|
+
}
|
|
3131
3519
|
}
|
|
3132
3520
|
);
|
|
3133
3521
|
return actions;
|
|
@@ -3141,17 +3529,39 @@ var CodePlugin = class {
|
|
|
3141
3529
|
let rawPages = [];
|
|
3142
3530
|
if (isTxt) {
|
|
3143
3531
|
const explicitPages = fullText.split(/(?:\f|\x0C)/);
|
|
3532
|
+
const charsPerLine = 85;
|
|
3533
|
+
const maxVisualLines = 45;
|
|
3534
|
+
const charsPerPage = charsPerLine * maxVisualLines;
|
|
3144
3535
|
for (const ep of explicitPages) {
|
|
3145
3536
|
const lines = ep.split(/\r?\n/);
|
|
3146
3537
|
let currentChunk = [];
|
|
3538
|
+
let currentLines = 0;
|
|
3147
3539
|
for (let i = 0; i < lines.length; i++) {
|
|
3148
|
-
|
|
3149
|
-
|
|
3540
|
+
const line = lines[i];
|
|
3541
|
+
const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
|
|
3542
|
+
if (currentLines + vLines > maxVisualLines && currentChunk.length > 0) {
|
|
3150
3543
|
rawPages.push(currentChunk.join("\n"));
|
|
3151
3544
|
currentChunk = [];
|
|
3545
|
+
currentLines = 0;
|
|
3546
|
+
}
|
|
3547
|
+
if (vLines > maxVisualLines) {
|
|
3548
|
+
let remaining = line;
|
|
3549
|
+
while (remaining.length > charsPerPage) {
|
|
3550
|
+
let splitIdx = remaining.lastIndexOf(" ", charsPerPage);
|
|
3551
|
+
if (splitIdx < charsPerPage * 0.75) splitIdx = charsPerPage;
|
|
3552
|
+
rawPages.push(remaining.slice(0, splitIdx));
|
|
3553
|
+
remaining = remaining.slice(splitIdx).trimStart();
|
|
3554
|
+
}
|
|
3555
|
+
if (remaining.length > 0) {
|
|
3556
|
+
currentChunk.push(remaining);
|
|
3557
|
+
currentLines = Math.ceil(remaining.length / charsPerLine);
|
|
3558
|
+
}
|
|
3559
|
+
} else {
|
|
3560
|
+
currentChunk.push(line);
|
|
3561
|
+
currentLines += vLines;
|
|
3152
3562
|
}
|
|
3153
3563
|
}
|
|
3154
|
-
if (currentChunk.length > 0
|
|
3564
|
+
if (currentChunk.length > 0) {
|
|
3155
3565
|
rawPages.push(currentChunk.join("\n"));
|
|
3156
3566
|
}
|
|
3157
3567
|
}
|
|
@@ -3261,6 +3671,7 @@ var CodePlugin = class {
|
|
|
3261
3671
|
if (indicator) {
|
|
3262
3672
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
3263
3673
|
}
|
|
3674
|
+
container.scrollTop = 0;
|
|
3264
3675
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
3265
3676
|
};
|
|
3266
3677
|
if (totalPages > 1) {
|
|
@@ -4273,6 +4684,14 @@ var RtfPlugin = class {
|
|
|
4273
4684
|
type: "button",
|
|
4274
4685
|
group: "actions",
|
|
4275
4686
|
execute: () => instance.print?.()
|
|
4687
|
+
},
|
|
4688
|
+
{
|
|
4689
|
+
id: "open-window",
|
|
4690
|
+
icon: "open-window",
|
|
4691
|
+
label: "Open in Separate Full Window",
|
|
4692
|
+
type: "button",
|
|
4693
|
+
group: "actions",
|
|
4694
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
4276
4695
|
}
|
|
4277
4696
|
);
|
|
4278
4697
|
return actions;
|
|
@@ -4325,11 +4744,55 @@ var RtfPlugin = class {
|
|
|
4325
4744
|
}
|
|
4326
4745
|
const doc = new RTFJS__namespace.Document(ctx.buffer, {});
|
|
4327
4746
|
const htmlElements = await doc.render();
|
|
4328
|
-
|
|
4329
|
-
for (
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4747
|
+
const contentNodes = [];
|
|
4748
|
+
for (const item of htmlElements) {
|
|
4749
|
+
if (item.children && item.children.length > 0 && !item.tagName.toLowerCase().startsWith("table")) {
|
|
4750
|
+
contentNodes.push(...Array.from(item.children));
|
|
4751
|
+
} else {
|
|
4752
|
+
contentNodes.push(item);
|
|
4753
|
+
}
|
|
4754
|
+
}
|
|
4755
|
+
wrapper.innerHTML = "";
|
|
4756
|
+
contentNodes.forEach((node) => wrapper.appendChild(node));
|
|
4757
|
+
const childHeights = contentNodes.map((c) => {
|
|
4758
|
+
const rectH = c.getBoundingClientRect ? c.getBoundingClientRect().height : 0;
|
|
4759
|
+
const offH = c.offsetHeight || 0;
|
|
4760
|
+
const textLen = c.textContent?.trim().length || 0;
|
|
4761
|
+
const estH = Math.max(24, Math.ceil(textLen / 75) * 22 + 14);
|
|
4762
|
+
return Math.max(rectH, offH, estH);
|
|
4763
|
+
});
|
|
4764
|
+
wrapper.innerHTML = "";
|
|
4765
|
+
const createRtfCard = () => {
|
|
4766
|
+
const card = document.createElement("div");
|
|
4767
|
+
card.className = "fp-rtf-page-card";
|
|
4768
|
+
card.style.backgroundColor = "#ffffff";
|
|
4769
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
4770
|
+
card.style.borderRadius = "4px";
|
|
4771
|
+
card.style.padding = "72px 56px";
|
|
4772
|
+
card.style.width = "816px";
|
|
4773
|
+
card.style.minHeight = "1056px";
|
|
4774
|
+
card.style.boxSizing = "border-box";
|
|
4775
|
+
card.style.marginBottom = "24px";
|
|
4776
|
+
card.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4777
|
+
card.style.lineHeight = "1.6";
|
|
4778
|
+
return card;
|
|
4779
|
+
};
|
|
4780
|
+
let curCard = createRtfCard();
|
|
4781
|
+
wrapper.appendChild(curCard);
|
|
4782
|
+
pageElements = [curCard];
|
|
4783
|
+
let curH = 0;
|
|
4784
|
+
const maxH = 912;
|
|
4785
|
+
for (let i = 0; i < contentNodes.length; i++) {
|
|
4786
|
+
const child = contentNodes[i];
|
|
4787
|
+
const chH = childHeights[i];
|
|
4788
|
+
curCard.appendChild(child);
|
|
4789
|
+
curH += chH;
|
|
4790
|
+
if (curH >= maxH && i < contentNodes.length - 1) {
|
|
4791
|
+
curCard = createRtfCard();
|
|
4792
|
+
wrapper.appendChild(curCard);
|
|
4793
|
+
pageElements.push(curCard);
|
|
4794
|
+
curH = 0;
|
|
4795
|
+
}
|
|
4333
4796
|
}
|
|
4334
4797
|
} catch (err) {
|
|
4335
4798
|
console.warn("[RtfPlugin] RTF render error, fallback text:", err);
|
|
@@ -4395,6 +4858,7 @@ var RtfPlugin = class {
|
|
|
4395
4858
|
if (indicator) {
|
|
4396
4859
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4397
4860
|
}
|
|
4861
|
+
ctx.container.scrollTop = 0;
|
|
4398
4862
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4399
4863
|
};
|
|
4400
4864
|
if (totalPages > 1) {
|
|
@@ -4696,6 +5160,14 @@ var OpenDocumentPlugin = class {
|
|
|
4696
5160
|
type: "button",
|
|
4697
5161
|
group: "actions",
|
|
4698
5162
|
execute: () => instance.print?.()
|
|
5163
|
+
},
|
|
5164
|
+
{
|
|
5165
|
+
id: "open-window",
|
|
5166
|
+
icon: "open-window",
|
|
5167
|
+
label: "Open in Separate Full Window",
|
|
5168
|
+
type: "button",
|
|
5169
|
+
group: "actions",
|
|
5170
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
4699
5171
|
}
|
|
4700
5172
|
);
|
|
4701
5173
|
return actions;
|
|
@@ -4866,12 +5338,9 @@ var OpenDocumentPlugin = class {
|
|
|
4866
5338
|
page.style.backgroundColor = "#ffffff";
|
|
4867
5339
|
page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
4868
5340
|
page.style.borderRadius = "4px";
|
|
4869
|
-
page.style.boxSizing = "border-box";
|
|
4870
5341
|
page.style.display = idx === 0 ? "block" : "none";
|
|
4871
|
-
page.style.
|
|
4872
|
-
page.style.
|
|
4873
|
-
page.style.left = "50%";
|
|
4874
|
-
page.style.transform = "translateX(-50%)";
|
|
5342
|
+
page.style.margin = "0 auto 24px";
|
|
5343
|
+
page.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
|
|
4875
5344
|
elements.forEach((el) => page.appendChild(el));
|
|
4876
5345
|
wrapper.appendChild(page);
|
|
4877
5346
|
slides.push(page);
|
|
@@ -4909,6 +5378,7 @@ var OpenDocumentPlugin = class {
|
|
|
4909
5378
|
if (indicator) {
|
|
4910
5379
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4911
5380
|
}
|
|
5381
|
+
container.scrollTop = 0;
|
|
4912
5382
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4913
5383
|
};
|
|
4914
5384
|
return {
|
|
@@ -5286,6 +5756,14 @@ var DocPlugin = class {
|
|
|
5286
5756
|
type: "button",
|
|
5287
5757
|
group: "actions",
|
|
5288
5758
|
execute: () => instance.print?.()
|
|
5759
|
+
},
|
|
5760
|
+
{
|
|
5761
|
+
id: "open-window",
|
|
5762
|
+
icon: "open-window",
|
|
5763
|
+
label: "Open in Separate Full Window",
|
|
5764
|
+
type: "button",
|
|
5765
|
+
group: "actions",
|
|
5766
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
5289
5767
|
}
|
|
5290
5768
|
);
|
|
5291
5769
|
return actions;
|
|
@@ -5401,6 +5879,7 @@ var DocPlugin = class {
|
|
|
5401
5879
|
if (indicator) {
|
|
5402
5880
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
5403
5881
|
}
|
|
5882
|
+
container.scrollTop = 0;
|
|
5404
5883
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
5405
5884
|
};
|
|
5406
5885
|
if (totalPages > 1) {
|
|
@@ -5576,47 +6055,69 @@ var DocPlugin = class {
|
|
|
5576
6055
|
heuristicTextExtraction(buffer) {
|
|
5577
6056
|
return this.extractStringsFromBytes(new Uint8Array(buffer));
|
|
5578
6057
|
}
|
|
6058
|
+
cleanWordDocFields(text) {
|
|
6059
|
+
if (!text) return "";
|
|
6060
|
+
let cleaned = text.replace(
|
|
6061
|
+
/\x13\s*HYPERLINK\s*"?([^"\x14]+)"?\s*\x14([\s\S]*?)\x15/gi,
|
|
6062
|
+
(_match, url, label) => {
|
|
6063
|
+
const cleanUrl = url.trim();
|
|
6064
|
+
const cleanLabel = label.trim() || cleanUrl;
|
|
6065
|
+
return `<a href="${cleanUrl}" target="_blank" rel="noopener noreferrer" style="color: #2563eb; text-decoration: underline;">${cleanLabel}</a>`;
|
|
6066
|
+
}
|
|
6067
|
+
);
|
|
6068
|
+
cleaned = cleaned.replace(/\x13[^\x14\x15]*\x14([^\x15]*)\x15/g, "$1");
|
|
6069
|
+
cleaned = cleaned.replace(/\x13[^\x15]*\x15/g, "");
|
|
6070
|
+
cleaned = cleaned.replace(/[\x13\x14\x15]/g, "");
|
|
6071
|
+
return cleaned;
|
|
6072
|
+
}
|
|
5579
6073
|
splitIntoPages(text) {
|
|
5580
6074
|
if (!text) return [""];
|
|
5581
|
-
const
|
|
5582
|
-
|
|
5583
|
-
const
|
|
6075
|
+
const cleanedText = this.cleanWordDocFields(text);
|
|
6076
|
+
const normalized = cleanedText.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ");
|
|
6077
|
+
const explicitParts = normalized.split(/[\x0C\f]|\n\s*[-=_]{3,}\s*(?:PAGE|Page|page break)[\s\d\w-]*[-=_]{3,}\s*\n/i).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
6078
|
+
if (explicitParts.length === 0) explicitParts.push(normalized);
|
|
6079
|
+
const maxLinesPerPage = 32;
|
|
6080
|
+
const charsPerLine = 80;
|
|
5584
6081
|
const finalPages = [];
|
|
5585
6082
|
for (const part of explicitParts) {
|
|
5586
|
-
const lines = part.split(
|
|
6083
|
+
const lines = part.split("\n");
|
|
5587
6084
|
let currentLines = [];
|
|
5588
6085
|
let count = 0;
|
|
5589
6086
|
for (const line of lines) {
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
if (count
|
|
6087
|
+
const plainLine = line.replace(/<[^>]+>/g, "");
|
|
6088
|
+
const vLines = Math.max(1, Math.ceil((plainLine.length || 1) / charsPerLine));
|
|
6089
|
+
if (count + vLines > maxLinesPerPage && currentLines.length > 0) {
|
|
5593
6090
|
finalPages.push(currentLines.join("\n"));
|
|
5594
6091
|
currentLines = [];
|
|
5595
6092
|
count = 0;
|
|
5596
6093
|
}
|
|
6094
|
+
currentLines.push(line);
|
|
6095
|
+
count += vLines;
|
|
5597
6096
|
}
|
|
5598
6097
|
if (currentLines.length > 0) {
|
|
5599
6098
|
finalPages.push(currentLines.join("\n"));
|
|
5600
6099
|
}
|
|
5601
6100
|
}
|
|
5602
|
-
return finalPages.length > 0 ? finalPages : [
|
|
6101
|
+
return finalPages.length > 0 ? finalPages : [normalized];
|
|
5603
6102
|
}
|
|
5604
6103
|
/**
|
|
5605
6104
|
* Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
|
|
5606
6105
|
*/
|
|
5607
6106
|
formatDocToHtml(text, filename) {
|
|
5608
|
-
const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
|
|
6107
|
+
const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ").split("\n");
|
|
5609
6108
|
let html = "";
|
|
5610
6109
|
let inList = false;
|
|
5611
6110
|
let tableLines = [];
|
|
5612
6111
|
const flushTable = () => {
|
|
5613
6112
|
if (tableLines.length > 0) {
|
|
5614
|
-
html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size:
|
|
5615
|
-
for (
|
|
5616
|
-
|
|
5617
|
-
const
|
|
6113
|
+
html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 13px; font-family: Calibri, sans-serif;">';
|
|
6114
|
+
for (let rIdx = 0; rIdx < tableLines.length; rIdx++) {
|
|
6115
|
+
const tLine = tableLines[rIdx];
|
|
6116
|
+
const isHeader = rIdx === 0;
|
|
6117
|
+
html += `<tr style="${isHeader ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
6118
|
+
const cols = tLine.split(" ").filter((c) => c.trim().length > 0);
|
|
5618
6119
|
for (const col of cols) {
|
|
5619
|
-
html += `<td style="border: 1px solid #cbd5e1; padding:
|
|
6120
|
+
html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
|
|
5620
6121
|
}
|
|
5621
6122
|
html += "</tr>";
|
|
5622
6123
|
}
|
|
@@ -5629,27 +6130,18 @@ var DocPlugin = class {
|
|
|
5629
6130
|
let line = lines[i];
|
|
5630
6131
|
let tabCount = (line.match(/\t/g) || []).length;
|
|
5631
6132
|
if (tabCount > 0) {
|
|
5632
|
-
let
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
const nextTabCount = (lines[j].match(/\t/g) || []).length;
|
|
5636
|
-
if (nextTabCount === tabCount) {
|
|
5637
|
-
consecutiveTableLines++;
|
|
5638
|
-
j++;
|
|
5639
|
-
} else {
|
|
5640
|
-
break;
|
|
5641
|
-
}
|
|
6133
|
+
let j = i;
|
|
6134
|
+
while (j < lines.length && (lines[j].match(/\t/g) || []).length > 0) {
|
|
6135
|
+
j++;
|
|
5642
6136
|
}
|
|
5643
|
-
if (
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
inList = false;
|
|
5647
|
-
}
|
|
5648
|
-
tableLines = lines.slice(i, j);
|
|
5649
|
-
flushTable();
|
|
5650
|
-
i = j;
|
|
5651
|
-
continue;
|
|
6137
|
+
if (inList) {
|
|
6138
|
+
html += "</ul>";
|
|
6139
|
+
inList = false;
|
|
5652
6140
|
}
|
|
6141
|
+
tableLines = lines.slice(i, j);
|
|
6142
|
+
flushTable();
|
|
6143
|
+
i = j;
|
|
6144
|
+
continue;
|
|
5653
6145
|
}
|
|
5654
6146
|
line = line.trim();
|
|
5655
6147
|
if (!line) {
|
|
@@ -5669,25 +6161,26 @@ var DocPlugin = class {
|
|
|
5669
6161
|
i++;
|
|
5670
6162
|
continue;
|
|
5671
6163
|
}
|
|
6164
|
+
const sanitizeOptions = { ADD_TAGS: ["a"], ADD_ATTR: ["href", "target", "rel", "style"] };
|
|
5672
6165
|
if (line.length < 60 && !line.endsWith(".") && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#"))) {
|
|
5673
6166
|
if (inList) {
|
|
5674
6167
|
html += "</ul>";
|
|
5675
6168
|
inList = false;
|
|
5676
6169
|
}
|
|
5677
|
-
html += `<h2 style="font-size: 16px; font-weight: 700; color: #1e3a8a; margin: 16px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify6__default.default.sanitize(line)}</h2>`;
|
|
6170
|
+
html += `<h2 style="font-size: 16px; font-weight: 700; color: #1e3a8a; margin: 16px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify6__default.default.sanitize(line, sanitizeOptions)}</h2>`;
|
|
5678
6171
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
5679
6172
|
if (!inList) {
|
|
5680
6173
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
5681
6174
|
inList = true;
|
|
5682
6175
|
}
|
|
5683
6176
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
5684
|
-
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6__default.default.sanitize(bulletText)}</li>`;
|
|
6177
|
+
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6__default.default.sanitize(bulletText, sanitizeOptions)}</li>`;
|
|
5685
6178
|
} else {
|
|
5686
6179
|
if (inList) {
|
|
5687
6180
|
html += "</ul>";
|
|
5688
6181
|
inList = false;
|
|
5689
6182
|
}
|
|
5690
|
-
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6__default.default.sanitize(line)}</p>`;
|
|
6183
|
+
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6__default.default.sanitize(line, sanitizeOptions)}</p>`;
|
|
5691
6184
|
}
|
|
5692
6185
|
i++;
|
|
5693
6186
|
}
|
|
@@ -6260,6 +6753,7 @@ exports.excelPlugin = excelPlugin;
|
|
|
6260
6753
|
exports.extractExtension = extractExtension;
|
|
6261
6754
|
exports.formatFileSize = formatFileSize;
|
|
6262
6755
|
exports.getDefaultPlugins = getDefaultPlugins;
|
|
6756
|
+
exports.getTransferPayload = getTransferPayload;
|
|
6263
6757
|
exports.htmlPreviewPlugin = htmlPreviewPlugin;
|
|
6264
6758
|
exports.markdownPlugin = markdownPlugin;
|
|
6265
6759
|
exports.mediaPlugin = mediaPlugin;
|
|
@@ -6272,6 +6766,7 @@ exports.printElement = printElement;
|
|
|
6272
6766
|
exports.rtfPlugin = rtfPlugin;
|
|
6273
6767
|
exports.sanitizeHTML = sanitizeHTML;
|
|
6274
6768
|
exports.sanitizeSVG = sanitizeSVG;
|
|
6769
|
+
exports.saveTransferPayload = saveTransferPayload;
|
|
6275
6770
|
exports.sourceToArrayBuffer = sourceToArrayBuffer;
|
|
6276
6771
|
exports.threeDPlugin = threeDPlugin;
|
|
6277
6772
|
//# sourceMappingURL=index.cjs.map
|