@files-preview-app/preview-file 1.2.9 → 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 +505 -147
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.js +504 -147
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +548 -147
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +546 -148
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +505 -147
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +504 -147
- package/dist/react.js.map +1 -1
- package/dist/vue.cjs +505 -147
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +504 -147
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
package/dist/angular.cjs
CHANGED
|
@@ -18,6 +18,7 @@ var OBJLoader_js = require('three/examples/jsm/loaders/OBJLoader.js');
|
|
|
18
18
|
var OrbitControls_js = require('three/examples/jsm/controls/OrbitControls.js');
|
|
19
19
|
var RTFJS = require('rtf.js/dist/RTFJS.bundle.js');
|
|
20
20
|
|
|
21
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
21
22
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
22
23
|
|
|
23
24
|
function _interopNamespace(e) {
|
|
@@ -417,16 +418,21 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
417
418
|
metadata.mimeType = source.type || void 0;
|
|
418
419
|
metadata.extension = extractExtension(source.name);
|
|
419
420
|
buffer = await source.arrayBuffer();
|
|
420
|
-
} else if (source instanceof Blob) {
|
|
421
|
+
} else if (source instanceof Blob || source && typeof source.arrayBuffer === "function" && typeof source.size === "number") {
|
|
421
422
|
metadata.size = source.size;
|
|
422
423
|
metadata.mimeType = source.type || void 0;
|
|
424
|
+
if (source.name) {
|
|
425
|
+
metadata.name = source.name;
|
|
426
|
+
metadata.extension = extractExtension(source.name);
|
|
427
|
+
}
|
|
423
428
|
buffer = await source.arrayBuffer();
|
|
424
|
-
} else if (source instanceof ArrayBuffer) {
|
|
429
|
+
} else if (source instanceof ArrayBuffer || Object.prototype.toString.call(source) === "[object ArrayBuffer]" || source && typeof source.byteLength === "number" && typeof source.slice === "function") {
|
|
425
430
|
buffer = source;
|
|
426
|
-
} else if (source instanceof Uint8Array) {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
431
|
+
} else if (source instanceof Uint8Array || ArrayBuffer.isView(source)) {
|
|
432
|
+
const view = source;
|
|
433
|
+
buffer = view.buffer.slice(
|
|
434
|
+
view.byteOffset,
|
|
435
|
+
view.byteOffset + view.byteLength
|
|
430
436
|
);
|
|
431
437
|
} else {
|
|
432
438
|
throw new Error("Unsupported file source type");
|
|
@@ -511,6 +517,45 @@ function createElement(tag, attrs, ...children) {
|
|
|
511
517
|
}
|
|
512
518
|
return el;
|
|
513
519
|
}
|
|
520
|
+
var DB_NAME = "PreviewFileTransferDB";
|
|
521
|
+
var DB_STORE = "transfers";
|
|
522
|
+
function openDB() {
|
|
523
|
+
return new Promise((resolve, reject) => {
|
|
524
|
+
if (typeof indexedDB === "undefined") {
|
|
525
|
+
return reject(new Error("IndexedDB is not available"));
|
|
526
|
+
}
|
|
527
|
+
const req = indexedDB.open(DB_NAME, 1);
|
|
528
|
+
req.onupgradeneeded = () => {
|
|
529
|
+
const db = req.result;
|
|
530
|
+
if (!db.objectStoreNames.contains(DB_STORE)) {
|
|
531
|
+
db.createObjectStore(DB_STORE, { keyPath: "id" });
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
req.onsuccess = () => resolve(req.result);
|
|
535
|
+
req.onerror = () => reject(req.error);
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
async function saveTransferPayload(id, payload) {
|
|
539
|
+
if (typeof window !== "undefined") {
|
|
540
|
+
try {
|
|
541
|
+
window[id] = payload;
|
|
542
|
+
window.__lastTransfer = payload;
|
|
543
|
+
} catch {
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
try {
|
|
547
|
+
const db = await openDB();
|
|
548
|
+
return new Promise((resolve, reject) => {
|
|
549
|
+
const tx = db.transaction(DB_STORE, "readwrite");
|
|
550
|
+
const store = tx.objectStore(DB_STORE);
|
|
551
|
+
store.put({ id, ...payload, timestamp: Date.now() });
|
|
552
|
+
tx.oncomplete = () => resolve();
|
|
553
|
+
tx.onerror = () => reject(tx.error);
|
|
554
|
+
});
|
|
555
|
+
} catch (e) {
|
|
556
|
+
console.warn("[saveTransferPayload] IndexedDB store warning:", e);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
514
559
|
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>`;
|
|
515
560
|
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>`;
|
|
516
561
|
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>`;
|
|
@@ -530,6 +575,7 @@ var ICON_COPY = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" str
|
|
|
530
575
|
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>`;
|
|
531
576
|
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>`;
|
|
532
577
|
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>`;
|
|
578
|
+
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>`;
|
|
533
579
|
var ICON_MAP = {
|
|
534
580
|
"zoom-in": ICON_ZOOM_IN,
|
|
535
581
|
"zoom-out": ICON_ZOOM_OUT,
|
|
@@ -556,7 +602,9 @@ var ICON_MAP = {
|
|
|
556
602
|
"forward-10": ICON_FAST_FORWARD,
|
|
557
603
|
"rewind": ICON_REWIND,
|
|
558
604
|
"replay-10": ICON_REWIND,
|
|
559
|
-
"speed": ICON_SPEED
|
|
605
|
+
"speed": ICON_SPEED,
|
|
606
|
+
"open-window": ICON_EXTERNAL_WINDOW,
|
|
607
|
+
"external-window": ICON_EXTERNAL_WINDOW
|
|
560
608
|
};
|
|
561
609
|
var ToolbarController = class {
|
|
562
610
|
el;
|
|
@@ -773,7 +821,7 @@ var ThumbnailPanel = class {
|
|
|
773
821
|
}
|
|
774
822
|
}
|
|
775
823
|
};
|
|
776
|
-
var FilePreviewViewer = class {
|
|
824
|
+
var FilePreviewViewer = class _FilePreviewViewer {
|
|
777
825
|
plugins = [];
|
|
778
826
|
activeInstance = null;
|
|
779
827
|
abortController = null;
|
|
@@ -810,6 +858,7 @@ var FilePreviewViewer = class {
|
|
|
810
858
|
* Preview a file in the given container element.
|
|
811
859
|
*/
|
|
812
860
|
async preview(container, source, options = {}) {
|
|
861
|
+
this.currentOptions = options;
|
|
813
862
|
this.abort();
|
|
814
863
|
this.abortController = new AbortController();
|
|
815
864
|
const { signal } = this.abortController;
|
|
@@ -819,7 +868,10 @@ var FilePreviewViewer = class {
|
|
|
819
868
|
this.showLoading();
|
|
820
869
|
try {
|
|
821
870
|
const { buffer, metadata } = await sourceToArrayBuffer(source, signal);
|
|
822
|
-
|
|
871
|
+
if (options.metadata) {
|
|
872
|
+
Object.assign(metadata, options.metadata);
|
|
873
|
+
}
|
|
874
|
+
this.currentBuffer = buffer.slice(0);
|
|
823
875
|
this.currentMetadata = metadata;
|
|
824
876
|
if (signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
825
877
|
const fileInfo = { metadata, buffer };
|
|
@@ -849,6 +901,7 @@ var FilePreviewViewer = class {
|
|
|
849
901
|
}
|
|
850
902
|
});
|
|
851
903
|
this.activeInstance = instance;
|
|
904
|
+
instance.openInSeparateWindow = () => this.openInSeparateWindow();
|
|
852
905
|
this.hideLoading();
|
|
853
906
|
this.eventEmitter.emit("loaded", { metadata, plugin: matchedPlugin.id });
|
|
854
907
|
if (options.showToolbar !== false && this.toolbar) {
|
|
@@ -858,26 +911,16 @@ var FilePreviewViewer = class {
|
|
|
858
911
|
actions.push({
|
|
859
912
|
id: "fullscreen",
|
|
860
913
|
icon: "fullscreen",
|
|
861
|
-
label: "
|
|
914
|
+
label: "Fullscreen",
|
|
862
915
|
type: "button",
|
|
863
916
|
group: "view",
|
|
864
|
-
execute:
|
|
917
|
+
execute: () => {
|
|
865
918
|
try {
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
if (this.wrapperEl?.requestFullscreen) {
|
|
870
|
-
await this.wrapperEl.requestFullscreen().catch(() => {
|
|
871
|
-
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
872
|
-
});
|
|
873
|
-
} else {
|
|
874
|
-
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
875
|
-
}
|
|
919
|
+
if (!document.fullscreenElement) {
|
|
920
|
+
this.wrapperEl?.requestFullscreen?.();
|
|
921
|
+
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
876
922
|
} else {
|
|
877
|
-
|
|
878
|
-
await document.exitFullscreen().catch(() => {
|
|
879
|
-
});
|
|
880
|
-
}
|
|
923
|
+
document.exitFullscreen?.();
|
|
881
924
|
this.wrapperEl?.classList.remove("fp-fullscreen-active");
|
|
882
925
|
}
|
|
883
926
|
} catch {
|
|
@@ -889,6 +932,28 @@ var FilePreviewViewer = class {
|
|
|
889
932
|
}
|
|
890
933
|
});
|
|
891
934
|
}
|
|
935
|
+
const openWinAction = actions.find((a) => a.id === "open-window");
|
|
936
|
+
if (openWinAction) {
|
|
937
|
+
if (options?._isSeparateWindow) {
|
|
938
|
+
const idx = actions.indexOf(openWinAction);
|
|
939
|
+
if (idx !== -1) actions.splice(idx, 1);
|
|
940
|
+
} else {
|
|
941
|
+
openWinAction.execute = () => {
|
|
942
|
+
this.openInSeparateWindow();
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
} else if (!options?._isSeparateWindow) {
|
|
946
|
+
actions.push({
|
|
947
|
+
id: "open-window",
|
|
948
|
+
icon: "open-window",
|
|
949
|
+
label: "Open in Separate Full Window",
|
|
950
|
+
type: "button",
|
|
951
|
+
group: "actions",
|
|
952
|
+
execute: () => {
|
|
953
|
+
this.openInSeparateWindow();
|
|
954
|
+
}
|
|
955
|
+
});
|
|
956
|
+
}
|
|
892
957
|
this.toolbar.update(actions);
|
|
893
958
|
this.toolbar.show();
|
|
894
959
|
}
|
|
@@ -921,6 +986,104 @@ var FilePreviewViewer = class {
|
|
|
921
986
|
throw error;
|
|
922
987
|
}
|
|
923
988
|
}
|
|
989
|
+
/**
|
|
990
|
+
* Opens the current file preview in a separate full browser window.
|
|
991
|
+
*/
|
|
992
|
+
openInSeparateWindow() {
|
|
993
|
+
if (!this.currentBuffer) {
|
|
994
|
+
console.warn("[FilePreviewViewer] No active file buffer to open in separate window");
|
|
995
|
+
return null;
|
|
996
|
+
}
|
|
997
|
+
if (this.currentOptions.onOpenSeparateWindow) {
|
|
998
|
+
return this.currentOptions.onOpenSeparateWindow({
|
|
999
|
+
buffer: this.currentBuffer,
|
|
1000
|
+
metadata: this.currentMetadata || { name: "Document" },
|
|
1001
|
+
options: this.currentOptions
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
const transferId = "fp_win_" + Date.now() + "_" + Math.random().toString(36).slice(2, 8);
|
|
1005
|
+
let clonedBuffer;
|
|
1006
|
+
try {
|
|
1007
|
+
clonedBuffer = this.currentBuffer.slice(0);
|
|
1008
|
+
} catch {
|
|
1009
|
+
clonedBuffer = this.currentBuffer;
|
|
1010
|
+
}
|
|
1011
|
+
const payload = {
|
|
1012
|
+
buffer: clonedBuffer,
|
|
1013
|
+
metadata: this.currentMetadata ? { ...this.currentMetadata } : void 0,
|
|
1014
|
+
options: { ...this.currentOptions, _isSeparateWindow: true }
|
|
1015
|
+
};
|
|
1016
|
+
if (typeof window !== "undefined") {
|
|
1017
|
+
try {
|
|
1018
|
+
window[transferId] = payload;
|
|
1019
|
+
window.__lastTransfer = payload;
|
|
1020
|
+
} catch {
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
saveTransferPayload(transferId, payload).catch((err) => {
|
|
1024
|
+
console.warn("[FilePreviewViewer] Transfer payload save warning:", err);
|
|
1025
|
+
});
|
|
1026
|
+
let targetUrl = null;
|
|
1027
|
+
if (this.currentOptions.standaloneViewerUrl) {
|
|
1028
|
+
const u = new URL(this.currentOptions.standaloneViewerUrl, window.location.href);
|
|
1029
|
+
u.searchParams.set("mode", "fullscreen");
|
|
1030
|
+
u.searchParams.set("transferId", transferId);
|
|
1031
|
+
targetUrl = u.toString();
|
|
1032
|
+
} else if (typeof window !== "undefined" && window.location?.href && !window.location.href.startsWith("about:")) {
|
|
1033
|
+
const u = new URL(window.location.href);
|
|
1034
|
+
u.searchParams.set("mode", "fullscreen");
|
|
1035
|
+
u.searchParams.set("transferId", transferId);
|
|
1036
|
+
targetUrl = u.toString();
|
|
1037
|
+
}
|
|
1038
|
+
if (targetUrl) {
|
|
1039
|
+
const newWin2 = window.open(targetUrl, "_blank");
|
|
1040
|
+
if (!newWin2) {
|
|
1041
|
+
alert("Popup blocker prevented opening the preview in a separate window. Please allow popups for this site.");
|
|
1042
|
+
return null;
|
|
1043
|
+
}
|
|
1044
|
+
return newWin2;
|
|
1045
|
+
}
|
|
1046
|
+
const title = (this.currentMetadata?.name || "Document Preview") + " - Full Preview";
|
|
1047
|
+
const newWin = window.open("", "_blank");
|
|
1048
|
+
if (!newWin) {
|
|
1049
|
+
alert("Popup blocker prevented opening the preview in a separate window. Please allow popups for this site.");
|
|
1050
|
+
return null;
|
|
1051
|
+
}
|
|
1052
|
+
newWin.document.title = title;
|
|
1053
|
+
newWin.document.body.style.margin = "0";
|
|
1054
|
+
newWin.document.body.style.padding = "0";
|
|
1055
|
+
newWin.document.body.style.width = "100vw";
|
|
1056
|
+
newWin.document.body.style.height = "100vh";
|
|
1057
|
+
newWin.document.body.style.overflow = "hidden";
|
|
1058
|
+
newWin.document.body.style.backgroundColor = "#f8fafc";
|
|
1059
|
+
const headNodes = document.querySelectorAll('link[rel="stylesheet"], style');
|
|
1060
|
+
headNodes.forEach((node) => {
|
|
1061
|
+
newWin.document.head.appendChild(node.cloneNode(true));
|
|
1062
|
+
});
|
|
1063
|
+
const root = newWin.document.createElement("div");
|
|
1064
|
+
root.id = "full-window-preview-root";
|
|
1065
|
+
root.style.width = "100%";
|
|
1066
|
+
root.style.height = "100%";
|
|
1067
|
+
root.style.overflow = "hidden";
|
|
1068
|
+
newWin.document.body.appendChild(root);
|
|
1069
|
+
const separateViewer = new _FilePreviewViewer();
|
|
1070
|
+
for (const plugin of this.plugins) {
|
|
1071
|
+
separateViewer.registerPlugin(plugin);
|
|
1072
|
+
}
|
|
1073
|
+
separateViewer.preview(root, this.currentBuffer.slice(0), {
|
|
1074
|
+
...this.currentOptions,
|
|
1075
|
+
showToolbar: true,
|
|
1076
|
+
toolbarPosition: "top",
|
|
1077
|
+
metadata: this.currentMetadata || void 0,
|
|
1078
|
+
_isSeparateWindow: true
|
|
1079
|
+
}).catch((err) => {
|
|
1080
|
+
console.error("[FilePreviewViewer] Error rendering in separate window:", err);
|
|
1081
|
+
});
|
|
1082
|
+
newWin.addEventListener("beforeunload", () => {
|
|
1083
|
+
separateViewer.destroy();
|
|
1084
|
+
});
|
|
1085
|
+
return newWin;
|
|
1086
|
+
}
|
|
924
1087
|
/**
|
|
925
1088
|
* Subscribe to viewer events.
|
|
926
1089
|
*/
|
|
@@ -1326,8 +1489,20 @@ var CfbfReader = class {
|
|
|
1326
1489
|
}
|
|
1327
1490
|
};
|
|
1328
1491
|
if (typeof window !== "undefined" && pdfjsLib__namespace.GlobalWorkerOptions) {
|
|
1329
|
-
if (!pdfjsLib__namespace.GlobalWorkerOptions.workerSrc) {
|
|
1330
|
-
|
|
1492
|
+
if (!pdfjsLib__namespace.GlobalWorkerOptions.workerPort && !pdfjsLib__namespace.GlobalWorkerOptions.workerSrc) {
|
|
1493
|
+
const customWorker = window.__PDF_WORKER_SRC__;
|
|
1494
|
+
if (customWorker) {
|
|
1495
|
+
pdfjsLib__namespace.GlobalWorkerOptions.workerSrc = customWorker;
|
|
1496
|
+
} else {
|
|
1497
|
+
try {
|
|
1498
|
+
pdfjsLib__namespace.GlobalWorkerOptions.workerPort = new Worker(
|
|
1499
|
+
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('angular.cjs', document.baseURI).href))),
|
|
1500
|
+
{ type: "module" }
|
|
1501
|
+
);
|
|
1502
|
+
} catch {
|
|
1503
|
+
pdfjsLib__namespace.GlobalWorkerOptions.workerSrc = "./pdf.worker.min.mjs";
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1331
1506
|
}
|
|
1332
1507
|
}
|
|
1333
1508
|
var PdfPlugin = class {
|
|
@@ -1421,6 +1596,14 @@ var PdfPlugin = class {
|
|
|
1421
1596
|
type: "button",
|
|
1422
1597
|
group: "actions",
|
|
1423
1598
|
execute: () => instance.print?.()
|
|
1599
|
+
},
|
|
1600
|
+
{
|
|
1601
|
+
id: "open-window",
|
|
1602
|
+
icon: "open-window",
|
|
1603
|
+
label: "Open in Separate Full Window",
|
|
1604
|
+
type: "button",
|
|
1605
|
+
group: "actions",
|
|
1606
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
1424
1607
|
}
|
|
1425
1608
|
];
|
|
1426
1609
|
}
|
|
@@ -1470,18 +1653,21 @@ var PdfPlugin = class {
|
|
|
1470
1653
|
indicator.style.pointerEvents = "none";
|
|
1471
1654
|
container.appendChild(indicator);
|
|
1472
1655
|
ctx.container.appendChild(container);
|
|
1656
|
+
const standardFontsUrl = typeof window !== "undefined" && window.__PDF_STANDARD_FONTS_URL__ || "./standard_fonts/";
|
|
1657
|
+
const cmapsUrl = typeof window !== "undefined" && window.__PDF_CMAPS_URL__ || "./cmaps/";
|
|
1473
1658
|
const loadingTask = pdfjsLib__namespace.getDocument({
|
|
1474
|
-
data: new Uint8Array(ctx.buffer),
|
|
1475
|
-
cMapUrl:
|
|
1659
|
+
data: new Uint8Array(ctx.buffer.slice(0)),
|
|
1660
|
+
cMapUrl: cmapsUrl,
|
|
1476
1661
|
cMapPacked: true,
|
|
1477
|
-
standardFontDataUrl:
|
|
1662
|
+
standardFontDataUrl: standardFontsUrl,
|
|
1663
|
+
verbosity: 0
|
|
1478
1664
|
});
|
|
1479
1665
|
const pdfDoc = await loadingTask.promise;
|
|
1480
1666
|
const totalPages = Math.max(1, pdfDoc.numPages);
|
|
1481
1667
|
let currentPage = 1;
|
|
1482
1668
|
let zoomScale = 1;
|
|
1483
1669
|
let rotation = 0;
|
|
1484
|
-
let fitMode = "
|
|
1670
|
+
let fitMode = "page";
|
|
1485
1671
|
let currentRenderTask = null;
|
|
1486
1672
|
const renderPage = async (pageNum) => {
|
|
1487
1673
|
if (currentRenderTask) {
|
|
@@ -1501,15 +1687,15 @@ var PdfPlugin = class {
|
|
|
1501
1687
|
const containerWidth = container.clientWidth || 900;
|
|
1502
1688
|
const containerHeight = container.clientHeight || 700;
|
|
1503
1689
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1504
|
-
const availWidth = Math.max(
|
|
1505
|
-
const availHeight = Math.max(
|
|
1690
|
+
const availWidth = Math.max(320, containerWidth - 48);
|
|
1691
|
+
const availHeight = Math.max(550, containerHeight - 88);
|
|
1506
1692
|
const scaleW = availWidth / unscaledVp.width;
|
|
1507
1693
|
const scaleH = availHeight / unscaledVp.height;
|
|
1508
1694
|
let fitScale;
|
|
1509
1695
|
if (fitMode === "page") {
|
|
1510
|
-
fitScale = Math.max(0.
|
|
1696
|
+
fitScale = Math.max(0.4, Math.min(scaleW, scaleH));
|
|
1511
1697
|
} else {
|
|
1512
|
-
fitScale = Math.max(0.65, Math.min(1.
|
|
1698
|
+
fitScale = Math.max(0.65, Math.min(1.25, scaleW));
|
|
1513
1699
|
}
|
|
1514
1700
|
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1515
1701
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
@@ -1535,7 +1721,7 @@ var PdfPlugin = class {
|
|
|
1535
1721
|
currentRenderTask = null;
|
|
1536
1722
|
}
|
|
1537
1723
|
};
|
|
1538
|
-
|
|
1724
|
+
renderPage(1);
|
|
1539
1725
|
let resizeTimer = null;
|
|
1540
1726
|
const resizeObserver = new ResizeObserver(() => {
|
|
1541
1727
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
@@ -1579,7 +1765,7 @@ var PdfPlugin = class {
|
|
|
1579
1765
|
renderPage(currentPage);
|
|
1580
1766
|
},
|
|
1581
1767
|
fitToPage: () => {
|
|
1582
|
-
fitMode = fitMode === "
|
|
1768
|
+
fitMode = fitMode === "page" ? "width" : "page";
|
|
1583
1769
|
zoomScale = 1;
|
|
1584
1770
|
rotation = 0;
|
|
1585
1771
|
renderPage(currentPage);
|
|
@@ -2056,6 +2242,14 @@ var DocxPlugin = class {
|
|
|
2056
2242
|
type: "button",
|
|
2057
2243
|
group: "actions",
|
|
2058
2244
|
execute: () => instance.print?.()
|
|
2245
|
+
},
|
|
2246
|
+
{
|
|
2247
|
+
id: "open-window",
|
|
2248
|
+
icon: "open-window",
|
|
2249
|
+
label: "Open in Separate Full Window",
|
|
2250
|
+
type: "button",
|
|
2251
|
+
group: "actions",
|
|
2252
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
2059
2253
|
}
|
|
2060
2254
|
);
|
|
2061
2255
|
return actions;
|
|
@@ -2115,6 +2309,31 @@ var DocxPlugin = class {
|
|
|
2115
2309
|
}
|
|
2116
2310
|
if (wrapper.children.length > 0 && (wrapper.textContent?.trim().length ?? 0) > 0) {
|
|
2117
2311
|
renderedSuccessfully = true;
|
|
2312
|
+
try {
|
|
2313
|
+
const unzipped = fflate.unzipSync(new Uint8Array(ctx.buffer));
|
|
2314
|
+
const chartKeys = Object.keys(unzipped).filter((k) => k.replace(/^[./\\]+/, "").toLowerCase().startsWith("word/charts/chart") && k.endsWith(".xml")).sort();
|
|
2315
|
+
if (chartKeys.length > 0) {
|
|
2316
|
+
const allDivs = Array.from(wrapper.querySelectorAll("div"));
|
|
2317
|
+
const emptyContainers = allDivs.filter((div) => {
|
|
2318
|
+
const st = div.getAttribute("style") || "";
|
|
2319
|
+
return st.includes("width:") && st.includes("height:") && div.children.length === 0 && (div.textContent?.trim().length ?? 0) === 0;
|
|
2320
|
+
});
|
|
2321
|
+
chartKeys.forEach((cKey, idx) => {
|
|
2322
|
+
const target = emptyContainers[idx];
|
|
2323
|
+
if (target) {
|
|
2324
|
+
const xmlStr = fflate.strFromU8(unzipped[cKey]);
|
|
2325
|
+
const svg = this.parseAndRenderChartSvg(xmlStr);
|
|
2326
|
+
if (svg) {
|
|
2327
|
+
target.innerHTML = svg;
|
|
2328
|
+
target.style.display = "block";
|
|
2329
|
+
target.style.margin = "12px auto";
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2334
|
+
} catch (chartErr) {
|
|
2335
|
+
console.warn("[DocxPlugin] Non-critical error rendering DrawingML charts:", chartErr);
|
|
2336
|
+
}
|
|
2118
2337
|
}
|
|
2119
2338
|
} catch (err) {
|
|
2120
2339
|
console.warn("[DocxPlugin] docx-preview failed, triggering native fallback:", err);
|
|
@@ -2146,64 +2365,74 @@ var DocxPlugin = class {
|
|
|
2146
2365
|
}
|
|
2147
2366
|
let sections = Array.from(wrapper.querySelectorAll("section.docx"));
|
|
2148
2367
|
const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
|
|
2149
|
-
if (sections.length
|
|
2150
|
-
const
|
|
2151
|
-
const
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
const
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
nextSec.
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
nextArticle
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
nextSec.appendChild(
|
|
2368
|
+
if (sections.length > 0 && cards.length === 0) {
|
|
2369
|
+
const finalSections = [];
|
|
2370
|
+
for (const singleSec of sections) {
|
|
2371
|
+
const contentContainer = singleSec.querySelector("article") || singleSec;
|
|
2372
|
+
const children = Array.from(contentContainer.children);
|
|
2373
|
+
const pageH = singleSec.offsetHeight > 1300 ? 1122 : Math.max(1056, singleSec.offsetHeight);
|
|
2374
|
+
const secH = singleSec.scrollHeight || singleSec.offsetHeight;
|
|
2375
|
+
if (secH > pageH * 1.25 && children.length > 1) {
|
|
2376
|
+
const childHeights = children.map((c) => {
|
|
2377
|
+
const rectH = c.getBoundingClientRect().height;
|
|
2378
|
+
const offH = c.offsetHeight;
|
|
2379
|
+
const textLen = c.textContent?.trim().length || 0;
|
|
2380
|
+
const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
|
|
2381
|
+
return Math.max(rectH, offH, estH);
|
|
2382
|
+
});
|
|
2383
|
+
const parent = singleSec.parentElement || wrapper;
|
|
2384
|
+
const headerEl = singleSec.querySelector("header");
|
|
2385
|
+
const footerEl = singleSec.querySelector("footer");
|
|
2386
|
+
contentContainer.innerHTML = "";
|
|
2387
|
+
singleSec.style.minHeight = `${pageH}px`;
|
|
2388
|
+
singleSec.style.boxSizing = "border-box";
|
|
2389
|
+
let curContent = contentContainer;
|
|
2390
|
+
let curSec = singleSec;
|
|
2391
|
+
let curH = 0;
|
|
2392
|
+
const maxH = pageH - 140;
|
|
2393
|
+
finalSections.push(singleSec);
|
|
2394
|
+
for (let i = 0; i < children.length; i++) {
|
|
2395
|
+
const child = children[i];
|
|
2396
|
+
const chH = childHeights[i];
|
|
2397
|
+
curContent.appendChild(child);
|
|
2398
|
+
curH += chH;
|
|
2399
|
+
if (curH >= maxH && i < children.length - 1) {
|
|
2400
|
+
const nextSec = document.createElement("section");
|
|
2401
|
+
nextSec.className = singleSec.className;
|
|
2402
|
+
nextSec.style.cssText = singleSec.style.cssText;
|
|
2403
|
+
nextSec.style.minHeight = `${pageH}px`;
|
|
2404
|
+
nextSec.style.boxSizing = "border-box";
|
|
2405
|
+
nextSec.style.backgroundColor = "#ffffff";
|
|
2406
|
+
nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
|
|
2407
|
+
nextSec.style.borderRadius = "4px";
|
|
2408
|
+
nextSec.style.marginBottom = "24px";
|
|
2409
|
+
if (headerEl) {
|
|
2410
|
+
nextSec.appendChild(headerEl.cloneNode(true));
|
|
2411
|
+
}
|
|
2412
|
+
const nextArticle = document.createElement("article");
|
|
2413
|
+
if (contentContainer.tagName.toLowerCase() === "article") {
|
|
2414
|
+
nextArticle.style.cssText = contentContainer.style.cssText;
|
|
2415
|
+
}
|
|
2416
|
+
nextSec.appendChild(nextArticle);
|
|
2417
|
+
if (footerEl) {
|
|
2418
|
+
nextSec.appendChild(footerEl.cloneNode(true));
|
|
2419
|
+
}
|
|
2420
|
+
if (curSec.nextSibling) {
|
|
2421
|
+
parent.insertBefore(nextSec, curSec.nextSibling);
|
|
2422
|
+
} else {
|
|
2423
|
+
parent.appendChild(nextSec);
|
|
2424
|
+
}
|
|
2425
|
+
finalSections.push(nextSec);
|
|
2426
|
+
curSec = nextSec;
|
|
2427
|
+
curContent = nextArticle;
|
|
2428
|
+
curH = 0;
|
|
2198
2429
|
}
|
|
2199
|
-
parent.appendChild(nextSec);
|
|
2200
|
-
newSections.push(nextSec);
|
|
2201
|
-
curContent = nextArticle;
|
|
2202
|
-
curH = 0;
|
|
2203
2430
|
}
|
|
2431
|
+
} else {
|
|
2432
|
+
finalSections.push(singleSec);
|
|
2204
2433
|
}
|
|
2205
|
-
sections = newSections;
|
|
2206
2434
|
}
|
|
2435
|
+
sections = finalSections;
|
|
2207
2436
|
}
|
|
2208
2437
|
const pageElements = sections.length > 0 ? sections : cards;
|
|
2209
2438
|
const totalPages = Math.max(1, pageElements.length);
|
|
@@ -2595,6 +2824,88 @@ var DocxPlugin = class {
|
|
|
2595
2824
|
}
|
|
2596
2825
|
return result;
|
|
2597
2826
|
}
|
|
2827
|
+
parseAndRenderChartSvg(xmlStr, width = 500, height = 260) {
|
|
2828
|
+
const catMatches = [...xmlStr.matchAll(/<c:cat>[\s\S]*?<c:strCache>([\s\S]*?)<\/c:strCache>/g)];
|
|
2829
|
+
let categories = [];
|
|
2830
|
+
if (catMatches.length > 0) {
|
|
2831
|
+
categories = [...catMatches[0][1].matchAll(/<c:v>([^<]+)<\/c:v>/g)].map((m) => m[1]);
|
|
2832
|
+
}
|
|
2833
|
+
if (categories.length === 0) {
|
|
2834
|
+
categories = ["Category 1", "Category 2", "Category 3", "Category 4"];
|
|
2835
|
+
}
|
|
2836
|
+
const defaultColors = ["#004586", "#ff420e", "#ffd320", "#579d1c", "#7e0021", "#83caff"];
|
|
2837
|
+
const sers = [...xmlStr.matchAll(/<c:ser>([\s\S]*?)<\/c:ser>/g)];
|
|
2838
|
+
const series = [];
|
|
2839
|
+
sers.forEach((s, sIdx) => {
|
|
2840
|
+
const titleMatch = s[1].match(/<c:tx>[\s\S]*?<c:v>([^<]+)<\/c:v>/);
|
|
2841
|
+
const title = titleMatch ? titleMatch[1] : `Series ${sIdx + 1}`;
|
|
2842
|
+
const clrMatch = s[1].match(/<a:srgbClr\s+val="([^"]+)"/);
|
|
2843
|
+
const color = clrMatch ? "#" + clrMatch[1] : defaultColors[sIdx % defaultColors.length];
|
|
2844
|
+
const valMatch = s[1].match(/<c:val>[\s\S]*?<c:numCache>([\s\S]*?)<\/c:numCache>/);
|
|
2845
|
+
let values = [];
|
|
2846
|
+
if (valMatch) {
|
|
2847
|
+
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);
|
|
2848
|
+
}
|
|
2849
|
+
series.push({ title, color, values });
|
|
2850
|
+
});
|
|
2851
|
+
if (series.length === 0) return "";
|
|
2852
|
+
let maxVal = 10;
|
|
2853
|
+
series.forEach((s) => s.values.forEach((v) => {
|
|
2854
|
+
if (v > maxVal) maxVal = v;
|
|
2855
|
+
}));
|
|
2856
|
+
maxVal = Math.ceil(maxVal * 1.15);
|
|
2857
|
+
if (maxVal % 2 !== 0) maxVal++;
|
|
2858
|
+
const padLeft = 45;
|
|
2859
|
+
const padBottom = 55;
|
|
2860
|
+
const padTop = 20;
|
|
2861
|
+
const padRight = 20;
|
|
2862
|
+
const plotW = width - padLeft - padRight;
|
|
2863
|
+
const plotH = height - padTop - padBottom;
|
|
2864
|
+
const yTicks = 5;
|
|
2865
|
+
let gridLines = "";
|
|
2866
|
+
for (let i = 0; i <= yTicks; i++) {
|
|
2867
|
+
const val = maxVal / yTicks * i;
|
|
2868
|
+
const y = padTop + plotH - val / maxVal * plotH;
|
|
2869
|
+
gridLines += `<line x1="${padLeft}" y1="${y}" x2="${padLeft + plotW}" y2="${y}" stroke="#e2e8f0" stroke-width="1" />`;
|
|
2870
|
+
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>`;
|
|
2871
|
+
}
|
|
2872
|
+
const numCats = categories.length;
|
|
2873
|
+
const numSers = series.length;
|
|
2874
|
+
const groupW = plotW / numCats;
|
|
2875
|
+
const barW = Math.max(8, Math.min(28, groupW * 0.7 / numSers));
|
|
2876
|
+
const groupPad = (groupW - barW * numSers) / 2;
|
|
2877
|
+
let bars = "";
|
|
2878
|
+
let catLabels = "";
|
|
2879
|
+
for (let c = 0; c < numCats; c++) {
|
|
2880
|
+
const catX = padLeft + c * groupW;
|
|
2881
|
+
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>`;
|
|
2882
|
+
for (let s = 0; s < numSers; s++) {
|
|
2883
|
+
const val = series[s].values[c] ?? 0;
|
|
2884
|
+
const bH = Math.max(0, val / maxVal * plotH);
|
|
2885
|
+
const bX = catX + groupPad + s * barW;
|
|
2886
|
+
const bY = padTop + plotH - bH;
|
|
2887
|
+
bars += `<rect x="${bX}" y="${bY}" width="${barW - 2}" height="${bH}" fill="${series[s].color}" rx="1" />`;
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
let legend = "";
|
|
2891
|
+
const legY = height - 12;
|
|
2892
|
+
let legX = padLeft + (plotW - numSers * 100) / 2;
|
|
2893
|
+
series.forEach((s) => {
|
|
2894
|
+
legend += `<rect x="${legX}" y="${legY - 9}" width="10" height="10" fill="${s.color}" rx="2" />`;
|
|
2895
|
+
legend += `<text x="${legX + 15}" y="${legY}" font-size="11" fill="#475569" font-family="Calibri, sans-serif">${s.title}</text>`;
|
|
2896
|
+
legX += 95;
|
|
2897
|
+
});
|
|
2898
|
+
return `
|
|
2899
|
+
<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">
|
|
2900
|
+
${gridLines}
|
|
2901
|
+
<line x1="${padLeft}" y1="${padTop + plotH}" x2="${padLeft + plotW}" y2="${padTop + plotH}" stroke="#94a3b8" stroke-width="1.5" />
|
|
2902
|
+
<line x1="${padLeft}" y1="${padTop}" x2="${padLeft}" y2="${padTop + plotH}" stroke="#94a3b8" stroke-width="1.5" />
|
|
2903
|
+
${bars}
|
|
2904
|
+
${catLabels}
|
|
2905
|
+
${legend}
|
|
2906
|
+
</svg>
|
|
2907
|
+
`.trim();
|
|
2908
|
+
}
|
|
2598
2909
|
};
|
|
2599
2910
|
function docxPlugin() {
|
|
2600
2911
|
return new DocxPlugin();
|
|
@@ -3161,6 +3472,16 @@ var CodePlugin = class {
|
|
|
3161
3472
|
execute: () => {
|
|
3162
3473
|
instance.print?.();
|
|
3163
3474
|
}
|
|
3475
|
+
},
|
|
3476
|
+
{
|
|
3477
|
+
id: "open-window",
|
|
3478
|
+
icon: "open-window",
|
|
3479
|
+
label: "Open in Separate Full Window",
|
|
3480
|
+
type: "button",
|
|
3481
|
+
group: "actions",
|
|
3482
|
+
execute: () => {
|
|
3483
|
+
instance.openInSeparateWindow?.();
|
|
3484
|
+
}
|
|
3164
3485
|
}
|
|
3165
3486
|
);
|
|
3166
3487
|
return actions;
|
|
@@ -4329,6 +4650,14 @@ var RtfPlugin = class {
|
|
|
4329
4650
|
type: "button",
|
|
4330
4651
|
group: "actions",
|
|
4331
4652
|
execute: () => instance.print?.()
|
|
4653
|
+
},
|
|
4654
|
+
{
|
|
4655
|
+
id: "open-window",
|
|
4656
|
+
icon: "open-window",
|
|
4657
|
+
label: "Open in Separate Full Window",
|
|
4658
|
+
type: "button",
|
|
4659
|
+
group: "actions",
|
|
4660
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
4332
4661
|
}
|
|
4333
4662
|
);
|
|
4334
4663
|
return actions;
|
|
@@ -4381,59 +4710,54 @@ var RtfPlugin = class {
|
|
|
4381
4710
|
}
|
|
4382
4711
|
const doc = new RTFJS__namespace.Document(ctx.buffer, {});
|
|
4383
4712
|
const htmlElements = await doc.render();
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
const secH = singleEl.offsetHeight || singleEl.scrollHeight;
|
|
4389
|
-
if (secH > 1300 && children.length > 1) {
|
|
4390
|
-
const childHeights = children.map((c) => {
|
|
4391
|
-
const rectH = c.getBoundingClientRect().height;
|
|
4392
|
-
const offH = c.offsetHeight;
|
|
4393
|
-
const textLen = c.textContent?.trim().length || 0;
|
|
4394
|
-
const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
|
|
4395
|
-
return Math.max(rectH, offH, estH);
|
|
4396
|
-
});
|
|
4397
|
-
wrapper.innerHTML = "";
|
|
4398
|
-
const createRtfCard = () => {
|
|
4399
|
-
const card = document.createElement("div");
|
|
4400
|
-
card.className = "fp-rtf-page-card";
|
|
4401
|
-
card.style.backgroundColor = "#ffffff";
|
|
4402
|
-
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
4403
|
-
card.style.borderRadius = "4px";
|
|
4404
|
-
card.style.padding = "72px 56px";
|
|
4405
|
-
card.style.width = "816px";
|
|
4406
|
-
card.style.minHeight = "1056px";
|
|
4407
|
-
card.style.boxSizing = "border-box";
|
|
4408
|
-
card.style.marginBottom = "24px";
|
|
4409
|
-
return card;
|
|
4410
|
-
};
|
|
4411
|
-
let curCard = createRtfCard();
|
|
4412
|
-
wrapper.appendChild(curCard);
|
|
4413
|
-
pageElements = [curCard];
|
|
4414
|
-
let curH = 0;
|
|
4415
|
-
const maxH = 920;
|
|
4416
|
-
for (let i = 0; i < children.length; i++) {
|
|
4417
|
-
const child = children[i];
|
|
4418
|
-
const chH = childHeights[i];
|
|
4419
|
-
curCard.appendChild(child);
|
|
4420
|
-
curH += chH;
|
|
4421
|
-
if (curH >= maxH && i < children.length - 1) {
|
|
4422
|
-
curCard = createRtfCard();
|
|
4423
|
-
wrapper.appendChild(curCard);
|
|
4424
|
-
pageElements.push(curCard);
|
|
4425
|
-
curH = 0;
|
|
4426
|
-
}
|
|
4427
|
-
}
|
|
4713
|
+
const contentNodes = [];
|
|
4714
|
+
for (const item of htmlElements) {
|
|
4715
|
+
if (item.children && item.children.length > 0 && !item.tagName.toLowerCase().startsWith("table")) {
|
|
4716
|
+
contentNodes.push(...Array.from(item.children));
|
|
4428
4717
|
} else {
|
|
4429
|
-
|
|
4718
|
+
contentNodes.push(item);
|
|
4430
4719
|
}
|
|
4431
|
-
}
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4720
|
+
}
|
|
4721
|
+
wrapper.innerHTML = "";
|
|
4722
|
+
contentNodes.forEach((node) => wrapper.appendChild(node));
|
|
4723
|
+
const childHeights = contentNodes.map((c) => {
|
|
4724
|
+
const rectH = c.getBoundingClientRect ? c.getBoundingClientRect().height : 0;
|
|
4725
|
+
const offH = c.offsetHeight || 0;
|
|
4726
|
+
const textLen = c.textContent?.trim().length || 0;
|
|
4727
|
+
const estH = Math.max(24, Math.ceil(textLen / 75) * 22 + 14);
|
|
4728
|
+
return Math.max(rectH, offH, estH);
|
|
4729
|
+
});
|
|
4730
|
+
wrapper.innerHTML = "";
|
|
4731
|
+
const createRtfCard = () => {
|
|
4732
|
+
const card = document.createElement("div");
|
|
4733
|
+
card.className = "fp-rtf-page-card";
|
|
4734
|
+
card.style.backgroundColor = "#ffffff";
|
|
4735
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
4736
|
+
card.style.borderRadius = "4px";
|
|
4737
|
+
card.style.padding = "72px 56px";
|
|
4738
|
+
card.style.width = "816px";
|
|
4739
|
+
card.style.minHeight = "1056px";
|
|
4740
|
+
card.style.boxSizing = "border-box";
|
|
4741
|
+
card.style.marginBottom = "24px";
|
|
4742
|
+
card.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4743
|
+
card.style.lineHeight = "1.6";
|
|
4744
|
+
return card;
|
|
4745
|
+
};
|
|
4746
|
+
let curCard = createRtfCard();
|
|
4747
|
+
wrapper.appendChild(curCard);
|
|
4748
|
+
pageElements = [curCard];
|
|
4749
|
+
let curH = 0;
|
|
4750
|
+
const maxH = 912;
|
|
4751
|
+
for (let i = 0; i < contentNodes.length; i++) {
|
|
4752
|
+
const child = contentNodes[i];
|
|
4753
|
+
const chH = childHeights[i];
|
|
4754
|
+
curCard.appendChild(child);
|
|
4755
|
+
curH += chH;
|
|
4756
|
+
if (curH >= maxH && i < contentNodes.length - 1) {
|
|
4757
|
+
curCard = createRtfCard();
|
|
4758
|
+
wrapper.appendChild(curCard);
|
|
4759
|
+
pageElements.push(curCard);
|
|
4760
|
+
curH = 0;
|
|
4437
4761
|
}
|
|
4438
4762
|
}
|
|
4439
4763
|
} catch (err) {
|
|
@@ -4802,6 +5126,14 @@ var OpenDocumentPlugin = class {
|
|
|
4802
5126
|
type: "button",
|
|
4803
5127
|
group: "actions",
|
|
4804
5128
|
execute: () => instance.print?.()
|
|
5129
|
+
},
|
|
5130
|
+
{
|
|
5131
|
+
id: "open-window",
|
|
5132
|
+
icon: "open-window",
|
|
5133
|
+
label: "Open in Separate Full Window",
|
|
5134
|
+
type: "button",
|
|
5135
|
+
group: "actions",
|
|
5136
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
4805
5137
|
}
|
|
4806
5138
|
);
|
|
4807
5139
|
return actions;
|
|
@@ -5390,6 +5722,14 @@ var DocPlugin = class {
|
|
|
5390
5722
|
type: "button",
|
|
5391
5723
|
group: "actions",
|
|
5392
5724
|
execute: () => instance.print?.()
|
|
5725
|
+
},
|
|
5726
|
+
{
|
|
5727
|
+
id: "open-window",
|
|
5728
|
+
icon: "open-window",
|
|
5729
|
+
label: "Open in Separate Full Window",
|
|
5730
|
+
type: "button",
|
|
5731
|
+
group: "actions",
|
|
5732
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
5393
5733
|
}
|
|
5394
5734
|
);
|
|
5395
5735
|
return actions;
|
|
@@ -5681,9 +6021,25 @@ var DocPlugin = class {
|
|
|
5681
6021
|
heuristicTextExtraction(buffer) {
|
|
5682
6022
|
return this.extractStringsFromBytes(new Uint8Array(buffer));
|
|
5683
6023
|
}
|
|
6024
|
+
cleanWordDocFields(text) {
|
|
6025
|
+
if (!text) return "";
|
|
6026
|
+
let cleaned = text.replace(
|
|
6027
|
+
/\x13\s*HYPERLINK\s*"?([^"\x14]+)"?\s*\x14([\s\S]*?)\x15/gi,
|
|
6028
|
+
(_match, url, label) => {
|
|
6029
|
+
const cleanUrl = url.trim();
|
|
6030
|
+
const cleanLabel = label.trim() || cleanUrl;
|
|
6031
|
+
return `<a href="${cleanUrl}" target="_blank" rel="noopener noreferrer" style="color: #2563eb; text-decoration: underline;">${cleanLabel}</a>`;
|
|
6032
|
+
}
|
|
6033
|
+
);
|
|
6034
|
+
cleaned = cleaned.replace(/\x13[^\x14\x15]*\x14([^\x15]*)\x15/g, "$1");
|
|
6035
|
+
cleaned = cleaned.replace(/\x13[^\x15]*\x15/g, "");
|
|
6036
|
+
cleaned = cleaned.replace(/[\x13\x14\x15]/g, "");
|
|
6037
|
+
return cleaned;
|
|
6038
|
+
}
|
|
5684
6039
|
splitIntoPages(text) {
|
|
5685
6040
|
if (!text) return [""];
|
|
5686
|
-
const
|
|
6041
|
+
const cleanedText = this.cleanWordDocFields(text);
|
|
6042
|
+
const normalized = cleanedText.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ");
|
|
5687
6043
|
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);
|
|
5688
6044
|
if (explicitParts.length === 0) explicitParts.push(normalized);
|
|
5689
6045
|
const maxLinesPerPage = 32;
|
|
@@ -5694,7 +6050,8 @@ var DocPlugin = class {
|
|
|
5694
6050
|
let currentLines = [];
|
|
5695
6051
|
let count = 0;
|
|
5696
6052
|
for (const line of lines) {
|
|
5697
|
-
const
|
|
6053
|
+
const plainLine = line.replace(/<[^>]+>/g, "");
|
|
6054
|
+
const vLines = Math.max(1, Math.ceil((plainLine.length || 1) / charsPerLine));
|
|
5698
6055
|
if (count + vLines > maxLinesPerPage && currentLines.length > 0) {
|
|
5699
6056
|
finalPages.push(currentLines.join("\n"));
|
|
5700
6057
|
currentLines = [];
|
|
@@ -5770,25 +6127,26 @@ var DocPlugin = class {
|
|
|
5770
6127
|
i++;
|
|
5771
6128
|
continue;
|
|
5772
6129
|
}
|
|
6130
|
+
const sanitizeOptions = { ADD_TAGS: ["a"], ADD_ATTR: ["href", "target", "rel", "style"] };
|
|
5773
6131
|
if (line.length < 60 && !line.endsWith(".") && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#"))) {
|
|
5774
6132
|
if (inList) {
|
|
5775
6133
|
html += "</ul>";
|
|
5776
6134
|
inList = false;
|
|
5777
6135
|
}
|
|
5778
|
-
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>`;
|
|
6136
|
+
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>`;
|
|
5779
6137
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
5780
6138
|
if (!inList) {
|
|
5781
6139
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
5782
6140
|
inList = true;
|
|
5783
6141
|
}
|
|
5784
6142
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
5785
|
-
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6__default.default.sanitize(bulletText)}</li>`;
|
|
6143
|
+
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6__default.default.sanitize(bulletText, sanitizeOptions)}</li>`;
|
|
5786
6144
|
} else {
|
|
5787
6145
|
if (inList) {
|
|
5788
6146
|
html += "</ul>";
|
|
5789
6147
|
inList = false;
|
|
5790
6148
|
}
|
|
5791
|
-
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6__default.default.sanitize(line)}</p>`;
|
|
6149
|
+
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6__default.default.sanitize(line, sanitizeOptions)}</p>`;
|
|
5792
6150
|
}
|
|
5793
6151
|
i++;
|
|
5794
6152
|
}
|