@files-preview-app/preview-file 1.2.9 → 1.3.1
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 +668 -154
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.js +667 -154
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +711 -154
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +709 -155
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +668 -154
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +667 -154
- package/dist/react.js.map +1 -1
- package/dist/vue.cjs +668 -154
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +667 -154
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import DOMPurify6 from 'dompurify';
|
|
2
2
|
import * as pdfjsLib from 'pdfjs-dist';
|
|
3
3
|
import * as docx from 'docx-preview';
|
|
4
|
+
import * as fflate from 'fflate';
|
|
4
5
|
import { unzipSync, strFromU8, unzip } from 'fflate';
|
|
5
6
|
import * as XLSX from 'xlsx';
|
|
6
7
|
import hljs from 'highlight.js';
|
|
@@ -336,16 +337,21 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
336
337
|
metadata.mimeType = source.type || void 0;
|
|
337
338
|
metadata.extension = extractExtension(source.name);
|
|
338
339
|
buffer = await source.arrayBuffer();
|
|
339
|
-
} else if (source instanceof Blob) {
|
|
340
|
+
} else if (source instanceof Blob || source && typeof source.arrayBuffer === "function" && typeof source.size === "number") {
|
|
340
341
|
metadata.size = source.size;
|
|
341
342
|
metadata.mimeType = source.type || void 0;
|
|
343
|
+
if (source.name) {
|
|
344
|
+
metadata.name = source.name;
|
|
345
|
+
metadata.extension = extractExtension(source.name);
|
|
346
|
+
}
|
|
342
347
|
buffer = await source.arrayBuffer();
|
|
343
|
-
} else if (source instanceof ArrayBuffer) {
|
|
348
|
+
} else if (source instanceof ArrayBuffer || Object.prototype.toString.call(source) === "[object ArrayBuffer]" || source && typeof source.byteLength === "number" && typeof source.slice === "function") {
|
|
344
349
|
buffer = source;
|
|
345
|
-
} else if (source instanceof Uint8Array) {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
350
|
+
} else if (source instanceof Uint8Array || ArrayBuffer.isView(source)) {
|
|
351
|
+
const view = source;
|
|
352
|
+
buffer = view.buffer.slice(
|
|
353
|
+
view.byteOffset,
|
|
354
|
+
view.byteOffset + view.byteLength
|
|
349
355
|
);
|
|
350
356
|
} else {
|
|
351
357
|
throw new Error("Unsupported file source type");
|
|
@@ -474,6 +480,86 @@ function createElement(tag, attrs, ...children) {
|
|
|
474
480
|
}
|
|
475
481
|
return el;
|
|
476
482
|
}
|
|
483
|
+
var DB_NAME = "PreviewFileTransferDB";
|
|
484
|
+
var DB_STORE = "transfers";
|
|
485
|
+
function openDB() {
|
|
486
|
+
return new Promise((resolve, reject) => {
|
|
487
|
+
if (typeof indexedDB === "undefined") {
|
|
488
|
+
return reject(new Error("IndexedDB is not available"));
|
|
489
|
+
}
|
|
490
|
+
const req = indexedDB.open(DB_NAME, 1);
|
|
491
|
+
req.onupgradeneeded = () => {
|
|
492
|
+
const db = req.result;
|
|
493
|
+
if (!db.objectStoreNames.contains(DB_STORE)) {
|
|
494
|
+
db.createObjectStore(DB_STORE, { keyPath: "id" });
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
req.onsuccess = () => resolve(req.result);
|
|
498
|
+
req.onerror = () => reject(req.error);
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
async function saveTransferPayload(id, payload) {
|
|
502
|
+
if (typeof window !== "undefined") {
|
|
503
|
+
try {
|
|
504
|
+
window[id] = payload;
|
|
505
|
+
window.__lastTransfer = payload;
|
|
506
|
+
} catch {
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
try {
|
|
510
|
+
const db = await openDB();
|
|
511
|
+
return new Promise((resolve, reject) => {
|
|
512
|
+
const tx = db.transaction(DB_STORE, "readwrite");
|
|
513
|
+
const store = tx.objectStore(DB_STORE);
|
|
514
|
+
store.put({ id, ...payload, timestamp: Date.now() });
|
|
515
|
+
tx.oncomplete = () => resolve();
|
|
516
|
+
tx.onerror = () => reject(tx.error);
|
|
517
|
+
});
|
|
518
|
+
} catch (e) {
|
|
519
|
+
console.warn("[saveTransferPayload] IndexedDB store warning:", e);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
async function getTransferPayload(id) {
|
|
523
|
+
if (typeof window !== "undefined") {
|
|
524
|
+
try {
|
|
525
|
+
if (window.opener && window.opener[id]) {
|
|
526
|
+
return window.opener[id];
|
|
527
|
+
}
|
|
528
|
+
if (window[id]) {
|
|
529
|
+
return window[id];
|
|
530
|
+
}
|
|
531
|
+
if (window.opener && window.opener.__lastTransfer) {
|
|
532
|
+
return window.opener.__lastTransfer;
|
|
533
|
+
}
|
|
534
|
+
if (window.__lastTransfer) {
|
|
535
|
+
return window.__lastTransfer;
|
|
536
|
+
}
|
|
537
|
+
} catch {
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
try {
|
|
541
|
+
const db = await openDB();
|
|
542
|
+
return new Promise((resolve) => {
|
|
543
|
+
const tx = db.transaction(DB_STORE, "readonly");
|
|
544
|
+
const store = tx.objectStore(DB_STORE);
|
|
545
|
+
const req = store.get(id);
|
|
546
|
+
req.onsuccess = () => {
|
|
547
|
+
if (req.result && req.result.buffer) {
|
|
548
|
+
resolve({
|
|
549
|
+
buffer: req.result.buffer,
|
|
550
|
+
metadata: req.result.metadata,
|
|
551
|
+
options: req.result.options
|
|
552
|
+
});
|
|
553
|
+
} else {
|
|
554
|
+
resolve(null);
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
req.onerror = () => resolve(null);
|
|
558
|
+
});
|
|
559
|
+
} catch {
|
|
560
|
+
return null;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
477
563
|
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>`;
|
|
478
564
|
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>`;
|
|
479
565
|
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>`;
|
|
@@ -493,6 +579,7 @@ var ICON_COPY = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" str
|
|
|
493
579
|
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>`;
|
|
494
580
|
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>`;
|
|
495
581
|
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>`;
|
|
582
|
+
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>`;
|
|
496
583
|
var ICON_MAP = {
|
|
497
584
|
"zoom-in": ICON_ZOOM_IN,
|
|
498
585
|
"zoom-out": ICON_ZOOM_OUT,
|
|
@@ -519,7 +606,9 @@ var ICON_MAP = {
|
|
|
519
606
|
"forward-10": ICON_FAST_FORWARD,
|
|
520
607
|
"rewind": ICON_REWIND,
|
|
521
608
|
"replay-10": ICON_REWIND,
|
|
522
|
-
"speed": ICON_SPEED
|
|
609
|
+
"speed": ICON_SPEED,
|
|
610
|
+
"open-window": ICON_EXTERNAL_WINDOW,
|
|
611
|
+
"external-window": ICON_EXTERNAL_WINDOW
|
|
523
612
|
};
|
|
524
613
|
var ToolbarController = class {
|
|
525
614
|
el;
|
|
@@ -662,9 +751,11 @@ var ToolbarController = class {
|
|
|
662
751
|
type: "button",
|
|
663
752
|
"data-action-id": id
|
|
664
753
|
});
|
|
665
|
-
const
|
|
666
|
-
if (
|
|
667
|
-
btn.innerHTML =
|
|
754
|
+
const internalSvg = ICON_MAP[iconHtml] || ICON_MAP[id];
|
|
755
|
+
if (internalSvg) {
|
|
756
|
+
btn.innerHTML = internalSvg;
|
|
757
|
+
} else if (iconHtml && iconHtml.startsWith("<svg")) {
|
|
758
|
+
btn.innerHTML = sanitizeSVG(iconHtml);
|
|
668
759
|
} else {
|
|
669
760
|
btn.textContent = title || id;
|
|
670
761
|
}
|
|
@@ -736,7 +827,7 @@ var ThumbnailPanel = class {
|
|
|
736
827
|
}
|
|
737
828
|
}
|
|
738
829
|
};
|
|
739
|
-
var FilePreviewViewer = class {
|
|
830
|
+
var FilePreviewViewer = class _FilePreviewViewer {
|
|
740
831
|
plugins = [];
|
|
741
832
|
activeInstance = null;
|
|
742
833
|
abortController = null;
|
|
@@ -773,6 +864,7 @@ var FilePreviewViewer = class {
|
|
|
773
864
|
* Preview a file in the given container element.
|
|
774
865
|
*/
|
|
775
866
|
async preview(container, source, options = {}) {
|
|
867
|
+
this.currentOptions = options;
|
|
776
868
|
this.abort();
|
|
777
869
|
this.abortController = new AbortController();
|
|
778
870
|
const { signal } = this.abortController;
|
|
@@ -782,7 +874,10 @@ var FilePreviewViewer = class {
|
|
|
782
874
|
this.showLoading();
|
|
783
875
|
try {
|
|
784
876
|
const { buffer, metadata } = await sourceToArrayBuffer(source, signal);
|
|
785
|
-
|
|
877
|
+
if (options.metadata) {
|
|
878
|
+
Object.assign(metadata, options.metadata);
|
|
879
|
+
}
|
|
880
|
+
this.currentBuffer = buffer.slice(0);
|
|
786
881
|
this.currentMetadata = metadata;
|
|
787
882
|
if (signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
788
883
|
const fileInfo = { metadata, buffer };
|
|
@@ -812,6 +907,7 @@ var FilePreviewViewer = class {
|
|
|
812
907
|
}
|
|
813
908
|
});
|
|
814
909
|
this.activeInstance = instance;
|
|
910
|
+
instance.openInSeparateWindow = () => this.openInSeparateWindow();
|
|
815
911
|
this.hideLoading();
|
|
816
912
|
this.eventEmitter.emit("loaded", { metadata, plugin: matchedPlugin.id });
|
|
817
913
|
if (options.showToolbar !== false && this.toolbar) {
|
|
@@ -821,26 +917,16 @@ var FilePreviewViewer = class {
|
|
|
821
917
|
actions.push({
|
|
822
918
|
id: "fullscreen",
|
|
823
919
|
icon: "fullscreen",
|
|
824
|
-
label: "
|
|
920
|
+
label: "Fullscreen",
|
|
825
921
|
type: "button",
|
|
826
922
|
group: "view",
|
|
827
|
-
execute:
|
|
923
|
+
execute: () => {
|
|
828
924
|
try {
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
if (this.wrapperEl?.requestFullscreen) {
|
|
833
|
-
await this.wrapperEl.requestFullscreen().catch(() => {
|
|
834
|
-
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
835
|
-
});
|
|
836
|
-
} else {
|
|
837
|
-
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
838
|
-
}
|
|
925
|
+
if (!document.fullscreenElement) {
|
|
926
|
+
this.wrapperEl?.requestFullscreen?.();
|
|
927
|
+
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
839
928
|
} else {
|
|
840
|
-
|
|
841
|
-
await document.exitFullscreen().catch(() => {
|
|
842
|
-
});
|
|
843
|
-
}
|
|
929
|
+
document.exitFullscreen?.();
|
|
844
930
|
this.wrapperEl?.classList.remove("fp-fullscreen-active");
|
|
845
931
|
}
|
|
846
932
|
} catch {
|
|
@@ -852,6 +938,28 @@ var FilePreviewViewer = class {
|
|
|
852
938
|
}
|
|
853
939
|
});
|
|
854
940
|
}
|
|
941
|
+
const openWinAction = actions.find((a) => a.id === "open-window");
|
|
942
|
+
if (openWinAction) {
|
|
943
|
+
if (options?._isSeparateWindow) {
|
|
944
|
+
const idx = actions.indexOf(openWinAction);
|
|
945
|
+
if (idx !== -1) actions.splice(idx, 1);
|
|
946
|
+
} else {
|
|
947
|
+
openWinAction.execute = () => {
|
|
948
|
+
this.openInSeparateWindow();
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
} else if (!options?._isSeparateWindow) {
|
|
952
|
+
actions.push({
|
|
953
|
+
id: "open-window",
|
|
954
|
+
icon: "open-window",
|
|
955
|
+
label: "Open in Separate Full Window",
|
|
956
|
+
type: "button",
|
|
957
|
+
group: "actions",
|
|
958
|
+
execute: () => {
|
|
959
|
+
this.openInSeparateWindow();
|
|
960
|
+
}
|
|
961
|
+
});
|
|
962
|
+
}
|
|
855
963
|
this.toolbar.update(actions);
|
|
856
964
|
this.toolbar.show();
|
|
857
965
|
}
|
|
@@ -884,6 +992,104 @@ var FilePreviewViewer = class {
|
|
|
884
992
|
throw error;
|
|
885
993
|
}
|
|
886
994
|
}
|
|
995
|
+
/**
|
|
996
|
+
* Opens the current file preview in a separate full browser window.
|
|
997
|
+
*/
|
|
998
|
+
openInSeparateWindow() {
|
|
999
|
+
if (!this.currentBuffer) {
|
|
1000
|
+
console.warn("[FilePreviewViewer] No active file buffer to open in separate window");
|
|
1001
|
+
return null;
|
|
1002
|
+
}
|
|
1003
|
+
if (this.currentOptions.onOpenSeparateWindow) {
|
|
1004
|
+
return this.currentOptions.onOpenSeparateWindow({
|
|
1005
|
+
buffer: this.currentBuffer,
|
|
1006
|
+
metadata: this.currentMetadata || { name: "Document" },
|
|
1007
|
+
options: this.currentOptions
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
const transferId = "fp_win_" + Date.now() + "_" + Math.random().toString(36).slice(2, 8);
|
|
1011
|
+
let clonedBuffer;
|
|
1012
|
+
try {
|
|
1013
|
+
clonedBuffer = this.currentBuffer.slice(0);
|
|
1014
|
+
} catch {
|
|
1015
|
+
clonedBuffer = this.currentBuffer;
|
|
1016
|
+
}
|
|
1017
|
+
const payload = {
|
|
1018
|
+
buffer: clonedBuffer,
|
|
1019
|
+
metadata: this.currentMetadata ? { ...this.currentMetadata } : void 0,
|
|
1020
|
+
options: { ...this.currentOptions, _isSeparateWindow: true }
|
|
1021
|
+
};
|
|
1022
|
+
if (typeof window !== "undefined") {
|
|
1023
|
+
try {
|
|
1024
|
+
window[transferId] = payload;
|
|
1025
|
+
window.__lastTransfer = payload;
|
|
1026
|
+
} catch {
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
saveTransferPayload(transferId, payload).catch((err) => {
|
|
1030
|
+
console.warn("[FilePreviewViewer] Transfer payload save warning:", err);
|
|
1031
|
+
});
|
|
1032
|
+
let targetUrl = null;
|
|
1033
|
+
if (this.currentOptions.standaloneViewerUrl) {
|
|
1034
|
+
const u = new URL(this.currentOptions.standaloneViewerUrl, window.location.href);
|
|
1035
|
+
u.searchParams.set("mode", "fullscreen");
|
|
1036
|
+
u.searchParams.set("transferId", transferId);
|
|
1037
|
+
targetUrl = u.toString();
|
|
1038
|
+
} else if (typeof window !== "undefined" && window.location?.href && !window.location.href.startsWith("about:")) {
|
|
1039
|
+
const u = new URL(window.location.href);
|
|
1040
|
+
u.searchParams.set("mode", "fullscreen");
|
|
1041
|
+
u.searchParams.set("transferId", transferId);
|
|
1042
|
+
targetUrl = u.toString();
|
|
1043
|
+
}
|
|
1044
|
+
if (targetUrl) {
|
|
1045
|
+
const newWin2 = window.open(targetUrl, "_blank");
|
|
1046
|
+
if (!newWin2) {
|
|
1047
|
+
alert("Popup blocker prevented opening the preview in a separate window. Please allow popups for this site.");
|
|
1048
|
+
return null;
|
|
1049
|
+
}
|
|
1050
|
+
return newWin2;
|
|
1051
|
+
}
|
|
1052
|
+
const title = (this.currentMetadata?.name || "Document Preview") + " - Full Preview";
|
|
1053
|
+
const newWin = window.open("", "_blank");
|
|
1054
|
+
if (!newWin) {
|
|
1055
|
+
alert("Popup blocker prevented opening the preview in a separate window. Please allow popups for this site.");
|
|
1056
|
+
return null;
|
|
1057
|
+
}
|
|
1058
|
+
newWin.document.title = title;
|
|
1059
|
+
newWin.document.body.style.margin = "0";
|
|
1060
|
+
newWin.document.body.style.padding = "0";
|
|
1061
|
+
newWin.document.body.style.width = "100vw";
|
|
1062
|
+
newWin.document.body.style.height = "100vh";
|
|
1063
|
+
newWin.document.body.style.overflow = "hidden";
|
|
1064
|
+
newWin.document.body.style.backgroundColor = "#f8fafc";
|
|
1065
|
+
const headNodes = document.querySelectorAll('link[rel="stylesheet"], style');
|
|
1066
|
+
headNodes.forEach((node) => {
|
|
1067
|
+
newWin.document.head.appendChild(node.cloneNode(true));
|
|
1068
|
+
});
|
|
1069
|
+
const root = newWin.document.createElement("div");
|
|
1070
|
+
root.id = "full-window-preview-root";
|
|
1071
|
+
root.style.width = "100%";
|
|
1072
|
+
root.style.height = "100%";
|
|
1073
|
+
root.style.overflow = "hidden";
|
|
1074
|
+
newWin.document.body.appendChild(root);
|
|
1075
|
+
const separateViewer = new _FilePreviewViewer();
|
|
1076
|
+
for (const plugin of this.plugins) {
|
|
1077
|
+
separateViewer.registerPlugin(plugin);
|
|
1078
|
+
}
|
|
1079
|
+
separateViewer.preview(root, this.currentBuffer.slice(0), {
|
|
1080
|
+
...this.currentOptions,
|
|
1081
|
+
showToolbar: true,
|
|
1082
|
+
toolbarPosition: "top",
|
|
1083
|
+
metadata: this.currentMetadata || void 0,
|
|
1084
|
+
_isSeparateWindow: true
|
|
1085
|
+
}).catch((err) => {
|
|
1086
|
+
console.error("[FilePreviewViewer] Error rendering in separate window:", err);
|
|
1087
|
+
});
|
|
1088
|
+
newWin.addEventListener("beforeunload", () => {
|
|
1089
|
+
separateViewer.destroy();
|
|
1090
|
+
});
|
|
1091
|
+
return newWin;
|
|
1092
|
+
}
|
|
887
1093
|
/**
|
|
888
1094
|
* Subscribe to viewer events.
|
|
889
1095
|
*/
|
|
@@ -1289,8 +1495,20 @@ var CfbfReader = class {
|
|
|
1289
1495
|
}
|
|
1290
1496
|
};
|
|
1291
1497
|
if (typeof window !== "undefined" && pdfjsLib.GlobalWorkerOptions) {
|
|
1292
|
-
if (!pdfjsLib.GlobalWorkerOptions.workerSrc) {
|
|
1293
|
-
|
|
1498
|
+
if (!pdfjsLib.GlobalWorkerOptions.workerPort && !pdfjsLib.GlobalWorkerOptions.workerSrc) {
|
|
1499
|
+
const customWorker = window.__PDF_WORKER_SRC__;
|
|
1500
|
+
if (customWorker) {
|
|
1501
|
+
pdfjsLib.GlobalWorkerOptions.workerSrc = customWorker;
|
|
1502
|
+
} else {
|
|
1503
|
+
try {
|
|
1504
|
+
pdfjsLib.GlobalWorkerOptions.workerPort = new Worker(
|
|
1505
|
+
new URL("pdfjs-dist/build/pdf.worker.min.mjs", import.meta.url),
|
|
1506
|
+
{ type: "module" }
|
|
1507
|
+
);
|
|
1508
|
+
} catch {
|
|
1509
|
+
pdfjsLib.GlobalWorkerOptions.workerSrc = "./pdf.worker.min.mjs";
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1294
1512
|
}
|
|
1295
1513
|
}
|
|
1296
1514
|
var PdfPlugin = class {
|
|
@@ -1384,6 +1602,14 @@ var PdfPlugin = class {
|
|
|
1384
1602
|
type: "button",
|
|
1385
1603
|
group: "actions",
|
|
1386
1604
|
execute: () => instance.print?.()
|
|
1605
|
+
},
|
|
1606
|
+
{
|
|
1607
|
+
id: "open-window",
|
|
1608
|
+
icon: "open-window",
|
|
1609
|
+
label: "Open in Separate Full Window",
|
|
1610
|
+
type: "button",
|
|
1611
|
+
group: "actions",
|
|
1612
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
1387
1613
|
}
|
|
1388
1614
|
];
|
|
1389
1615
|
}
|
|
@@ -1433,18 +1659,21 @@ var PdfPlugin = class {
|
|
|
1433
1659
|
indicator.style.pointerEvents = "none";
|
|
1434
1660
|
container.appendChild(indicator);
|
|
1435
1661
|
ctx.container.appendChild(container);
|
|
1662
|
+
const standardFontsUrl = typeof window !== "undefined" && window.__PDF_STANDARD_FONTS_URL__ || "./standard_fonts/";
|
|
1663
|
+
const cmapsUrl = typeof window !== "undefined" && window.__PDF_CMAPS_URL__ || "./cmaps/";
|
|
1436
1664
|
const loadingTask = pdfjsLib.getDocument({
|
|
1437
|
-
data: new Uint8Array(ctx.buffer),
|
|
1438
|
-
cMapUrl:
|
|
1665
|
+
data: new Uint8Array(ctx.buffer.slice(0)),
|
|
1666
|
+
cMapUrl: cmapsUrl,
|
|
1439
1667
|
cMapPacked: true,
|
|
1440
|
-
standardFontDataUrl:
|
|
1668
|
+
standardFontDataUrl: standardFontsUrl,
|
|
1669
|
+
verbosity: 0
|
|
1441
1670
|
});
|
|
1442
1671
|
const pdfDoc = await loadingTask.promise;
|
|
1443
1672
|
const totalPages = Math.max(1, pdfDoc.numPages);
|
|
1444
1673
|
let currentPage = 1;
|
|
1445
1674
|
let zoomScale = 1;
|
|
1446
1675
|
let rotation = 0;
|
|
1447
|
-
let fitMode = "
|
|
1676
|
+
let fitMode = "page";
|
|
1448
1677
|
let currentRenderTask = null;
|
|
1449
1678
|
const renderPage = async (pageNum) => {
|
|
1450
1679
|
if (currentRenderTask) {
|
|
@@ -1464,15 +1693,15 @@ var PdfPlugin = class {
|
|
|
1464
1693
|
const containerWidth = container.clientWidth || 900;
|
|
1465
1694
|
const containerHeight = container.clientHeight || 700;
|
|
1466
1695
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1467
|
-
const availWidth = Math.max(
|
|
1468
|
-
const availHeight = Math.max(
|
|
1696
|
+
const availWidth = Math.max(320, containerWidth - 48);
|
|
1697
|
+
const availHeight = Math.max(550, containerHeight - 88);
|
|
1469
1698
|
const scaleW = availWidth / unscaledVp.width;
|
|
1470
1699
|
const scaleH = availHeight / unscaledVp.height;
|
|
1471
1700
|
let fitScale;
|
|
1472
1701
|
if (fitMode === "page") {
|
|
1473
|
-
fitScale = Math.max(0.
|
|
1702
|
+
fitScale = Math.max(0.4, Math.min(scaleW, scaleH));
|
|
1474
1703
|
} else {
|
|
1475
|
-
fitScale = Math.max(0.65, Math.min(1.
|
|
1704
|
+
fitScale = Math.max(0.65, Math.min(1.25, scaleW));
|
|
1476
1705
|
}
|
|
1477
1706
|
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1478
1707
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
@@ -1498,7 +1727,7 @@ var PdfPlugin = class {
|
|
|
1498
1727
|
currentRenderTask = null;
|
|
1499
1728
|
}
|
|
1500
1729
|
};
|
|
1501
|
-
|
|
1730
|
+
renderPage(1);
|
|
1502
1731
|
let resizeTimer = null;
|
|
1503
1732
|
const resizeObserver = new ResizeObserver(() => {
|
|
1504
1733
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
@@ -1542,7 +1771,7 @@ var PdfPlugin = class {
|
|
|
1542
1771
|
renderPage(currentPage);
|
|
1543
1772
|
},
|
|
1544
1773
|
fitToPage: () => {
|
|
1545
|
-
fitMode = fitMode === "
|
|
1774
|
+
fitMode = fitMode === "page" ? "width" : "page";
|
|
1546
1775
|
zoomScale = 1;
|
|
1547
1776
|
rotation = 0;
|
|
1548
1777
|
renderPage(currentPage);
|
|
@@ -2019,6 +2248,14 @@ var DocxPlugin = class {
|
|
|
2019
2248
|
type: "button",
|
|
2020
2249
|
group: "actions",
|
|
2021
2250
|
execute: () => instance.print?.()
|
|
2251
|
+
},
|
|
2252
|
+
{
|
|
2253
|
+
id: "open-window",
|
|
2254
|
+
icon: "open-window",
|
|
2255
|
+
label: "Open in Separate Full Window",
|
|
2256
|
+
type: "button",
|
|
2257
|
+
group: "actions",
|
|
2258
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
2022
2259
|
}
|
|
2023
2260
|
);
|
|
2024
2261
|
return actions;
|
|
@@ -2078,6 +2315,31 @@ var DocxPlugin = class {
|
|
|
2078
2315
|
}
|
|
2079
2316
|
if (wrapper.children.length > 0 && (wrapper.textContent?.trim().length ?? 0) > 0) {
|
|
2080
2317
|
renderedSuccessfully = true;
|
|
2318
|
+
try {
|
|
2319
|
+
const unzipped = unzipSync(new Uint8Array(ctx.buffer));
|
|
2320
|
+
const chartKeys = Object.keys(unzipped).filter((k) => k.replace(/^[./\\]+/, "").toLowerCase().startsWith("word/charts/chart") && k.endsWith(".xml")).sort();
|
|
2321
|
+
if (chartKeys.length > 0) {
|
|
2322
|
+
const allDivs = Array.from(wrapper.querySelectorAll("div"));
|
|
2323
|
+
const emptyContainers = allDivs.filter((div) => {
|
|
2324
|
+
const st = div.getAttribute("style") || "";
|
|
2325
|
+
return st.includes("width:") && st.includes("height:") && div.children.length === 0 && (div.textContent?.trim().length ?? 0) === 0;
|
|
2326
|
+
});
|
|
2327
|
+
chartKeys.forEach((cKey, idx) => {
|
|
2328
|
+
const target = emptyContainers[idx];
|
|
2329
|
+
if (target) {
|
|
2330
|
+
const xmlStr = strFromU8(unzipped[cKey]);
|
|
2331
|
+
const svg = this.parseAndRenderChartSvg(xmlStr);
|
|
2332
|
+
if (svg) {
|
|
2333
|
+
target.innerHTML = svg;
|
|
2334
|
+
target.style.display = "block";
|
|
2335
|
+
target.style.margin = "12px auto";
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
});
|
|
2339
|
+
}
|
|
2340
|
+
} catch (chartErr) {
|
|
2341
|
+
console.warn("[DocxPlugin] Non-critical error rendering DrawingML charts:", chartErr);
|
|
2342
|
+
}
|
|
2081
2343
|
}
|
|
2082
2344
|
} catch (err) {
|
|
2083
2345
|
console.warn("[DocxPlugin] docx-preview failed, triggering native fallback:", err);
|
|
@@ -2109,64 +2371,74 @@ var DocxPlugin = class {
|
|
|
2109
2371
|
}
|
|
2110
2372
|
let sections = Array.from(wrapper.querySelectorAll("section.docx"));
|
|
2111
2373
|
const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
|
|
2112
|
-
if (sections.length
|
|
2113
|
-
const
|
|
2114
|
-
const
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
const
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
nextSec.
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
nextArticle
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
nextSec.appendChild(
|
|
2374
|
+
if (sections.length > 0 && cards.length === 0) {
|
|
2375
|
+
const finalSections = [];
|
|
2376
|
+
for (const singleSec of sections) {
|
|
2377
|
+
const contentContainer = singleSec.querySelector("article") || singleSec;
|
|
2378
|
+
const children = Array.from(contentContainer.children);
|
|
2379
|
+
const pageH = singleSec.offsetHeight > 1300 ? 1122 : Math.max(1056, singleSec.offsetHeight);
|
|
2380
|
+
const secH = singleSec.scrollHeight || singleSec.offsetHeight;
|
|
2381
|
+
if (secH > pageH * 1.25 && children.length > 1) {
|
|
2382
|
+
const childHeights = children.map((c) => {
|
|
2383
|
+
const rectH = c.getBoundingClientRect().height;
|
|
2384
|
+
const offH = c.offsetHeight;
|
|
2385
|
+
const textLen = c.textContent?.trim().length || 0;
|
|
2386
|
+
const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
|
|
2387
|
+
return Math.max(rectH, offH, estH);
|
|
2388
|
+
});
|
|
2389
|
+
const parent = singleSec.parentElement || wrapper;
|
|
2390
|
+
const headerEl = singleSec.querySelector("header");
|
|
2391
|
+
const footerEl = singleSec.querySelector("footer");
|
|
2392
|
+
contentContainer.innerHTML = "";
|
|
2393
|
+
singleSec.style.minHeight = `${pageH}px`;
|
|
2394
|
+
singleSec.style.boxSizing = "border-box";
|
|
2395
|
+
let curContent = contentContainer;
|
|
2396
|
+
let curSec = singleSec;
|
|
2397
|
+
let curH = 0;
|
|
2398
|
+
const maxH = pageH - 140;
|
|
2399
|
+
finalSections.push(singleSec);
|
|
2400
|
+
for (let i = 0; i < children.length; i++) {
|
|
2401
|
+
const child = children[i];
|
|
2402
|
+
const chH = childHeights[i];
|
|
2403
|
+
curContent.appendChild(child);
|
|
2404
|
+
curH += chH;
|
|
2405
|
+
if (curH >= maxH && i < children.length - 1) {
|
|
2406
|
+
const nextSec = document.createElement("section");
|
|
2407
|
+
nextSec.className = singleSec.className;
|
|
2408
|
+
nextSec.style.cssText = singleSec.style.cssText;
|
|
2409
|
+
nextSec.style.minHeight = `${pageH}px`;
|
|
2410
|
+
nextSec.style.boxSizing = "border-box";
|
|
2411
|
+
nextSec.style.backgroundColor = "#ffffff";
|
|
2412
|
+
nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
|
|
2413
|
+
nextSec.style.borderRadius = "4px";
|
|
2414
|
+
nextSec.style.marginBottom = "24px";
|
|
2415
|
+
if (headerEl) {
|
|
2416
|
+
nextSec.appendChild(headerEl.cloneNode(true));
|
|
2417
|
+
}
|
|
2418
|
+
const nextArticle = document.createElement("article");
|
|
2419
|
+
if (contentContainer.tagName.toLowerCase() === "article") {
|
|
2420
|
+
nextArticle.style.cssText = contentContainer.style.cssText;
|
|
2421
|
+
}
|
|
2422
|
+
nextSec.appendChild(nextArticle);
|
|
2423
|
+
if (footerEl) {
|
|
2424
|
+
nextSec.appendChild(footerEl.cloneNode(true));
|
|
2425
|
+
}
|
|
2426
|
+
if (curSec.nextSibling) {
|
|
2427
|
+
parent.insertBefore(nextSec, curSec.nextSibling);
|
|
2428
|
+
} else {
|
|
2429
|
+
parent.appendChild(nextSec);
|
|
2430
|
+
}
|
|
2431
|
+
finalSections.push(nextSec);
|
|
2432
|
+
curSec = nextSec;
|
|
2433
|
+
curContent = nextArticle;
|
|
2434
|
+
curH = 0;
|
|
2161
2435
|
}
|
|
2162
|
-
parent.appendChild(nextSec);
|
|
2163
|
-
newSections.push(nextSec);
|
|
2164
|
-
curContent = nextArticle;
|
|
2165
|
-
curH = 0;
|
|
2166
2436
|
}
|
|
2437
|
+
} else {
|
|
2438
|
+
finalSections.push(singleSec);
|
|
2167
2439
|
}
|
|
2168
|
-
sections = newSections;
|
|
2169
2440
|
}
|
|
2441
|
+
sections = finalSections;
|
|
2170
2442
|
}
|
|
2171
2443
|
const pageElements = sections.length > 0 ? sections : cards;
|
|
2172
2444
|
const totalPages = Math.max(1, pageElements.length);
|
|
@@ -2558,6 +2830,88 @@ var DocxPlugin = class {
|
|
|
2558
2830
|
}
|
|
2559
2831
|
return result;
|
|
2560
2832
|
}
|
|
2833
|
+
parseAndRenderChartSvg(xmlStr, width = 500, height = 260) {
|
|
2834
|
+
const catMatches = [...xmlStr.matchAll(/<c:cat>[\s\S]*?<c:strCache>([\s\S]*?)<\/c:strCache>/g)];
|
|
2835
|
+
let categories = [];
|
|
2836
|
+
if (catMatches.length > 0) {
|
|
2837
|
+
categories = [...catMatches[0][1].matchAll(/<c:v>([^<]+)<\/c:v>/g)].map((m) => m[1]);
|
|
2838
|
+
}
|
|
2839
|
+
if (categories.length === 0) {
|
|
2840
|
+
categories = ["Category 1", "Category 2", "Category 3", "Category 4"];
|
|
2841
|
+
}
|
|
2842
|
+
const defaultColors = ["#004586", "#ff420e", "#ffd320", "#579d1c", "#7e0021", "#83caff"];
|
|
2843
|
+
const sers = [...xmlStr.matchAll(/<c:ser>([\s\S]*?)<\/c:ser>/g)];
|
|
2844
|
+
const series = [];
|
|
2845
|
+
sers.forEach((s, sIdx) => {
|
|
2846
|
+
const titleMatch = s[1].match(/<c:tx>[\s\S]*?<c:v>([^<]+)<\/c:v>/);
|
|
2847
|
+
const title = titleMatch ? titleMatch[1] : `Series ${sIdx + 1}`;
|
|
2848
|
+
const clrMatch = s[1].match(/<a:srgbClr\s+val="([^"]+)"/);
|
|
2849
|
+
const color = clrMatch ? "#" + clrMatch[1] : defaultColors[sIdx % defaultColors.length];
|
|
2850
|
+
const valMatch = s[1].match(/<c:val>[\s\S]*?<c:numCache>([\s\S]*?)<\/c:numCache>/);
|
|
2851
|
+
let values = [];
|
|
2852
|
+
if (valMatch) {
|
|
2853
|
+
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);
|
|
2854
|
+
}
|
|
2855
|
+
series.push({ title, color, values });
|
|
2856
|
+
});
|
|
2857
|
+
if (series.length === 0) return "";
|
|
2858
|
+
let maxVal = 10;
|
|
2859
|
+
series.forEach((s) => s.values.forEach((v) => {
|
|
2860
|
+
if (v > maxVal) maxVal = v;
|
|
2861
|
+
}));
|
|
2862
|
+
maxVal = Math.ceil(maxVal * 1.15);
|
|
2863
|
+
if (maxVal % 2 !== 0) maxVal++;
|
|
2864
|
+
const padLeft = 45;
|
|
2865
|
+
const padBottom = 55;
|
|
2866
|
+
const padTop = 20;
|
|
2867
|
+
const padRight = 20;
|
|
2868
|
+
const plotW = width - padLeft - padRight;
|
|
2869
|
+
const plotH = height - padTop - padBottom;
|
|
2870
|
+
const yTicks = 5;
|
|
2871
|
+
let gridLines = "";
|
|
2872
|
+
for (let i = 0; i <= yTicks; i++) {
|
|
2873
|
+
const val = maxVal / yTicks * i;
|
|
2874
|
+
const y = padTop + plotH - val / maxVal * plotH;
|
|
2875
|
+
gridLines += `<line x1="${padLeft}" y1="${y}" x2="${padLeft + plotW}" y2="${y}" stroke="#e2e8f0" stroke-width="1" />`;
|
|
2876
|
+
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>`;
|
|
2877
|
+
}
|
|
2878
|
+
const numCats = categories.length;
|
|
2879
|
+
const numSers = series.length;
|
|
2880
|
+
const groupW = plotW / numCats;
|
|
2881
|
+
const barW = Math.max(8, Math.min(28, groupW * 0.7 / numSers));
|
|
2882
|
+
const groupPad = (groupW - barW * numSers) / 2;
|
|
2883
|
+
let bars = "";
|
|
2884
|
+
let catLabels = "";
|
|
2885
|
+
for (let c = 0; c < numCats; c++) {
|
|
2886
|
+
const catX = padLeft + c * groupW;
|
|
2887
|
+
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>`;
|
|
2888
|
+
for (let s = 0; s < numSers; s++) {
|
|
2889
|
+
const val = series[s].values[c] ?? 0;
|
|
2890
|
+
const bH = Math.max(0, val / maxVal * plotH);
|
|
2891
|
+
const bX = catX + groupPad + s * barW;
|
|
2892
|
+
const bY = padTop + plotH - bH;
|
|
2893
|
+
bars += `<rect x="${bX}" y="${bY}" width="${barW - 2}" height="${bH}" fill="${series[s].color}" rx="1" />`;
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
let legend = "";
|
|
2897
|
+
const legY = height - 12;
|
|
2898
|
+
let legX = padLeft + (plotW - numSers * 100) / 2;
|
|
2899
|
+
series.forEach((s) => {
|
|
2900
|
+
legend += `<rect x="${legX}" y="${legY - 9}" width="10" height="10" fill="${s.color}" rx="2" />`;
|
|
2901
|
+
legend += `<text x="${legX + 15}" y="${legY}" font-size="11" fill="#475569" font-family="Calibri, sans-serif">${s.title}</text>`;
|
|
2902
|
+
legX += 95;
|
|
2903
|
+
});
|
|
2904
|
+
return `
|
|
2905
|
+
<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">
|
|
2906
|
+
${gridLines}
|
|
2907
|
+
<line x1="${padLeft}" y1="${padTop + plotH}" x2="${padLeft + plotW}" y2="${padTop + plotH}" stroke="#94a3b8" stroke-width="1.5" />
|
|
2908
|
+
<line x1="${padLeft}" y1="${padTop}" x2="${padLeft}" y2="${padTop + plotH}" stroke="#94a3b8" stroke-width="1.5" />
|
|
2909
|
+
${bars}
|
|
2910
|
+
${catLabels}
|
|
2911
|
+
${legend}
|
|
2912
|
+
</svg>
|
|
2913
|
+
`.trim();
|
|
2914
|
+
}
|
|
2561
2915
|
};
|
|
2562
2916
|
function docxPlugin() {
|
|
2563
2917
|
return new DocxPlugin();
|
|
@@ -3124,6 +3478,16 @@ var CodePlugin = class {
|
|
|
3124
3478
|
execute: () => {
|
|
3125
3479
|
instance.print?.();
|
|
3126
3480
|
}
|
|
3481
|
+
},
|
|
3482
|
+
{
|
|
3483
|
+
id: "open-window",
|
|
3484
|
+
icon: "open-window",
|
|
3485
|
+
label: "Open in Separate Full Window",
|
|
3486
|
+
type: "button",
|
|
3487
|
+
group: "actions",
|
|
3488
|
+
execute: () => {
|
|
3489
|
+
instance.openInSeparateWindow?.();
|
|
3490
|
+
}
|
|
3127
3491
|
}
|
|
3128
3492
|
);
|
|
3129
3493
|
return actions;
|
|
@@ -4292,6 +4656,14 @@ var RtfPlugin = class {
|
|
|
4292
4656
|
type: "button",
|
|
4293
4657
|
group: "actions",
|
|
4294
4658
|
execute: () => instance.print?.()
|
|
4659
|
+
},
|
|
4660
|
+
{
|
|
4661
|
+
id: "open-window",
|
|
4662
|
+
icon: "open-window",
|
|
4663
|
+
label: "Open in Separate Full Window",
|
|
4664
|
+
type: "button",
|
|
4665
|
+
group: "actions",
|
|
4666
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
4295
4667
|
}
|
|
4296
4668
|
);
|
|
4297
4669
|
return actions;
|
|
@@ -4344,59 +4716,54 @@ var RtfPlugin = class {
|
|
|
4344
4716
|
}
|
|
4345
4717
|
const doc = new RTFJS.Document(ctx.buffer, {});
|
|
4346
4718
|
const htmlElements = await doc.render();
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
const secH = singleEl.offsetHeight || singleEl.scrollHeight;
|
|
4352
|
-
if (secH > 1300 && children.length > 1) {
|
|
4353
|
-
const childHeights = children.map((c) => {
|
|
4354
|
-
const rectH = c.getBoundingClientRect().height;
|
|
4355
|
-
const offH = c.offsetHeight;
|
|
4356
|
-
const textLen = c.textContent?.trim().length || 0;
|
|
4357
|
-
const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
|
|
4358
|
-
return Math.max(rectH, offH, estH);
|
|
4359
|
-
});
|
|
4360
|
-
wrapper.innerHTML = "";
|
|
4361
|
-
const createRtfCard = () => {
|
|
4362
|
-
const card = document.createElement("div");
|
|
4363
|
-
card.className = "fp-rtf-page-card";
|
|
4364
|
-
card.style.backgroundColor = "#ffffff";
|
|
4365
|
-
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
4366
|
-
card.style.borderRadius = "4px";
|
|
4367
|
-
card.style.padding = "72px 56px";
|
|
4368
|
-
card.style.width = "816px";
|
|
4369
|
-
card.style.minHeight = "1056px";
|
|
4370
|
-
card.style.boxSizing = "border-box";
|
|
4371
|
-
card.style.marginBottom = "24px";
|
|
4372
|
-
return card;
|
|
4373
|
-
};
|
|
4374
|
-
let curCard = createRtfCard();
|
|
4375
|
-
wrapper.appendChild(curCard);
|
|
4376
|
-
pageElements = [curCard];
|
|
4377
|
-
let curH = 0;
|
|
4378
|
-
const maxH = 920;
|
|
4379
|
-
for (let i = 0; i < children.length; i++) {
|
|
4380
|
-
const child = children[i];
|
|
4381
|
-
const chH = childHeights[i];
|
|
4382
|
-
curCard.appendChild(child);
|
|
4383
|
-
curH += chH;
|
|
4384
|
-
if (curH >= maxH && i < children.length - 1) {
|
|
4385
|
-
curCard = createRtfCard();
|
|
4386
|
-
wrapper.appendChild(curCard);
|
|
4387
|
-
pageElements.push(curCard);
|
|
4388
|
-
curH = 0;
|
|
4389
|
-
}
|
|
4390
|
-
}
|
|
4719
|
+
const contentNodes = [];
|
|
4720
|
+
for (const item of htmlElements) {
|
|
4721
|
+
if (item.children && item.children.length > 0 && !item.tagName.toLowerCase().startsWith("table")) {
|
|
4722
|
+
contentNodes.push(...Array.from(item.children));
|
|
4391
4723
|
} else {
|
|
4392
|
-
|
|
4724
|
+
contentNodes.push(item);
|
|
4393
4725
|
}
|
|
4394
|
-
}
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4726
|
+
}
|
|
4727
|
+
wrapper.innerHTML = "";
|
|
4728
|
+
contentNodes.forEach((node) => wrapper.appendChild(node));
|
|
4729
|
+
const childHeights = contentNodes.map((c) => {
|
|
4730
|
+
const rectH = c.getBoundingClientRect ? c.getBoundingClientRect().height : 0;
|
|
4731
|
+
const offH = c.offsetHeight || 0;
|
|
4732
|
+
const textLen = c.textContent?.trim().length || 0;
|
|
4733
|
+
const estH = Math.max(24, Math.ceil(textLen / 75) * 22 + 14);
|
|
4734
|
+
return Math.max(rectH, offH, estH);
|
|
4735
|
+
});
|
|
4736
|
+
wrapper.innerHTML = "";
|
|
4737
|
+
const createRtfCard = () => {
|
|
4738
|
+
const card = document.createElement("div");
|
|
4739
|
+
card.className = "fp-rtf-page-card";
|
|
4740
|
+
card.style.backgroundColor = "#ffffff";
|
|
4741
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
4742
|
+
card.style.borderRadius = "4px";
|
|
4743
|
+
card.style.padding = "72px 56px";
|
|
4744
|
+
card.style.width = "816px";
|
|
4745
|
+
card.style.minHeight = "1056px";
|
|
4746
|
+
card.style.boxSizing = "border-box";
|
|
4747
|
+
card.style.marginBottom = "24px";
|
|
4748
|
+
card.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4749
|
+
card.style.lineHeight = "1.6";
|
|
4750
|
+
return card;
|
|
4751
|
+
};
|
|
4752
|
+
let curCard = createRtfCard();
|
|
4753
|
+
wrapper.appendChild(curCard);
|
|
4754
|
+
pageElements = [curCard];
|
|
4755
|
+
let curH = 0;
|
|
4756
|
+
const maxH = 912;
|
|
4757
|
+
for (let i = 0; i < contentNodes.length; i++) {
|
|
4758
|
+
const child = contentNodes[i];
|
|
4759
|
+
const chH = childHeights[i];
|
|
4760
|
+
curCard.appendChild(child);
|
|
4761
|
+
curH += chH;
|
|
4762
|
+
if (curH >= maxH && i < contentNodes.length - 1) {
|
|
4763
|
+
curCard = createRtfCard();
|
|
4764
|
+
wrapper.appendChild(curCard);
|
|
4765
|
+
pageElements.push(curCard);
|
|
4766
|
+
curH = 0;
|
|
4400
4767
|
}
|
|
4401
4768
|
}
|
|
4402
4769
|
} catch (err) {
|
|
@@ -4765,6 +5132,14 @@ var OpenDocumentPlugin = class {
|
|
|
4765
5132
|
type: "button",
|
|
4766
5133
|
group: "actions",
|
|
4767
5134
|
execute: () => instance.print?.()
|
|
5135
|
+
},
|
|
5136
|
+
{
|
|
5137
|
+
id: "open-window",
|
|
5138
|
+
icon: "open-window",
|
|
5139
|
+
label: "Open in Separate Full Window",
|
|
5140
|
+
type: "button",
|
|
5141
|
+
group: "actions",
|
|
5142
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
4768
5143
|
}
|
|
4769
5144
|
);
|
|
4770
5145
|
return actions;
|
|
@@ -5353,6 +5728,14 @@ var DocPlugin = class {
|
|
|
5353
5728
|
type: "button",
|
|
5354
5729
|
group: "actions",
|
|
5355
5730
|
execute: () => instance.print?.()
|
|
5731
|
+
},
|
|
5732
|
+
{
|
|
5733
|
+
id: "open-window",
|
|
5734
|
+
icon: "open-window",
|
|
5735
|
+
label: "Open in Separate Full Window",
|
|
5736
|
+
type: "button",
|
|
5737
|
+
group: "actions",
|
|
5738
|
+
execute: () => instance.openInSeparateWindow?.()
|
|
5356
5739
|
}
|
|
5357
5740
|
);
|
|
5358
5741
|
return actions;
|
|
@@ -5372,8 +5755,17 @@ var DocPlugin = class {
|
|
|
5372
5755
|
let scale = 1;
|
|
5373
5756
|
let extractedRawText = "";
|
|
5374
5757
|
let isFallback = false;
|
|
5758
|
+
let chartSvg = "";
|
|
5375
5759
|
try {
|
|
5376
5760
|
const cfbf = new CfbfReader(ctx.buffer);
|
|
5761
|
+
try {
|
|
5762
|
+
const pkg = cfbf.readStream("package_stream");
|
|
5763
|
+
if (pkg && pkg.length > 100) {
|
|
5764
|
+
chartSvg = this.parseOdfChartToSvg(pkg);
|
|
5765
|
+
}
|
|
5766
|
+
} catch (chartErr) {
|
|
5767
|
+
console.warn("[DocPlugin] Chart stream parsing info:", chartErr);
|
|
5768
|
+
}
|
|
5377
5769
|
const wordDocStream = cfbf.readStream("WordDocument");
|
|
5378
5770
|
if (!wordDocStream || wordDocStream.length < 512) {
|
|
5379
5771
|
throw new Error("WordDocument stream not found or invalid in CFBF archive");
|
|
@@ -5391,7 +5783,7 @@ var DocPlugin = class {
|
|
|
5391
5783
|
extractedRawText = fallback;
|
|
5392
5784
|
isFallback = true;
|
|
5393
5785
|
}
|
|
5394
|
-
const rawPages = this.splitIntoPages(extractedRawText);
|
|
5786
|
+
const rawPages = this.splitIntoPages(extractedRawText, chartSvg);
|
|
5395
5787
|
const totalPages = Math.max(1, rawPages.length);
|
|
5396
5788
|
let currentPage = 1;
|
|
5397
5789
|
const pageCards = [];
|
|
@@ -5633,7 +6025,7 @@ var DocPlugin = class {
|
|
|
5633
6025
|
for (const run of [...ansiRuns, ...utf16Runs]) {
|
|
5634
6026
|
const trimmed = run.trim();
|
|
5635
6027
|
if (trimmed.length >= 4 && /[a-zA-Z]/.test(trimmed) && !seen.has(trimmed)) {
|
|
5636
|
-
if (!trimmed.includes("Normal.dot") && !trimmed.includes("Microsoft Word") && !trimmed.includes("Times New Roman") && !trimmed.startsWith("\xD0\xCF\xE0\xA1\xB1\xE1") && !/^[\W_0-9]+$/.test(trimmed)) {
|
|
6028
|
+
if (!trimmed.includes("Normal.dot") && !trimmed.includes("Microsoft Word") && !trimmed.includes("Times New Roman") && !trimmed.startsWith("\xD0\xCF\xE0\xA1\xB1\xE1") && !/^EMBED\b/i.test(trimmed) && !trimmed.includes("ChartDocument") && !/^[\W_0-9]+$/.test(trimmed)) {
|
|
5637
6029
|
seen.add(trimmed);
|
|
5638
6030
|
candidateLines.push(trimmed);
|
|
5639
6031
|
}
|
|
@@ -5644,12 +6036,138 @@ var DocPlugin = class {
|
|
|
5644
6036
|
heuristicTextExtraction(buffer) {
|
|
5645
6037
|
return this.extractStringsFromBytes(new Uint8Array(buffer));
|
|
5646
6038
|
}
|
|
5647
|
-
|
|
6039
|
+
/**
|
|
6040
|
+
* Parses an embedded OpenDocument Chart package into a vector SVG bar/column chart
|
|
6041
|
+
*/
|
|
6042
|
+
parseOdfChartToSvg(zipBytes) {
|
|
6043
|
+
try {
|
|
6044
|
+
const unzipped = fflate.unzipSync(zipBytes);
|
|
6045
|
+
const contentXml = unzipped["content.xml"] ? new TextDecoder("utf-8").decode(unzipped["content.xml"]) : "";
|
|
6046
|
+
if (!contentXml) return "";
|
|
6047
|
+
const rowsMatch = contentXml.match(/<table:table-row[\s\S]*?<\/table:table-row>/g) || [];
|
|
6048
|
+
if (rowsMatch.length < 2) return "";
|
|
6049
|
+
const headers = [];
|
|
6050
|
+
const firstRow = rowsMatch[0];
|
|
6051
|
+
const headerCells = firstRow ? firstRow.match(/<text:p>([^<]+)<\/text:p>/g) || [] : [];
|
|
6052
|
+
for (const h of headerCells) {
|
|
6053
|
+
headers.push(h.replace(/<\/?text:p>/g, "").trim());
|
|
6054
|
+
}
|
|
6055
|
+
const categories = [];
|
|
6056
|
+
const seriesValues = headers.map(() => []);
|
|
6057
|
+
for (let r = 1; r < rowsMatch.length; r++) {
|
|
6058
|
+
const rowStr = rowsMatch[r];
|
|
6059
|
+
if (!rowStr) continue;
|
|
6060
|
+
const cells = rowStr.match(/<table:table-cell[\s\S]*?<\/table:table-cell>/g) || [];
|
|
6061
|
+
if (cells.length > 0 && cells[0]) {
|
|
6062
|
+
const catMatch = cells[0].match(/<text:p>([^<]+)<\/text:p>/);
|
|
6063
|
+
categories.push(catMatch ? catMatch[1] : "Row " + r);
|
|
6064
|
+
for (let c = 1; c < cells.length && c - 1 < headers.length; c++) {
|
|
6065
|
+
const cellStr = cells[c];
|
|
6066
|
+
if (!cellStr) continue;
|
|
6067
|
+
const valMatch = cellStr.match(/office:value="([0-9.]+)"/) || cellStr.match(/<text:p>([0-9.]+)<\/text:p>/);
|
|
6068
|
+
const series = seriesValues[c - 1];
|
|
6069
|
+
if (series) {
|
|
6070
|
+
series.push(valMatch ? parseFloat(valMatch[1]) : 0);
|
|
6071
|
+
}
|
|
6072
|
+
}
|
|
6073
|
+
}
|
|
6074
|
+
}
|
|
6075
|
+
const colors = ["#004586", "#ff420e", "#ffd320", "#579d1c", "#7e0021"];
|
|
6076
|
+
const colorMatches = contentXml.matchAll(/draw:fill-color="(#[0-9a-fA-F]{6})"/g);
|
|
6077
|
+
let cIdx = 0;
|
|
6078
|
+
for (const cm of colorMatches) {
|
|
6079
|
+
if (cIdx < colors.length) colors[cIdx] = cm[1];
|
|
6080
|
+
cIdx++;
|
|
6081
|
+
}
|
|
6082
|
+
let maxVal = 10;
|
|
6083
|
+
for (const s of seriesValues) {
|
|
6084
|
+
for (const v of s) {
|
|
6085
|
+
if (v > maxVal) maxVal = v;
|
|
6086
|
+
}
|
|
6087
|
+
}
|
|
6088
|
+
maxVal = Math.ceil(maxVal * 1.15);
|
|
6089
|
+
const width = 560;
|
|
6090
|
+
const height = 280;
|
|
6091
|
+
const padLeft = 45;
|
|
6092
|
+
const padRight = 100;
|
|
6093
|
+
const padTop = 20;
|
|
6094
|
+
const padBottom = 40;
|
|
6095
|
+
const chartW = width - padLeft - padRight;
|
|
6096
|
+
const chartH = height - padTop - padBottom;
|
|
6097
|
+
let svg = `<svg viewBox="0 0 ${width} ${height}" width="100%" height="auto" style="max-width: 560px; height: 280px; margin: 16px auto; display: block; font-family: Calibri, sans-serif; background: #ffffff; border: 1px solid #e2e8f0; border-radius: 6px; box-shadow: 0 1px 4px rgba(0,0,0,0.05);">`;
|
|
6098
|
+
for (let step = 0; step <= 4; step++) {
|
|
6099
|
+
const yVal = (maxVal / 4 * step).toFixed(1);
|
|
6100
|
+
const yPos = padTop + chartH - step / 4 * chartH;
|
|
6101
|
+
svg += `<line x1="${padLeft}" y1="${yPos}" x2="${padLeft + chartW}" y2="${yPos}" stroke="#e2e8f0" stroke-dasharray="2,2" />`;
|
|
6102
|
+
svg += `<text x="${padLeft - 8}" y="${yPos + 4}" font-size="11" fill="#64748b" text-anchor="end">${yVal}</text>`;
|
|
6103
|
+
}
|
|
6104
|
+
const numCats = categories.length;
|
|
6105
|
+
const numSeries = headers.length;
|
|
6106
|
+
const groupW = chartW / numCats;
|
|
6107
|
+
const barW = Math.max(8, groupW * 0.7 / numSeries);
|
|
6108
|
+
const groupPad = (groupW - barW * numSeries) / 2;
|
|
6109
|
+
for (let catIdx = 0; catIdx < numCats; catIdx++) {
|
|
6110
|
+
const groupX = padLeft + catIdx * groupW + groupPad;
|
|
6111
|
+
for (let sIdx = 0; sIdx < numSeries; sIdx++) {
|
|
6112
|
+
const val = seriesValues[sIdx][catIdx] || 0;
|
|
6113
|
+
const barH = val / maxVal * chartH;
|
|
6114
|
+
const barX = groupX + sIdx * barW;
|
|
6115
|
+
const barY = padTop + chartH - barH;
|
|
6116
|
+
const col = colors[sIdx % colors.length];
|
|
6117
|
+
svg += `<rect x="${barX}" y="${barY}" width="${barW - 2}" height="${barH}" fill="${col}" rx="2"><title>${headers[sIdx]}: ${val}</title></rect>`;
|
|
6118
|
+
}
|
|
6119
|
+
const catX = padLeft + catIdx * groupW + groupW / 2;
|
|
6120
|
+
svg += `<text x="${catX}" y="${padTop + chartH + 18}" font-size="11" fill="#475569" text-anchor="middle">${categories[catIdx]}</text>`;
|
|
6121
|
+
}
|
|
6122
|
+
let legendY = padTop + 20;
|
|
6123
|
+
for (let sIdx = 0; sIdx < numSeries; sIdx++) {
|
|
6124
|
+
const col = colors[sIdx % colors.length];
|
|
6125
|
+
svg += `<rect x="${padLeft + chartW + 15}" y="${legendY}" width="12" height="12" fill="${col}" rx="2" />`;
|
|
6126
|
+
svg += `<text x="${padLeft + chartW + 32}" y="${legendY + 10}" font-size="11" fill="#334155">${headers[sIdx]}</text>`;
|
|
6127
|
+
legendY += 20;
|
|
6128
|
+
}
|
|
6129
|
+
svg += "</svg>";
|
|
6130
|
+
return svg;
|
|
6131
|
+
} catch (e) {
|
|
6132
|
+
console.warn("[DocPlugin] Error generating chart SVG:", e);
|
|
6133
|
+
return "";
|
|
6134
|
+
}
|
|
6135
|
+
}
|
|
6136
|
+
cleanWordDocFields(text, chartSvg = "") {
|
|
6137
|
+
if (!text) return "";
|
|
6138
|
+
let cleaned = text.replace(
|
|
6139
|
+
/\x13\s*EMBED\b[\s\S]*?\x15/gi,
|
|
6140
|
+
() => chartSvg ? `
|
|
6141
|
+
|
|
6142
|
+
${chartSvg}
|
|
6143
|
+
|
|
6144
|
+
` : ""
|
|
6145
|
+
);
|
|
6146
|
+
cleaned = cleaned.replace(
|
|
6147
|
+
/\x13\s*HYPERLINK\s*"?([^"\x14]+)"?\s*\x14([\s\S]*?)\x15/gi,
|
|
6148
|
+
(_match, url, label) => {
|
|
6149
|
+
const cleanUrl = url.trim();
|
|
6150
|
+
const cleanLabel = label.trim() || cleanUrl;
|
|
6151
|
+
return `<a href="${cleanUrl}" target="_blank" rel="noopener noreferrer" style="color: #2563eb; text-decoration: underline;">${cleanLabel}</a>`;
|
|
6152
|
+
}
|
|
6153
|
+
);
|
|
6154
|
+
cleaned = cleaned.replace(/\x13[^\x14\x15]*\x14([^\x15]*)\x15/g, (_m, res) => {
|
|
6155
|
+
if (/[\x00-\x1F]/.test(res)) return "";
|
|
6156
|
+
return res.trim();
|
|
6157
|
+
});
|
|
6158
|
+
cleaned = cleaned.replace(/\x13[^\x15]*\x15/g, "");
|
|
6159
|
+
cleaned = cleaned.replace(/[\x13\x14\x15]/g, "");
|
|
6160
|
+
cleaned = cleaned.replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/g, "");
|
|
6161
|
+
cleaned = cleaned.replace(/EMBED\s+LibreOffice\.ChartDocument\.[0-9]+/gi, chartSvg || "");
|
|
6162
|
+
return cleaned;
|
|
6163
|
+
}
|
|
6164
|
+
splitIntoPages(text, chartSvg = "") {
|
|
5648
6165
|
if (!text) return [""];
|
|
5649
|
-
const
|
|
6166
|
+
const cleanedText = this.cleanWordDocFields(text, chartSvg);
|
|
6167
|
+
const normalized = cleanedText.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ");
|
|
5650
6168
|
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);
|
|
5651
6169
|
if (explicitParts.length === 0) explicitParts.push(normalized);
|
|
5652
|
-
const maxLinesPerPage =
|
|
6170
|
+
const maxLinesPerPage = 34;
|
|
5653
6171
|
const charsPerLine = 80;
|
|
5654
6172
|
const finalPages = [];
|
|
5655
6173
|
for (const part of explicitParts) {
|
|
@@ -5657,7 +6175,8 @@ var DocPlugin = class {
|
|
|
5657
6175
|
let currentLines = [];
|
|
5658
6176
|
let count = 0;
|
|
5659
6177
|
for (const line of lines) {
|
|
5660
|
-
const
|
|
6178
|
+
const isSvg = line.includes("<svg");
|
|
6179
|
+
const vLines = isSvg ? 12 : Math.max(1, Math.ceil((line.replace(/<[^>]+>/g, "").length || 1) / charsPerLine));
|
|
5661
6180
|
if (count + vLines > maxLinesPerPage && currentLines.length > 0) {
|
|
5662
6181
|
finalPages.push(currentLines.join("\n"));
|
|
5663
6182
|
currentLines = [];
|
|
@@ -5697,9 +6216,44 @@ var DocPlugin = class {
|
|
|
5697
6216
|
tableLines = [];
|
|
5698
6217
|
}
|
|
5699
6218
|
};
|
|
6219
|
+
const sanitizeOptions = {
|
|
6220
|
+
ADD_TAGS: ["a", "svg", "g", "path", "line", "rect", "circle", "text", "title"],
|
|
6221
|
+
ADD_ATTR: [
|
|
6222
|
+
"href",
|
|
6223
|
+
"target",
|
|
6224
|
+
"rel",
|
|
6225
|
+
"style",
|
|
6226
|
+
"viewBox",
|
|
6227
|
+
"width",
|
|
6228
|
+
"height",
|
|
6229
|
+
"x",
|
|
6230
|
+
"y",
|
|
6231
|
+
"x1",
|
|
6232
|
+
"y1",
|
|
6233
|
+
"x2",
|
|
6234
|
+
"y2",
|
|
6235
|
+
"fill",
|
|
6236
|
+
"stroke",
|
|
6237
|
+
"stroke-width",
|
|
6238
|
+
"stroke-dasharray",
|
|
6239
|
+
"rx",
|
|
6240
|
+
"font-size",
|
|
6241
|
+
"text-anchor"
|
|
6242
|
+
]
|
|
6243
|
+
};
|
|
5700
6244
|
let i = 0;
|
|
5701
6245
|
while (i < lines.length) {
|
|
5702
6246
|
let line = lines[i];
|
|
6247
|
+
if (line.includes("<svg")) {
|
|
6248
|
+
if (inList) {
|
|
6249
|
+
html += "</ul>";
|
|
6250
|
+
inList = false;
|
|
6251
|
+
}
|
|
6252
|
+
flushTable();
|
|
6253
|
+
html += line;
|
|
6254
|
+
i++;
|
|
6255
|
+
continue;
|
|
6256
|
+
}
|
|
5703
6257
|
let tabCount = (line.match(/\t/g) || []).length;
|
|
5704
6258
|
if (tabCount > 0) {
|
|
5705
6259
|
let j = i;
|
|
@@ -5738,20 +6292,20 @@ var DocPlugin = class {
|
|
|
5738
6292
|
html += "</ul>";
|
|
5739
6293
|
inList = false;
|
|
5740
6294
|
}
|
|
5741
|
-
html += `<h2 style="font-size: 16px; font-weight: 700; color: #1e3a8a; margin: 16px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify6.sanitize(line)}</h2>`;
|
|
6295
|
+
html += `<h2 style="font-size: 16px; font-weight: 700; color: #1e3a8a; margin: 16px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify6.sanitize(line, sanitizeOptions)}</h2>`;
|
|
5742
6296
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
5743
6297
|
if (!inList) {
|
|
5744
6298
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
5745
6299
|
inList = true;
|
|
5746
6300
|
}
|
|
5747
6301
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
5748
|
-
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6.sanitize(bulletText)}</li>`;
|
|
6302
|
+
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6.sanitize(bulletText, sanitizeOptions)}</li>`;
|
|
5749
6303
|
} else {
|
|
5750
6304
|
if (inList) {
|
|
5751
6305
|
html += "</ul>";
|
|
5752
6306
|
inList = false;
|
|
5753
6307
|
}
|
|
5754
|
-
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6.sanitize(line)}</p>`;
|
|
6308
|
+
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6.sanitize(line, sanitizeOptions)}</p>`;
|
|
5755
6309
|
}
|
|
5756
6310
|
i++;
|
|
5757
6311
|
}
|
|
@@ -6304,6 +6858,6 @@ var FilePreviewViewer2 = class extends FilePreviewViewer {
|
|
|
6304
6858
|
}
|
|
6305
6859
|
};
|
|
6306
6860
|
|
|
6307
|
-
export { CfbfReader, EventEmitter, FilePreviewViewer2 as FilePreviewViewer, ThumbnailPanel, ToolbarController, archivePlugin, clamp, codePlugin, createElement, csvPlugin, debounce, detectMagicBytes, detectOoxmlType, docPlugin, docxPlugin, downloadFile, excelPlugin, extractExtension, formatFileSize, getDefaultPlugins, htmlPreviewPlugin, markdownPlugin, mediaPlugin, mimeFromExtension, openDocumentPlugin, pdfPlugin, pptPlugin, pptxPlugin, printElement, rtfPlugin, sanitizeHTML, sanitizeSVG, sourceToArrayBuffer, threeDPlugin };
|
|
6861
|
+
export { CfbfReader, EventEmitter, FilePreviewViewer2 as FilePreviewViewer, ThumbnailPanel, ToolbarController, archivePlugin, clamp, codePlugin, createElement, csvPlugin, debounce, detectMagicBytes, detectOoxmlType, docPlugin, docxPlugin, downloadFile, excelPlugin, extractExtension, formatFileSize, getDefaultPlugins, getTransferPayload, htmlPreviewPlugin, markdownPlugin, mediaPlugin, mimeFromExtension, openDocumentPlugin, pdfPlugin, pptPlugin, pptxPlugin, printElement, rtfPlugin, sanitizeHTML, sanitizeSVG, saveTransferPayload, sourceToArrayBuffer, threeDPlugin };
|
|
6308
6862
|
//# sourceMappingURL=index.js.map
|
|
6309
6863
|
//# sourceMappingURL=index.js.map
|