@files-preview-app/preview-file 1.2.5 → 1.2.7
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 +933 -208
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.js +932 -207
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +934 -209
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +933 -208
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +933 -208
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +932 -207
- package/dist/react.js.map +1 -1
- package/dist/styles.css +28 -1
- package/dist/vue.cjs +933 -208
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +932 -207
- package/dist/vue.js.map +1 -1
- package/package.json +179 -169
package/dist/angular.cjs
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var core = require('@angular/core');
|
|
6
6
|
var common = require('@angular/common');
|
|
7
|
-
var
|
|
7
|
+
var DOMPurify6 = require('dompurify');
|
|
8
8
|
var pdfjsLib = require('pdfjs-dist');
|
|
9
9
|
var docx = require('docx-preview');
|
|
10
10
|
var fflate = require('fflate');
|
|
@@ -38,7 +38,7 @@ function _interopNamespace(e) {
|
|
|
38
38
|
return Object.freeze(n);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
var
|
|
41
|
+
var DOMPurify6__default = /*#__PURE__*/_interopDefault(DOMPurify6);
|
|
42
42
|
var pdfjsLib__namespace = /*#__PURE__*/_interopNamespace(pdfjsLib);
|
|
43
43
|
var docx__namespace = /*#__PURE__*/_interopNamespace(docx);
|
|
44
44
|
var XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
|
|
@@ -437,7 +437,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
437
437
|
if (magicMime === "application/zip") {
|
|
438
438
|
const ooxmlMime = detectOoxmlType(buffer);
|
|
439
439
|
if (ooxmlMime && ooxmlMime !== "application/zip") {
|
|
440
|
-
metadata.mimeType = ooxmlMime;
|
|
440
|
+
metadata.mimeType = metadata.mimeType ?? ooxmlMime;
|
|
441
441
|
if (ooxmlMime.includes("wordprocessing")) metadata.extension = metadata.extension ?? ".docx";
|
|
442
442
|
else if (ooxmlMime.includes("spreadsheet")) metadata.extension = metadata.extension ?? ".xlsx";
|
|
443
443
|
else if (ooxmlMime.includes("presentation")) metadata.extension = metadata.extension ?? ".pptx";
|
|
@@ -466,7 +466,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
466
466
|
return { buffer, metadata };
|
|
467
467
|
}
|
|
468
468
|
function sanitizeSVG(svg) {
|
|
469
|
-
return
|
|
469
|
+
return DOMPurify6__default.default.sanitize(svg, {
|
|
470
470
|
USE_PROFILES: { svg: true, svgFilters: true }
|
|
471
471
|
});
|
|
472
472
|
}
|
|
@@ -785,6 +785,8 @@ var FilePreviewViewer = class {
|
|
|
785
785
|
keyHandler = null;
|
|
786
786
|
currentContainer = null;
|
|
787
787
|
currentOptions = {};
|
|
788
|
+
resizeObserver = null;
|
|
789
|
+
fullscreenHandler = null;
|
|
788
790
|
/**
|
|
789
791
|
* Register a preview plugin.
|
|
790
792
|
*/
|
|
@@ -857,12 +859,31 @@ var FilePreviewViewer = class {
|
|
|
857
859
|
label: "Toggle Fullscreen",
|
|
858
860
|
type: "button",
|
|
859
861
|
group: "view",
|
|
860
|
-
execute: () => {
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
862
|
+
execute: async () => {
|
|
863
|
+
try {
|
|
864
|
+
const isNativeFs = !!document.fullscreenElement;
|
|
865
|
+
const isCssFs = this.wrapperEl?.classList.contains("fp-fullscreen-active");
|
|
866
|
+
if (!isNativeFs && !isCssFs) {
|
|
867
|
+
if (this.wrapperEl?.requestFullscreen) {
|
|
868
|
+
await this.wrapperEl.requestFullscreen().catch(() => {
|
|
869
|
+
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
870
|
+
});
|
|
871
|
+
} else {
|
|
872
|
+
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
873
|
+
}
|
|
874
|
+
} else {
|
|
875
|
+
if (document.fullscreenElement) {
|
|
876
|
+
await document.exitFullscreen().catch(() => {
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
this.wrapperEl?.classList.remove("fp-fullscreen-active");
|
|
880
|
+
}
|
|
881
|
+
} catch {
|
|
882
|
+
this.wrapperEl?.classList.toggle("fp-fullscreen-active");
|
|
865
883
|
}
|
|
884
|
+
setTimeout(() => {
|
|
885
|
+
this.activeInstance?.fitToPage?.();
|
|
886
|
+
}, 120);
|
|
866
887
|
}
|
|
867
888
|
});
|
|
868
889
|
}
|
|
@@ -912,6 +933,15 @@ var FilePreviewViewer = class {
|
|
|
912
933
|
window.removeEventListener("keydown", this.keyHandler);
|
|
913
934
|
this.keyHandler = null;
|
|
914
935
|
}
|
|
936
|
+
if (this.resizeObserver) {
|
|
937
|
+
this.resizeObserver.disconnect();
|
|
938
|
+
this.resizeObserver = null;
|
|
939
|
+
}
|
|
940
|
+
if (this.fullscreenHandler) {
|
|
941
|
+
document.removeEventListener("fullscreenchange", this.fullscreenHandler);
|
|
942
|
+
document.removeEventListener("webkitfullscreenchange", this.fullscreenHandler);
|
|
943
|
+
this.fullscreenHandler = null;
|
|
944
|
+
}
|
|
915
945
|
this.abort();
|
|
916
946
|
this.destroyInstance();
|
|
917
947
|
this.toolbar?.destroy();
|
|
@@ -991,6 +1021,25 @@ var FilePreviewViewer = class {
|
|
|
991
1021
|
this.thumbnailPanel = new ThumbnailPanel(thumbnailEl);
|
|
992
1022
|
this.setupKeyboardShortcuts();
|
|
993
1023
|
this.setupDragAndDrop(container, options);
|
|
1024
|
+
this.setupResizeAndFullscreenListeners();
|
|
1025
|
+
}
|
|
1026
|
+
setupResizeAndFullscreenListeners() {
|
|
1027
|
+
if (this.fullscreenHandler) return;
|
|
1028
|
+
this.fullscreenHandler = () => {
|
|
1029
|
+
setTimeout(() => {
|
|
1030
|
+
this.activeInstance?.fitToPage?.();
|
|
1031
|
+
}, 100);
|
|
1032
|
+
};
|
|
1033
|
+
document.addEventListener("fullscreenchange", this.fullscreenHandler);
|
|
1034
|
+
document.addEventListener("webkitfullscreenchange", this.fullscreenHandler);
|
|
1035
|
+
if (typeof ResizeObserver !== "undefined" && this.contentEl) {
|
|
1036
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
1037
|
+
if (this.activeInstance && (!this.activeInstance.getZoom || Math.abs((this.activeInstance.getZoom?.() ?? 1) - 1) < 0.05)) {
|
|
1038
|
+
this.activeInstance.fitToPage?.();
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
this.resizeObserver.observe(this.contentEl);
|
|
1042
|
+
}
|
|
994
1043
|
}
|
|
995
1044
|
setupKeyboardShortcuts() {
|
|
996
1045
|
if (this.keyHandler) return;
|
|
@@ -1382,7 +1431,8 @@ var PdfPlugin = class {
|
|
|
1382
1431
|
container.style.display = "flex";
|
|
1383
1432
|
container.style.flexDirection = "column";
|
|
1384
1433
|
container.style.alignItems = "center";
|
|
1385
|
-
container.style.
|
|
1434
|
+
container.style.justifyContent = "flex-start";
|
|
1435
|
+
container.style.padding = "20px 16px";
|
|
1386
1436
|
container.style.backgroundColor = "#0f172a";
|
|
1387
1437
|
container.style.boxSizing = "border-box";
|
|
1388
1438
|
container.style.position = "relative";
|
|
@@ -1395,7 +1445,8 @@ var PdfPlugin = class {
|
|
|
1395
1445
|
pageCard.style.lineHeight = "0";
|
|
1396
1446
|
pageCard.style.transition = "transform 0.15s ease";
|
|
1397
1447
|
pageCard.style.position = "relative";
|
|
1398
|
-
|
|
1448
|
+
pageCard.style.flexShrink = "0";
|
|
1449
|
+
let canvas = document.createElement("canvas");
|
|
1399
1450
|
pageCard.appendChild(canvas);
|
|
1400
1451
|
container.appendChild(pageCard);
|
|
1401
1452
|
const indicator = document.createElement("div");
|
|
@@ -1437,14 +1488,22 @@ var PdfPlugin = class {
|
|
|
1437
1488
|
}
|
|
1438
1489
|
currentRenderTask = null;
|
|
1439
1490
|
}
|
|
1491
|
+
const newCanvas = document.createElement("canvas");
|
|
1492
|
+
pageCard.replaceChild(newCanvas, canvas);
|
|
1493
|
+
canvas = newCanvas;
|
|
1440
1494
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
1441
1495
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
1442
1496
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
1443
1497
|
const page = await pdfDoc.getPage(currentPage);
|
|
1444
1498
|
const containerWidth = container.clientWidth || 900;
|
|
1499
|
+
const containerHeight = container.clientHeight || 700;
|
|
1445
1500
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1446
|
-
const
|
|
1447
|
-
const
|
|
1501
|
+
const availWidth = Math.max(100, containerWidth - 48);
|
|
1502
|
+
const availHeight = Math.max(100, containerHeight - 88);
|
|
1503
|
+
const scaleW = availWidth / unscaledVp.width;
|
|
1504
|
+
const scaleH = availHeight / unscaledVp.height;
|
|
1505
|
+
const fitScale = Math.min(scaleW, scaleH);
|
|
1506
|
+
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1448
1507
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
1449
1508
|
const viewport = page.getViewport({ scale: effectiveScale, rotation });
|
|
1450
1509
|
canvas.width = Math.floor(viewport.width * pixelRatio);
|
|
@@ -1469,7 +1528,19 @@ var PdfPlugin = class {
|
|
|
1469
1528
|
}
|
|
1470
1529
|
};
|
|
1471
1530
|
await renderPage(1);
|
|
1531
|
+
let resizeTimer = null;
|
|
1532
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
1533
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1534
|
+
resizeTimer = setTimeout(() => {
|
|
1535
|
+
if (Math.abs(zoomScale - 1) < 0.05) {
|
|
1536
|
+
renderPage(currentPage);
|
|
1537
|
+
}
|
|
1538
|
+
}, 150);
|
|
1539
|
+
});
|
|
1540
|
+
resizeObserver.observe(container);
|
|
1472
1541
|
const cleanup = () => {
|
|
1542
|
+
resizeObserver.disconnect();
|
|
1543
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1473
1544
|
if (currentRenderTask) {
|
|
1474
1545
|
try {
|
|
1475
1546
|
currentRenderTask.cancel();
|
|
@@ -1501,6 +1572,7 @@ var PdfPlugin = class {
|
|
|
1501
1572
|
},
|
|
1502
1573
|
fitToPage: () => {
|
|
1503
1574
|
zoomScale = 1;
|
|
1575
|
+
rotation = 0;
|
|
1504
1576
|
renderPage(currentPage);
|
|
1505
1577
|
},
|
|
1506
1578
|
rotateCW: () => {
|
|
@@ -1951,6 +2023,14 @@ var DocxPlugin = class {
|
|
|
1951
2023
|
group: "zoom",
|
|
1952
2024
|
execute: () => instance.fitToPage?.()
|
|
1953
2025
|
},
|
|
2026
|
+
{
|
|
2027
|
+
id: "rotate-cw",
|
|
2028
|
+
icon: "rotate-cw",
|
|
2029
|
+
label: "Rotate",
|
|
2030
|
+
type: "button",
|
|
2031
|
+
group: "view",
|
|
2032
|
+
execute: () => instance.rotateCW?.()
|
|
2033
|
+
},
|
|
1954
2034
|
{
|
|
1955
2035
|
id: "download",
|
|
1956
2036
|
icon: "download",
|
|
@@ -2087,6 +2167,26 @@ var DocxPlugin = class {
|
|
|
2087
2167
|
if (totalPages > 1) {
|
|
2088
2168
|
showPage(1);
|
|
2089
2169
|
}
|
|
2170
|
+
scale = 1;
|
|
2171
|
+
let rotation = 0;
|
|
2172
|
+
const calculateFitScale = () => {
|
|
2173
|
+
const activeEl = pageElements[currentPage - 1] || wrapper.firstElementChild || wrapper;
|
|
2174
|
+
const elW = activeEl.offsetWidth || 816;
|
|
2175
|
+
const elH = activeEl.offsetHeight || 1056;
|
|
2176
|
+
const availW = Math.max(200, ctx.container.clientWidth - 48);
|
|
2177
|
+
const availH = Math.max(200, ctx.container.clientHeight - 80);
|
|
2178
|
+
const sW = availW / elW;
|
|
2179
|
+
const sH = availH / elH;
|
|
2180
|
+
return Math.min(1.1, Math.min(sW, sH));
|
|
2181
|
+
};
|
|
2182
|
+
const applyTransform = () => {
|
|
2183
|
+
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
2184
|
+
wrapper.style.transformOrigin = "top center";
|
|
2185
|
+
};
|
|
2186
|
+
setTimeout(() => {
|
|
2187
|
+
scale = calculateFitScale();
|
|
2188
|
+
applyTransform();
|
|
2189
|
+
}, 60);
|
|
2090
2190
|
const cleanup = () => {
|
|
2091
2191
|
indicator?.remove();
|
|
2092
2192
|
for (const url of createdBlobUrls) {
|
|
@@ -2105,21 +2205,30 @@ var DocxPlugin = class {
|
|
|
2105
2205
|
showPage(page);
|
|
2106
2206
|
},
|
|
2107
2207
|
zoomIn: () => {
|
|
2108
|
-
scale += 0.
|
|
2109
|
-
|
|
2208
|
+
scale += 0.15;
|
|
2209
|
+
applyTransform();
|
|
2110
2210
|
},
|
|
2111
2211
|
zoomOut: () => {
|
|
2112
|
-
scale = Math.max(0.2, scale - 0.
|
|
2113
|
-
|
|
2212
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
2213
|
+
applyTransform();
|
|
2114
2214
|
},
|
|
2115
2215
|
getZoom: () => scale,
|
|
2116
2216
|
setZoom: (level) => {
|
|
2117
2217
|
scale = level;
|
|
2118
|
-
|
|
2218
|
+
applyTransform();
|
|
2119
2219
|
},
|
|
2120
2220
|
fitToPage: () => {
|
|
2121
|
-
scale =
|
|
2122
|
-
|
|
2221
|
+
scale = calculateFitScale();
|
|
2222
|
+
rotation = 0;
|
|
2223
|
+
applyTransform();
|
|
2224
|
+
},
|
|
2225
|
+
rotateCW: () => {
|
|
2226
|
+
rotation = (rotation + 90) % 360;
|
|
2227
|
+
applyTransform();
|
|
2228
|
+
},
|
|
2229
|
+
rotateCCW: () => {
|
|
2230
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
2231
|
+
applyTransform();
|
|
2123
2232
|
},
|
|
2124
2233
|
download: () => {
|
|
2125
2234
|
const blob = new Blob([ctx.buffer], { type: this.mimeTypes[0] });
|
|
@@ -2179,90 +2288,149 @@ var DocxPlugin = class {
|
|
|
2179
2288
|
console.warn("[DocxPlugin] Error parsing relationships:", relsErr);
|
|
2180
2289
|
}
|
|
2181
2290
|
}
|
|
2182
|
-
const
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2291
|
+
const sectPrs = Array.from(doc.getElementsByTagNameNS("*", "sectPr"));
|
|
2292
|
+
const lastSectPr = sectPrs[sectPrs.length - 1];
|
|
2293
|
+
let defaultW = 12240;
|
|
2294
|
+
let defaultH = 15840;
|
|
2295
|
+
let margins = { top: 1440, right: 1440, bottom: 1440, left: 1440 };
|
|
2296
|
+
if (lastSectPr) {
|
|
2297
|
+
const pgSz = lastSectPr.getElementsByTagNameNS("*", "pgSz")[0];
|
|
2298
|
+
if (pgSz) {
|
|
2299
|
+
defaultW = parseInt(pgSz.getAttribute("w:w") || pgSz.getAttribute("w") || "12240", 10);
|
|
2300
|
+
defaultH = parseInt(pgSz.getAttribute("w:h") || pgSz.getAttribute("h") || "15840", 10);
|
|
2301
|
+
}
|
|
2302
|
+
const pgMar = lastSectPr.getElementsByTagNameNS("*", "pgMar")[0];
|
|
2303
|
+
if (pgMar) {
|
|
2304
|
+
margins.top = parseInt(pgMar.getAttribute("w:top") || pgMar.getAttribute("top") || "1440", 10);
|
|
2305
|
+
margins.bottom = parseInt(pgMar.getAttribute("w:bottom") || pgMar.getAttribute("bottom") || "1440", 10);
|
|
2306
|
+
margins.left = parseInt(pgMar.getAttribute("w:left") || pgMar.getAttribute("left") || "1440", 10);
|
|
2307
|
+
margins.right = parseInt(pgMar.getAttribute("w:right") || pgMar.getAttribute("right") || "1440", 10);
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
const createPageCard = () => {
|
|
2311
|
+
const card = document.createElement("div");
|
|
2312
|
+
card.className = "fp-docx-page-card";
|
|
2313
|
+
card.style.backgroundColor = "#ffffff";
|
|
2314
|
+
card.style.borderRadius = "4px";
|
|
2315
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
2316
|
+
card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2317
|
+
card.style.color = "#1e293b";
|
|
2318
|
+
card.style.lineHeight = "1.6";
|
|
2319
|
+
card.style.boxSizing = "border-box";
|
|
2320
|
+
card.style.overflow = "hidden";
|
|
2321
|
+
card.style.position = "relative";
|
|
2322
|
+
card.style.marginBottom = "24px";
|
|
2323
|
+
card.style.width = `${defaultW / 15}px`;
|
|
2324
|
+
card.style.height = `${defaultH / 15}px`;
|
|
2325
|
+
card.style.padding = `${margins.top / 15}px ${margins.right / 15}px ${margins.bottom / 15}px ${margins.left / 15}px`;
|
|
2326
|
+
return card;
|
|
2327
|
+
};
|
|
2328
|
+
let currentCard = createPageCard();
|
|
2329
|
+
let currentHtml = "";
|
|
2330
|
+
const pages = [{ card: currentCard, html: "" }];
|
|
2331
|
+
const flushHtml = () => {
|
|
2332
|
+
pages[pages.length - 1].html += currentHtml;
|
|
2333
|
+
currentHtml = "";
|
|
2334
|
+
};
|
|
2335
|
+
const newPage = () => {
|
|
2336
|
+
flushHtml();
|
|
2337
|
+
currentCard = createPageCard();
|
|
2338
|
+
pages.push({ card: currentCard, html: "" });
|
|
2339
|
+
};
|
|
2191
2340
|
const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
|
|
2192
|
-
let html = "";
|
|
2193
2341
|
for (const child of Array.from(body.children)) {
|
|
2194
2342
|
const tag = child.localName || child.nodeName.split(":").pop();
|
|
2195
2343
|
if (tag === "p") {
|
|
2196
2344
|
const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
|
|
2197
2345
|
const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
|
|
2198
2346
|
const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
|
|
2199
|
-
const
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2347
|
+
const chunks = this.extractParagraphChunks(child, imageMap);
|
|
2348
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
2349
|
+
if (i > 0) {
|
|
2350
|
+
newPage();
|
|
2351
|
+
}
|
|
2352
|
+
const textContent = chunks[i];
|
|
2353
|
+
if (!textContent.trim() && !textContent.includes("<img")) {
|
|
2354
|
+
currentHtml += '<div style="height: 10px;"></div>';
|
|
2355
|
+
continue;
|
|
2356
|
+
}
|
|
2357
|
+
const lowerStyle = styleVal.toLowerCase();
|
|
2358
|
+
if (lowerStyle.includes("title")) {
|
|
2359
|
+
currentHtml += `<h1 style="font-size: 28px; font-weight: 700; color: #1e3a8a; margin: 24px 0 12px; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px;">${textContent}</h1>`;
|
|
2360
|
+
} else if (lowerStyle.includes("heading1") || styleVal === "1") {
|
|
2361
|
+
currentHtml += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
|
|
2362
|
+
} else if (lowerStyle.includes("heading2") || styleVal === "2") {
|
|
2363
|
+
currentHtml += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
|
|
2364
|
+
} else if (lowerStyle.includes("heading3") || styleVal === "3") {
|
|
2365
|
+
currentHtml += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
|
|
2366
|
+
} else if (numPr) {
|
|
2367
|
+
currentHtml += `<div style="display: flex; gap: 8px; margin: 4px 0 4px 20px;"><span style="color: #2563eb; font-weight: bold;">\u2022</span><span>${textContent}</span></div>`;
|
|
2368
|
+
} else {
|
|
2369
|
+
currentHtml += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
|
|
2370
|
+
}
|
|
2217
2371
|
}
|
|
2218
2372
|
} else if (tag === "tbl") {
|
|
2219
|
-
|
|
2373
|
+
currentHtml += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
|
|
2220
2374
|
const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
|
|
2221
2375
|
rows.forEach((tr, rIdx) => {
|
|
2222
|
-
|
|
2376
|
+
currentHtml += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
2223
2377
|
const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
|
|
2224
2378
|
cells.forEach((tc) => {
|
|
2225
2379
|
const cellText = this.extractParagraphHtml(tc, imageMap);
|
|
2226
|
-
|
|
2380
|
+
currentHtml += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || " "}</td>`;
|
|
2227
2381
|
});
|
|
2228
|
-
|
|
2382
|
+
currentHtml += "</tr>";
|
|
2229
2383
|
});
|
|
2230
|
-
|
|
2384
|
+
currentHtml += "</table>";
|
|
2231
2385
|
}
|
|
2232
2386
|
}
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2387
|
+
flushHtml();
|
|
2388
|
+
for (const page of pages) {
|
|
2389
|
+
page.card.innerHTML = DOMPurify6__default.default.sanitize(page.html, {
|
|
2390
|
+
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
|
|
2391
|
+
ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
|
|
2392
|
+
});
|
|
2393
|
+
wrapper.appendChild(page.card);
|
|
2394
|
+
}
|
|
2238
2395
|
}
|
|
2239
2396
|
extractParagraphHtml(pElement, imageMap = {}) {
|
|
2240
|
-
|
|
2397
|
+
return this.extractParagraphChunks(pElement, imageMap).join("<br/>");
|
|
2398
|
+
}
|
|
2399
|
+
extractParagraphChunks(pElement, imageMap = {}) {
|
|
2400
|
+
const chunks = [""];
|
|
2401
|
+
let currentChunkIndex = 0;
|
|
2241
2402
|
const drawings = Array.from(pElement.getElementsByTagNameNS("*", "drawing"));
|
|
2242
2403
|
for (const drawing of drawings) {
|
|
2243
2404
|
const blip = drawing.getElementsByTagNameNS("*", "blip")[0];
|
|
2244
2405
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2245
2406
|
if (rId && imageMap[rId]) {
|
|
2246
|
-
|
|
2407
|
+
chunks[currentChunkIndex] += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
|
|
2247
2408
|
}
|
|
2248
2409
|
}
|
|
2249
2410
|
const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
|
|
2250
|
-
if (runs.length === 0 && !
|
|
2251
|
-
|
|
2411
|
+
if (runs.length === 0 && !chunks[currentChunkIndex]) {
|
|
2412
|
+
chunks[currentChunkIndex] = DOMPurify6__default.default.sanitize(pElement.textContent || "");
|
|
2413
|
+
return chunks;
|
|
2252
2414
|
}
|
|
2253
2415
|
for (const r of runs) {
|
|
2254
2416
|
const blip = r.getElementsByTagNameNS("*", "blip")[0] || r.getElementsByTagNameNS("*", "imagedata")[0];
|
|
2255
2417
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2256
2418
|
if (rId && imageMap[rId]) {
|
|
2257
|
-
|
|
2419
|
+
chunks[currentChunkIndex] += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
|
|
2258
2420
|
}
|
|
2259
|
-
const brs = r.getElementsByTagNameNS("*", "br");
|
|
2260
|
-
for (
|
|
2261
|
-
|
|
2421
|
+
const brs = Array.from(r.getElementsByTagNameNS("*", "br"));
|
|
2422
|
+
for (const br of brs) {
|
|
2423
|
+
const type = br.getAttribute("w:type") || br.getAttribute("type");
|
|
2424
|
+
if (type === "page") {
|
|
2425
|
+
chunks.push("");
|
|
2426
|
+
currentChunkIndex++;
|
|
2427
|
+
} else {
|
|
2428
|
+
chunks[currentChunkIndex] += "<br/>";
|
|
2429
|
+
}
|
|
2262
2430
|
}
|
|
2263
2431
|
const tabs = r.getElementsByTagNameNS("*", "tab");
|
|
2264
2432
|
if (tabs.length > 0) {
|
|
2265
|
-
|
|
2433
|
+
chunks[currentChunkIndex] += " ";
|
|
2266
2434
|
}
|
|
2267
2435
|
const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
|
|
2268
2436
|
const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
|
|
@@ -2276,7 +2444,7 @@ var DocxPlugin = class {
|
|
|
2276
2444
|
const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
|
|
2277
2445
|
let text = texts.map((t) => t.textContent || "").join("");
|
|
2278
2446
|
if (!text) continue;
|
|
2279
|
-
text =
|
|
2447
|
+
text = DOMPurify6__default.default.sanitize(text);
|
|
2280
2448
|
let styles = "";
|
|
2281
2449
|
if (isBold) styles += "font-weight: bold; ";
|
|
2282
2450
|
if (isItalic) styles += "font-style: italic; ";
|
|
@@ -2288,12 +2456,12 @@ var DocxPlugin = class {
|
|
|
2288
2456
|
if (!isNaN(pt) && pt > 0) styles += `font-size: ${pt}pt; `;
|
|
2289
2457
|
}
|
|
2290
2458
|
if (styles) {
|
|
2291
|
-
|
|
2459
|
+
chunks[currentChunkIndex] += `<span style="${styles}">${text}</span>`;
|
|
2292
2460
|
} else {
|
|
2293
|
-
|
|
2461
|
+
chunks[currentChunkIndex] += text;
|
|
2294
2462
|
}
|
|
2295
2463
|
}
|
|
2296
|
-
return
|
|
2464
|
+
return chunks;
|
|
2297
2465
|
}
|
|
2298
2466
|
renderBinaryDocFallback(ctx, wrapper) {
|
|
2299
2467
|
const card = document.createElement("div");
|
|
@@ -2310,14 +2478,14 @@ var DocxPlugin = class {
|
|
|
2310
2478
|
const wordDocStream = cfbf.readStream("WordDocument");
|
|
2311
2479
|
if (wordDocStream && wordDocStream.length >= 512) {
|
|
2312
2480
|
const text2 = this.extractReadableStrings(wordDocStream);
|
|
2313
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2481
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text2)}</div>`;
|
|
2314
2482
|
wrapper.appendChild(card);
|
|
2315
2483
|
return;
|
|
2316
2484
|
}
|
|
2317
2485
|
} catch {
|
|
2318
2486
|
}
|
|
2319
2487
|
const text = this.extractReadableStrings(new Uint8Array(ctx.buffer));
|
|
2320
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2488
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text)}</div>`;
|
|
2321
2489
|
wrapper.appendChild(card);
|
|
2322
2490
|
}
|
|
2323
2491
|
extractReadableStrings(bytes) {
|
|
@@ -2413,6 +2581,26 @@ var ExcelPlugin = class {
|
|
|
2413
2581
|
instance.zoomIn?.();
|
|
2414
2582
|
}
|
|
2415
2583
|
},
|
|
2584
|
+
{
|
|
2585
|
+
id: "fit-page",
|
|
2586
|
+
icon: "fit-page",
|
|
2587
|
+
label: "Fit to View",
|
|
2588
|
+
type: "button",
|
|
2589
|
+
group: "zoom",
|
|
2590
|
+
execute: () => {
|
|
2591
|
+
instance.fitToPage?.();
|
|
2592
|
+
}
|
|
2593
|
+
},
|
|
2594
|
+
{
|
|
2595
|
+
id: "rotate-cw",
|
|
2596
|
+
icon: "rotate-cw",
|
|
2597
|
+
label: "Rotate",
|
|
2598
|
+
type: "button",
|
|
2599
|
+
group: "view",
|
|
2600
|
+
execute: () => {
|
|
2601
|
+
instance.rotateCW?.();
|
|
2602
|
+
}
|
|
2603
|
+
},
|
|
2416
2604
|
{
|
|
2417
2605
|
id: "download",
|
|
2418
2606
|
icon: "download",
|
|
@@ -2463,9 +2651,23 @@ var ExcelPlugin = class {
|
|
|
2463
2651
|
container.appendChild(tabsArea);
|
|
2464
2652
|
ctx.container.appendChild(container);
|
|
2465
2653
|
let scale = 1;
|
|
2654
|
+
let rotation = 0;
|
|
2466
2655
|
let currentSheetIndex = 1;
|
|
2467
2656
|
let sheetNames = [];
|
|
2468
2657
|
let wb = null;
|
|
2658
|
+
const applyTransform = () => {
|
|
2659
|
+
contentArea.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
2660
|
+
contentArea.style.transformOrigin = "top left";
|
|
2661
|
+
};
|
|
2662
|
+
const calculateFitScale = () => {
|
|
2663
|
+
const table = contentArea.querySelector("table");
|
|
2664
|
+
if (!table) return 1;
|
|
2665
|
+
const availW = Math.max(200, container.clientWidth - 48);
|
|
2666
|
+
const availH = Math.max(200, container.clientHeight - 80);
|
|
2667
|
+
const tW = table.offsetWidth || 800;
|
|
2668
|
+
const tH = table.offsetHeight || 600;
|
|
2669
|
+
return Math.min(1, Math.min(availW / tW, availH / tH));
|
|
2670
|
+
};
|
|
2469
2671
|
try {
|
|
2470
2672
|
wb = XLSX__namespace.read(new Uint8Array(ctx.buffer), { type: "array", cellDates: true });
|
|
2471
2673
|
sheetNames = wb.SheetNames || [];
|
|
@@ -2553,17 +2755,30 @@ var ExcelPlugin = class {
|
|
|
2553
2755
|
return {
|
|
2554
2756
|
destroy: cleanup,
|
|
2555
2757
|
zoomIn: () => {
|
|
2556
|
-
scale += 0.
|
|
2557
|
-
|
|
2758
|
+
scale += 0.15;
|
|
2759
|
+
applyTransform();
|
|
2558
2760
|
},
|
|
2559
2761
|
zoomOut: () => {
|
|
2560
|
-
scale = Math.max(0.2, scale - 0.
|
|
2561
|
-
|
|
2762
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
2763
|
+
applyTransform();
|
|
2562
2764
|
},
|
|
2563
2765
|
getZoom: () => scale,
|
|
2564
2766
|
setZoom: (level) => {
|
|
2565
2767
|
scale = level;
|
|
2566
|
-
|
|
2768
|
+
applyTransform();
|
|
2769
|
+
},
|
|
2770
|
+
fitToPage: () => {
|
|
2771
|
+
scale = calculateFitScale();
|
|
2772
|
+
rotation = 0;
|
|
2773
|
+
applyTransform();
|
|
2774
|
+
},
|
|
2775
|
+
rotateCW: () => {
|
|
2776
|
+
rotation = (rotation + 90) % 360;
|
|
2777
|
+
applyTransform();
|
|
2778
|
+
},
|
|
2779
|
+
rotateCCW: () => {
|
|
2780
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
2781
|
+
applyTransform();
|
|
2567
2782
|
},
|
|
2568
2783
|
goToPage: (page) => {
|
|
2569
2784
|
if (page > 0 && page <= sheetNames.length) {
|
|
@@ -2813,6 +3028,26 @@ var CodePlugin = class {
|
|
|
2813
3028
|
instance.zoomIn?.();
|
|
2814
3029
|
}
|
|
2815
3030
|
},
|
|
3031
|
+
{
|
|
3032
|
+
id: "fit-page",
|
|
3033
|
+
icon: "fit-page",
|
|
3034
|
+
label: "Fit to View",
|
|
3035
|
+
type: "button",
|
|
3036
|
+
group: "zoom",
|
|
3037
|
+
execute: () => {
|
|
3038
|
+
instance.fitToPage?.();
|
|
3039
|
+
}
|
|
3040
|
+
},
|
|
3041
|
+
{
|
|
3042
|
+
id: "rotate-cw",
|
|
3043
|
+
icon: "rotate-cw",
|
|
3044
|
+
label: "Rotate",
|
|
3045
|
+
type: "button",
|
|
3046
|
+
group: "view",
|
|
3047
|
+
execute: () => {
|
|
3048
|
+
instance.rotateCW?.();
|
|
3049
|
+
}
|
|
3050
|
+
},
|
|
2816
3051
|
{
|
|
2817
3052
|
id: "copy",
|
|
2818
3053
|
icon: "copy",
|
|
@@ -2849,40 +3084,94 @@ var CodePlugin = class {
|
|
|
2849
3084
|
async render(ctx) {
|
|
2850
3085
|
const decoder = new TextDecoder("utf-8");
|
|
2851
3086
|
const fullText = decoder.decode(ctx.buffer);
|
|
2852
|
-
const
|
|
2853
|
-
const
|
|
3087
|
+
const extRaw = ctx.metadata.extension?.toLowerCase();
|
|
3088
|
+
const mimeRaw = ctx.metadata.mimeType?.toLowerCase();
|
|
3089
|
+
const isTxt = extRaw === ".txt" || mimeRaw === "text/plain" && (!extRaw || !this.extensions.filter((e) => e !== ".txt").includes(extRaw));
|
|
3090
|
+
let rawPages = [];
|
|
3091
|
+
if (isTxt) {
|
|
3092
|
+
const explicitPages = fullText.split(/(?:\f|\x0C)/);
|
|
3093
|
+
for (const ep of explicitPages) {
|
|
3094
|
+
const lines = ep.split(/\r?\n/);
|
|
3095
|
+
let currentChunk = [];
|
|
3096
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3097
|
+
currentChunk.push(lines[i]);
|
|
3098
|
+
if (currentChunk.length >= 46) {
|
|
3099
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3100
|
+
currentChunk = [];
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
if (currentChunk.length > 0 || lines.length === 0) {
|
|
3104
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3107
|
+
if (rawPages.length === 0) rawPages = [""];
|
|
3108
|
+
} else {
|
|
3109
|
+
const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
|
|
3110
|
+
rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
3111
|
+
}
|
|
2854
3112
|
const totalPages = Math.max(1, rawPages.length);
|
|
2855
3113
|
let currentPage = 1;
|
|
2856
3114
|
const container = document.createElement("div");
|
|
2857
3115
|
container.style.width = "100%";
|
|
2858
3116
|
container.style.height = "100%";
|
|
2859
3117
|
container.style.overflow = "auto";
|
|
2860
|
-
container.style.backgroundColor = "#1e1e1e";
|
|
2861
|
-
container.style.color = "#d4d4d4";
|
|
2862
|
-
container.style.padding = "16px";
|
|
2863
|
-
container.style.boxSizing = "border-box";
|
|
2864
3118
|
let fontSize = 13;
|
|
3119
|
+
let rotation = 0;
|
|
3120
|
+
let zoomLevel = 1;
|
|
2865
3121
|
const pre = document.createElement("pre");
|
|
2866
|
-
pre.style.margin = "0";
|
|
2867
|
-
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
2868
|
-
pre.style.fontSize = `${fontSize}px`;
|
|
2869
|
-
pre.style.lineHeight = "1.5";
|
|
2870
|
-
pre.style.whiteSpace = "pre-wrap";
|
|
2871
|
-
pre.style.wordBreak = "break-all";
|
|
2872
3122
|
const code = document.createElement("code");
|
|
3123
|
+
if (isTxt) {
|
|
3124
|
+
container.style.backgroundColor = "#f1f5f9";
|
|
3125
|
+
container.style.padding = "32px";
|
|
3126
|
+
container.style.boxSizing = "border-box";
|
|
3127
|
+
container.style.display = "flex";
|
|
3128
|
+
container.style.flexDirection = "column";
|
|
3129
|
+
container.style.alignItems = "center";
|
|
3130
|
+
pre.style.margin = "0";
|
|
3131
|
+
pre.style.fontFamily = "Consolas, 'Courier New', monospace";
|
|
3132
|
+
pre.style.fontSize = "13px";
|
|
3133
|
+
pre.style.color = "#1e293b";
|
|
3134
|
+
pre.style.lineHeight = "1.5";
|
|
3135
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3136
|
+
pre.style.wordBreak = "break-word";
|
|
3137
|
+
pre.style.backgroundColor = "#ffffff";
|
|
3138
|
+
pre.style.width = "816px";
|
|
3139
|
+
pre.style.minHeight = "1056px";
|
|
3140
|
+
pre.style.padding = "72px 56px";
|
|
3141
|
+
pre.style.boxSizing = "border-box";
|
|
3142
|
+
pre.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)";
|
|
3143
|
+
pre.style.borderRadius = "4px";
|
|
3144
|
+
pre.style.transformOrigin = "top center";
|
|
3145
|
+
} else {
|
|
3146
|
+
container.style.backgroundColor = "#1e1e1e";
|
|
3147
|
+
container.style.color = "#d4d4d4";
|
|
3148
|
+
container.style.padding = "16px";
|
|
3149
|
+
container.style.boxSizing = "border-box";
|
|
3150
|
+
pre.style.margin = "0";
|
|
3151
|
+
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
3152
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3153
|
+
pre.style.lineHeight = "1.5";
|
|
3154
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3155
|
+
pre.style.wordBreak = "break-all";
|
|
3156
|
+
pre.style.transformOrigin = "top left";
|
|
3157
|
+
}
|
|
2873
3158
|
const ext = (ctx.metadata.extension || "").replace(".", "");
|
|
2874
3159
|
const renderCodePage = (text) => {
|
|
2875
|
-
|
|
2876
|
-
if (ext && hljs__default.default.getLanguage(ext)) {
|
|
2877
|
-
code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
|
|
2878
|
-
} else {
|
|
2879
|
-
code.innerHTML = hljs__default.default.highlightAuto(text).value;
|
|
2880
|
-
}
|
|
2881
|
-
} catch {
|
|
3160
|
+
if (isTxt) {
|
|
2882
3161
|
code.textContent = text;
|
|
3162
|
+
} else {
|
|
3163
|
+
try {
|
|
3164
|
+
if (ext && hljs__default.default.getLanguage(ext)) {
|
|
3165
|
+
code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
|
|
3166
|
+
} else {
|
|
3167
|
+
code.innerHTML = hljs__default.default.highlightAuto(text).value;
|
|
3168
|
+
}
|
|
3169
|
+
} catch {
|
|
3170
|
+
code.textContent = text;
|
|
3171
|
+
}
|
|
2883
3172
|
}
|
|
2884
3173
|
};
|
|
2885
|
-
renderCodePage(rawPages[0] || fullText);
|
|
3174
|
+
renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
|
|
2886
3175
|
pre.appendChild(code);
|
|
2887
3176
|
container.appendChild(pre);
|
|
2888
3177
|
let indicator = null;
|
|
@@ -2891,15 +3180,22 @@ var CodePlugin = class {
|
|
|
2891
3180
|
indicator.className = "fp-code-page-indicator";
|
|
2892
3181
|
indicator.style.position = "sticky";
|
|
2893
3182
|
indicator.style.bottom = "16px";
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
3183
|
+
if (isTxt) {
|
|
3184
|
+
indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
3185
|
+
indicator.style.color = "#334155";
|
|
3186
|
+
indicator.style.border = "1px solid #e2e8f0";
|
|
3187
|
+
indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
|
|
3188
|
+
} else {
|
|
3189
|
+
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3190
|
+
indicator.style.color = "#f8fafc";
|
|
3191
|
+
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3192
|
+
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3193
|
+
indicator.style.backdropFilter = "blur(8px)";
|
|
3194
|
+
}
|
|
2897
3195
|
indicator.style.fontSize = "12px";
|
|
2898
3196
|
indicator.style.fontWeight = "600";
|
|
2899
3197
|
indicator.style.padding = "5px 14px";
|
|
2900
3198
|
indicator.style.borderRadius = "20px";
|
|
2901
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
2902
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
2903
3199
|
indicator.style.zIndex = "10";
|
|
2904
3200
|
indicator.style.userSelect = "none";
|
|
2905
3201
|
indicator.style.pointerEvents = "none";
|
|
@@ -2910,7 +3206,7 @@ var CodePlugin = class {
|
|
|
2910
3206
|
}
|
|
2911
3207
|
const showPage = (pageNum) => {
|
|
2912
3208
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
2913
|
-
renderCodePage(rawPages[currentPage - 1] || fullText);
|
|
3209
|
+
renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
|
|
2914
3210
|
if (indicator) {
|
|
2915
3211
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
2916
3212
|
}
|
|
@@ -2926,23 +3222,57 @@ var CodePlugin = class {
|
|
|
2926
3222
|
ctx.container.innerHTML = "";
|
|
2927
3223
|
};
|
|
2928
3224
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3225
|
+
const updateTransform = () => {
|
|
3226
|
+
if (isTxt) {
|
|
3227
|
+
pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
|
|
3228
|
+
} else {
|
|
3229
|
+
pre.style.transform = `rotate(${rotation}deg)`;
|
|
3230
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3231
|
+
}
|
|
3232
|
+
};
|
|
2929
3233
|
return {
|
|
2930
3234
|
destroy: cleanup,
|
|
2931
3235
|
getPageCount: () => totalPages,
|
|
2932
3236
|
getCurrentPage: () => currentPage,
|
|
2933
3237
|
goToPage: (page) => showPage(page),
|
|
2934
3238
|
zoomIn: () => {
|
|
2935
|
-
|
|
2936
|
-
|
|
3239
|
+
if (isTxt) {
|
|
3240
|
+
zoomLevel = Math.min(3, zoomLevel + 0.1);
|
|
3241
|
+
} else {
|
|
3242
|
+
fontSize = Math.min(32, fontSize + 2);
|
|
3243
|
+
}
|
|
3244
|
+
updateTransform();
|
|
2937
3245
|
},
|
|
2938
3246
|
zoomOut: () => {
|
|
2939
|
-
|
|
2940
|
-
|
|
3247
|
+
if (isTxt) {
|
|
3248
|
+
zoomLevel = Math.max(0.1, zoomLevel - 0.1);
|
|
3249
|
+
} else {
|
|
3250
|
+
fontSize = Math.max(8, fontSize - 2);
|
|
3251
|
+
}
|
|
3252
|
+
updateTransform();
|
|
2941
3253
|
},
|
|
2942
|
-
getZoom: () => fontSize / 13,
|
|
3254
|
+
getZoom: () => isTxt ? zoomLevel : fontSize / 13,
|
|
2943
3255
|
setZoom: (level) => {
|
|
2944
|
-
|
|
2945
|
-
|
|
3256
|
+
if (isTxt) {
|
|
3257
|
+
zoomLevel = level;
|
|
3258
|
+
} else {
|
|
3259
|
+
fontSize = Math.round(13 * level);
|
|
3260
|
+
}
|
|
3261
|
+
updateTransform();
|
|
3262
|
+
},
|
|
3263
|
+
fitToPage: () => {
|
|
3264
|
+
fontSize = 13;
|
|
3265
|
+
rotation = 0;
|
|
3266
|
+
zoomLevel = 1;
|
|
3267
|
+
updateTransform();
|
|
3268
|
+
},
|
|
3269
|
+
rotateCW: () => {
|
|
3270
|
+
rotation = (rotation + 90) % 360;
|
|
3271
|
+
updateTransform();
|
|
3272
|
+
},
|
|
3273
|
+
rotateCCW: () => {
|
|
3274
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
3275
|
+
updateTransform();
|
|
2946
3276
|
},
|
|
2947
3277
|
download: () => {
|
|
2948
3278
|
const mimeType = ctx.metadata.mimeType || "text/plain";
|
|
@@ -3241,7 +3571,7 @@ var MarkdownPlugin = class {
|
|
|
3241
3571
|
gfm: true,
|
|
3242
3572
|
breaks: true
|
|
3243
3573
|
});
|
|
3244
|
-
const cleanHtml =
|
|
3574
|
+
const cleanHtml = DOMPurify6__default.default.sanitize(rawHtml, {
|
|
3245
3575
|
USE_PROFILES: { html: true }
|
|
3246
3576
|
});
|
|
3247
3577
|
const wrapper = document.createElement("div");
|
|
@@ -3455,6 +3785,14 @@ var PptxPlugin = class {
|
|
|
3455
3785
|
group: "zoom",
|
|
3456
3786
|
execute: () => instance.fitToPage?.()
|
|
3457
3787
|
},
|
|
3788
|
+
{
|
|
3789
|
+
id: "rotate-cw",
|
|
3790
|
+
icon: "rotate-cw",
|
|
3791
|
+
label: "Rotate",
|
|
3792
|
+
type: "button",
|
|
3793
|
+
group: "view",
|
|
3794
|
+
execute: () => instance.rotateCW?.()
|
|
3795
|
+
},
|
|
3458
3796
|
{
|
|
3459
3797
|
id: "download",
|
|
3460
3798
|
icon: "download",
|
|
@@ -3479,6 +3817,7 @@ var PptxPlugin = class {
|
|
|
3479
3817
|
const slideCount = renderer.slidePaths?.length || 1;
|
|
3480
3818
|
let currentSlide = 1;
|
|
3481
3819
|
let scale = 1;
|
|
3820
|
+
let rotation = 0;
|
|
3482
3821
|
const wrapper = document.createElement("div");
|
|
3483
3822
|
wrapper.className = "fp-pptx-wrapper";
|
|
3484
3823
|
wrapper.style.cssText = `
|
|
@@ -3501,6 +3840,8 @@ var PptxPlugin = class {
|
|
|
3501
3840
|
background: #ffffff;
|
|
3502
3841
|
transform-origin: top center;
|
|
3503
3842
|
transition: transform 0.2s ease;
|
|
3843
|
+
max-width: calc(100% - 32px);
|
|
3844
|
+
max-height: calc(100% - 48px);
|
|
3504
3845
|
`;
|
|
3505
3846
|
const canvas = document.createElement("canvas");
|
|
3506
3847
|
slideContainer.appendChild(canvas);
|
|
@@ -3508,10 +3849,22 @@ var PptxPlugin = class {
|
|
|
3508
3849
|
ctx.container.innerHTML = "";
|
|
3509
3850
|
ctx.container.style.overflow = "auto";
|
|
3510
3851
|
ctx.container.appendChild(wrapper);
|
|
3852
|
+
const calculateFitScale = () => {
|
|
3853
|
+
const availW = Math.max(200, ctx.container.clientWidth - 48);
|
|
3854
|
+
const availH = Math.max(200, ctx.container.clientHeight - 72);
|
|
3855
|
+
const cW = canvas.offsetWidth || 1280;
|
|
3856
|
+
const cH = canvas.offsetHeight || 720;
|
|
3857
|
+
return Math.min(1, Math.min(availW / cW, availH / cH));
|
|
3858
|
+
};
|
|
3859
|
+
const applyTransform = () => {
|
|
3860
|
+
slideContainer.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
3861
|
+
};
|
|
3511
3862
|
const renderCurrentSlide = async () => {
|
|
3512
3863
|
try {
|
|
3513
3864
|
await renderer.renderSlide(currentSlide - 1, canvas, 1280);
|
|
3514
3865
|
ctx.emit("page-change", { page: currentSlide, totalPages: slideCount });
|
|
3866
|
+
scale = calculateFitScale();
|
|
3867
|
+
applyTransform();
|
|
3515
3868
|
} catch (err) {
|
|
3516
3869
|
console.error("[PptxPlugin] Failed to render slide:", err);
|
|
3517
3870
|
}
|
|
@@ -3534,21 +3887,30 @@ var PptxPlugin = class {
|
|
|
3534
3887
|
getPageCount: () => slideCount,
|
|
3535
3888
|
getCurrentPage: () => currentSlide,
|
|
3536
3889
|
zoomIn: () => {
|
|
3537
|
-
scale += 0.
|
|
3538
|
-
|
|
3890
|
+
scale += 0.15;
|
|
3891
|
+
applyTransform();
|
|
3539
3892
|
},
|
|
3540
3893
|
zoomOut: () => {
|
|
3541
|
-
scale = Math.max(0.2, scale - 0.
|
|
3542
|
-
|
|
3894
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
3895
|
+
applyTransform();
|
|
3543
3896
|
},
|
|
3544
3897
|
getZoom: () => scale,
|
|
3545
3898
|
setZoom: (level) => {
|
|
3546
3899
|
scale = level;
|
|
3547
|
-
|
|
3900
|
+
applyTransform();
|
|
3548
3901
|
},
|
|
3549
3902
|
fitToPage: () => {
|
|
3550
|
-
scale =
|
|
3551
|
-
|
|
3903
|
+
scale = calculateFitScale();
|
|
3904
|
+
rotation = 0;
|
|
3905
|
+
applyTransform();
|
|
3906
|
+
},
|
|
3907
|
+
rotateCW: () => {
|
|
3908
|
+
rotation = (rotation + 90) % 360;
|
|
3909
|
+
applyTransform();
|
|
3910
|
+
},
|
|
3911
|
+
rotateCCW: () => {
|
|
3912
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
3913
|
+
applyTransform();
|
|
3552
3914
|
},
|
|
3553
3915
|
getThumbnails: () => {
|
|
3554
3916
|
const list = [];
|
|
@@ -3829,6 +4191,14 @@ var RtfPlugin = class {
|
|
|
3829
4191
|
group: "zoom",
|
|
3830
4192
|
execute: () => instance.fitToPage?.()
|
|
3831
4193
|
},
|
|
4194
|
+
{
|
|
4195
|
+
id: "rotate-cw",
|
|
4196
|
+
icon: "rotate-cw",
|
|
4197
|
+
label: "Rotate",
|
|
4198
|
+
type: "button",
|
|
4199
|
+
group: "view",
|
|
4200
|
+
execute: () => instance.rotateCW?.()
|
|
4201
|
+
},
|
|
3832
4202
|
{
|
|
3833
4203
|
id: "download",
|
|
3834
4204
|
icon: "download",
|
|
@@ -3837,6 +4207,14 @@ var RtfPlugin = class {
|
|
|
3837
4207
|
group: "actions",
|
|
3838
4208
|
execute: () => instance.download?.()
|
|
3839
4209
|
},
|
|
4210
|
+
{
|
|
4211
|
+
id: "copy",
|
|
4212
|
+
icon: "copy",
|
|
4213
|
+
label: "Copy Text",
|
|
4214
|
+
type: "button",
|
|
4215
|
+
group: "actions",
|
|
4216
|
+
execute: () => instance.copy?.()
|
|
4217
|
+
},
|
|
3840
4218
|
{
|
|
3841
4219
|
id: "print",
|
|
3842
4220
|
icon: "print",
|
|
@@ -3865,7 +4243,24 @@ var RtfPlugin = class {
|
|
|
3865
4243
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
3866
4244
|
ctx.container.appendChild(wrapper);
|
|
3867
4245
|
let scale = 1;
|
|
4246
|
+
let rotation = 0;
|
|
3868
4247
|
let pageElements = [];
|
|
4248
|
+
const calculateFitScale = () => {
|
|
4249
|
+
const activeEl = pageElements[currentPage - 1] || wrapper;
|
|
4250
|
+
const elW = activeEl.offsetWidth || 850;
|
|
4251
|
+
const elH = activeEl.offsetHeight || 1e3;
|
|
4252
|
+
const availW = Math.max(200, ctx.container.clientWidth - 48);
|
|
4253
|
+
const availH = Math.max(200, ctx.container.clientHeight - 80);
|
|
4254
|
+
return Math.min(1.1, Math.min(availW / elW, availH / elH));
|
|
4255
|
+
};
|
|
4256
|
+
const applyTransform = () => {
|
|
4257
|
+
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4258
|
+
wrapper.style.transformOrigin = "top center";
|
|
4259
|
+
};
|
|
4260
|
+
setTimeout(() => {
|
|
4261
|
+
scale = calculateFitScale();
|
|
4262
|
+
applyTransform();
|
|
4263
|
+
}, 60);
|
|
3869
4264
|
try {
|
|
3870
4265
|
if (typeof RTFJS__namespace.loggingEnabled === "function") {
|
|
3871
4266
|
RTFJS__namespace.loggingEnabled(false);
|
|
@@ -3881,14 +4276,31 @@ var RtfPlugin = class {
|
|
|
3881
4276
|
} catch (err) {
|
|
3882
4277
|
console.warn("[RtfPlugin] RTF render error, fallback text:", err);
|
|
3883
4278
|
const text = new TextDecoder("latin1").decode(ctx.buffer);
|
|
3884
|
-
const
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
4279
|
+
const rawPages = text.split(/\\page\b/).map((segment) => {
|
|
4280
|
+
return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
|
|
4281
|
+
}).filter((p) => p.length > 0);
|
|
4282
|
+
const pages = rawPages.length > 0 ? rawPages : [text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim()];
|
|
4283
|
+
for (let i = 0; i < pages.length; i++) {
|
|
4284
|
+
const pageCard = document.createElement("div");
|
|
4285
|
+
pageCard.className = "fp-rtf-page-card";
|
|
4286
|
+
pageCard.style.backgroundColor = "#ffffff";
|
|
4287
|
+
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4288
|
+
pageCard.style.borderRadius = "4px";
|
|
4289
|
+
pageCard.style.padding = "72px 56px";
|
|
4290
|
+
pageCard.style.width = "816px";
|
|
4291
|
+
pageCard.style.minHeight = "1056px";
|
|
4292
|
+
pageCard.style.maxWidth = "100%";
|
|
4293
|
+
pageCard.style.boxSizing = "border-box";
|
|
4294
|
+
pageCard.style.fontFamily = "serif";
|
|
4295
|
+
pageCard.style.fontSize = "12pt";
|
|
4296
|
+
pageCard.style.lineHeight = "1.6";
|
|
4297
|
+
pageCard.style.color = "#1e293b";
|
|
4298
|
+
pageCard.style.whiteSpace = "pre-wrap";
|
|
4299
|
+
pageCard.style.display = i === 0 ? "block" : "none";
|
|
4300
|
+
pageCard.textContent = pages[i];
|
|
4301
|
+
wrapper.appendChild(pageCard);
|
|
4302
|
+
pageElements.push(pageCard);
|
|
4303
|
+
}
|
|
3892
4304
|
}
|
|
3893
4305
|
const totalPages = Math.max(1, pageElements.length);
|
|
3894
4306
|
let currentPage = 1;
|
|
@@ -3942,21 +4354,30 @@ var RtfPlugin = class {
|
|
|
3942
4354
|
getCurrentPage: () => currentPage,
|
|
3943
4355
|
goToPage: (page) => showPage(page),
|
|
3944
4356
|
zoomIn: () => {
|
|
3945
|
-
scale += 0.
|
|
3946
|
-
|
|
4357
|
+
scale += 0.15;
|
|
4358
|
+
applyTransform();
|
|
3947
4359
|
},
|
|
3948
4360
|
zoomOut: () => {
|
|
3949
|
-
scale = Math.max(0.2, scale - 0.
|
|
3950
|
-
|
|
4361
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
4362
|
+
applyTransform();
|
|
3951
4363
|
},
|
|
3952
4364
|
getZoom: () => scale,
|
|
3953
4365
|
setZoom: (level) => {
|
|
3954
4366
|
scale = level;
|
|
3955
|
-
|
|
4367
|
+
applyTransform();
|
|
3956
4368
|
},
|
|
3957
4369
|
fitToPage: () => {
|
|
3958
|
-
scale =
|
|
3959
|
-
|
|
4370
|
+
scale = calculateFitScale();
|
|
4371
|
+
rotation = 0;
|
|
4372
|
+
applyTransform();
|
|
4373
|
+
},
|
|
4374
|
+
rotateCW: () => {
|
|
4375
|
+
rotation = (rotation + 90) % 360;
|
|
4376
|
+
applyTransform();
|
|
4377
|
+
},
|
|
4378
|
+
rotateCCW: () => {
|
|
4379
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
4380
|
+
applyTransform();
|
|
3960
4381
|
},
|
|
3961
4382
|
download: () => {
|
|
3962
4383
|
const blob = new Blob([ctx.buffer], { type: "application/rtf" });
|
|
@@ -3967,6 +4388,10 @@ var RtfPlugin = class {
|
|
|
3967
4388
|
a.click();
|
|
3968
4389
|
URL.revokeObjectURL(url);
|
|
3969
4390
|
},
|
|
4391
|
+
copy: () => {
|
|
4392
|
+
const text = wrapper.textContent || "";
|
|
4393
|
+
navigator.clipboard?.writeText(text);
|
|
4394
|
+
},
|
|
3970
4395
|
print: () => {
|
|
3971
4396
|
window.print();
|
|
3972
4397
|
}
|
|
@@ -4041,7 +4466,7 @@ var HtmlPreviewPlugin = class {
|
|
|
4041
4466
|
}
|
|
4042
4467
|
async render(ctx) {
|
|
4043
4468
|
const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
|
|
4044
|
-
const sanitized =
|
|
4469
|
+
const sanitized = DOMPurify6__default.default.sanitize(rawHtml, {
|
|
4045
4470
|
WHOLE_DOCUMENT: true,
|
|
4046
4471
|
ADD_TAGS: ["style", "link"],
|
|
4047
4472
|
ADD_ATTR: ["target", "rel"]
|
|
@@ -4184,11 +4609,19 @@ var OpenDocumentPlugin = class {
|
|
|
4184
4609
|
{
|
|
4185
4610
|
id: "fit-page",
|
|
4186
4611
|
icon: "fit-page",
|
|
4187
|
-
label: "Fit to Page",
|
|
4612
|
+
label: isPresentation ? "Fit to Slide" : "Fit to Page",
|
|
4188
4613
|
type: "button",
|
|
4189
4614
|
group: "zoom",
|
|
4190
4615
|
execute: () => instance.fitToPage?.()
|
|
4191
4616
|
},
|
|
4617
|
+
{
|
|
4618
|
+
id: "rotate-cw",
|
|
4619
|
+
icon: "rotate-cw",
|
|
4620
|
+
label: "Rotate",
|
|
4621
|
+
type: "button",
|
|
4622
|
+
group: "view",
|
|
4623
|
+
execute: () => instance.rotateCW?.()
|
|
4624
|
+
},
|
|
4192
4625
|
{
|
|
4193
4626
|
id: "download",
|
|
4194
4627
|
icon: "download",
|
|
@@ -4252,6 +4685,22 @@ var OpenDocumentPlugin = class {
|
|
|
4252
4685
|
container.appendChild(wrapper);
|
|
4253
4686
|
ctx.container.appendChild(container);
|
|
4254
4687
|
let scale = 1;
|
|
4688
|
+
let rotation = 0;
|
|
4689
|
+
const calculateFitScale = () => {
|
|
4690
|
+
const elW = wrapper.offsetWidth || 850;
|
|
4691
|
+
const elH = wrapper.offsetHeight || (isPresentation ? 540 : 1e3);
|
|
4692
|
+
const availW = Math.max(200, ctx.container.clientWidth - 48);
|
|
4693
|
+
const availH = Math.max(200, ctx.container.clientHeight - 80);
|
|
4694
|
+
return Math.min(1, Math.min(availW / elW, availH / elH));
|
|
4695
|
+
};
|
|
4696
|
+
const applyTransform = () => {
|
|
4697
|
+
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4698
|
+
wrapper.style.transformOrigin = "top center";
|
|
4699
|
+
};
|
|
4700
|
+
setTimeout(() => {
|
|
4701
|
+
scale = calculateFitScale();
|
|
4702
|
+
applyTransform();
|
|
4703
|
+
}, 60);
|
|
4255
4704
|
let currentPage = 1;
|
|
4256
4705
|
let totalPages = 1;
|
|
4257
4706
|
let slides = [];
|
|
@@ -4283,14 +4732,97 @@ var OpenDocumentPlugin = class {
|
|
|
4283
4732
|
wrapper.textContent = contentDoc.documentElement.textContent || "Formula content";
|
|
4284
4733
|
}
|
|
4285
4734
|
} else {
|
|
4286
|
-
wrapper.style.maxWidth = "
|
|
4287
|
-
wrapper.style.padding = "
|
|
4735
|
+
wrapper.style.maxWidth = "none";
|
|
4736
|
+
wrapper.style.padding = "0";
|
|
4288
4737
|
wrapper.style.minHeight = "100%";
|
|
4738
|
+
wrapper.style.backgroundColor = "transparent";
|
|
4739
|
+
wrapper.style.boxShadow = "none";
|
|
4740
|
+
wrapper.style.position = "relative";
|
|
4741
|
+
const dims = this.getPageDimensions(stylesDoc, contentDoc);
|
|
4289
4742
|
const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
|
|
4290
|
-
|
|
4291
|
-
|
|
4743
|
+
const tempDiv = document.createElement("div");
|
|
4744
|
+
tempDiv.style.width = `${dims.width - dims.marginLeft - dims.marginRight}px`;
|
|
4745
|
+
tempDiv.style.position = "absolute";
|
|
4746
|
+
tempDiv.style.visibility = "hidden";
|
|
4747
|
+
tempDiv.innerHTML = DOMPurify6__default.default.sanitize(bodyHtml, {
|
|
4748
|
+
ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub", "hr"],
|
|
4292
4749
|
ADD_ATTR: ["style", "colspan", "rowspan"]
|
|
4293
4750
|
});
|
|
4751
|
+
document.body.appendChild(tempDiv);
|
|
4752
|
+
const contentHeight = dims.height - dims.marginTop - dims.marginBottom;
|
|
4753
|
+
const pageElements = [[]];
|
|
4754
|
+
let currentHeight = 0;
|
|
4755
|
+
let currentPageIdx = 0;
|
|
4756
|
+
Array.from(tempDiv.children).forEach((child) => {
|
|
4757
|
+
const el = child;
|
|
4758
|
+
const style = el.getAttribute("style") || "";
|
|
4759
|
+
const isBreakBefore = style.includes("page-break-before: always");
|
|
4760
|
+
const isBreakAfter = style.includes("page-break-after: always");
|
|
4761
|
+
const isSoftBreak = el.classList.contains("odf-page-break");
|
|
4762
|
+
if (isBreakBefore) {
|
|
4763
|
+
if (pageElements[currentPageIdx].length > 0) {
|
|
4764
|
+
currentPageIdx++;
|
|
4765
|
+
pageElements.push([]);
|
|
4766
|
+
currentHeight = 0;
|
|
4767
|
+
}
|
|
4768
|
+
}
|
|
4769
|
+
const h = el.offsetHeight || 0;
|
|
4770
|
+
if (currentHeight + h > contentHeight && pageElements[currentPageIdx].length > 0 && !isSoftBreak) {
|
|
4771
|
+
currentPageIdx++;
|
|
4772
|
+
pageElements.push([]);
|
|
4773
|
+
currentHeight = 0;
|
|
4774
|
+
}
|
|
4775
|
+
if (!isSoftBreak) {
|
|
4776
|
+
pageElements[currentPageIdx].push(el.cloneNode(true));
|
|
4777
|
+
currentHeight += h;
|
|
4778
|
+
}
|
|
4779
|
+
if (isBreakAfter || isSoftBreak) {
|
|
4780
|
+
currentPageIdx++;
|
|
4781
|
+
pageElements.push([]);
|
|
4782
|
+
currentHeight = 0;
|
|
4783
|
+
}
|
|
4784
|
+
});
|
|
4785
|
+
document.body.removeChild(tempDiv);
|
|
4786
|
+
if (pageElements.length > 1 && pageElements[pageElements.length - 1].length === 0) {
|
|
4787
|
+
pageElements.pop();
|
|
4788
|
+
}
|
|
4789
|
+
totalPages = Math.max(1, pageElements.length);
|
|
4790
|
+
pageElements.forEach((elements, idx) => {
|
|
4791
|
+
const page = document.createElement("div");
|
|
4792
|
+
page.className = `fp-odt-page fp-odt-page-${idx + 1}`;
|
|
4793
|
+
page.style.width = `${dims.width}px`;
|
|
4794
|
+
page.style.minHeight = `${dims.height}px`;
|
|
4795
|
+
page.style.padding = `${dims.marginTop}px ${dims.marginRight}px ${dims.marginBottom}px ${dims.marginLeft}px`;
|
|
4796
|
+
page.style.margin = "0 auto";
|
|
4797
|
+
page.style.backgroundColor = "#ffffff";
|
|
4798
|
+
page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
4799
|
+
page.style.borderRadius = "4px";
|
|
4800
|
+
page.style.boxSizing = "border-box";
|
|
4801
|
+
page.style.display = idx === 0 ? "block" : "none";
|
|
4802
|
+
page.style.position = "absolute";
|
|
4803
|
+
page.style.top = "0";
|
|
4804
|
+
page.style.left = "50%";
|
|
4805
|
+
page.style.transform = "translateX(-50%)";
|
|
4806
|
+
elements.forEach((el) => page.appendChild(el));
|
|
4807
|
+
wrapper.appendChild(page);
|
|
4808
|
+
slides.push(page);
|
|
4809
|
+
});
|
|
4810
|
+
const pageIndicator = document.createElement("div");
|
|
4811
|
+
pageIndicator.className = "fp-odt-page-indicator";
|
|
4812
|
+
pageIndicator.style.position = "sticky";
|
|
4813
|
+
pageIndicator.style.bottom = "16px";
|
|
4814
|
+
pageIndicator.style.left = "50%";
|
|
4815
|
+
pageIndicator.style.transform = "translateX(-50%)";
|
|
4816
|
+
pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
|
4817
|
+
pageIndicator.style.color = "#fff";
|
|
4818
|
+
pageIndicator.style.padding = "6px 12px";
|
|
4819
|
+
pageIndicator.style.borderRadius = "16px";
|
|
4820
|
+
pageIndicator.style.fontSize = "12px";
|
|
4821
|
+
pageIndicator.style.zIndex = "100";
|
|
4822
|
+
pageIndicator.style.display = "inline-block";
|
|
4823
|
+
pageIndicator.style.width = "fit-content";
|
|
4824
|
+
pageIndicator.textContent = `Page 1 of ${totalPages}`;
|
|
4825
|
+
container.appendChild(pageIndicator);
|
|
4294
4826
|
}
|
|
4295
4827
|
const cleanup = () => {
|
|
4296
4828
|
imageUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
@@ -4299,32 +4831,45 @@ var OpenDocumentPlugin = class {
|
|
|
4299
4831
|
};
|
|
4300
4832
|
ctx.signal.addEventListener("abort", cleanup);
|
|
4301
4833
|
const goToPage = (page) => {
|
|
4302
|
-
if (
|
|
4834
|
+
if (page < 1 || page > totalPages) return;
|
|
4303
4835
|
currentPage = page;
|
|
4304
4836
|
slides.forEach((s, idx) => {
|
|
4305
4837
|
s.style.display = idx === page - 1 ? "block" : "none";
|
|
4306
4838
|
});
|
|
4839
|
+
const indicator = container.querySelector(".fp-odt-page-indicator");
|
|
4840
|
+
if (indicator) {
|
|
4841
|
+
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4842
|
+
}
|
|
4307
4843
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4308
4844
|
};
|
|
4309
4845
|
return {
|
|
4310
4846
|
destroy: cleanup,
|
|
4311
4847
|
isPresentation,
|
|
4312
4848
|
zoomIn: () => {
|
|
4313
|
-
scale += 0.
|
|
4314
|
-
|
|
4849
|
+
scale += 0.15;
|
|
4850
|
+
applyTransform();
|
|
4315
4851
|
},
|
|
4316
4852
|
zoomOut: () => {
|
|
4317
|
-
scale = Math.max(0.2, scale - 0.
|
|
4318
|
-
|
|
4853
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
4854
|
+
applyTransform();
|
|
4319
4855
|
},
|
|
4320
4856
|
getZoom: () => scale,
|
|
4321
4857
|
setZoom: (level) => {
|
|
4322
4858
|
scale = level;
|
|
4323
|
-
|
|
4859
|
+
applyTransform();
|
|
4324
4860
|
},
|
|
4325
4861
|
fitToPage: () => {
|
|
4326
|
-
scale =
|
|
4327
|
-
|
|
4862
|
+
scale = calculateFitScale();
|
|
4863
|
+
rotation = 0;
|
|
4864
|
+
applyTransform();
|
|
4865
|
+
},
|
|
4866
|
+
rotateCW: () => {
|
|
4867
|
+
rotation = (rotation + 90) % 360;
|
|
4868
|
+
applyTransform();
|
|
4869
|
+
},
|
|
4870
|
+
rotateCCW: () => {
|
|
4871
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
4872
|
+
applyTransform();
|
|
4328
4873
|
},
|
|
4329
4874
|
goToPage,
|
|
4330
4875
|
getPageCount: () => totalPages,
|
|
@@ -4363,6 +4908,43 @@ var OpenDocumentPlugin = class {
|
|
|
4363
4908
|
}
|
|
4364
4909
|
};
|
|
4365
4910
|
}
|
|
4911
|
+
getPageDimensions(stylesDoc, contentDoc) {
|
|
4912
|
+
let width = 850;
|
|
4913
|
+
let height = 1123;
|
|
4914
|
+
let marginTop = 48;
|
|
4915
|
+
let marginBottom = 48;
|
|
4916
|
+
let marginLeft = 48;
|
|
4917
|
+
let marginRight = 48;
|
|
4918
|
+
const parseUnit = (val) => {
|
|
4919
|
+
if (!val) return null;
|
|
4920
|
+
if (val.endsWith("cm")) return parseFloat(val) * 37.8;
|
|
4921
|
+
if (val.endsWith("mm")) return parseFloat(val) * 3.78;
|
|
4922
|
+
if (val.endsWith("in")) return parseFloat(val) * 96;
|
|
4923
|
+
if (val.endsWith("pt")) return parseFloat(val) * 1.33;
|
|
4924
|
+
if (val.endsWith("px")) return parseFloat(val);
|
|
4925
|
+
return parseFloat(val);
|
|
4926
|
+
};
|
|
4927
|
+
const docs = [stylesDoc, contentDoc].filter(Boolean);
|
|
4928
|
+
for (const doc of docs) {
|
|
4929
|
+
const pageLayout = doc.querySelector("page-layout-properties, [page-width]");
|
|
4930
|
+
if (pageLayout) {
|
|
4931
|
+
const w = parseUnit(pageLayout.getAttribute("fo:page-width") || pageLayout.getAttribute("page-width"));
|
|
4932
|
+
const h = parseUnit(pageLayout.getAttribute("fo:page-height") || pageLayout.getAttribute("page-height"));
|
|
4933
|
+
const mt = parseUnit(pageLayout.getAttribute("fo:margin-top") || pageLayout.getAttribute("margin-top"));
|
|
4934
|
+
const mb = parseUnit(pageLayout.getAttribute("fo:margin-bottom") || pageLayout.getAttribute("margin-bottom"));
|
|
4935
|
+
const ml = parseUnit(pageLayout.getAttribute("fo:margin-left") || pageLayout.getAttribute("margin-left"));
|
|
4936
|
+
const mr = parseUnit(pageLayout.getAttribute("fo:margin-right") || pageLayout.getAttribute("margin-right"));
|
|
4937
|
+
if (w !== null) width = w;
|
|
4938
|
+
if (h !== null) height = h;
|
|
4939
|
+
if (mt !== null) marginTop = mt;
|
|
4940
|
+
if (mb !== null) marginBottom = mb;
|
|
4941
|
+
if (ml !== null) marginLeft = ml;
|
|
4942
|
+
if (mr !== null) marginRight = mr;
|
|
4943
|
+
break;
|
|
4944
|
+
}
|
|
4945
|
+
}
|
|
4946
|
+
return { width, height, marginTop, marginBottom, marginLeft, marginRight };
|
|
4947
|
+
}
|
|
4366
4948
|
extractStyles(stylesDoc, contentDoc) {
|
|
4367
4949
|
const map = /* @__PURE__ */ new Map();
|
|
4368
4950
|
const styleNodes = [];
|
|
@@ -4385,14 +4967,21 @@ var OpenDocumentPlugin = class {
|
|
|
4385
4967
|
if (color) css += `color: ${color}; `;
|
|
4386
4968
|
if (size) css += `font-size: ${size}; `;
|
|
4387
4969
|
}
|
|
4388
|
-
|
|
4970
|
+
let paraProp = node.querySelector("paragraph-properties, [text-align]");
|
|
4971
|
+
if (!paraProp) {
|
|
4972
|
+
paraProp = Array.from(node.children).find((c) => c.tagName.includes("paragraph-properties")) || null;
|
|
4973
|
+
}
|
|
4389
4974
|
if (paraProp) {
|
|
4390
4975
|
const align = paraProp.getAttribute("fo:text-align") || paraProp.getAttribute("text-align");
|
|
4391
4976
|
const mt = paraProp.getAttribute("fo:margin-top") || paraProp.getAttribute("margin-top");
|
|
4392
4977
|
const mb = paraProp.getAttribute("fo:margin-bottom") || paraProp.getAttribute("margin-bottom");
|
|
4978
|
+
const breakBefore = paraProp.getAttribute("fo:break-before") || paraProp.getAttribute("break-before");
|
|
4979
|
+
const breakAfter = paraProp.getAttribute("fo:break-after") || paraProp.getAttribute("break-after");
|
|
4393
4980
|
if (align) css += `text-align: ${align}; `;
|
|
4394
4981
|
if (mt) css += `margin-top: ${mt}; `;
|
|
4395
4982
|
if (mb) css += `margin-bottom: ${mb}; `;
|
|
4983
|
+
if (breakBefore === "page") css += "page-break-before: always; ";
|
|
4984
|
+
if (breakAfter === "page") css += "page-break-after: always; ";
|
|
4396
4985
|
}
|
|
4397
4986
|
if (css) map.set(name, css);
|
|
4398
4987
|
}
|
|
@@ -4477,6 +5066,8 @@ var OpenDocumentPlugin = class {
|
|
|
4477
5066
|
result += " ";
|
|
4478
5067
|
} else if (tag === "line-break") {
|
|
4479
5068
|
result += "<br/>";
|
|
5069
|
+
} else if (tag === "soft-page-break") {
|
|
5070
|
+
result += '<hr class="odf-page-break" style="page-break-after: always; border: none; margin: 0; padding: 0; height: 0;" />';
|
|
4480
5071
|
} else {
|
|
4481
5072
|
result += el.textContent || "";
|
|
4482
5073
|
}
|
|
@@ -4594,6 +5185,14 @@ var DocPlugin = class {
|
|
|
4594
5185
|
group: "zoom",
|
|
4595
5186
|
execute: () => instance.fitToPage?.()
|
|
4596
5187
|
},
|
|
5188
|
+
{
|
|
5189
|
+
id: "rotate-cw",
|
|
5190
|
+
icon: "rotate-cw",
|
|
5191
|
+
label: "Rotate",
|
|
5192
|
+
type: "button",
|
|
5193
|
+
group: "view",
|
|
5194
|
+
execute: () => instance.rotateCW?.()
|
|
5195
|
+
},
|
|
4597
5196
|
{
|
|
4598
5197
|
id: "copy",
|
|
4599
5198
|
icon: "copy",
|
|
@@ -4629,20 +5228,9 @@ var DocPlugin = class {
|
|
|
4629
5228
|
container.style.overflow = "auto";
|
|
4630
5229
|
container.style.padding = "32px 16px";
|
|
4631
5230
|
container.style.backgroundColor = "#f1f5f9";
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
wrapper.style.margin = "0 auto";
|
|
4636
|
-
wrapper.style.backgroundColor = "#ffffff";
|
|
4637
|
-
wrapper.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4638
|
-
wrapper.style.borderRadius = "4px";
|
|
4639
|
-
wrapper.style.padding = "56px 48px";
|
|
4640
|
-
wrapper.style.minHeight = "100%";
|
|
4641
|
-
wrapper.style.transformOrigin = "top center";
|
|
4642
|
-
wrapper.style.transition = "transform 0.2s ease";
|
|
4643
|
-
wrapper.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4644
|
-
wrapper.style.color = "#1e293b";
|
|
4645
|
-
container.appendChild(wrapper);
|
|
5231
|
+
container.style.display = "flex";
|
|
5232
|
+
container.style.justifyContent = "center";
|
|
5233
|
+
container.style.alignItems = "flex-start";
|
|
4646
5234
|
ctx.container.appendChild(container);
|
|
4647
5235
|
let scale = 1;
|
|
4648
5236
|
let extractedRawText = "";
|
|
@@ -4669,21 +5257,27 @@ var DocPlugin = class {
|
|
|
4669
5257
|
const rawPages = this.splitIntoPages(extractedRawText);
|
|
4670
5258
|
const totalPages = Math.max(1, rawPages.length);
|
|
4671
5259
|
let currentPage = 1;
|
|
4672
|
-
wrapper.innerHTML = "";
|
|
4673
5260
|
const pageCards = [];
|
|
4674
5261
|
for (let i = 0; i < totalPages; i++) {
|
|
4675
5262
|
const pageCard = document.createElement("div");
|
|
4676
5263
|
pageCard.className = "fp-doc-page-card";
|
|
5264
|
+
pageCard.style.width = "816px";
|
|
5265
|
+
pageCard.style.height = "1056px";
|
|
4677
5266
|
pageCard.style.backgroundColor = "#ffffff";
|
|
4678
5267
|
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4679
5268
|
pageCard.style.borderRadius = "4px";
|
|
4680
|
-
pageCard.style.padding = "
|
|
4681
|
-
pageCard.style.
|
|
5269
|
+
pageCard.style.padding = "96px 72px";
|
|
5270
|
+
pageCard.style.boxSizing = "border-box";
|
|
5271
|
+
pageCard.style.overflow = "hidden";
|
|
4682
5272
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5273
|
+
pageCard.style.transformOrigin = "top center";
|
|
5274
|
+
pageCard.style.transition = "transform 0.2s ease";
|
|
5275
|
+
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
5276
|
+
pageCard.style.color = "#1e293b";
|
|
4683
5277
|
if (isFallback && i === 0) {
|
|
4684
5278
|
pageCard.innerHTML = `
|
|
4685
5279
|
<div style="border-bottom: 1px solid #e2e8f0; padding-bottom: 12px; margin-bottom: 24px;">
|
|
4686
|
-
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${
|
|
5280
|
+
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify6__default.default.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
|
|
4687
5281
|
<span style="font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 4px;">Legacy Word 97-2003 Binary Preview</span>
|
|
4688
5282
|
</div>
|
|
4689
5283
|
${this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document")}
|
|
@@ -4691,15 +5285,17 @@ var DocPlugin = class {
|
|
|
4691
5285
|
} else {
|
|
4692
5286
|
pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
|
|
4693
5287
|
}
|
|
4694
|
-
|
|
5288
|
+
container.appendChild(pageCard);
|
|
4695
5289
|
pageCards.push(pageCard);
|
|
4696
5290
|
}
|
|
4697
5291
|
let indicator = null;
|
|
4698
5292
|
if (totalPages > 1) {
|
|
4699
5293
|
indicator = document.createElement("div");
|
|
4700
5294
|
indicator.className = "fp-doc-page-indicator";
|
|
4701
|
-
indicator.style.position = "
|
|
5295
|
+
indicator.style.position = "fixed";
|
|
4702
5296
|
indicator.style.bottom = "16px";
|
|
5297
|
+
indicator.style.left = "50%";
|
|
5298
|
+
indicator.style.transform = "translateX(-50%)";
|
|
4703
5299
|
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4704
5300
|
indicator.style.backdropFilter = "blur(8px)";
|
|
4705
5301
|
indicator.style.color = "#f8fafc";
|
|
@@ -4713,17 +5309,25 @@ var DocPlugin = class {
|
|
|
4713
5309
|
indicator.style.userSelect = "none";
|
|
4714
5310
|
indicator.style.pointerEvents = "none";
|
|
4715
5311
|
indicator.style.textAlign = "center";
|
|
4716
|
-
indicator.style.width = "fit-content";
|
|
4717
|
-
indicator.style.margin = "16px auto 0";
|
|
4718
5312
|
container.appendChild(indicator);
|
|
4719
5313
|
}
|
|
5314
|
+
let rotation = 0;
|
|
5315
|
+
const applyTransform = () => {
|
|
5316
|
+
const activeCard = pageCards[currentPage - 1];
|
|
5317
|
+
if (activeCard) {
|
|
5318
|
+
activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5319
|
+
}
|
|
5320
|
+
};
|
|
4720
5321
|
const showPage = (pageNum) => {
|
|
4721
5322
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
card.style.display =
|
|
4725
|
-
|
|
4726
|
-
|
|
5323
|
+
pageCards.forEach((card, idx) => {
|
|
5324
|
+
if (idx + 1 === currentPage) {
|
|
5325
|
+
card.style.display = "block";
|
|
5326
|
+
card.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5327
|
+
} else {
|
|
5328
|
+
card.style.display = "none";
|
|
5329
|
+
}
|
|
5330
|
+
});
|
|
4727
5331
|
if (indicator) {
|
|
4728
5332
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4729
5333
|
}
|
|
@@ -4732,6 +5336,17 @@ var DocPlugin = class {
|
|
|
4732
5336
|
if (totalPages > 1) {
|
|
4733
5337
|
showPage(1);
|
|
4734
5338
|
}
|
|
5339
|
+
const calculateFitScale = () => {
|
|
5340
|
+
const elW = 816;
|
|
5341
|
+
const elH = 1056;
|
|
5342
|
+
const availW = Math.max(200, ctx.container.clientWidth - 48);
|
|
5343
|
+
const availH = Math.max(200, ctx.container.clientHeight - 80);
|
|
5344
|
+
return Math.min(1.1, Math.min(availW / elW, availH / elH));
|
|
5345
|
+
};
|
|
5346
|
+
setTimeout(() => {
|
|
5347
|
+
scale = calculateFitScale();
|
|
5348
|
+
applyTransform();
|
|
5349
|
+
}, 60);
|
|
4735
5350
|
const cleanup = () => {
|
|
4736
5351
|
indicator?.remove();
|
|
4737
5352
|
container.remove();
|
|
@@ -4744,21 +5359,30 @@ var DocPlugin = class {
|
|
|
4744
5359
|
getCurrentPage: () => currentPage,
|
|
4745
5360
|
goToPage: (page) => showPage(page),
|
|
4746
5361
|
zoomIn: () => {
|
|
4747
|
-
scale += 0.
|
|
4748
|
-
|
|
5362
|
+
scale += 0.15;
|
|
5363
|
+
applyTransform();
|
|
4749
5364
|
},
|
|
4750
5365
|
zoomOut: () => {
|
|
4751
|
-
scale = Math.max(0.2, scale - 0.
|
|
4752
|
-
|
|
5366
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
5367
|
+
applyTransform();
|
|
4753
5368
|
},
|
|
4754
5369
|
getZoom: () => scale,
|
|
4755
5370
|
setZoom: (level) => {
|
|
4756
5371
|
scale = level;
|
|
4757
|
-
|
|
5372
|
+
applyTransform();
|
|
4758
5373
|
},
|
|
4759
5374
|
fitToPage: () => {
|
|
4760
|
-
scale =
|
|
4761
|
-
|
|
5375
|
+
scale = calculateFitScale();
|
|
5376
|
+
rotation = 0;
|
|
5377
|
+
applyTransform();
|
|
5378
|
+
},
|
|
5379
|
+
rotateCW: () => {
|
|
5380
|
+
rotation = (rotation + 90) % 360;
|
|
5381
|
+
applyTransform();
|
|
5382
|
+
},
|
|
5383
|
+
rotateCCW: () => {
|
|
5384
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
5385
|
+
applyTransform();
|
|
4762
5386
|
},
|
|
4763
5387
|
copy: () => {
|
|
4764
5388
|
navigator.clipboard.writeText(extractedRawText);
|
|
@@ -4876,8 +5500,28 @@ var DocPlugin = class {
|
|
|
4876
5500
|
}
|
|
4877
5501
|
splitIntoPages(text) {
|
|
4878
5502
|
if (!text) return [""];
|
|
4879
|
-
const
|
|
4880
|
-
|
|
5503
|
+
const explicitParts = text.split(/[\x0C\f]|\r?\n\s*[-=_]{3,}\s*(?:PAGE|Page|page break)[\s\d\w-]*[-=_]{3,}\s*\r?\n/i).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
5504
|
+
if (explicitParts.length === 0) explicitParts.push(text);
|
|
5505
|
+
const maxLinesPerPage = 48;
|
|
5506
|
+
const finalPages = [];
|
|
5507
|
+
for (const part of explicitParts) {
|
|
5508
|
+
const lines = part.split(/\r?\n/);
|
|
5509
|
+
let currentLines = [];
|
|
5510
|
+
let count = 0;
|
|
5511
|
+
for (const line of lines) {
|
|
5512
|
+
currentLines.push(line);
|
|
5513
|
+
count++;
|
|
5514
|
+
if (count >= maxLinesPerPage) {
|
|
5515
|
+
finalPages.push(currentLines.join("\n"));
|
|
5516
|
+
currentLines = [];
|
|
5517
|
+
count = 0;
|
|
5518
|
+
}
|
|
5519
|
+
}
|
|
5520
|
+
if (currentLines.length > 0) {
|
|
5521
|
+
finalPages.push(currentLines.join("\n"));
|
|
5522
|
+
}
|
|
5523
|
+
}
|
|
5524
|
+
return finalPages.length > 0 ? finalPages : [text];
|
|
4881
5525
|
}
|
|
4882
5526
|
/**
|
|
4883
5527
|
* Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
|
|
@@ -4886,17 +5530,65 @@ var DocPlugin = class {
|
|
|
4886
5530
|
const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
|
|
4887
5531
|
let html = "";
|
|
4888
5532
|
let inList = false;
|
|
4889
|
-
|
|
4890
|
-
|
|
5533
|
+
let tableLines = [];
|
|
5534
|
+
const flushTable = () => {
|
|
5535
|
+
if (tableLines.length > 0) {
|
|
5536
|
+
html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
|
|
5537
|
+
for (const tLine of tableLines) {
|
|
5538
|
+
html += "<tr>";
|
|
5539
|
+
const cols = tLine.split(" ");
|
|
5540
|
+
for (const col of cols) {
|
|
5541
|
+
html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
|
|
5542
|
+
}
|
|
5543
|
+
html += "</tr>";
|
|
5544
|
+
}
|
|
5545
|
+
html += "</table>";
|
|
5546
|
+
tableLines = [];
|
|
5547
|
+
}
|
|
5548
|
+
};
|
|
5549
|
+
let i = 0;
|
|
5550
|
+
while (i < lines.length) {
|
|
5551
|
+
let line = lines[i];
|
|
5552
|
+
let tabCount = (line.match(/\t/g) || []).length;
|
|
5553
|
+
if (tabCount > 0) {
|
|
5554
|
+
let consecutiveTableLines = 1;
|
|
5555
|
+
let j = i + 1;
|
|
5556
|
+
while (j < lines.length) {
|
|
5557
|
+
const nextTabCount = (lines[j].match(/\t/g) || []).length;
|
|
5558
|
+
if (nextTabCount === tabCount) {
|
|
5559
|
+
consecutiveTableLines++;
|
|
5560
|
+
j++;
|
|
5561
|
+
} else {
|
|
5562
|
+
break;
|
|
5563
|
+
}
|
|
5564
|
+
}
|
|
5565
|
+
if (consecutiveTableLines >= 3) {
|
|
5566
|
+
if (inList) {
|
|
5567
|
+
html += "</ul>";
|
|
5568
|
+
inList = false;
|
|
5569
|
+
}
|
|
5570
|
+
tableLines = lines.slice(i, j);
|
|
5571
|
+
flushTable();
|
|
5572
|
+
i = j;
|
|
5573
|
+
continue;
|
|
5574
|
+
}
|
|
5575
|
+
}
|
|
5576
|
+
line = line.trim();
|
|
4891
5577
|
if (!line) {
|
|
4892
5578
|
if (inList) {
|
|
4893
5579
|
html += "</ul>";
|
|
4894
5580
|
inList = false;
|
|
4895
5581
|
}
|
|
5582
|
+
html += '<div style="height: 1.15em;"></div>';
|
|
5583
|
+
i++;
|
|
4896
5584
|
continue;
|
|
4897
5585
|
}
|
|
4898
|
-
if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line))
|
|
4899
|
-
|
|
5586
|
+
if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line)) {
|
|
5587
|
+
i++;
|
|
5588
|
+
continue;
|
|
5589
|
+
}
|
|
5590
|
+
if ((line.includes("Normal.dot") || line.includes("Microsoft Word") || line.includes("Times New Roman")) && line.length < 30) {
|
|
5591
|
+
i++;
|
|
4900
5592
|
continue;
|
|
4901
5593
|
}
|
|
4902
5594
|
if (line.length < 60 && !line.endsWith(".") && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#"))) {
|
|
@@ -4904,24 +5596,26 @@ var DocPlugin = class {
|
|
|
4904
5596
|
html += "</ul>";
|
|
4905
5597
|
inList = false;
|
|
4906
5598
|
}
|
|
4907
|
-
html += `<h2 style="font-size:
|
|
5599
|
+
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>`;
|
|
4908
5600
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
4909
5601
|
if (!inList) {
|
|
4910
5602
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
4911
5603
|
inList = true;
|
|
4912
5604
|
}
|
|
4913
5605
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
4914
|
-
html += `<li style="margin: 4px 0; line-height: 1.
|
|
5606
|
+
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6__default.default.sanitize(bulletText)}</li>`;
|
|
4915
5607
|
} else {
|
|
4916
5608
|
if (inList) {
|
|
4917
5609
|
html += "</ul>";
|
|
4918
5610
|
inList = false;
|
|
4919
5611
|
}
|
|
4920
|
-
html += `<p style="line-height: 1.
|
|
5612
|
+
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6__default.default.sanitize(line)}</p>`;
|
|
4921
5613
|
}
|
|
5614
|
+
i++;
|
|
4922
5615
|
}
|
|
4923
5616
|
if (inList) html += "</ul>";
|
|
4924
|
-
|
|
5617
|
+
flushTable();
|
|
5618
|
+
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6__default.default.sanitize(filename)})</p>`;
|
|
4925
5619
|
}
|
|
4926
5620
|
};
|
|
4927
5621
|
function docPlugin() {
|
|
@@ -4998,6 +5692,14 @@ var PptPlugin = class {
|
|
|
4998
5692
|
group: "zoom",
|
|
4999
5693
|
execute: () => instance.fitToPage?.()
|
|
5000
5694
|
},
|
|
5695
|
+
{
|
|
5696
|
+
id: "rotate-cw",
|
|
5697
|
+
icon: "rotate-cw",
|
|
5698
|
+
label: "Rotate",
|
|
5699
|
+
type: "button",
|
|
5700
|
+
group: "view",
|
|
5701
|
+
execute: () => instance.rotateCW?.()
|
|
5702
|
+
},
|
|
5001
5703
|
{
|
|
5002
5704
|
id: "download",
|
|
5003
5705
|
icon: "download",
|
|
@@ -5031,22 +5733,36 @@ var PptPlugin = class {
|
|
|
5031
5733
|
const slideCard = document.createElement("div");
|
|
5032
5734
|
slideCard.className = "fp-ppt-slide-card";
|
|
5033
5735
|
slideCard.style.width = "960px";
|
|
5034
|
-
slideCard.style.maxWidth = "
|
|
5736
|
+
slideCard.style.maxWidth = "calc(100% - 32px)";
|
|
5737
|
+
slideCard.style.maxHeight = "calc(100% - 48px)";
|
|
5035
5738
|
slideCard.style.aspectRatio = "16 / 9";
|
|
5036
5739
|
slideCard.style.backgroundColor = "#ffffff";
|
|
5037
5740
|
slideCard.style.boxShadow = "0 12px 40px rgba(0,0,0,0.35)";
|
|
5038
5741
|
slideCard.style.borderRadius = "8px";
|
|
5039
5742
|
slideCard.style.boxSizing = "border-box";
|
|
5040
5743
|
slideCard.style.position = "relative";
|
|
5041
|
-
slideCard.style.overflow = "hidden";
|
|
5042
|
-
slideCard.style.transformOrigin = "center center";
|
|
5043
5744
|
slideCard.style.transition = "transform 0.2s ease";
|
|
5745
|
+
slideCard.style.transformOrigin = "center center";
|
|
5746
|
+
slideCard.style.flexShrink = "0";
|
|
5044
5747
|
container.appendChild(slideCard);
|
|
5045
5748
|
ctx.container.appendChild(container);
|
|
5046
5749
|
let scale = 1;
|
|
5750
|
+
let rotation = 0;
|
|
5047
5751
|
let currentSlide = 1;
|
|
5048
5752
|
let slides = [];
|
|
5049
5753
|
const createdBlobUrls = [];
|
|
5754
|
+
const calculateFitScale = () => {
|
|
5755
|
+
const availW = Math.max(200, container.clientWidth - 48);
|
|
5756
|
+
const availH = Math.max(200, container.clientHeight - 72);
|
|
5757
|
+
return Math.min(1, Math.min(availW / 960, availH / 540));
|
|
5758
|
+
};
|
|
5759
|
+
const applyTransform = () => {
|
|
5760
|
+
slideCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5761
|
+
};
|
|
5762
|
+
setTimeout(() => {
|
|
5763
|
+
scale = calculateFitScale();
|
|
5764
|
+
applyTransform();
|
|
5765
|
+
}, 60);
|
|
5050
5766
|
try {
|
|
5051
5767
|
const cfbf = new CfbfReader(ctx.buffer);
|
|
5052
5768
|
const pptStream = cfbf.readStream("PowerPoint Document");
|
|
@@ -5077,7 +5793,7 @@ var PptPlugin = class {
|
|
|
5077
5793
|
if (s.pictureUrl) {
|
|
5078
5794
|
contentHtml = `
|
|
5079
5795
|
<div style="flex: 1; display: flex; justify-content: center; align-items: center; padding: 12px; overflow: hidden;">
|
|
5080
|
-
<img src="${s.pictureUrl}" alt="${
|
|
5796
|
+
<img src="${s.pictureUrl}" alt="${DOMPurify6__default.default.sanitize(s.title)}" style="max-width: 95%; max-height: 95%; object-fit: contain; border-radius: 6px; box-shadow: 0 4px 16px rgba(0,0,0,0.1); background: #ffffff;" />
|
|
5081
5797
|
</div>
|
|
5082
5798
|
`;
|
|
5083
5799
|
} else if (s.tableColumns.length > 0) {
|
|
@@ -5087,7 +5803,7 @@ var PptPlugin = class {
|
|
|
5087
5803
|
<table style="width: 100%; border-collapse: collapse; border: 1px solid #cbd5e1; border-radius: 6px; overflow: hidden; background: #ffffff;">
|
|
5088
5804
|
<thead>
|
|
5089
5805
|
<tr style="background: #e2e8f0; color: #1e293b; font-weight: 600; font-size: 14px;">
|
|
5090
|
-
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${
|
|
5806
|
+
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${DOMPurify6__default.default.sanitize(c)}</th>`).join("")}
|
|
5091
5807
|
</tr>
|
|
5092
5808
|
</thead>
|
|
5093
5809
|
<tbody>
|
|
@@ -5103,7 +5819,7 @@ var PptPlugin = class {
|
|
|
5103
5819
|
} else {
|
|
5104
5820
|
const pTags = s.paragraphs.map((p) => {
|
|
5105
5821
|
const lines = p.split(/[\r\n]+/).map((l) => l.trim()).filter(Boolean);
|
|
5106
|
-
return lines.map((l) => `<p style="margin: 0 0 14px; font-size: 14px; line-height: 1.65; color: #334155; text-align: justify;">${
|
|
5822
|
+
return lines.map((l) => `<p style="margin: 0 0 14px; font-size: 14px; line-height: 1.65; color: #334155; text-align: justify;">${DOMPurify6__default.default.sanitize(l)}</p>`).join("");
|
|
5107
5823
|
}).join("");
|
|
5108
5824
|
contentHtml = `
|
|
5109
5825
|
<div style="flex: 1; overflow: auto; padding: 4px 8px; display: flex; flex-direction: column; justify-content: flex-start;">
|
|
@@ -5116,11 +5832,11 @@ var PptPlugin = class {
|
|
|
5116
5832
|
<!-- Header Banner matching PowerPoint design -->
|
|
5117
5833
|
<div style="background: linear-gradient(90deg, #a3e635 0%, #84cc16 100%); padding: 12px 24px; border-radius: 4px; display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); flex-shrink: 0;">
|
|
5118
5834
|
<h1 style="margin: 0; font-size: 26px; font-weight: 700; color: #1e293b; letter-spacing: -0.3px;">
|
|
5119
|
-
${
|
|
5835
|
+
${DOMPurify6__default.default.sanitize(s.title)}
|
|
5120
5836
|
</h1>
|
|
5121
5837
|
${s.subtitle ? `
|
|
5122
5838
|
<span style="background: #38bdf8; color: #ffffff; padding: 4px 14px; border-radius: 4px; font-weight: 700; font-size: 13px; letter-spacing: 0.5px; box-shadow: 0 1px 4px rgba(0,0,0,0.15);">
|
|
5123
|
-
${
|
|
5839
|
+
${DOMPurify6__default.default.sanitize(s.subtitle)}
|
|
5124
5840
|
</span>
|
|
5125
5841
|
` : `
|
|
5126
5842
|
<span style="font-size: 12px; color: #365314; font-weight: 600;">
|
|
@@ -5147,21 +5863,30 @@ var PptPlugin = class {
|
|
|
5147
5863
|
return {
|
|
5148
5864
|
destroy: cleanup,
|
|
5149
5865
|
zoomIn: () => {
|
|
5150
|
-
scale += 0.
|
|
5151
|
-
|
|
5866
|
+
scale += 0.15;
|
|
5867
|
+
applyTransform();
|
|
5152
5868
|
},
|
|
5153
5869
|
zoomOut: () => {
|
|
5154
|
-
scale = Math.max(0.
|
|
5155
|
-
|
|
5870
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
5871
|
+
applyTransform();
|
|
5156
5872
|
},
|
|
5157
5873
|
getZoom: () => scale,
|
|
5158
5874
|
setZoom: (level) => {
|
|
5159
5875
|
scale = level;
|
|
5160
|
-
|
|
5876
|
+
applyTransform();
|
|
5161
5877
|
},
|
|
5162
5878
|
fitToPage: () => {
|
|
5163
|
-
scale =
|
|
5164
|
-
|
|
5879
|
+
scale = calculateFitScale();
|
|
5880
|
+
rotation = 0;
|
|
5881
|
+
applyTransform();
|
|
5882
|
+
},
|
|
5883
|
+
rotateCW: () => {
|
|
5884
|
+
rotation = (rotation + 90) % 360;
|
|
5885
|
+
applyTransform();
|
|
5886
|
+
},
|
|
5887
|
+
rotateCCW: () => {
|
|
5888
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
5889
|
+
applyTransform();
|
|
5165
5890
|
},
|
|
5166
5891
|
goToPage: (page) => {
|
|
5167
5892
|
if (page >= 1 && page <= totalSlides) {
|