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