@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/react.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var react = require('react');
|
|
6
|
-
var
|
|
6
|
+
var DOMPurify6 = require('dompurify');
|
|
7
7
|
var pdfjsLib = require('pdfjs-dist');
|
|
8
8
|
var docx = require('docx-preview');
|
|
9
9
|
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);
|
|
@@ -390,7 +390,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
390
390
|
if (magicMime === "application/zip") {
|
|
391
391
|
const ooxmlMime = detectOoxmlType(buffer);
|
|
392
392
|
if (ooxmlMime && ooxmlMime !== "application/zip") {
|
|
393
|
-
metadata.mimeType = ooxmlMime;
|
|
393
|
+
metadata.mimeType = metadata.mimeType ?? ooxmlMime;
|
|
394
394
|
if (ooxmlMime.includes("wordprocessing")) metadata.extension = metadata.extension ?? ".docx";
|
|
395
395
|
else if (ooxmlMime.includes("spreadsheet")) metadata.extension = metadata.extension ?? ".xlsx";
|
|
396
396
|
else if (ooxmlMime.includes("presentation")) metadata.extension = metadata.extension ?? ".pptx";
|
|
@@ -419,7 +419,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
419
419
|
return { buffer, metadata };
|
|
420
420
|
}
|
|
421
421
|
function sanitizeSVG(svg) {
|
|
422
|
-
return
|
|
422
|
+
return DOMPurify6__default.default.sanitize(svg, {
|
|
423
423
|
USE_PROFILES: { svg: true, svgFilters: true }
|
|
424
424
|
});
|
|
425
425
|
}
|
|
@@ -738,6 +738,8 @@ var FilePreviewViewer = class {
|
|
|
738
738
|
keyHandler = null;
|
|
739
739
|
currentContainer = null;
|
|
740
740
|
currentOptions = {};
|
|
741
|
+
resizeObserver = null;
|
|
742
|
+
fullscreenHandler = null;
|
|
741
743
|
/**
|
|
742
744
|
* Register a preview plugin.
|
|
743
745
|
*/
|
|
@@ -810,12 +812,31 @@ var FilePreviewViewer = class {
|
|
|
810
812
|
label: "Toggle Fullscreen",
|
|
811
813
|
type: "button",
|
|
812
814
|
group: "view",
|
|
813
|
-
execute: () => {
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
815
|
+
execute: async () => {
|
|
816
|
+
try {
|
|
817
|
+
const isNativeFs = !!document.fullscreenElement;
|
|
818
|
+
const isCssFs = this.wrapperEl?.classList.contains("fp-fullscreen-active");
|
|
819
|
+
if (!isNativeFs && !isCssFs) {
|
|
820
|
+
if (this.wrapperEl?.requestFullscreen) {
|
|
821
|
+
await this.wrapperEl.requestFullscreen().catch(() => {
|
|
822
|
+
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
823
|
+
});
|
|
824
|
+
} else {
|
|
825
|
+
this.wrapperEl?.classList.add("fp-fullscreen-active");
|
|
826
|
+
}
|
|
827
|
+
} else {
|
|
828
|
+
if (document.fullscreenElement) {
|
|
829
|
+
await document.exitFullscreen().catch(() => {
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
this.wrapperEl?.classList.remove("fp-fullscreen-active");
|
|
833
|
+
}
|
|
834
|
+
} catch {
|
|
835
|
+
this.wrapperEl?.classList.toggle("fp-fullscreen-active");
|
|
818
836
|
}
|
|
837
|
+
setTimeout(() => {
|
|
838
|
+
this.activeInstance?.fitToPage?.();
|
|
839
|
+
}, 120);
|
|
819
840
|
}
|
|
820
841
|
});
|
|
821
842
|
}
|
|
@@ -865,6 +886,15 @@ var FilePreviewViewer = class {
|
|
|
865
886
|
window.removeEventListener("keydown", this.keyHandler);
|
|
866
887
|
this.keyHandler = null;
|
|
867
888
|
}
|
|
889
|
+
if (this.resizeObserver) {
|
|
890
|
+
this.resizeObserver.disconnect();
|
|
891
|
+
this.resizeObserver = null;
|
|
892
|
+
}
|
|
893
|
+
if (this.fullscreenHandler) {
|
|
894
|
+
document.removeEventListener("fullscreenchange", this.fullscreenHandler);
|
|
895
|
+
document.removeEventListener("webkitfullscreenchange", this.fullscreenHandler);
|
|
896
|
+
this.fullscreenHandler = null;
|
|
897
|
+
}
|
|
868
898
|
this.abort();
|
|
869
899
|
this.destroyInstance();
|
|
870
900
|
this.toolbar?.destroy();
|
|
@@ -944,6 +974,25 @@ var FilePreviewViewer = class {
|
|
|
944
974
|
this.thumbnailPanel = new ThumbnailPanel(thumbnailEl);
|
|
945
975
|
this.setupKeyboardShortcuts();
|
|
946
976
|
this.setupDragAndDrop(container, options);
|
|
977
|
+
this.setupResizeAndFullscreenListeners();
|
|
978
|
+
}
|
|
979
|
+
setupResizeAndFullscreenListeners() {
|
|
980
|
+
if (this.fullscreenHandler) return;
|
|
981
|
+
this.fullscreenHandler = () => {
|
|
982
|
+
setTimeout(() => {
|
|
983
|
+
this.activeInstance?.fitToPage?.();
|
|
984
|
+
}, 100);
|
|
985
|
+
};
|
|
986
|
+
document.addEventListener("fullscreenchange", this.fullscreenHandler);
|
|
987
|
+
document.addEventListener("webkitfullscreenchange", this.fullscreenHandler);
|
|
988
|
+
if (typeof ResizeObserver !== "undefined" && this.contentEl) {
|
|
989
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
990
|
+
if (this.activeInstance && (!this.activeInstance.getZoom || Math.abs((this.activeInstance.getZoom?.() ?? 1) - 1) < 0.05)) {
|
|
991
|
+
this.activeInstance.fitToPage?.();
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
this.resizeObserver.observe(this.contentEl);
|
|
995
|
+
}
|
|
947
996
|
}
|
|
948
997
|
setupKeyboardShortcuts() {
|
|
949
998
|
if (this.keyHandler) return;
|
|
@@ -1335,7 +1384,8 @@ var PdfPlugin = class {
|
|
|
1335
1384
|
container.style.display = "flex";
|
|
1336
1385
|
container.style.flexDirection = "column";
|
|
1337
1386
|
container.style.alignItems = "center";
|
|
1338
|
-
container.style.
|
|
1387
|
+
container.style.justifyContent = "flex-start";
|
|
1388
|
+
container.style.padding = "20px 16px";
|
|
1339
1389
|
container.style.backgroundColor = "#0f172a";
|
|
1340
1390
|
container.style.boxSizing = "border-box";
|
|
1341
1391
|
container.style.position = "relative";
|
|
@@ -1348,7 +1398,8 @@ var PdfPlugin = class {
|
|
|
1348
1398
|
pageCard.style.lineHeight = "0";
|
|
1349
1399
|
pageCard.style.transition = "transform 0.15s ease";
|
|
1350
1400
|
pageCard.style.position = "relative";
|
|
1351
|
-
|
|
1401
|
+
pageCard.style.flexShrink = "0";
|
|
1402
|
+
let canvas = document.createElement("canvas");
|
|
1352
1403
|
pageCard.appendChild(canvas);
|
|
1353
1404
|
container.appendChild(pageCard);
|
|
1354
1405
|
const indicator = document.createElement("div");
|
|
@@ -1390,14 +1441,22 @@ var PdfPlugin = class {
|
|
|
1390
1441
|
}
|
|
1391
1442
|
currentRenderTask = null;
|
|
1392
1443
|
}
|
|
1444
|
+
const newCanvas = document.createElement("canvas");
|
|
1445
|
+
pageCard.replaceChild(newCanvas, canvas);
|
|
1446
|
+
canvas = newCanvas;
|
|
1393
1447
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
1394
1448
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
1395
1449
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
1396
1450
|
const page = await pdfDoc.getPage(currentPage);
|
|
1397
1451
|
const containerWidth = container.clientWidth || 900;
|
|
1452
|
+
const containerHeight = container.clientHeight || 700;
|
|
1398
1453
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1399
|
-
const
|
|
1400
|
-
const
|
|
1454
|
+
const availWidth = Math.max(100, containerWidth - 48);
|
|
1455
|
+
const availHeight = Math.max(100, containerHeight - 88);
|
|
1456
|
+
const scaleW = availWidth / unscaledVp.width;
|
|
1457
|
+
const scaleH = availHeight / unscaledVp.height;
|
|
1458
|
+
const fitScale = Math.min(scaleW, scaleH);
|
|
1459
|
+
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1401
1460
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
1402
1461
|
const viewport = page.getViewport({ scale: effectiveScale, rotation });
|
|
1403
1462
|
canvas.width = Math.floor(viewport.width * pixelRatio);
|
|
@@ -1422,7 +1481,19 @@ var PdfPlugin = class {
|
|
|
1422
1481
|
}
|
|
1423
1482
|
};
|
|
1424
1483
|
await renderPage(1);
|
|
1484
|
+
let resizeTimer = null;
|
|
1485
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
1486
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1487
|
+
resizeTimer = setTimeout(() => {
|
|
1488
|
+
if (Math.abs(zoomScale - 1) < 0.05) {
|
|
1489
|
+
renderPage(currentPage);
|
|
1490
|
+
}
|
|
1491
|
+
}, 150);
|
|
1492
|
+
});
|
|
1493
|
+
resizeObserver.observe(container);
|
|
1425
1494
|
const cleanup = () => {
|
|
1495
|
+
resizeObserver.disconnect();
|
|
1496
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1426
1497
|
if (currentRenderTask) {
|
|
1427
1498
|
try {
|
|
1428
1499
|
currentRenderTask.cancel();
|
|
@@ -1454,6 +1525,7 @@ var PdfPlugin = class {
|
|
|
1454
1525
|
},
|
|
1455
1526
|
fitToPage: () => {
|
|
1456
1527
|
zoomScale = 1;
|
|
1528
|
+
rotation = 0;
|
|
1457
1529
|
renderPage(currentPage);
|
|
1458
1530
|
},
|
|
1459
1531
|
rotateCW: () => {
|
|
@@ -1904,6 +1976,14 @@ var DocxPlugin = class {
|
|
|
1904
1976
|
group: "zoom",
|
|
1905
1977
|
execute: () => instance.fitToPage?.()
|
|
1906
1978
|
},
|
|
1979
|
+
{
|
|
1980
|
+
id: "rotate-cw",
|
|
1981
|
+
icon: "rotate-cw",
|
|
1982
|
+
label: "Rotate",
|
|
1983
|
+
type: "button",
|
|
1984
|
+
group: "view",
|
|
1985
|
+
execute: () => instance.rotateCW?.()
|
|
1986
|
+
},
|
|
1907
1987
|
{
|
|
1908
1988
|
id: "download",
|
|
1909
1989
|
icon: "download",
|
|
@@ -2040,6 +2120,26 @@ var DocxPlugin = class {
|
|
|
2040
2120
|
if (totalPages > 1) {
|
|
2041
2121
|
showPage(1);
|
|
2042
2122
|
}
|
|
2123
|
+
scale = 1;
|
|
2124
|
+
let rotation = 0;
|
|
2125
|
+
const calculateFitScale = () => {
|
|
2126
|
+
const activeEl = pageElements[currentPage - 1] || wrapper.firstElementChild || wrapper;
|
|
2127
|
+
const elW = activeEl.offsetWidth || 816;
|
|
2128
|
+
const elH = activeEl.offsetHeight || 1056;
|
|
2129
|
+
const availW = Math.max(200, ctx.container.clientWidth - 48);
|
|
2130
|
+
const availH = Math.max(200, ctx.container.clientHeight - 80);
|
|
2131
|
+
const sW = availW / elW;
|
|
2132
|
+
const sH = availH / elH;
|
|
2133
|
+
return Math.min(1.1, Math.min(sW, sH));
|
|
2134
|
+
};
|
|
2135
|
+
const applyTransform = () => {
|
|
2136
|
+
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
2137
|
+
wrapper.style.transformOrigin = "top center";
|
|
2138
|
+
};
|
|
2139
|
+
setTimeout(() => {
|
|
2140
|
+
scale = calculateFitScale();
|
|
2141
|
+
applyTransform();
|
|
2142
|
+
}, 60);
|
|
2043
2143
|
const cleanup = () => {
|
|
2044
2144
|
indicator?.remove();
|
|
2045
2145
|
for (const url of createdBlobUrls) {
|
|
@@ -2058,21 +2158,30 @@ var DocxPlugin = class {
|
|
|
2058
2158
|
showPage(page);
|
|
2059
2159
|
},
|
|
2060
2160
|
zoomIn: () => {
|
|
2061
|
-
scale += 0.
|
|
2062
|
-
|
|
2161
|
+
scale += 0.15;
|
|
2162
|
+
applyTransform();
|
|
2063
2163
|
},
|
|
2064
2164
|
zoomOut: () => {
|
|
2065
|
-
scale = Math.max(0.2, scale - 0.
|
|
2066
|
-
|
|
2165
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
2166
|
+
applyTransform();
|
|
2067
2167
|
},
|
|
2068
2168
|
getZoom: () => scale,
|
|
2069
2169
|
setZoom: (level) => {
|
|
2070
2170
|
scale = level;
|
|
2071
|
-
|
|
2171
|
+
applyTransform();
|
|
2072
2172
|
},
|
|
2073
2173
|
fitToPage: () => {
|
|
2074
|
-
scale =
|
|
2075
|
-
|
|
2174
|
+
scale = calculateFitScale();
|
|
2175
|
+
rotation = 0;
|
|
2176
|
+
applyTransform();
|
|
2177
|
+
},
|
|
2178
|
+
rotateCW: () => {
|
|
2179
|
+
rotation = (rotation + 90) % 360;
|
|
2180
|
+
applyTransform();
|
|
2181
|
+
},
|
|
2182
|
+
rotateCCW: () => {
|
|
2183
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
2184
|
+
applyTransform();
|
|
2076
2185
|
},
|
|
2077
2186
|
download: () => {
|
|
2078
2187
|
const blob = new Blob([ctx.buffer], { type: this.mimeTypes[0] });
|
|
@@ -2132,90 +2241,149 @@ var DocxPlugin = class {
|
|
|
2132
2241
|
console.warn("[DocxPlugin] Error parsing relationships:", relsErr);
|
|
2133
2242
|
}
|
|
2134
2243
|
}
|
|
2135
|
-
const
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2244
|
+
const sectPrs = Array.from(doc.getElementsByTagNameNS("*", "sectPr"));
|
|
2245
|
+
const lastSectPr = sectPrs[sectPrs.length - 1];
|
|
2246
|
+
let defaultW = 12240;
|
|
2247
|
+
let defaultH = 15840;
|
|
2248
|
+
let margins = { top: 1440, right: 1440, bottom: 1440, left: 1440 };
|
|
2249
|
+
if (lastSectPr) {
|
|
2250
|
+
const pgSz = lastSectPr.getElementsByTagNameNS("*", "pgSz")[0];
|
|
2251
|
+
if (pgSz) {
|
|
2252
|
+
defaultW = parseInt(pgSz.getAttribute("w:w") || pgSz.getAttribute("w") || "12240", 10);
|
|
2253
|
+
defaultH = parseInt(pgSz.getAttribute("w:h") || pgSz.getAttribute("h") || "15840", 10);
|
|
2254
|
+
}
|
|
2255
|
+
const pgMar = lastSectPr.getElementsByTagNameNS("*", "pgMar")[0];
|
|
2256
|
+
if (pgMar) {
|
|
2257
|
+
margins.top = parseInt(pgMar.getAttribute("w:top") || pgMar.getAttribute("top") || "1440", 10);
|
|
2258
|
+
margins.bottom = parseInt(pgMar.getAttribute("w:bottom") || pgMar.getAttribute("bottom") || "1440", 10);
|
|
2259
|
+
margins.left = parseInt(pgMar.getAttribute("w:left") || pgMar.getAttribute("left") || "1440", 10);
|
|
2260
|
+
margins.right = parseInt(pgMar.getAttribute("w:right") || pgMar.getAttribute("right") || "1440", 10);
|
|
2261
|
+
}
|
|
2262
|
+
}
|
|
2263
|
+
const createPageCard = () => {
|
|
2264
|
+
const card = document.createElement("div");
|
|
2265
|
+
card.className = "fp-docx-page-card";
|
|
2266
|
+
card.style.backgroundColor = "#ffffff";
|
|
2267
|
+
card.style.borderRadius = "4px";
|
|
2268
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
2269
|
+
card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2270
|
+
card.style.color = "#1e293b";
|
|
2271
|
+
card.style.lineHeight = "1.6";
|
|
2272
|
+
card.style.boxSizing = "border-box";
|
|
2273
|
+
card.style.overflow = "hidden";
|
|
2274
|
+
card.style.position = "relative";
|
|
2275
|
+
card.style.marginBottom = "24px";
|
|
2276
|
+
card.style.width = `${defaultW / 15}px`;
|
|
2277
|
+
card.style.height = `${defaultH / 15}px`;
|
|
2278
|
+
card.style.padding = `${margins.top / 15}px ${margins.right / 15}px ${margins.bottom / 15}px ${margins.left / 15}px`;
|
|
2279
|
+
return card;
|
|
2280
|
+
};
|
|
2281
|
+
let currentCard = createPageCard();
|
|
2282
|
+
let currentHtml = "";
|
|
2283
|
+
const pages = [{ card: currentCard, html: "" }];
|
|
2284
|
+
const flushHtml = () => {
|
|
2285
|
+
pages[pages.length - 1].html += currentHtml;
|
|
2286
|
+
currentHtml = "";
|
|
2287
|
+
};
|
|
2288
|
+
const newPage = () => {
|
|
2289
|
+
flushHtml();
|
|
2290
|
+
currentCard = createPageCard();
|
|
2291
|
+
pages.push({ card: currentCard, html: "" });
|
|
2292
|
+
};
|
|
2144
2293
|
const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
|
|
2145
|
-
let html = "";
|
|
2146
2294
|
for (const child of Array.from(body.children)) {
|
|
2147
2295
|
const tag = child.localName || child.nodeName.split(":").pop();
|
|
2148
2296
|
if (tag === "p") {
|
|
2149
2297
|
const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
|
|
2150
2298
|
const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
|
|
2151
2299
|
const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
|
|
2152
|
-
const
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2300
|
+
const chunks = this.extractParagraphChunks(child, imageMap);
|
|
2301
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
2302
|
+
if (i > 0) {
|
|
2303
|
+
newPage();
|
|
2304
|
+
}
|
|
2305
|
+
const textContent = chunks[i];
|
|
2306
|
+
if (!textContent.trim() && !textContent.includes("<img")) {
|
|
2307
|
+
currentHtml += '<div style="height: 10px;"></div>';
|
|
2308
|
+
continue;
|
|
2309
|
+
}
|
|
2310
|
+
const lowerStyle = styleVal.toLowerCase();
|
|
2311
|
+
if (lowerStyle.includes("title")) {
|
|
2312
|
+
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>`;
|
|
2313
|
+
} else if (lowerStyle.includes("heading1") || styleVal === "1") {
|
|
2314
|
+
currentHtml += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
|
|
2315
|
+
} else if (lowerStyle.includes("heading2") || styleVal === "2") {
|
|
2316
|
+
currentHtml += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
|
|
2317
|
+
} else if (lowerStyle.includes("heading3") || styleVal === "3") {
|
|
2318
|
+
currentHtml += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
|
|
2319
|
+
} else if (numPr) {
|
|
2320
|
+
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>`;
|
|
2321
|
+
} else {
|
|
2322
|
+
currentHtml += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
|
|
2323
|
+
}
|
|
2170
2324
|
}
|
|
2171
2325
|
} else if (tag === "tbl") {
|
|
2172
|
-
|
|
2326
|
+
currentHtml += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
|
|
2173
2327
|
const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
|
|
2174
2328
|
rows.forEach((tr, rIdx) => {
|
|
2175
|
-
|
|
2329
|
+
currentHtml += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
2176
2330
|
const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
|
|
2177
2331
|
cells.forEach((tc) => {
|
|
2178
2332
|
const cellText = this.extractParagraphHtml(tc, imageMap);
|
|
2179
|
-
|
|
2333
|
+
currentHtml += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || " "}</td>`;
|
|
2180
2334
|
});
|
|
2181
|
-
|
|
2335
|
+
currentHtml += "</tr>";
|
|
2182
2336
|
});
|
|
2183
|
-
|
|
2337
|
+
currentHtml += "</table>";
|
|
2184
2338
|
}
|
|
2185
2339
|
}
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2340
|
+
flushHtml();
|
|
2341
|
+
for (const page of pages) {
|
|
2342
|
+
page.card.innerHTML = DOMPurify6__default.default.sanitize(page.html, {
|
|
2343
|
+
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
|
|
2344
|
+
ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
|
|
2345
|
+
});
|
|
2346
|
+
wrapper.appendChild(page.card);
|
|
2347
|
+
}
|
|
2191
2348
|
}
|
|
2192
2349
|
extractParagraphHtml(pElement, imageMap = {}) {
|
|
2193
|
-
|
|
2350
|
+
return this.extractParagraphChunks(pElement, imageMap).join("<br/>");
|
|
2351
|
+
}
|
|
2352
|
+
extractParagraphChunks(pElement, imageMap = {}) {
|
|
2353
|
+
const chunks = [""];
|
|
2354
|
+
let currentChunkIndex = 0;
|
|
2194
2355
|
const drawings = Array.from(pElement.getElementsByTagNameNS("*", "drawing"));
|
|
2195
2356
|
for (const drawing of drawings) {
|
|
2196
2357
|
const blip = drawing.getElementsByTagNameNS("*", "blip")[0];
|
|
2197
2358
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2198
2359
|
if (rId && imageMap[rId]) {
|
|
2199
|
-
|
|
2360
|
+
chunks[currentChunkIndex] += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
|
|
2200
2361
|
}
|
|
2201
2362
|
}
|
|
2202
2363
|
const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
|
|
2203
|
-
if (runs.length === 0 && !
|
|
2204
|
-
|
|
2364
|
+
if (runs.length === 0 && !chunks[currentChunkIndex]) {
|
|
2365
|
+
chunks[currentChunkIndex] = DOMPurify6__default.default.sanitize(pElement.textContent || "");
|
|
2366
|
+
return chunks;
|
|
2205
2367
|
}
|
|
2206
2368
|
for (const r of runs) {
|
|
2207
2369
|
const blip = r.getElementsByTagNameNS("*", "blip")[0] || r.getElementsByTagNameNS("*", "imagedata")[0];
|
|
2208
2370
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2209
2371
|
if (rId && imageMap[rId]) {
|
|
2210
|
-
|
|
2372
|
+
chunks[currentChunkIndex] += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
|
|
2211
2373
|
}
|
|
2212
|
-
const brs = r.getElementsByTagNameNS("*", "br");
|
|
2213
|
-
for (
|
|
2214
|
-
|
|
2374
|
+
const brs = Array.from(r.getElementsByTagNameNS("*", "br"));
|
|
2375
|
+
for (const br of brs) {
|
|
2376
|
+
const type = br.getAttribute("w:type") || br.getAttribute("type");
|
|
2377
|
+
if (type === "page") {
|
|
2378
|
+
chunks.push("");
|
|
2379
|
+
currentChunkIndex++;
|
|
2380
|
+
} else {
|
|
2381
|
+
chunks[currentChunkIndex] += "<br/>";
|
|
2382
|
+
}
|
|
2215
2383
|
}
|
|
2216
2384
|
const tabs = r.getElementsByTagNameNS("*", "tab");
|
|
2217
2385
|
if (tabs.length > 0) {
|
|
2218
|
-
|
|
2386
|
+
chunks[currentChunkIndex] += " ";
|
|
2219
2387
|
}
|
|
2220
2388
|
const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
|
|
2221
2389
|
const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
|
|
@@ -2229,7 +2397,7 @@ var DocxPlugin = class {
|
|
|
2229
2397
|
const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
|
|
2230
2398
|
let text = texts.map((t) => t.textContent || "").join("");
|
|
2231
2399
|
if (!text) continue;
|
|
2232
|
-
text =
|
|
2400
|
+
text = DOMPurify6__default.default.sanitize(text);
|
|
2233
2401
|
let styles = "";
|
|
2234
2402
|
if (isBold) styles += "font-weight: bold; ";
|
|
2235
2403
|
if (isItalic) styles += "font-style: italic; ";
|
|
@@ -2241,12 +2409,12 @@ var DocxPlugin = class {
|
|
|
2241
2409
|
if (!isNaN(pt) && pt > 0) styles += `font-size: ${pt}pt; `;
|
|
2242
2410
|
}
|
|
2243
2411
|
if (styles) {
|
|
2244
|
-
|
|
2412
|
+
chunks[currentChunkIndex] += `<span style="${styles}">${text}</span>`;
|
|
2245
2413
|
} else {
|
|
2246
|
-
|
|
2414
|
+
chunks[currentChunkIndex] += text;
|
|
2247
2415
|
}
|
|
2248
2416
|
}
|
|
2249
|
-
return
|
|
2417
|
+
return chunks;
|
|
2250
2418
|
}
|
|
2251
2419
|
renderBinaryDocFallback(ctx, wrapper) {
|
|
2252
2420
|
const card = document.createElement("div");
|
|
@@ -2263,14 +2431,14 @@ var DocxPlugin = class {
|
|
|
2263
2431
|
const wordDocStream = cfbf.readStream("WordDocument");
|
|
2264
2432
|
if (wordDocStream && wordDocStream.length >= 512) {
|
|
2265
2433
|
const text2 = this.extractReadableStrings(wordDocStream);
|
|
2266
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2434
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text2)}</div>`;
|
|
2267
2435
|
wrapper.appendChild(card);
|
|
2268
2436
|
return;
|
|
2269
2437
|
}
|
|
2270
2438
|
} catch {
|
|
2271
2439
|
}
|
|
2272
2440
|
const text = this.extractReadableStrings(new Uint8Array(ctx.buffer));
|
|
2273
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2441
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text)}</div>`;
|
|
2274
2442
|
wrapper.appendChild(card);
|
|
2275
2443
|
}
|
|
2276
2444
|
extractReadableStrings(bytes) {
|
|
@@ -2366,6 +2534,26 @@ var ExcelPlugin = class {
|
|
|
2366
2534
|
instance.zoomIn?.();
|
|
2367
2535
|
}
|
|
2368
2536
|
},
|
|
2537
|
+
{
|
|
2538
|
+
id: "fit-page",
|
|
2539
|
+
icon: "fit-page",
|
|
2540
|
+
label: "Fit to View",
|
|
2541
|
+
type: "button",
|
|
2542
|
+
group: "zoom",
|
|
2543
|
+
execute: () => {
|
|
2544
|
+
instance.fitToPage?.();
|
|
2545
|
+
}
|
|
2546
|
+
},
|
|
2547
|
+
{
|
|
2548
|
+
id: "rotate-cw",
|
|
2549
|
+
icon: "rotate-cw",
|
|
2550
|
+
label: "Rotate",
|
|
2551
|
+
type: "button",
|
|
2552
|
+
group: "view",
|
|
2553
|
+
execute: () => {
|
|
2554
|
+
instance.rotateCW?.();
|
|
2555
|
+
}
|
|
2556
|
+
},
|
|
2369
2557
|
{
|
|
2370
2558
|
id: "download",
|
|
2371
2559
|
icon: "download",
|
|
@@ -2416,9 +2604,23 @@ var ExcelPlugin = class {
|
|
|
2416
2604
|
container.appendChild(tabsArea);
|
|
2417
2605
|
ctx.container.appendChild(container);
|
|
2418
2606
|
let scale = 1;
|
|
2607
|
+
let rotation = 0;
|
|
2419
2608
|
let currentSheetIndex = 1;
|
|
2420
2609
|
let sheetNames = [];
|
|
2421
2610
|
let wb = null;
|
|
2611
|
+
const applyTransform = () => {
|
|
2612
|
+
contentArea.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
2613
|
+
contentArea.style.transformOrigin = "top left";
|
|
2614
|
+
};
|
|
2615
|
+
const calculateFitScale = () => {
|
|
2616
|
+
const table = contentArea.querySelector("table");
|
|
2617
|
+
if (!table) return 1;
|
|
2618
|
+
const availW = Math.max(200, container.clientWidth - 48);
|
|
2619
|
+
const availH = Math.max(200, container.clientHeight - 80);
|
|
2620
|
+
const tW = table.offsetWidth || 800;
|
|
2621
|
+
const tH = table.offsetHeight || 600;
|
|
2622
|
+
return Math.min(1, Math.min(availW / tW, availH / tH));
|
|
2623
|
+
};
|
|
2422
2624
|
try {
|
|
2423
2625
|
wb = XLSX__namespace.read(new Uint8Array(ctx.buffer), { type: "array", cellDates: true });
|
|
2424
2626
|
sheetNames = wb.SheetNames || [];
|
|
@@ -2506,17 +2708,30 @@ var ExcelPlugin = class {
|
|
|
2506
2708
|
return {
|
|
2507
2709
|
destroy: cleanup,
|
|
2508
2710
|
zoomIn: () => {
|
|
2509
|
-
scale += 0.
|
|
2510
|
-
|
|
2711
|
+
scale += 0.15;
|
|
2712
|
+
applyTransform();
|
|
2511
2713
|
},
|
|
2512
2714
|
zoomOut: () => {
|
|
2513
|
-
scale = Math.max(0.2, scale - 0.
|
|
2514
|
-
|
|
2715
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
2716
|
+
applyTransform();
|
|
2515
2717
|
},
|
|
2516
2718
|
getZoom: () => scale,
|
|
2517
2719
|
setZoom: (level) => {
|
|
2518
2720
|
scale = level;
|
|
2519
|
-
|
|
2721
|
+
applyTransform();
|
|
2722
|
+
},
|
|
2723
|
+
fitToPage: () => {
|
|
2724
|
+
scale = calculateFitScale();
|
|
2725
|
+
rotation = 0;
|
|
2726
|
+
applyTransform();
|
|
2727
|
+
},
|
|
2728
|
+
rotateCW: () => {
|
|
2729
|
+
rotation = (rotation + 90) % 360;
|
|
2730
|
+
applyTransform();
|
|
2731
|
+
},
|
|
2732
|
+
rotateCCW: () => {
|
|
2733
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
2734
|
+
applyTransform();
|
|
2520
2735
|
},
|
|
2521
2736
|
goToPage: (page) => {
|
|
2522
2737
|
if (page > 0 && page <= sheetNames.length) {
|
|
@@ -2766,6 +2981,26 @@ var CodePlugin = class {
|
|
|
2766
2981
|
instance.zoomIn?.();
|
|
2767
2982
|
}
|
|
2768
2983
|
},
|
|
2984
|
+
{
|
|
2985
|
+
id: "fit-page",
|
|
2986
|
+
icon: "fit-page",
|
|
2987
|
+
label: "Fit to View",
|
|
2988
|
+
type: "button",
|
|
2989
|
+
group: "zoom",
|
|
2990
|
+
execute: () => {
|
|
2991
|
+
instance.fitToPage?.();
|
|
2992
|
+
}
|
|
2993
|
+
},
|
|
2994
|
+
{
|
|
2995
|
+
id: "rotate-cw",
|
|
2996
|
+
icon: "rotate-cw",
|
|
2997
|
+
label: "Rotate",
|
|
2998
|
+
type: "button",
|
|
2999
|
+
group: "view",
|
|
3000
|
+
execute: () => {
|
|
3001
|
+
instance.rotateCW?.();
|
|
3002
|
+
}
|
|
3003
|
+
},
|
|
2769
3004
|
{
|
|
2770
3005
|
id: "copy",
|
|
2771
3006
|
icon: "copy",
|
|
@@ -2802,40 +3037,94 @@ var CodePlugin = class {
|
|
|
2802
3037
|
async render(ctx) {
|
|
2803
3038
|
const decoder = new TextDecoder("utf-8");
|
|
2804
3039
|
const fullText = decoder.decode(ctx.buffer);
|
|
2805
|
-
const
|
|
2806
|
-
const
|
|
3040
|
+
const extRaw = ctx.metadata.extension?.toLowerCase();
|
|
3041
|
+
const mimeRaw = ctx.metadata.mimeType?.toLowerCase();
|
|
3042
|
+
const isTxt = extRaw === ".txt" || mimeRaw === "text/plain" && (!extRaw || !this.extensions.filter((e) => e !== ".txt").includes(extRaw));
|
|
3043
|
+
let rawPages = [];
|
|
3044
|
+
if (isTxt) {
|
|
3045
|
+
const explicitPages = fullText.split(/(?:\f|\x0C)/);
|
|
3046
|
+
for (const ep of explicitPages) {
|
|
3047
|
+
const lines = ep.split(/\r?\n/);
|
|
3048
|
+
let currentChunk = [];
|
|
3049
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3050
|
+
currentChunk.push(lines[i]);
|
|
3051
|
+
if (currentChunk.length >= 46) {
|
|
3052
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3053
|
+
currentChunk = [];
|
|
3054
|
+
}
|
|
3055
|
+
}
|
|
3056
|
+
if (currentChunk.length > 0 || lines.length === 0) {
|
|
3057
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
if (rawPages.length === 0) rawPages = [""];
|
|
3061
|
+
} else {
|
|
3062
|
+
const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
|
|
3063
|
+
rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
3064
|
+
}
|
|
2807
3065
|
const totalPages = Math.max(1, rawPages.length);
|
|
2808
3066
|
let currentPage = 1;
|
|
2809
3067
|
const container = document.createElement("div");
|
|
2810
3068
|
container.style.width = "100%";
|
|
2811
3069
|
container.style.height = "100%";
|
|
2812
3070
|
container.style.overflow = "auto";
|
|
2813
|
-
container.style.backgroundColor = "#1e1e1e";
|
|
2814
|
-
container.style.color = "#d4d4d4";
|
|
2815
|
-
container.style.padding = "16px";
|
|
2816
|
-
container.style.boxSizing = "border-box";
|
|
2817
3071
|
let fontSize = 13;
|
|
3072
|
+
let rotation = 0;
|
|
3073
|
+
let zoomLevel = 1;
|
|
2818
3074
|
const pre = document.createElement("pre");
|
|
2819
|
-
pre.style.margin = "0";
|
|
2820
|
-
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
2821
|
-
pre.style.fontSize = `${fontSize}px`;
|
|
2822
|
-
pre.style.lineHeight = "1.5";
|
|
2823
|
-
pre.style.whiteSpace = "pre-wrap";
|
|
2824
|
-
pre.style.wordBreak = "break-all";
|
|
2825
3075
|
const code = document.createElement("code");
|
|
3076
|
+
if (isTxt) {
|
|
3077
|
+
container.style.backgroundColor = "#f1f5f9";
|
|
3078
|
+
container.style.padding = "32px";
|
|
3079
|
+
container.style.boxSizing = "border-box";
|
|
3080
|
+
container.style.display = "flex";
|
|
3081
|
+
container.style.flexDirection = "column";
|
|
3082
|
+
container.style.alignItems = "center";
|
|
3083
|
+
pre.style.margin = "0";
|
|
3084
|
+
pre.style.fontFamily = "Consolas, 'Courier New', monospace";
|
|
3085
|
+
pre.style.fontSize = "13px";
|
|
3086
|
+
pre.style.color = "#1e293b";
|
|
3087
|
+
pre.style.lineHeight = "1.5";
|
|
3088
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3089
|
+
pre.style.wordBreak = "break-word";
|
|
3090
|
+
pre.style.backgroundColor = "#ffffff";
|
|
3091
|
+
pre.style.width = "816px";
|
|
3092
|
+
pre.style.minHeight = "1056px";
|
|
3093
|
+
pre.style.padding = "72px 56px";
|
|
3094
|
+
pre.style.boxSizing = "border-box";
|
|
3095
|
+
pre.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)";
|
|
3096
|
+
pre.style.borderRadius = "4px";
|
|
3097
|
+
pre.style.transformOrigin = "top center";
|
|
3098
|
+
} else {
|
|
3099
|
+
container.style.backgroundColor = "#1e1e1e";
|
|
3100
|
+
container.style.color = "#d4d4d4";
|
|
3101
|
+
container.style.padding = "16px";
|
|
3102
|
+
container.style.boxSizing = "border-box";
|
|
3103
|
+
pre.style.margin = "0";
|
|
3104
|
+
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
3105
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3106
|
+
pre.style.lineHeight = "1.5";
|
|
3107
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3108
|
+
pre.style.wordBreak = "break-all";
|
|
3109
|
+
pre.style.transformOrigin = "top left";
|
|
3110
|
+
}
|
|
2826
3111
|
const ext = (ctx.metadata.extension || "").replace(".", "");
|
|
2827
3112
|
const renderCodePage = (text) => {
|
|
2828
|
-
|
|
2829
|
-
if (ext && hljs__default.default.getLanguage(ext)) {
|
|
2830
|
-
code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
|
|
2831
|
-
} else {
|
|
2832
|
-
code.innerHTML = hljs__default.default.highlightAuto(text).value;
|
|
2833
|
-
}
|
|
2834
|
-
} catch {
|
|
3113
|
+
if (isTxt) {
|
|
2835
3114
|
code.textContent = text;
|
|
3115
|
+
} else {
|
|
3116
|
+
try {
|
|
3117
|
+
if (ext && hljs__default.default.getLanguage(ext)) {
|
|
3118
|
+
code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
|
|
3119
|
+
} else {
|
|
3120
|
+
code.innerHTML = hljs__default.default.highlightAuto(text).value;
|
|
3121
|
+
}
|
|
3122
|
+
} catch {
|
|
3123
|
+
code.textContent = text;
|
|
3124
|
+
}
|
|
2836
3125
|
}
|
|
2837
3126
|
};
|
|
2838
|
-
renderCodePage(rawPages[0] || fullText);
|
|
3127
|
+
renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
|
|
2839
3128
|
pre.appendChild(code);
|
|
2840
3129
|
container.appendChild(pre);
|
|
2841
3130
|
let indicator = null;
|
|
@@ -2844,15 +3133,22 @@ var CodePlugin = class {
|
|
|
2844
3133
|
indicator.className = "fp-code-page-indicator";
|
|
2845
3134
|
indicator.style.position = "sticky";
|
|
2846
3135
|
indicator.style.bottom = "16px";
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
3136
|
+
if (isTxt) {
|
|
3137
|
+
indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
3138
|
+
indicator.style.color = "#334155";
|
|
3139
|
+
indicator.style.border = "1px solid #e2e8f0";
|
|
3140
|
+
indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
|
|
3141
|
+
} else {
|
|
3142
|
+
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3143
|
+
indicator.style.color = "#f8fafc";
|
|
3144
|
+
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3145
|
+
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3146
|
+
indicator.style.backdropFilter = "blur(8px)";
|
|
3147
|
+
}
|
|
2850
3148
|
indicator.style.fontSize = "12px";
|
|
2851
3149
|
indicator.style.fontWeight = "600";
|
|
2852
3150
|
indicator.style.padding = "5px 14px";
|
|
2853
3151
|
indicator.style.borderRadius = "20px";
|
|
2854
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
2855
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
2856
3152
|
indicator.style.zIndex = "10";
|
|
2857
3153
|
indicator.style.userSelect = "none";
|
|
2858
3154
|
indicator.style.pointerEvents = "none";
|
|
@@ -2863,7 +3159,7 @@ var CodePlugin = class {
|
|
|
2863
3159
|
}
|
|
2864
3160
|
const showPage = (pageNum) => {
|
|
2865
3161
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
2866
|
-
renderCodePage(rawPages[currentPage - 1] || fullText);
|
|
3162
|
+
renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
|
|
2867
3163
|
if (indicator) {
|
|
2868
3164
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
2869
3165
|
}
|
|
@@ -2879,23 +3175,57 @@ var CodePlugin = class {
|
|
|
2879
3175
|
ctx.container.innerHTML = "";
|
|
2880
3176
|
};
|
|
2881
3177
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3178
|
+
const updateTransform = () => {
|
|
3179
|
+
if (isTxt) {
|
|
3180
|
+
pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
|
|
3181
|
+
} else {
|
|
3182
|
+
pre.style.transform = `rotate(${rotation}deg)`;
|
|
3183
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3184
|
+
}
|
|
3185
|
+
};
|
|
2882
3186
|
return {
|
|
2883
3187
|
destroy: cleanup,
|
|
2884
3188
|
getPageCount: () => totalPages,
|
|
2885
3189
|
getCurrentPage: () => currentPage,
|
|
2886
3190
|
goToPage: (page) => showPage(page),
|
|
2887
3191
|
zoomIn: () => {
|
|
2888
|
-
|
|
2889
|
-
|
|
3192
|
+
if (isTxt) {
|
|
3193
|
+
zoomLevel = Math.min(3, zoomLevel + 0.1);
|
|
3194
|
+
} else {
|
|
3195
|
+
fontSize = Math.min(32, fontSize + 2);
|
|
3196
|
+
}
|
|
3197
|
+
updateTransform();
|
|
2890
3198
|
},
|
|
2891
3199
|
zoomOut: () => {
|
|
2892
|
-
|
|
2893
|
-
|
|
3200
|
+
if (isTxt) {
|
|
3201
|
+
zoomLevel = Math.max(0.1, zoomLevel - 0.1);
|
|
3202
|
+
} else {
|
|
3203
|
+
fontSize = Math.max(8, fontSize - 2);
|
|
3204
|
+
}
|
|
3205
|
+
updateTransform();
|
|
2894
3206
|
},
|
|
2895
|
-
getZoom: () => fontSize / 13,
|
|
3207
|
+
getZoom: () => isTxt ? zoomLevel : fontSize / 13,
|
|
2896
3208
|
setZoom: (level) => {
|
|
2897
|
-
|
|
2898
|
-
|
|
3209
|
+
if (isTxt) {
|
|
3210
|
+
zoomLevel = level;
|
|
3211
|
+
} else {
|
|
3212
|
+
fontSize = Math.round(13 * level);
|
|
3213
|
+
}
|
|
3214
|
+
updateTransform();
|
|
3215
|
+
},
|
|
3216
|
+
fitToPage: () => {
|
|
3217
|
+
fontSize = 13;
|
|
3218
|
+
rotation = 0;
|
|
3219
|
+
zoomLevel = 1;
|
|
3220
|
+
updateTransform();
|
|
3221
|
+
},
|
|
3222
|
+
rotateCW: () => {
|
|
3223
|
+
rotation = (rotation + 90) % 360;
|
|
3224
|
+
updateTransform();
|
|
3225
|
+
},
|
|
3226
|
+
rotateCCW: () => {
|
|
3227
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
3228
|
+
updateTransform();
|
|
2899
3229
|
},
|
|
2900
3230
|
download: () => {
|
|
2901
3231
|
const mimeType = ctx.metadata.mimeType || "text/plain";
|
|
@@ -3194,7 +3524,7 @@ var MarkdownPlugin = class {
|
|
|
3194
3524
|
gfm: true,
|
|
3195
3525
|
breaks: true
|
|
3196
3526
|
});
|
|
3197
|
-
const cleanHtml =
|
|
3527
|
+
const cleanHtml = DOMPurify6__default.default.sanitize(rawHtml, {
|
|
3198
3528
|
USE_PROFILES: { html: true }
|
|
3199
3529
|
});
|
|
3200
3530
|
const wrapper = document.createElement("div");
|
|
@@ -3408,6 +3738,14 @@ var PptxPlugin = class {
|
|
|
3408
3738
|
group: "zoom",
|
|
3409
3739
|
execute: () => instance.fitToPage?.()
|
|
3410
3740
|
},
|
|
3741
|
+
{
|
|
3742
|
+
id: "rotate-cw",
|
|
3743
|
+
icon: "rotate-cw",
|
|
3744
|
+
label: "Rotate",
|
|
3745
|
+
type: "button",
|
|
3746
|
+
group: "view",
|
|
3747
|
+
execute: () => instance.rotateCW?.()
|
|
3748
|
+
},
|
|
3411
3749
|
{
|
|
3412
3750
|
id: "download",
|
|
3413
3751
|
icon: "download",
|
|
@@ -3432,6 +3770,7 @@ var PptxPlugin = class {
|
|
|
3432
3770
|
const slideCount = renderer.slidePaths?.length || 1;
|
|
3433
3771
|
let currentSlide = 1;
|
|
3434
3772
|
let scale = 1;
|
|
3773
|
+
let rotation = 0;
|
|
3435
3774
|
const wrapper = document.createElement("div");
|
|
3436
3775
|
wrapper.className = "fp-pptx-wrapper";
|
|
3437
3776
|
wrapper.style.cssText = `
|
|
@@ -3454,6 +3793,8 @@ var PptxPlugin = class {
|
|
|
3454
3793
|
background: #ffffff;
|
|
3455
3794
|
transform-origin: top center;
|
|
3456
3795
|
transition: transform 0.2s ease;
|
|
3796
|
+
max-width: calc(100% - 32px);
|
|
3797
|
+
max-height: calc(100% - 48px);
|
|
3457
3798
|
`;
|
|
3458
3799
|
const canvas = document.createElement("canvas");
|
|
3459
3800
|
slideContainer.appendChild(canvas);
|
|
@@ -3461,10 +3802,22 @@ var PptxPlugin = class {
|
|
|
3461
3802
|
ctx.container.innerHTML = "";
|
|
3462
3803
|
ctx.container.style.overflow = "auto";
|
|
3463
3804
|
ctx.container.appendChild(wrapper);
|
|
3805
|
+
const calculateFitScale = () => {
|
|
3806
|
+
const availW = Math.max(200, ctx.container.clientWidth - 48);
|
|
3807
|
+
const availH = Math.max(200, ctx.container.clientHeight - 72);
|
|
3808
|
+
const cW = canvas.offsetWidth || 1280;
|
|
3809
|
+
const cH = canvas.offsetHeight || 720;
|
|
3810
|
+
return Math.min(1, Math.min(availW / cW, availH / cH));
|
|
3811
|
+
};
|
|
3812
|
+
const applyTransform = () => {
|
|
3813
|
+
slideContainer.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
3814
|
+
};
|
|
3464
3815
|
const renderCurrentSlide = async () => {
|
|
3465
3816
|
try {
|
|
3466
3817
|
await renderer.renderSlide(currentSlide - 1, canvas, 1280);
|
|
3467
3818
|
ctx.emit("page-change", { page: currentSlide, totalPages: slideCount });
|
|
3819
|
+
scale = calculateFitScale();
|
|
3820
|
+
applyTransform();
|
|
3468
3821
|
} catch (err) {
|
|
3469
3822
|
console.error("[PptxPlugin] Failed to render slide:", err);
|
|
3470
3823
|
}
|
|
@@ -3487,21 +3840,30 @@ var PptxPlugin = class {
|
|
|
3487
3840
|
getPageCount: () => slideCount,
|
|
3488
3841
|
getCurrentPage: () => currentSlide,
|
|
3489
3842
|
zoomIn: () => {
|
|
3490
|
-
scale += 0.
|
|
3491
|
-
|
|
3843
|
+
scale += 0.15;
|
|
3844
|
+
applyTransform();
|
|
3492
3845
|
},
|
|
3493
3846
|
zoomOut: () => {
|
|
3494
|
-
scale = Math.max(0.2, scale - 0.
|
|
3495
|
-
|
|
3847
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
3848
|
+
applyTransform();
|
|
3496
3849
|
},
|
|
3497
3850
|
getZoom: () => scale,
|
|
3498
3851
|
setZoom: (level) => {
|
|
3499
3852
|
scale = level;
|
|
3500
|
-
|
|
3853
|
+
applyTransform();
|
|
3501
3854
|
},
|
|
3502
3855
|
fitToPage: () => {
|
|
3503
|
-
scale =
|
|
3504
|
-
|
|
3856
|
+
scale = calculateFitScale();
|
|
3857
|
+
rotation = 0;
|
|
3858
|
+
applyTransform();
|
|
3859
|
+
},
|
|
3860
|
+
rotateCW: () => {
|
|
3861
|
+
rotation = (rotation + 90) % 360;
|
|
3862
|
+
applyTransform();
|
|
3863
|
+
},
|
|
3864
|
+
rotateCCW: () => {
|
|
3865
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
3866
|
+
applyTransform();
|
|
3505
3867
|
},
|
|
3506
3868
|
getThumbnails: () => {
|
|
3507
3869
|
const list = [];
|
|
@@ -3782,6 +4144,14 @@ var RtfPlugin = class {
|
|
|
3782
4144
|
group: "zoom",
|
|
3783
4145
|
execute: () => instance.fitToPage?.()
|
|
3784
4146
|
},
|
|
4147
|
+
{
|
|
4148
|
+
id: "rotate-cw",
|
|
4149
|
+
icon: "rotate-cw",
|
|
4150
|
+
label: "Rotate",
|
|
4151
|
+
type: "button",
|
|
4152
|
+
group: "view",
|
|
4153
|
+
execute: () => instance.rotateCW?.()
|
|
4154
|
+
},
|
|
3785
4155
|
{
|
|
3786
4156
|
id: "download",
|
|
3787
4157
|
icon: "download",
|
|
@@ -3790,6 +4160,14 @@ var RtfPlugin = class {
|
|
|
3790
4160
|
group: "actions",
|
|
3791
4161
|
execute: () => instance.download?.()
|
|
3792
4162
|
},
|
|
4163
|
+
{
|
|
4164
|
+
id: "copy",
|
|
4165
|
+
icon: "copy",
|
|
4166
|
+
label: "Copy Text",
|
|
4167
|
+
type: "button",
|
|
4168
|
+
group: "actions",
|
|
4169
|
+
execute: () => instance.copy?.()
|
|
4170
|
+
},
|
|
3793
4171
|
{
|
|
3794
4172
|
id: "print",
|
|
3795
4173
|
icon: "print",
|
|
@@ -3818,7 +4196,24 @@ var RtfPlugin = class {
|
|
|
3818
4196
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
3819
4197
|
ctx.container.appendChild(wrapper);
|
|
3820
4198
|
let scale = 1;
|
|
4199
|
+
let rotation = 0;
|
|
3821
4200
|
let pageElements = [];
|
|
4201
|
+
const calculateFitScale = () => {
|
|
4202
|
+
const activeEl = pageElements[currentPage - 1] || wrapper;
|
|
4203
|
+
const elW = activeEl.offsetWidth || 850;
|
|
4204
|
+
const elH = activeEl.offsetHeight || 1e3;
|
|
4205
|
+
const availW = Math.max(200, ctx.container.clientWidth - 48);
|
|
4206
|
+
const availH = Math.max(200, ctx.container.clientHeight - 80);
|
|
4207
|
+
return Math.min(1.1, Math.min(availW / elW, availH / elH));
|
|
4208
|
+
};
|
|
4209
|
+
const applyTransform = () => {
|
|
4210
|
+
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4211
|
+
wrapper.style.transformOrigin = "top center";
|
|
4212
|
+
};
|
|
4213
|
+
setTimeout(() => {
|
|
4214
|
+
scale = calculateFitScale();
|
|
4215
|
+
applyTransform();
|
|
4216
|
+
}, 60);
|
|
3822
4217
|
try {
|
|
3823
4218
|
if (typeof RTFJS__namespace.loggingEnabled === "function") {
|
|
3824
4219
|
RTFJS__namespace.loggingEnabled(false);
|
|
@@ -3834,14 +4229,31 @@ var RtfPlugin = class {
|
|
|
3834
4229
|
} catch (err) {
|
|
3835
4230
|
console.warn("[RtfPlugin] RTF render error, fallback text:", err);
|
|
3836
4231
|
const text = new TextDecoder("latin1").decode(ctx.buffer);
|
|
3837
|
-
const
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
4232
|
+
const rawPages = text.split(/\\page\b/).map((segment) => {
|
|
4233
|
+
return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
|
|
4234
|
+
}).filter((p) => p.length > 0);
|
|
4235
|
+
const pages = rawPages.length > 0 ? rawPages : [text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim()];
|
|
4236
|
+
for (let i = 0; i < pages.length; i++) {
|
|
4237
|
+
const pageCard = document.createElement("div");
|
|
4238
|
+
pageCard.className = "fp-rtf-page-card";
|
|
4239
|
+
pageCard.style.backgroundColor = "#ffffff";
|
|
4240
|
+
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4241
|
+
pageCard.style.borderRadius = "4px";
|
|
4242
|
+
pageCard.style.padding = "72px 56px";
|
|
4243
|
+
pageCard.style.width = "816px";
|
|
4244
|
+
pageCard.style.minHeight = "1056px";
|
|
4245
|
+
pageCard.style.maxWidth = "100%";
|
|
4246
|
+
pageCard.style.boxSizing = "border-box";
|
|
4247
|
+
pageCard.style.fontFamily = "serif";
|
|
4248
|
+
pageCard.style.fontSize = "12pt";
|
|
4249
|
+
pageCard.style.lineHeight = "1.6";
|
|
4250
|
+
pageCard.style.color = "#1e293b";
|
|
4251
|
+
pageCard.style.whiteSpace = "pre-wrap";
|
|
4252
|
+
pageCard.style.display = i === 0 ? "block" : "none";
|
|
4253
|
+
pageCard.textContent = pages[i];
|
|
4254
|
+
wrapper.appendChild(pageCard);
|
|
4255
|
+
pageElements.push(pageCard);
|
|
4256
|
+
}
|
|
3845
4257
|
}
|
|
3846
4258
|
const totalPages = Math.max(1, pageElements.length);
|
|
3847
4259
|
let currentPage = 1;
|
|
@@ -3895,21 +4307,30 @@ var RtfPlugin = class {
|
|
|
3895
4307
|
getCurrentPage: () => currentPage,
|
|
3896
4308
|
goToPage: (page) => showPage(page),
|
|
3897
4309
|
zoomIn: () => {
|
|
3898
|
-
scale += 0.
|
|
3899
|
-
|
|
4310
|
+
scale += 0.15;
|
|
4311
|
+
applyTransform();
|
|
3900
4312
|
},
|
|
3901
4313
|
zoomOut: () => {
|
|
3902
|
-
scale = Math.max(0.2, scale - 0.
|
|
3903
|
-
|
|
4314
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
4315
|
+
applyTransform();
|
|
3904
4316
|
},
|
|
3905
4317
|
getZoom: () => scale,
|
|
3906
4318
|
setZoom: (level) => {
|
|
3907
4319
|
scale = level;
|
|
3908
|
-
|
|
4320
|
+
applyTransform();
|
|
3909
4321
|
},
|
|
3910
4322
|
fitToPage: () => {
|
|
3911
|
-
scale =
|
|
3912
|
-
|
|
4323
|
+
scale = calculateFitScale();
|
|
4324
|
+
rotation = 0;
|
|
4325
|
+
applyTransform();
|
|
4326
|
+
},
|
|
4327
|
+
rotateCW: () => {
|
|
4328
|
+
rotation = (rotation + 90) % 360;
|
|
4329
|
+
applyTransform();
|
|
4330
|
+
},
|
|
4331
|
+
rotateCCW: () => {
|
|
4332
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
4333
|
+
applyTransform();
|
|
3913
4334
|
},
|
|
3914
4335
|
download: () => {
|
|
3915
4336
|
const blob = new Blob([ctx.buffer], { type: "application/rtf" });
|
|
@@ -3920,6 +4341,10 @@ var RtfPlugin = class {
|
|
|
3920
4341
|
a.click();
|
|
3921
4342
|
URL.revokeObjectURL(url);
|
|
3922
4343
|
},
|
|
4344
|
+
copy: () => {
|
|
4345
|
+
const text = wrapper.textContent || "";
|
|
4346
|
+
navigator.clipboard?.writeText(text);
|
|
4347
|
+
},
|
|
3923
4348
|
print: () => {
|
|
3924
4349
|
window.print();
|
|
3925
4350
|
}
|
|
@@ -3994,7 +4419,7 @@ var HtmlPreviewPlugin = class {
|
|
|
3994
4419
|
}
|
|
3995
4420
|
async render(ctx) {
|
|
3996
4421
|
const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
|
|
3997
|
-
const sanitized =
|
|
4422
|
+
const sanitized = DOMPurify6__default.default.sanitize(rawHtml, {
|
|
3998
4423
|
WHOLE_DOCUMENT: true,
|
|
3999
4424
|
ADD_TAGS: ["style", "link"],
|
|
4000
4425
|
ADD_ATTR: ["target", "rel"]
|
|
@@ -4137,11 +4562,19 @@ var OpenDocumentPlugin = class {
|
|
|
4137
4562
|
{
|
|
4138
4563
|
id: "fit-page",
|
|
4139
4564
|
icon: "fit-page",
|
|
4140
|
-
label: "Fit to Page",
|
|
4565
|
+
label: isPresentation ? "Fit to Slide" : "Fit to Page",
|
|
4141
4566
|
type: "button",
|
|
4142
4567
|
group: "zoom",
|
|
4143
4568
|
execute: () => instance.fitToPage?.()
|
|
4144
4569
|
},
|
|
4570
|
+
{
|
|
4571
|
+
id: "rotate-cw",
|
|
4572
|
+
icon: "rotate-cw",
|
|
4573
|
+
label: "Rotate",
|
|
4574
|
+
type: "button",
|
|
4575
|
+
group: "view",
|
|
4576
|
+
execute: () => instance.rotateCW?.()
|
|
4577
|
+
},
|
|
4145
4578
|
{
|
|
4146
4579
|
id: "download",
|
|
4147
4580
|
icon: "download",
|
|
@@ -4205,6 +4638,22 @@ var OpenDocumentPlugin = class {
|
|
|
4205
4638
|
container.appendChild(wrapper);
|
|
4206
4639
|
ctx.container.appendChild(container);
|
|
4207
4640
|
let scale = 1;
|
|
4641
|
+
let rotation = 0;
|
|
4642
|
+
const calculateFitScale = () => {
|
|
4643
|
+
const elW = wrapper.offsetWidth || 850;
|
|
4644
|
+
const elH = wrapper.offsetHeight || (isPresentation ? 540 : 1e3);
|
|
4645
|
+
const availW = Math.max(200, ctx.container.clientWidth - 48);
|
|
4646
|
+
const availH = Math.max(200, ctx.container.clientHeight - 80);
|
|
4647
|
+
return Math.min(1, Math.min(availW / elW, availH / elH));
|
|
4648
|
+
};
|
|
4649
|
+
const applyTransform = () => {
|
|
4650
|
+
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4651
|
+
wrapper.style.transformOrigin = "top center";
|
|
4652
|
+
};
|
|
4653
|
+
setTimeout(() => {
|
|
4654
|
+
scale = calculateFitScale();
|
|
4655
|
+
applyTransform();
|
|
4656
|
+
}, 60);
|
|
4208
4657
|
let currentPage = 1;
|
|
4209
4658
|
let totalPages = 1;
|
|
4210
4659
|
let slides = [];
|
|
@@ -4236,14 +4685,97 @@ var OpenDocumentPlugin = class {
|
|
|
4236
4685
|
wrapper.textContent = contentDoc.documentElement.textContent || "Formula content";
|
|
4237
4686
|
}
|
|
4238
4687
|
} else {
|
|
4239
|
-
wrapper.style.maxWidth = "
|
|
4240
|
-
wrapper.style.padding = "
|
|
4688
|
+
wrapper.style.maxWidth = "none";
|
|
4689
|
+
wrapper.style.padding = "0";
|
|
4241
4690
|
wrapper.style.minHeight = "100%";
|
|
4691
|
+
wrapper.style.backgroundColor = "transparent";
|
|
4692
|
+
wrapper.style.boxShadow = "none";
|
|
4693
|
+
wrapper.style.position = "relative";
|
|
4694
|
+
const dims = this.getPageDimensions(stylesDoc, contentDoc);
|
|
4242
4695
|
const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
|
|
4243
|
-
|
|
4244
|
-
|
|
4696
|
+
const tempDiv = document.createElement("div");
|
|
4697
|
+
tempDiv.style.width = `${dims.width - dims.marginLeft - dims.marginRight}px`;
|
|
4698
|
+
tempDiv.style.position = "absolute";
|
|
4699
|
+
tempDiv.style.visibility = "hidden";
|
|
4700
|
+
tempDiv.innerHTML = DOMPurify6__default.default.sanitize(bodyHtml, {
|
|
4701
|
+
ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub", "hr"],
|
|
4245
4702
|
ADD_ATTR: ["style", "colspan", "rowspan"]
|
|
4246
4703
|
});
|
|
4704
|
+
document.body.appendChild(tempDiv);
|
|
4705
|
+
const contentHeight = dims.height - dims.marginTop - dims.marginBottom;
|
|
4706
|
+
const pageElements = [[]];
|
|
4707
|
+
let currentHeight = 0;
|
|
4708
|
+
let currentPageIdx = 0;
|
|
4709
|
+
Array.from(tempDiv.children).forEach((child) => {
|
|
4710
|
+
const el = child;
|
|
4711
|
+
const style = el.getAttribute("style") || "";
|
|
4712
|
+
const isBreakBefore = style.includes("page-break-before: always");
|
|
4713
|
+
const isBreakAfter = style.includes("page-break-after: always");
|
|
4714
|
+
const isSoftBreak = el.classList.contains("odf-page-break");
|
|
4715
|
+
if (isBreakBefore) {
|
|
4716
|
+
if (pageElements[currentPageIdx].length > 0) {
|
|
4717
|
+
currentPageIdx++;
|
|
4718
|
+
pageElements.push([]);
|
|
4719
|
+
currentHeight = 0;
|
|
4720
|
+
}
|
|
4721
|
+
}
|
|
4722
|
+
const h = el.offsetHeight || 0;
|
|
4723
|
+
if (currentHeight + h > contentHeight && pageElements[currentPageIdx].length > 0 && !isSoftBreak) {
|
|
4724
|
+
currentPageIdx++;
|
|
4725
|
+
pageElements.push([]);
|
|
4726
|
+
currentHeight = 0;
|
|
4727
|
+
}
|
|
4728
|
+
if (!isSoftBreak) {
|
|
4729
|
+
pageElements[currentPageIdx].push(el.cloneNode(true));
|
|
4730
|
+
currentHeight += h;
|
|
4731
|
+
}
|
|
4732
|
+
if (isBreakAfter || isSoftBreak) {
|
|
4733
|
+
currentPageIdx++;
|
|
4734
|
+
pageElements.push([]);
|
|
4735
|
+
currentHeight = 0;
|
|
4736
|
+
}
|
|
4737
|
+
});
|
|
4738
|
+
document.body.removeChild(tempDiv);
|
|
4739
|
+
if (pageElements.length > 1 && pageElements[pageElements.length - 1].length === 0) {
|
|
4740
|
+
pageElements.pop();
|
|
4741
|
+
}
|
|
4742
|
+
totalPages = Math.max(1, pageElements.length);
|
|
4743
|
+
pageElements.forEach((elements, idx) => {
|
|
4744
|
+
const page = document.createElement("div");
|
|
4745
|
+
page.className = `fp-odt-page fp-odt-page-${idx + 1}`;
|
|
4746
|
+
page.style.width = `${dims.width}px`;
|
|
4747
|
+
page.style.minHeight = `${dims.height}px`;
|
|
4748
|
+
page.style.padding = `${dims.marginTop}px ${dims.marginRight}px ${dims.marginBottom}px ${dims.marginLeft}px`;
|
|
4749
|
+
page.style.margin = "0 auto";
|
|
4750
|
+
page.style.backgroundColor = "#ffffff";
|
|
4751
|
+
page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
4752
|
+
page.style.borderRadius = "4px";
|
|
4753
|
+
page.style.boxSizing = "border-box";
|
|
4754
|
+
page.style.display = idx === 0 ? "block" : "none";
|
|
4755
|
+
page.style.position = "absolute";
|
|
4756
|
+
page.style.top = "0";
|
|
4757
|
+
page.style.left = "50%";
|
|
4758
|
+
page.style.transform = "translateX(-50%)";
|
|
4759
|
+
elements.forEach((el) => page.appendChild(el));
|
|
4760
|
+
wrapper.appendChild(page);
|
|
4761
|
+
slides.push(page);
|
|
4762
|
+
});
|
|
4763
|
+
const pageIndicator = document.createElement("div");
|
|
4764
|
+
pageIndicator.className = "fp-odt-page-indicator";
|
|
4765
|
+
pageIndicator.style.position = "sticky";
|
|
4766
|
+
pageIndicator.style.bottom = "16px";
|
|
4767
|
+
pageIndicator.style.left = "50%";
|
|
4768
|
+
pageIndicator.style.transform = "translateX(-50%)";
|
|
4769
|
+
pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
|
4770
|
+
pageIndicator.style.color = "#fff";
|
|
4771
|
+
pageIndicator.style.padding = "6px 12px";
|
|
4772
|
+
pageIndicator.style.borderRadius = "16px";
|
|
4773
|
+
pageIndicator.style.fontSize = "12px";
|
|
4774
|
+
pageIndicator.style.zIndex = "100";
|
|
4775
|
+
pageIndicator.style.display = "inline-block";
|
|
4776
|
+
pageIndicator.style.width = "fit-content";
|
|
4777
|
+
pageIndicator.textContent = `Page 1 of ${totalPages}`;
|
|
4778
|
+
container.appendChild(pageIndicator);
|
|
4247
4779
|
}
|
|
4248
4780
|
const cleanup = () => {
|
|
4249
4781
|
imageUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
@@ -4252,32 +4784,45 @@ var OpenDocumentPlugin = class {
|
|
|
4252
4784
|
};
|
|
4253
4785
|
ctx.signal.addEventListener("abort", cleanup);
|
|
4254
4786
|
const goToPage = (page) => {
|
|
4255
|
-
if (
|
|
4787
|
+
if (page < 1 || page > totalPages) return;
|
|
4256
4788
|
currentPage = page;
|
|
4257
4789
|
slides.forEach((s, idx) => {
|
|
4258
4790
|
s.style.display = idx === page - 1 ? "block" : "none";
|
|
4259
4791
|
});
|
|
4792
|
+
const indicator = container.querySelector(".fp-odt-page-indicator");
|
|
4793
|
+
if (indicator) {
|
|
4794
|
+
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4795
|
+
}
|
|
4260
4796
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4261
4797
|
};
|
|
4262
4798
|
return {
|
|
4263
4799
|
destroy: cleanup,
|
|
4264
4800
|
isPresentation,
|
|
4265
4801
|
zoomIn: () => {
|
|
4266
|
-
scale += 0.
|
|
4267
|
-
|
|
4802
|
+
scale += 0.15;
|
|
4803
|
+
applyTransform();
|
|
4268
4804
|
},
|
|
4269
4805
|
zoomOut: () => {
|
|
4270
|
-
scale = Math.max(0.2, scale - 0.
|
|
4271
|
-
|
|
4806
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
4807
|
+
applyTransform();
|
|
4272
4808
|
},
|
|
4273
4809
|
getZoom: () => scale,
|
|
4274
4810
|
setZoom: (level) => {
|
|
4275
4811
|
scale = level;
|
|
4276
|
-
|
|
4812
|
+
applyTransform();
|
|
4277
4813
|
},
|
|
4278
4814
|
fitToPage: () => {
|
|
4279
|
-
scale =
|
|
4280
|
-
|
|
4815
|
+
scale = calculateFitScale();
|
|
4816
|
+
rotation = 0;
|
|
4817
|
+
applyTransform();
|
|
4818
|
+
},
|
|
4819
|
+
rotateCW: () => {
|
|
4820
|
+
rotation = (rotation + 90) % 360;
|
|
4821
|
+
applyTransform();
|
|
4822
|
+
},
|
|
4823
|
+
rotateCCW: () => {
|
|
4824
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
4825
|
+
applyTransform();
|
|
4281
4826
|
},
|
|
4282
4827
|
goToPage,
|
|
4283
4828
|
getPageCount: () => totalPages,
|
|
@@ -4316,6 +4861,43 @@ var OpenDocumentPlugin = class {
|
|
|
4316
4861
|
}
|
|
4317
4862
|
};
|
|
4318
4863
|
}
|
|
4864
|
+
getPageDimensions(stylesDoc, contentDoc) {
|
|
4865
|
+
let width = 850;
|
|
4866
|
+
let height = 1123;
|
|
4867
|
+
let marginTop = 48;
|
|
4868
|
+
let marginBottom = 48;
|
|
4869
|
+
let marginLeft = 48;
|
|
4870
|
+
let marginRight = 48;
|
|
4871
|
+
const parseUnit = (val) => {
|
|
4872
|
+
if (!val) return null;
|
|
4873
|
+
if (val.endsWith("cm")) return parseFloat(val) * 37.8;
|
|
4874
|
+
if (val.endsWith("mm")) return parseFloat(val) * 3.78;
|
|
4875
|
+
if (val.endsWith("in")) return parseFloat(val) * 96;
|
|
4876
|
+
if (val.endsWith("pt")) return parseFloat(val) * 1.33;
|
|
4877
|
+
if (val.endsWith("px")) return parseFloat(val);
|
|
4878
|
+
return parseFloat(val);
|
|
4879
|
+
};
|
|
4880
|
+
const docs = [stylesDoc, contentDoc].filter(Boolean);
|
|
4881
|
+
for (const doc of docs) {
|
|
4882
|
+
const pageLayout = doc.querySelector("page-layout-properties, [page-width]");
|
|
4883
|
+
if (pageLayout) {
|
|
4884
|
+
const w = parseUnit(pageLayout.getAttribute("fo:page-width") || pageLayout.getAttribute("page-width"));
|
|
4885
|
+
const h = parseUnit(pageLayout.getAttribute("fo:page-height") || pageLayout.getAttribute("page-height"));
|
|
4886
|
+
const mt = parseUnit(pageLayout.getAttribute("fo:margin-top") || pageLayout.getAttribute("margin-top"));
|
|
4887
|
+
const mb = parseUnit(pageLayout.getAttribute("fo:margin-bottom") || pageLayout.getAttribute("margin-bottom"));
|
|
4888
|
+
const ml = parseUnit(pageLayout.getAttribute("fo:margin-left") || pageLayout.getAttribute("margin-left"));
|
|
4889
|
+
const mr = parseUnit(pageLayout.getAttribute("fo:margin-right") || pageLayout.getAttribute("margin-right"));
|
|
4890
|
+
if (w !== null) width = w;
|
|
4891
|
+
if (h !== null) height = h;
|
|
4892
|
+
if (mt !== null) marginTop = mt;
|
|
4893
|
+
if (mb !== null) marginBottom = mb;
|
|
4894
|
+
if (ml !== null) marginLeft = ml;
|
|
4895
|
+
if (mr !== null) marginRight = mr;
|
|
4896
|
+
break;
|
|
4897
|
+
}
|
|
4898
|
+
}
|
|
4899
|
+
return { width, height, marginTop, marginBottom, marginLeft, marginRight };
|
|
4900
|
+
}
|
|
4319
4901
|
extractStyles(stylesDoc, contentDoc) {
|
|
4320
4902
|
const map = /* @__PURE__ */ new Map();
|
|
4321
4903
|
const styleNodes = [];
|
|
@@ -4338,14 +4920,21 @@ var OpenDocumentPlugin = class {
|
|
|
4338
4920
|
if (color) css += `color: ${color}; `;
|
|
4339
4921
|
if (size) css += `font-size: ${size}; `;
|
|
4340
4922
|
}
|
|
4341
|
-
|
|
4923
|
+
let paraProp = node.querySelector("paragraph-properties, [text-align]");
|
|
4924
|
+
if (!paraProp) {
|
|
4925
|
+
paraProp = Array.from(node.children).find((c) => c.tagName.includes("paragraph-properties")) || null;
|
|
4926
|
+
}
|
|
4342
4927
|
if (paraProp) {
|
|
4343
4928
|
const align = paraProp.getAttribute("fo:text-align") || paraProp.getAttribute("text-align");
|
|
4344
4929
|
const mt = paraProp.getAttribute("fo:margin-top") || paraProp.getAttribute("margin-top");
|
|
4345
4930
|
const mb = paraProp.getAttribute("fo:margin-bottom") || paraProp.getAttribute("margin-bottom");
|
|
4931
|
+
const breakBefore = paraProp.getAttribute("fo:break-before") || paraProp.getAttribute("break-before");
|
|
4932
|
+
const breakAfter = paraProp.getAttribute("fo:break-after") || paraProp.getAttribute("break-after");
|
|
4346
4933
|
if (align) css += `text-align: ${align}; `;
|
|
4347
4934
|
if (mt) css += `margin-top: ${mt}; `;
|
|
4348
4935
|
if (mb) css += `margin-bottom: ${mb}; `;
|
|
4936
|
+
if (breakBefore === "page") css += "page-break-before: always; ";
|
|
4937
|
+
if (breakAfter === "page") css += "page-break-after: always; ";
|
|
4349
4938
|
}
|
|
4350
4939
|
if (css) map.set(name, css);
|
|
4351
4940
|
}
|
|
@@ -4430,6 +5019,8 @@ var OpenDocumentPlugin = class {
|
|
|
4430
5019
|
result += " ";
|
|
4431
5020
|
} else if (tag === "line-break") {
|
|
4432
5021
|
result += "<br/>";
|
|
5022
|
+
} else if (tag === "soft-page-break") {
|
|
5023
|
+
result += '<hr class="odf-page-break" style="page-break-after: always; border: none; margin: 0; padding: 0; height: 0;" />';
|
|
4433
5024
|
} else {
|
|
4434
5025
|
result += el.textContent || "";
|
|
4435
5026
|
}
|
|
@@ -4547,6 +5138,14 @@ var DocPlugin = class {
|
|
|
4547
5138
|
group: "zoom",
|
|
4548
5139
|
execute: () => instance.fitToPage?.()
|
|
4549
5140
|
},
|
|
5141
|
+
{
|
|
5142
|
+
id: "rotate-cw",
|
|
5143
|
+
icon: "rotate-cw",
|
|
5144
|
+
label: "Rotate",
|
|
5145
|
+
type: "button",
|
|
5146
|
+
group: "view",
|
|
5147
|
+
execute: () => instance.rotateCW?.()
|
|
5148
|
+
},
|
|
4550
5149
|
{
|
|
4551
5150
|
id: "copy",
|
|
4552
5151
|
icon: "copy",
|
|
@@ -4582,20 +5181,9 @@ var DocPlugin = class {
|
|
|
4582
5181
|
container.style.overflow = "auto";
|
|
4583
5182
|
container.style.padding = "32px 16px";
|
|
4584
5183
|
container.style.backgroundColor = "#f1f5f9";
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
wrapper.style.margin = "0 auto";
|
|
4589
|
-
wrapper.style.backgroundColor = "#ffffff";
|
|
4590
|
-
wrapper.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4591
|
-
wrapper.style.borderRadius = "4px";
|
|
4592
|
-
wrapper.style.padding = "56px 48px";
|
|
4593
|
-
wrapper.style.minHeight = "100%";
|
|
4594
|
-
wrapper.style.transformOrigin = "top center";
|
|
4595
|
-
wrapper.style.transition = "transform 0.2s ease";
|
|
4596
|
-
wrapper.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4597
|
-
wrapper.style.color = "#1e293b";
|
|
4598
|
-
container.appendChild(wrapper);
|
|
5184
|
+
container.style.display = "flex";
|
|
5185
|
+
container.style.justifyContent = "center";
|
|
5186
|
+
container.style.alignItems = "flex-start";
|
|
4599
5187
|
ctx.container.appendChild(container);
|
|
4600
5188
|
let scale = 1;
|
|
4601
5189
|
let extractedRawText = "";
|
|
@@ -4622,21 +5210,27 @@ var DocPlugin = class {
|
|
|
4622
5210
|
const rawPages = this.splitIntoPages(extractedRawText);
|
|
4623
5211
|
const totalPages = Math.max(1, rawPages.length);
|
|
4624
5212
|
let currentPage = 1;
|
|
4625
|
-
wrapper.innerHTML = "";
|
|
4626
5213
|
const pageCards = [];
|
|
4627
5214
|
for (let i = 0; i < totalPages; i++) {
|
|
4628
5215
|
const pageCard = document.createElement("div");
|
|
4629
5216
|
pageCard.className = "fp-doc-page-card";
|
|
5217
|
+
pageCard.style.width = "816px";
|
|
5218
|
+
pageCard.style.height = "1056px";
|
|
4630
5219
|
pageCard.style.backgroundColor = "#ffffff";
|
|
4631
5220
|
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4632
5221
|
pageCard.style.borderRadius = "4px";
|
|
4633
|
-
pageCard.style.padding = "
|
|
4634
|
-
pageCard.style.
|
|
5222
|
+
pageCard.style.padding = "96px 72px";
|
|
5223
|
+
pageCard.style.boxSizing = "border-box";
|
|
5224
|
+
pageCard.style.overflow = "hidden";
|
|
4635
5225
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5226
|
+
pageCard.style.transformOrigin = "top center";
|
|
5227
|
+
pageCard.style.transition = "transform 0.2s ease";
|
|
5228
|
+
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
5229
|
+
pageCard.style.color = "#1e293b";
|
|
4636
5230
|
if (isFallback && i === 0) {
|
|
4637
5231
|
pageCard.innerHTML = `
|
|
4638
5232
|
<div style="border-bottom: 1px solid #e2e8f0; padding-bottom: 12px; margin-bottom: 24px;">
|
|
4639
|
-
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${
|
|
5233
|
+
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify6__default.default.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
|
|
4640
5234
|
<span style="font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 4px;">Legacy Word 97-2003 Binary Preview</span>
|
|
4641
5235
|
</div>
|
|
4642
5236
|
${this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document")}
|
|
@@ -4644,15 +5238,17 @@ var DocPlugin = class {
|
|
|
4644
5238
|
} else {
|
|
4645
5239
|
pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
|
|
4646
5240
|
}
|
|
4647
|
-
|
|
5241
|
+
container.appendChild(pageCard);
|
|
4648
5242
|
pageCards.push(pageCard);
|
|
4649
5243
|
}
|
|
4650
5244
|
let indicator = null;
|
|
4651
5245
|
if (totalPages > 1) {
|
|
4652
5246
|
indicator = document.createElement("div");
|
|
4653
5247
|
indicator.className = "fp-doc-page-indicator";
|
|
4654
|
-
indicator.style.position = "
|
|
5248
|
+
indicator.style.position = "fixed";
|
|
4655
5249
|
indicator.style.bottom = "16px";
|
|
5250
|
+
indicator.style.left = "50%";
|
|
5251
|
+
indicator.style.transform = "translateX(-50%)";
|
|
4656
5252
|
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4657
5253
|
indicator.style.backdropFilter = "blur(8px)";
|
|
4658
5254
|
indicator.style.color = "#f8fafc";
|
|
@@ -4666,17 +5262,25 @@ var DocPlugin = class {
|
|
|
4666
5262
|
indicator.style.userSelect = "none";
|
|
4667
5263
|
indicator.style.pointerEvents = "none";
|
|
4668
5264
|
indicator.style.textAlign = "center";
|
|
4669
|
-
indicator.style.width = "fit-content";
|
|
4670
|
-
indicator.style.margin = "16px auto 0";
|
|
4671
5265
|
container.appendChild(indicator);
|
|
4672
5266
|
}
|
|
5267
|
+
let rotation = 0;
|
|
5268
|
+
const applyTransform = () => {
|
|
5269
|
+
const activeCard = pageCards[currentPage - 1];
|
|
5270
|
+
if (activeCard) {
|
|
5271
|
+
activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5272
|
+
}
|
|
5273
|
+
};
|
|
4673
5274
|
const showPage = (pageNum) => {
|
|
4674
5275
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
card.style.display =
|
|
4678
|
-
|
|
4679
|
-
|
|
5276
|
+
pageCards.forEach((card, idx) => {
|
|
5277
|
+
if (idx + 1 === currentPage) {
|
|
5278
|
+
card.style.display = "block";
|
|
5279
|
+
card.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5280
|
+
} else {
|
|
5281
|
+
card.style.display = "none";
|
|
5282
|
+
}
|
|
5283
|
+
});
|
|
4680
5284
|
if (indicator) {
|
|
4681
5285
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4682
5286
|
}
|
|
@@ -4685,6 +5289,17 @@ var DocPlugin = class {
|
|
|
4685
5289
|
if (totalPages > 1) {
|
|
4686
5290
|
showPage(1);
|
|
4687
5291
|
}
|
|
5292
|
+
const calculateFitScale = () => {
|
|
5293
|
+
const elW = 816;
|
|
5294
|
+
const elH = 1056;
|
|
5295
|
+
const availW = Math.max(200, ctx.container.clientWidth - 48);
|
|
5296
|
+
const availH = Math.max(200, ctx.container.clientHeight - 80);
|
|
5297
|
+
return Math.min(1.1, Math.min(availW / elW, availH / elH));
|
|
5298
|
+
};
|
|
5299
|
+
setTimeout(() => {
|
|
5300
|
+
scale = calculateFitScale();
|
|
5301
|
+
applyTransform();
|
|
5302
|
+
}, 60);
|
|
4688
5303
|
const cleanup = () => {
|
|
4689
5304
|
indicator?.remove();
|
|
4690
5305
|
container.remove();
|
|
@@ -4697,21 +5312,30 @@ var DocPlugin = class {
|
|
|
4697
5312
|
getCurrentPage: () => currentPage,
|
|
4698
5313
|
goToPage: (page) => showPage(page),
|
|
4699
5314
|
zoomIn: () => {
|
|
4700
|
-
scale += 0.
|
|
4701
|
-
|
|
5315
|
+
scale += 0.15;
|
|
5316
|
+
applyTransform();
|
|
4702
5317
|
},
|
|
4703
5318
|
zoomOut: () => {
|
|
4704
|
-
scale = Math.max(0.2, scale - 0.
|
|
4705
|
-
|
|
5319
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
5320
|
+
applyTransform();
|
|
4706
5321
|
},
|
|
4707
5322
|
getZoom: () => scale,
|
|
4708
5323
|
setZoom: (level) => {
|
|
4709
5324
|
scale = level;
|
|
4710
|
-
|
|
5325
|
+
applyTransform();
|
|
4711
5326
|
},
|
|
4712
5327
|
fitToPage: () => {
|
|
4713
|
-
scale =
|
|
4714
|
-
|
|
5328
|
+
scale = calculateFitScale();
|
|
5329
|
+
rotation = 0;
|
|
5330
|
+
applyTransform();
|
|
5331
|
+
},
|
|
5332
|
+
rotateCW: () => {
|
|
5333
|
+
rotation = (rotation + 90) % 360;
|
|
5334
|
+
applyTransform();
|
|
5335
|
+
},
|
|
5336
|
+
rotateCCW: () => {
|
|
5337
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
5338
|
+
applyTransform();
|
|
4715
5339
|
},
|
|
4716
5340
|
copy: () => {
|
|
4717
5341
|
navigator.clipboard.writeText(extractedRawText);
|
|
@@ -4829,8 +5453,28 @@ var DocPlugin = class {
|
|
|
4829
5453
|
}
|
|
4830
5454
|
splitIntoPages(text) {
|
|
4831
5455
|
if (!text) return [""];
|
|
4832
|
-
const
|
|
4833
|
-
|
|
5456
|
+
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);
|
|
5457
|
+
if (explicitParts.length === 0) explicitParts.push(text);
|
|
5458
|
+
const maxLinesPerPage = 48;
|
|
5459
|
+
const finalPages = [];
|
|
5460
|
+
for (const part of explicitParts) {
|
|
5461
|
+
const lines = part.split(/\r?\n/);
|
|
5462
|
+
let currentLines = [];
|
|
5463
|
+
let count = 0;
|
|
5464
|
+
for (const line of lines) {
|
|
5465
|
+
currentLines.push(line);
|
|
5466
|
+
count++;
|
|
5467
|
+
if (count >= maxLinesPerPage) {
|
|
5468
|
+
finalPages.push(currentLines.join("\n"));
|
|
5469
|
+
currentLines = [];
|
|
5470
|
+
count = 0;
|
|
5471
|
+
}
|
|
5472
|
+
}
|
|
5473
|
+
if (currentLines.length > 0) {
|
|
5474
|
+
finalPages.push(currentLines.join("\n"));
|
|
5475
|
+
}
|
|
5476
|
+
}
|
|
5477
|
+
return finalPages.length > 0 ? finalPages : [text];
|
|
4834
5478
|
}
|
|
4835
5479
|
/**
|
|
4836
5480
|
* Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
|
|
@@ -4839,17 +5483,65 @@ var DocPlugin = class {
|
|
|
4839
5483
|
const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
|
|
4840
5484
|
let html = "";
|
|
4841
5485
|
let inList = false;
|
|
4842
|
-
|
|
4843
|
-
|
|
5486
|
+
let tableLines = [];
|
|
5487
|
+
const flushTable = () => {
|
|
5488
|
+
if (tableLines.length > 0) {
|
|
5489
|
+
html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
|
|
5490
|
+
for (const tLine of tableLines) {
|
|
5491
|
+
html += "<tr>";
|
|
5492
|
+
const cols = tLine.split(" ");
|
|
5493
|
+
for (const col of cols) {
|
|
5494
|
+
html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
|
|
5495
|
+
}
|
|
5496
|
+
html += "</tr>";
|
|
5497
|
+
}
|
|
5498
|
+
html += "</table>";
|
|
5499
|
+
tableLines = [];
|
|
5500
|
+
}
|
|
5501
|
+
};
|
|
5502
|
+
let i = 0;
|
|
5503
|
+
while (i < lines.length) {
|
|
5504
|
+
let line = lines[i];
|
|
5505
|
+
let tabCount = (line.match(/\t/g) || []).length;
|
|
5506
|
+
if (tabCount > 0) {
|
|
5507
|
+
let consecutiveTableLines = 1;
|
|
5508
|
+
let j = i + 1;
|
|
5509
|
+
while (j < lines.length) {
|
|
5510
|
+
const nextTabCount = (lines[j].match(/\t/g) || []).length;
|
|
5511
|
+
if (nextTabCount === tabCount) {
|
|
5512
|
+
consecutiveTableLines++;
|
|
5513
|
+
j++;
|
|
5514
|
+
} else {
|
|
5515
|
+
break;
|
|
5516
|
+
}
|
|
5517
|
+
}
|
|
5518
|
+
if (consecutiveTableLines >= 3) {
|
|
5519
|
+
if (inList) {
|
|
5520
|
+
html += "</ul>";
|
|
5521
|
+
inList = false;
|
|
5522
|
+
}
|
|
5523
|
+
tableLines = lines.slice(i, j);
|
|
5524
|
+
flushTable();
|
|
5525
|
+
i = j;
|
|
5526
|
+
continue;
|
|
5527
|
+
}
|
|
5528
|
+
}
|
|
5529
|
+
line = line.trim();
|
|
4844
5530
|
if (!line) {
|
|
4845
5531
|
if (inList) {
|
|
4846
5532
|
html += "</ul>";
|
|
4847
5533
|
inList = false;
|
|
4848
5534
|
}
|
|
5535
|
+
html += '<div style="height: 1.15em;"></div>';
|
|
5536
|
+
i++;
|
|
4849
5537
|
continue;
|
|
4850
5538
|
}
|
|
4851
|
-
if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line))
|
|
4852
|
-
|
|
5539
|
+
if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line)) {
|
|
5540
|
+
i++;
|
|
5541
|
+
continue;
|
|
5542
|
+
}
|
|
5543
|
+
if ((line.includes("Normal.dot") || line.includes("Microsoft Word") || line.includes("Times New Roman")) && line.length < 30) {
|
|
5544
|
+
i++;
|
|
4853
5545
|
continue;
|
|
4854
5546
|
}
|
|
4855
5547
|
if (line.length < 60 && !line.endsWith(".") && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#"))) {
|
|
@@ -4857,24 +5549,26 @@ var DocPlugin = class {
|
|
|
4857
5549
|
html += "</ul>";
|
|
4858
5550
|
inList = false;
|
|
4859
5551
|
}
|
|
4860
|
-
html += `<h2 style="font-size:
|
|
5552
|
+
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>`;
|
|
4861
5553
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
4862
5554
|
if (!inList) {
|
|
4863
5555
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
4864
5556
|
inList = true;
|
|
4865
5557
|
}
|
|
4866
5558
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
4867
|
-
html += `<li style="margin: 4px 0; line-height: 1.
|
|
5559
|
+
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6__default.default.sanitize(bulletText)}</li>`;
|
|
4868
5560
|
} else {
|
|
4869
5561
|
if (inList) {
|
|
4870
5562
|
html += "</ul>";
|
|
4871
5563
|
inList = false;
|
|
4872
5564
|
}
|
|
4873
|
-
html += `<p style="line-height: 1.
|
|
5565
|
+
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6__default.default.sanitize(line)}</p>`;
|
|
4874
5566
|
}
|
|
5567
|
+
i++;
|
|
4875
5568
|
}
|
|
4876
5569
|
if (inList) html += "</ul>";
|
|
4877
|
-
|
|
5570
|
+
flushTable();
|
|
5571
|
+
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6__default.default.sanitize(filename)})</p>`;
|
|
4878
5572
|
}
|
|
4879
5573
|
};
|
|
4880
5574
|
function docPlugin() {
|
|
@@ -4951,6 +5645,14 @@ var PptPlugin = class {
|
|
|
4951
5645
|
group: "zoom",
|
|
4952
5646
|
execute: () => instance.fitToPage?.()
|
|
4953
5647
|
},
|
|
5648
|
+
{
|
|
5649
|
+
id: "rotate-cw",
|
|
5650
|
+
icon: "rotate-cw",
|
|
5651
|
+
label: "Rotate",
|
|
5652
|
+
type: "button",
|
|
5653
|
+
group: "view",
|
|
5654
|
+
execute: () => instance.rotateCW?.()
|
|
5655
|
+
},
|
|
4954
5656
|
{
|
|
4955
5657
|
id: "download",
|
|
4956
5658
|
icon: "download",
|
|
@@ -4984,22 +5686,36 @@ var PptPlugin = class {
|
|
|
4984
5686
|
const slideCard = document.createElement("div");
|
|
4985
5687
|
slideCard.className = "fp-ppt-slide-card";
|
|
4986
5688
|
slideCard.style.width = "960px";
|
|
4987
|
-
slideCard.style.maxWidth = "
|
|
5689
|
+
slideCard.style.maxWidth = "calc(100% - 32px)";
|
|
5690
|
+
slideCard.style.maxHeight = "calc(100% - 48px)";
|
|
4988
5691
|
slideCard.style.aspectRatio = "16 / 9";
|
|
4989
5692
|
slideCard.style.backgroundColor = "#ffffff";
|
|
4990
5693
|
slideCard.style.boxShadow = "0 12px 40px rgba(0,0,0,0.35)";
|
|
4991
5694
|
slideCard.style.borderRadius = "8px";
|
|
4992
5695
|
slideCard.style.boxSizing = "border-box";
|
|
4993
5696
|
slideCard.style.position = "relative";
|
|
4994
|
-
slideCard.style.overflow = "hidden";
|
|
4995
|
-
slideCard.style.transformOrigin = "center center";
|
|
4996
5697
|
slideCard.style.transition = "transform 0.2s ease";
|
|
5698
|
+
slideCard.style.transformOrigin = "center center";
|
|
5699
|
+
slideCard.style.flexShrink = "0";
|
|
4997
5700
|
container.appendChild(slideCard);
|
|
4998
5701
|
ctx.container.appendChild(container);
|
|
4999
5702
|
let scale = 1;
|
|
5703
|
+
let rotation = 0;
|
|
5000
5704
|
let currentSlide = 1;
|
|
5001
5705
|
let slides = [];
|
|
5002
5706
|
const createdBlobUrls = [];
|
|
5707
|
+
const calculateFitScale = () => {
|
|
5708
|
+
const availW = Math.max(200, container.clientWidth - 48);
|
|
5709
|
+
const availH = Math.max(200, container.clientHeight - 72);
|
|
5710
|
+
return Math.min(1, Math.min(availW / 960, availH / 540));
|
|
5711
|
+
};
|
|
5712
|
+
const applyTransform = () => {
|
|
5713
|
+
slideCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5714
|
+
};
|
|
5715
|
+
setTimeout(() => {
|
|
5716
|
+
scale = calculateFitScale();
|
|
5717
|
+
applyTransform();
|
|
5718
|
+
}, 60);
|
|
5003
5719
|
try {
|
|
5004
5720
|
const cfbf = new CfbfReader(ctx.buffer);
|
|
5005
5721
|
const pptStream = cfbf.readStream("PowerPoint Document");
|
|
@@ -5030,7 +5746,7 @@ var PptPlugin = class {
|
|
|
5030
5746
|
if (s.pictureUrl) {
|
|
5031
5747
|
contentHtml = `
|
|
5032
5748
|
<div style="flex: 1; display: flex; justify-content: center; align-items: center; padding: 12px; overflow: hidden;">
|
|
5033
|
-
<img src="${s.pictureUrl}" alt="${
|
|
5749
|
+
<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;" />
|
|
5034
5750
|
</div>
|
|
5035
5751
|
`;
|
|
5036
5752
|
} else if (s.tableColumns.length > 0) {
|
|
@@ -5040,7 +5756,7 @@ var PptPlugin = class {
|
|
|
5040
5756
|
<table style="width: 100%; border-collapse: collapse; border: 1px solid #cbd5e1; border-radius: 6px; overflow: hidden; background: #ffffff;">
|
|
5041
5757
|
<thead>
|
|
5042
5758
|
<tr style="background: #e2e8f0; color: #1e293b; font-weight: 600; font-size: 14px;">
|
|
5043
|
-
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${
|
|
5759
|
+
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${DOMPurify6__default.default.sanitize(c)}</th>`).join("")}
|
|
5044
5760
|
</tr>
|
|
5045
5761
|
</thead>
|
|
5046
5762
|
<tbody>
|
|
@@ -5056,7 +5772,7 @@ var PptPlugin = class {
|
|
|
5056
5772
|
} else {
|
|
5057
5773
|
const pTags = s.paragraphs.map((p) => {
|
|
5058
5774
|
const lines = p.split(/[\r\n]+/).map((l) => l.trim()).filter(Boolean);
|
|
5059
|
-
return lines.map((l) => `<p style="margin: 0 0 14px; font-size: 14px; line-height: 1.65; color: #334155; text-align: justify;">${
|
|
5775
|
+
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("");
|
|
5060
5776
|
}).join("");
|
|
5061
5777
|
contentHtml = `
|
|
5062
5778
|
<div style="flex: 1; overflow: auto; padding: 4px 8px; display: flex; flex-direction: column; justify-content: flex-start;">
|
|
@@ -5069,11 +5785,11 @@ var PptPlugin = class {
|
|
|
5069
5785
|
<!-- Header Banner matching PowerPoint design -->
|
|
5070
5786
|
<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;">
|
|
5071
5787
|
<h1 style="margin: 0; font-size: 26px; font-weight: 700; color: #1e293b; letter-spacing: -0.3px;">
|
|
5072
|
-
${
|
|
5788
|
+
${DOMPurify6__default.default.sanitize(s.title)}
|
|
5073
5789
|
</h1>
|
|
5074
5790
|
${s.subtitle ? `
|
|
5075
5791
|
<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);">
|
|
5076
|
-
${
|
|
5792
|
+
${DOMPurify6__default.default.sanitize(s.subtitle)}
|
|
5077
5793
|
</span>
|
|
5078
5794
|
` : `
|
|
5079
5795
|
<span style="font-size: 12px; color: #365314; font-weight: 600;">
|
|
@@ -5100,21 +5816,30 @@ var PptPlugin = class {
|
|
|
5100
5816
|
return {
|
|
5101
5817
|
destroy: cleanup,
|
|
5102
5818
|
zoomIn: () => {
|
|
5103
|
-
scale += 0.
|
|
5104
|
-
|
|
5819
|
+
scale += 0.15;
|
|
5820
|
+
applyTransform();
|
|
5105
5821
|
},
|
|
5106
5822
|
zoomOut: () => {
|
|
5107
|
-
scale = Math.max(0.
|
|
5108
|
-
|
|
5823
|
+
scale = Math.max(0.2, scale - 0.15);
|
|
5824
|
+
applyTransform();
|
|
5109
5825
|
},
|
|
5110
5826
|
getZoom: () => scale,
|
|
5111
5827
|
setZoom: (level) => {
|
|
5112
5828
|
scale = level;
|
|
5113
|
-
|
|
5829
|
+
applyTransform();
|
|
5114
5830
|
},
|
|
5115
5831
|
fitToPage: () => {
|
|
5116
|
-
scale =
|
|
5117
|
-
|
|
5832
|
+
scale = calculateFitScale();
|
|
5833
|
+
rotation = 0;
|
|
5834
|
+
applyTransform();
|
|
5835
|
+
},
|
|
5836
|
+
rotateCW: () => {
|
|
5837
|
+
rotation = (rotation + 90) % 360;
|
|
5838
|
+
applyTransform();
|
|
5839
|
+
},
|
|
5840
|
+
rotateCCW: () => {
|
|
5841
|
+
rotation = (rotation - 90 + 360) % 360;
|
|
5842
|
+
applyTransform();
|
|
5118
5843
|
},
|
|
5119
5844
|
goToPage: (page) => {
|
|
5120
5845
|
if (page >= 1 && page <= totalSlides) {
|