@files-preview-app/preview-file 1.2.6 → 1.2.8
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 +665 -200
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.js +664 -199
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +666 -201
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +665 -200
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +665 -200
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +664 -199
- package/dist/react.js.map +1 -1
- package/dist/vue.cjs +665 -200
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +664 -199
- package/dist/vue.js.map +1 -1
- package/package.json +179 -169
package/dist/vue.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineComponent, ref, onMounted, watch, onBeforeUnmount, h } from 'vue';
|
|
2
|
-
import
|
|
2
|
+
import DOMPurify6 from 'dompurify';
|
|
3
3
|
import * as pdfjsLib from 'pdfjs-dist';
|
|
4
4
|
import * as docx from 'docx-preview';
|
|
5
5
|
import { unzipSync, strFromU8, unzip } from 'fflate';
|
|
@@ -357,7 +357,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
357
357
|
if (magicMime === "application/zip") {
|
|
358
358
|
const ooxmlMime = detectOoxmlType(buffer);
|
|
359
359
|
if (ooxmlMime && ooxmlMime !== "application/zip") {
|
|
360
|
-
metadata.mimeType = ooxmlMime;
|
|
360
|
+
metadata.mimeType = metadata.mimeType ?? ooxmlMime;
|
|
361
361
|
if (ooxmlMime.includes("wordprocessing")) metadata.extension = metadata.extension ?? ".docx";
|
|
362
362
|
else if (ooxmlMime.includes("spreadsheet")) metadata.extension = metadata.extension ?? ".xlsx";
|
|
363
363
|
else if (ooxmlMime.includes("presentation")) metadata.extension = metadata.extension ?? ".pptx";
|
|
@@ -386,7 +386,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
386
386
|
return { buffer, metadata };
|
|
387
387
|
}
|
|
388
388
|
function sanitizeSVG(svg) {
|
|
389
|
-
return
|
|
389
|
+
return DOMPurify6.sanitize(svg, {
|
|
390
390
|
USE_PROFILES: { svg: true, svgFilters: true }
|
|
391
391
|
});
|
|
392
392
|
}
|
|
@@ -433,7 +433,8 @@ function createElement(tag, attrs, ...children) {
|
|
|
433
433
|
}
|
|
434
434
|
var ICON_ZOOM_IN = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><line x1="11" y1="8" x2="11" y2="14"></line><line x1="8" y1="11" x2="14" y2="11"></line></svg>`;
|
|
435
435
|
var ICON_ZOOM_OUT = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><line x1="8" y1="11" x2="14" y2="11"></line></svg>`;
|
|
436
|
-
var ICON_FIT_PAGE = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><
|
|
436
|
+
var ICON_FIT_PAGE = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"></rect><line x1="8" y1="12" x2="16" y2="12"></line><polyline points="11 9 8 12 11 15"></polyline><polyline points="13 9 16 12 13 15"></polyline></svg>`;
|
|
437
|
+
var ICON_FIT_WIDTH = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="2" y1="12" x2="22" y2="12"></line><polyline points="5 9 2 12 5 15"></polyline><polyline points="19 9 22 12 19 15"></polyline><line x1="2" y1="5" x2="2" y2="19"></line><line x1="22" y1="5" x2="22" y2="19"></line></svg>`;
|
|
437
438
|
var ICON_ROTATE_CW = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"></polyline><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path></svg>`;
|
|
438
439
|
var ICON_ROTATE_CCW = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"></polyline><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path></svg>`;
|
|
439
440
|
var ICON_DOWNLOAD = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>`;
|
|
@@ -453,6 +454,7 @@ var ICON_MAP = {
|
|
|
453
454
|
"zoom-in": ICON_ZOOM_IN,
|
|
454
455
|
"zoom-out": ICON_ZOOM_OUT,
|
|
455
456
|
"fit-page": ICON_FIT_PAGE,
|
|
457
|
+
"fit-width": ICON_FIT_WIDTH,
|
|
456
458
|
"fit-slide": ICON_FIT_PAGE,
|
|
457
459
|
"rotate-cw": ICON_ROTATE_CW,
|
|
458
460
|
"rotate-ccw": ICON_ROTATE_CCW,
|
|
@@ -1399,6 +1401,7 @@ var PdfPlugin = class {
|
|
|
1399
1401
|
let currentPage = 1;
|
|
1400
1402
|
let zoomScale = 1;
|
|
1401
1403
|
let rotation = 0;
|
|
1404
|
+
let fitMode = "width";
|
|
1402
1405
|
let currentRenderTask = null;
|
|
1403
1406
|
const renderPage = async (pageNum) => {
|
|
1404
1407
|
if (currentRenderTask) {
|
|
@@ -1418,11 +1421,16 @@ var PdfPlugin = class {
|
|
|
1418
1421
|
const containerWidth = container.clientWidth || 900;
|
|
1419
1422
|
const containerHeight = container.clientHeight || 700;
|
|
1420
1423
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1421
|
-
const availWidth = Math.max(
|
|
1422
|
-
const availHeight = Math.max(
|
|
1424
|
+
const availWidth = Math.max(280, containerWidth - 48);
|
|
1425
|
+
const availHeight = Math.max(280, containerHeight - 88);
|
|
1423
1426
|
const scaleW = availWidth / unscaledVp.width;
|
|
1424
1427
|
const scaleH = availHeight / unscaledVp.height;
|
|
1425
|
-
|
|
1428
|
+
let fitScale;
|
|
1429
|
+
if (fitMode === "page") {
|
|
1430
|
+
fitScale = Math.max(0.5, Math.min(scaleW, scaleH));
|
|
1431
|
+
} else {
|
|
1432
|
+
fitScale = Math.max(0.65, Math.min(1.15, scaleW));
|
|
1433
|
+
}
|
|
1426
1434
|
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1427
1435
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
1428
1436
|
const viewport = page.getViewport({ scale: effectiveScale, rotation });
|
|
@@ -1448,7 +1456,19 @@ var PdfPlugin = class {
|
|
|
1448
1456
|
}
|
|
1449
1457
|
};
|
|
1450
1458
|
await renderPage(1);
|
|
1459
|
+
let resizeTimer = null;
|
|
1460
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
1461
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1462
|
+
resizeTimer = setTimeout(() => {
|
|
1463
|
+
if (Math.abs(zoomScale - 1) < 0.05) {
|
|
1464
|
+
renderPage(currentPage);
|
|
1465
|
+
}
|
|
1466
|
+
}, 150);
|
|
1467
|
+
});
|
|
1468
|
+
resizeObserver.observe(container);
|
|
1451
1469
|
const cleanup = () => {
|
|
1470
|
+
resizeObserver.disconnect();
|
|
1471
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1452
1472
|
if (currentRenderTask) {
|
|
1453
1473
|
try {
|
|
1454
1474
|
currentRenderTask.cancel();
|
|
@@ -1479,6 +1499,7 @@ var PdfPlugin = class {
|
|
|
1479
1499
|
renderPage(currentPage);
|
|
1480
1500
|
},
|
|
1481
1501
|
fitToPage: () => {
|
|
1502
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
1482
1503
|
zoomScale = 1;
|
|
1483
1504
|
rotation = 0;
|
|
1484
1505
|
renderPage(currentPage);
|
|
@@ -2032,8 +2053,53 @@ var DocxPlugin = class {
|
|
|
2032
2053
|
}
|
|
2033
2054
|
}
|
|
2034
2055
|
}
|
|
2035
|
-
|
|
2036
|
-
const cards = wrapper.querySelectorAll(".fp-docx-page-card");
|
|
2056
|
+
let sections = Array.from(wrapper.querySelectorAll("section.docx"));
|
|
2057
|
+
const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
|
|
2058
|
+
if (sections.length === 1 && cards.length === 0) {
|
|
2059
|
+
const singleSec = sections[0];
|
|
2060
|
+
const pageH = 1056;
|
|
2061
|
+
const secH = singleSec.offsetHeight || singleSec.scrollHeight;
|
|
2062
|
+
if (secH > pageH * 1.25) {
|
|
2063
|
+
const children = Array.from(singleSec.children);
|
|
2064
|
+
if (children.length > 1) {
|
|
2065
|
+
const parent = singleSec.parentElement || wrapper;
|
|
2066
|
+
const newSections = [singleSec];
|
|
2067
|
+
singleSec.innerHTML = "";
|
|
2068
|
+
singleSec.style.minHeight = `${pageH}px`;
|
|
2069
|
+
singleSec.style.maxHeight = `${pageH}px`;
|
|
2070
|
+
singleSec.style.overflow = "hidden";
|
|
2071
|
+
singleSec.style.boxSizing = "border-box";
|
|
2072
|
+
let curSec = singleSec;
|
|
2073
|
+
let curH = 0;
|
|
2074
|
+
const maxH = pageH - 96;
|
|
2075
|
+
for (let i = 0; i < children.length; i++) {
|
|
2076
|
+
const child = children[i];
|
|
2077
|
+
curSec.appendChild(child);
|
|
2078
|
+
const chH = child.offsetHeight || 28;
|
|
2079
|
+
curH += chH;
|
|
2080
|
+
if (curH >= maxH && i < children.length - 1) {
|
|
2081
|
+
const nextSec = document.createElement("section");
|
|
2082
|
+
nextSec.className = singleSec.className;
|
|
2083
|
+
nextSec.style.cssText = singleSec.style.cssText;
|
|
2084
|
+
nextSec.style.width = singleSec.style.width || "816px";
|
|
2085
|
+
nextSec.style.minHeight = `${pageH}px`;
|
|
2086
|
+
nextSec.style.maxHeight = `${pageH}px`;
|
|
2087
|
+
nextSec.style.overflow = "hidden";
|
|
2088
|
+
nextSec.style.boxSizing = "border-box";
|
|
2089
|
+
nextSec.style.backgroundColor = "#ffffff";
|
|
2090
|
+
nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
|
|
2091
|
+
nextSec.style.borderRadius = "4px";
|
|
2092
|
+
nextSec.style.marginBottom = "24px";
|
|
2093
|
+
parent.appendChild(nextSec);
|
|
2094
|
+
newSections.push(nextSec);
|
|
2095
|
+
curSec = nextSec;
|
|
2096
|
+
curH = 0;
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
sections = newSections;
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
}
|
|
2037
2103
|
const pageElements = sections.length > 0 ? sections : cards;
|
|
2038
2104
|
const totalPages = Math.max(1, pageElements.length);
|
|
2039
2105
|
let currentPage = 1;
|
|
@@ -2077,22 +2143,27 @@ var DocxPlugin = class {
|
|
|
2077
2143
|
}
|
|
2078
2144
|
scale = 1;
|
|
2079
2145
|
let rotation = 0;
|
|
2080
|
-
|
|
2146
|
+
let fitMode = "width";
|
|
2147
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
2081
2148
|
const activeEl = pageElements[currentPage - 1] || wrapper.firstElementChild || wrapper;
|
|
2082
2149
|
const elW = activeEl.offsetWidth || 816;
|
|
2083
|
-
const
|
|
2084
|
-
const availW = Math.max(
|
|
2085
|
-
const availH = Math.max(
|
|
2150
|
+
const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
2151
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
2152
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
2086
2153
|
const sW = availW / elW;
|
|
2087
|
-
const sH = availH /
|
|
2088
|
-
|
|
2154
|
+
const sH = availH / singlePageH;
|
|
2155
|
+
if (mode === "page") {
|
|
2156
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
2157
|
+
}
|
|
2158
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
2089
2159
|
};
|
|
2090
2160
|
const applyTransform = () => {
|
|
2091
2161
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
2092
2162
|
wrapper.style.transformOrigin = "top center";
|
|
2093
2163
|
};
|
|
2094
2164
|
setTimeout(() => {
|
|
2095
|
-
|
|
2165
|
+
fitMode = "width";
|
|
2166
|
+
scale = calculateFitScale("width");
|
|
2096
2167
|
applyTransform();
|
|
2097
2168
|
}, 60);
|
|
2098
2169
|
const cleanup = () => {
|
|
@@ -2126,7 +2197,8 @@ var DocxPlugin = class {
|
|
|
2126
2197
|
applyTransform();
|
|
2127
2198
|
},
|
|
2128
2199
|
fitToPage: () => {
|
|
2129
|
-
|
|
2200
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
2201
|
+
scale = calculateFitScale(fitMode);
|
|
2130
2202
|
rotation = 0;
|
|
2131
2203
|
applyTransform();
|
|
2132
2204
|
},
|
|
@@ -2196,90 +2268,149 @@ var DocxPlugin = class {
|
|
|
2196
2268
|
console.warn("[DocxPlugin] Error parsing relationships:", relsErr);
|
|
2197
2269
|
}
|
|
2198
2270
|
}
|
|
2199
|
-
const
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2271
|
+
const sectPrs = Array.from(doc.getElementsByTagNameNS("*", "sectPr"));
|
|
2272
|
+
const lastSectPr = sectPrs[sectPrs.length - 1];
|
|
2273
|
+
let defaultW = 12240;
|
|
2274
|
+
let defaultH = 15840;
|
|
2275
|
+
let margins = { top: 1440, right: 1440, bottom: 1440, left: 1440 };
|
|
2276
|
+
if (lastSectPr) {
|
|
2277
|
+
const pgSz = lastSectPr.getElementsByTagNameNS("*", "pgSz")[0];
|
|
2278
|
+
if (pgSz) {
|
|
2279
|
+
defaultW = parseInt(pgSz.getAttribute("w:w") || pgSz.getAttribute("w") || "12240", 10);
|
|
2280
|
+
defaultH = parseInt(pgSz.getAttribute("w:h") || pgSz.getAttribute("h") || "15840", 10);
|
|
2281
|
+
}
|
|
2282
|
+
const pgMar = lastSectPr.getElementsByTagNameNS("*", "pgMar")[0];
|
|
2283
|
+
if (pgMar) {
|
|
2284
|
+
margins.top = parseInt(pgMar.getAttribute("w:top") || pgMar.getAttribute("top") || "1440", 10);
|
|
2285
|
+
margins.bottom = parseInt(pgMar.getAttribute("w:bottom") || pgMar.getAttribute("bottom") || "1440", 10);
|
|
2286
|
+
margins.left = parseInt(pgMar.getAttribute("w:left") || pgMar.getAttribute("left") || "1440", 10);
|
|
2287
|
+
margins.right = parseInt(pgMar.getAttribute("w:right") || pgMar.getAttribute("right") || "1440", 10);
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
const createPageCard = () => {
|
|
2291
|
+
const card = document.createElement("div");
|
|
2292
|
+
card.className = "fp-docx-page-card";
|
|
2293
|
+
card.style.backgroundColor = "#ffffff";
|
|
2294
|
+
card.style.borderRadius = "4px";
|
|
2295
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
2296
|
+
card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2297
|
+
card.style.color = "#1e293b";
|
|
2298
|
+
card.style.lineHeight = "1.6";
|
|
2299
|
+
card.style.boxSizing = "border-box";
|
|
2300
|
+
card.style.overflow = "hidden";
|
|
2301
|
+
card.style.position = "relative";
|
|
2302
|
+
card.style.marginBottom = "24px";
|
|
2303
|
+
card.style.width = `${defaultW / 15}px`;
|
|
2304
|
+
card.style.height = `${defaultH / 15}px`;
|
|
2305
|
+
card.style.padding = `${margins.top / 15}px ${margins.right / 15}px ${margins.bottom / 15}px ${margins.left / 15}px`;
|
|
2306
|
+
return card;
|
|
2307
|
+
};
|
|
2308
|
+
let currentCard = createPageCard();
|
|
2309
|
+
let currentHtml = "";
|
|
2310
|
+
const pages = [{ card: currentCard, html: "" }];
|
|
2311
|
+
const flushHtml = () => {
|
|
2312
|
+
pages[pages.length - 1].html += currentHtml;
|
|
2313
|
+
currentHtml = "";
|
|
2314
|
+
};
|
|
2315
|
+
const newPage = () => {
|
|
2316
|
+
flushHtml();
|
|
2317
|
+
currentCard = createPageCard();
|
|
2318
|
+
pages.push({ card: currentCard, html: "" });
|
|
2319
|
+
};
|
|
2208
2320
|
const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
|
|
2209
|
-
let html = "";
|
|
2210
2321
|
for (const child of Array.from(body.children)) {
|
|
2211
2322
|
const tag = child.localName || child.nodeName.split(":").pop();
|
|
2212
2323
|
if (tag === "p") {
|
|
2213
2324
|
const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
|
|
2214
2325
|
const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
|
|
2215
2326
|
const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
|
|
2216
|
-
const
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2327
|
+
const chunks = this.extractParagraphChunks(child, imageMap);
|
|
2328
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
2329
|
+
if (i > 0) {
|
|
2330
|
+
newPage();
|
|
2331
|
+
}
|
|
2332
|
+
const textContent = chunks[i];
|
|
2333
|
+
if (!textContent.trim() && !textContent.includes("<img")) {
|
|
2334
|
+
currentHtml += '<div style="height: 10px;"></div>';
|
|
2335
|
+
continue;
|
|
2336
|
+
}
|
|
2337
|
+
const lowerStyle = styleVal.toLowerCase();
|
|
2338
|
+
if (lowerStyle.includes("title")) {
|
|
2339
|
+
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>`;
|
|
2340
|
+
} else if (lowerStyle.includes("heading1") || styleVal === "1") {
|
|
2341
|
+
currentHtml += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
|
|
2342
|
+
} else if (lowerStyle.includes("heading2") || styleVal === "2") {
|
|
2343
|
+
currentHtml += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
|
|
2344
|
+
} else if (lowerStyle.includes("heading3") || styleVal === "3") {
|
|
2345
|
+
currentHtml += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
|
|
2346
|
+
} else if (numPr) {
|
|
2347
|
+
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>`;
|
|
2348
|
+
} else {
|
|
2349
|
+
currentHtml += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
|
|
2350
|
+
}
|
|
2234
2351
|
}
|
|
2235
2352
|
} else if (tag === "tbl") {
|
|
2236
|
-
|
|
2353
|
+
currentHtml += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
|
|
2237
2354
|
const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
|
|
2238
2355
|
rows.forEach((tr, rIdx) => {
|
|
2239
|
-
|
|
2356
|
+
currentHtml += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
2240
2357
|
const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
|
|
2241
2358
|
cells.forEach((tc) => {
|
|
2242
2359
|
const cellText = this.extractParagraphHtml(tc, imageMap);
|
|
2243
|
-
|
|
2360
|
+
currentHtml += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || " "}</td>`;
|
|
2244
2361
|
});
|
|
2245
|
-
|
|
2362
|
+
currentHtml += "</tr>";
|
|
2246
2363
|
});
|
|
2247
|
-
|
|
2364
|
+
currentHtml += "</table>";
|
|
2248
2365
|
}
|
|
2249
2366
|
}
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2367
|
+
flushHtml();
|
|
2368
|
+
for (const page of pages) {
|
|
2369
|
+
page.card.innerHTML = DOMPurify6.sanitize(page.html, {
|
|
2370
|
+
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
|
|
2371
|
+
ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
|
|
2372
|
+
});
|
|
2373
|
+
wrapper.appendChild(page.card);
|
|
2374
|
+
}
|
|
2255
2375
|
}
|
|
2256
2376
|
extractParagraphHtml(pElement, imageMap = {}) {
|
|
2257
|
-
|
|
2377
|
+
return this.extractParagraphChunks(pElement, imageMap).join("<br/>");
|
|
2378
|
+
}
|
|
2379
|
+
extractParagraphChunks(pElement, imageMap = {}) {
|
|
2380
|
+
const chunks = [""];
|
|
2381
|
+
let currentChunkIndex = 0;
|
|
2258
2382
|
const drawings = Array.from(pElement.getElementsByTagNameNS("*", "drawing"));
|
|
2259
2383
|
for (const drawing of drawings) {
|
|
2260
2384
|
const blip = drawing.getElementsByTagNameNS("*", "blip")[0];
|
|
2261
2385
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2262
2386
|
if (rId && imageMap[rId]) {
|
|
2263
|
-
|
|
2387
|
+
chunks[currentChunkIndex] += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
|
|
2264
2388
|
}
|
|
2265
2389
|
}
|
|
2266
2390
|
const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
|
|
2267
|
-
if (runs.length === 0 && !
|
|
2268
|
-
|
|
2391
|
+
if (runs.length === 0 && !chunks[currentChunkIndex]) {
|
|
2392
|
+
chunks[currentChunkIndex] = DOMPurify6.sanitize(pElement.textContent || "");
|
|
2393
|
+
return chunks;
|
|
2269
2394
|
}
|
|
2270
2395
|
for (const r of runs) {
|
|
2271
2396
|
const blip = r.getElementsByTagNameNS("*", "blip")[0] || r.getElementsByTagNameNS("*", "imagedata")[0];
|
|
2272
2397
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2273
2398
|
if (rId && imageMap[rId]) {
|
|
2274
|
-
|
|
2399
|
+
chunks[currentChunkIndex] += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
|
|
2275
2400
|
}
|
|
2276
|
-
const brs = r.getElementsByTagNameNS("*", "br");
|
|
2277
|
-
for (
|
|
2278
|
-
|
|
2401
|
+
const brs = Array.from(r.getElementsByTagNameNS("*", "br"));
|
|
2402
|
+
for (const br of brs) {
|
|
2403
|
+
const type = br.getAttribute("w:type") || br.getAttribute("type");
|
|
2404
|
+
if (type === "page") {
|
|
2405
|
+
chunks.push("");
|
|
2406
|
+
currentChunkIndex++;
|
|
2407
|
+
} else {
|
|
2408
|
+
chunks[currentChunkIndex] += "<br/>";
|
|
2409
|
+
}
|
|
2279
2410
|
}
|
|
2280
2411
|
const tabs = r.getElementsByTagNameNS("*", "tab");
|
|
2281
2412
|
if (tabs.length > 0) {
|
|
2282
|
-
|
|
2413
|
+
chunks[currentChunkIndex] += " ";
|
|
2283
2414
|
}
|
|
2284
2415
|
const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
|
|
2285
2416
|
const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
|
|
@@ -2293,7 +2424,7 @@ var DocxPlugin = class {
|
|
|
2293
2424
|
const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
|
|
2294
2425
|
let text = texts.map((t) => t.textContent || "").join("");
|
|
2295
2426
|
if (!text) continue;
|
|
2296
|
-
text =
|
|
2427
|
+
text = DOMPurify6.sanitize(text);
|
|
2297
2428
|
let styles = "";
|
|
2298
2429
|
if (isBold) styles += "font-weight: bold; ";
|
|
2299
2430
|
if (isItalic) styles += "font-style: italic; ";
|
|
@@ -2305,12 +2436,12 @@ var DocxPlugin = class {
|
|
|
2305
2436
|
if (!isNaN(pt) && pt > 0) styles += `font-size: ${pt}pt; `;
|
|
2306
2437
|
}
|
|
2307
2438
|
if (styles) {
|
|
2308
|
-
|
|
2439
|
+
chunks[currentChunkIndex] += `<span style="${styles}">${text}</span>`;
|
|
2309
2440
|
} else {
|
|
2310
|
-
|
|
2441
|
+
chunks[currentChunkIndex] += text;
|
|
2311
2442
|
}
|
|
2312
2443
|
}
|
|
2313
|
-
return
|
|
2444
|
+
return chunks;
|
|
2314
2445
|
}
|
|
2315
2446
|
renderBinaryDocFallback(ctx, wrapper) {
|
|
2316
2447
|
const card = document.createElement("div");
|
|
@@ -2327,14 +2458,14 @@ var DocxPlugin = class {
|
|
|
2327
2458
|
const wordDocStream = cfbf.readStream("WordDocument");
|
|
2328
2459
|
if (wordDocStream && wordDocStream.length >= 512) {
|
|
2329
2460
|
const text2 = this.extractReadableStrings(wordDocStream);
|
|
2330
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2461
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6.sanitize(text2)}</div>`;
|
|
2331
2462
|
wrapper.appendChild(card);
|
|
2332
2463
|
return;
|
|
2333
2464
|
}
|
|
2334
2465
|
} catch {
|
|
2335
2466
|
}
|
|
2336
2467
|
const text = this.extractReadableStrings(new Uint8Array(ctx.buffer));
|
|
2337
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2468
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6.sanitize(text)}</div>`;
|
|
2338
2469
|
wrapper.appendChild(card);
|
|
2339
2470
|
}
|
|
2340
2471
|
extractReadableStrings(bytes) {
|
|
@@ -2511,11 +2642,9 @@ var ExcelPlugin = class {
|
|
|
2511
2642
|
const calculateFitScale = () => {
|
|
2512
2643
|
const table = contentArea.querySelector("table");
|
|
2513
2644
|
if (!table) return 1;
|
|
2514
|
-
const availW = Math.max(
|
|
2515
|
-
const availH = Math.max(200, container.clientHeight - 80);
|
|
2645
|
+
const availW = Math.max(280, container.clientWidth - 48);
|
|
2516
2646
|
const tW = table.offsetWidth || 800;
|
|
2517
|
-
|
|
2518
|
-
return Math.min(1, Math.min(availW / tW, availH / tH));
|
|
2647
|
+
return Math.max(0.65, Math.min(1, availW / tW));
|
|
2519
2648
|
};
|
|
2520
2649
|
try {
|
|
2521
2650
|
wb = XLSX.read(new Uint8Array(ctx.buffer), { type: "array", cellDates: true });
|
|
@@ -2933,41 +3062,94 @@ var CodePlugin = class {
|
|
|
2933
3062
|
async render(ctx) {
|
|
2934
3063
|
const decoder = new TextDecoder("utf-8");
|
|
2935
3064
|
const fullText = decoder.decode(ctx.buffer);
|
|
2936
|
-
const
|
|
2937
|
-
const
|
|
3065
|
+
const extRaw = ctx.metadata.extension?.toLowerCase();
|
|
3066
|
+
const mimeRaw = ctx.metadata.mimeType?.toLowerCase();
|
|
3067
|
+
const isTxt = extRaw === ".txt" || mimeRaw === "text/plain" && (!extRaw || !this.extensions.filter((e) => e !== ".txt").includes(extRaw));
|
|
3068
|
+
let rawPages = [];
|
|
3069
|
+
if (isTxt) {
|
|
3070
|
+
const explicitPages = fullText.split(/(?:\f|\x0C)/);
|
|
3071
|
+
for (const ep of explicitPages) {
|
|
3072
|
+
const lines = ep.split(/\r?\n/);
|
|
3073
|
+
let currentChunk = [];
|
|
3074
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3075
|
+
currentChunk.push(lines[i]);
|
|
3076
|
+
if (currentChunk.length >= 46) {
|
|
3077
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3078
|
+
currentChunk = [];
|
|
3079
|
+
}
|
|
3080
|
+
}
|
|
3081
|
+
if (currentChunk.length > 0 || lines.length === 0) {
|
|
3082
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
if (rawPages.length === 0) rawPages = [""];
|
|
3086
|
+
} else {
|
|
3087
|
+
const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
|
|
3088
|
+
rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
3089
|
+
}
|
|
2938
3090
|
const totalPages = Math.max(1, rawPages.length);
|
|
2939
3091
|
let currentPage = 1;
|
|
2940
3092
|
const container = document.createElement("div");
|
|
2941
3093
|
container.style.width = "100%";
|
|
2942
3094
|
container.style.height = "100%";
|
|
2943
3095
|
container.style.overflow = "auto";
|
|
2944
|
-
container.style.backgroundColor = "#1e1e1e";
|
|
2945
|
-
container.style.color = "#d4d4d4";
|
|
2946
|
-
container.style.padding = "16px";
|
|
2947
|
-
container.style.boxSizing = "border-box";
|
|
2948
3096
|
let fontSize = 13;
|
|
2949
3097
|
let rotation = 0;
|
|
3098
|
+
let zoomLevel = 1;
|
|
2950
3099
|
const pre = document.createElement("pre");
|
|
2951
|
-
pre.style.margin = "0";
|
|
2952
|
-
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
2953
|
-
pre.style.fontSize = `${fontSize}px`;
|
|
2954
|
-
pre.style.lineHeight = "1.5";
|
|
2955
|
-
pre.style.whiteSpace = "pre-wrap";
|
|
2956
|
-
pre.style.wordBreak = "break-all";
|
|
2957
3100
|
const code = document.createElement("code");
|
|
3101
|
+
if (isTxt) {
|
|
3102
|
+
container.style.backgroundColor = "#f1f5f9";
|
|
3103
|
+
container.style.padding = "32px";
|
|
3104
|
+
container.style.boxSizing = "border-box";
|
|
3105
|
+
container.style.display = "flex";
|
|
3106
|
+
container.style.flexDirection = "column";
|
|
3107
|
+
container.style.alignItems = "center";
|
|
3108
|
+
pre.style.margin = "0";
|
|
3109
|
+
pre.style.fontFamily = "Consolas, 'Courier New', monospace";
|
|
3110
|
+
pre.style.fontSize = "13px";
|
|
3111
|
+
pre.style.color = "#1e293b";
|
|
3112
|
+
pre.style.lineHeight = "1.5";
|
|
3113
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3114
|
+
pre.style.wordBreak = "break-word";
|
|
3115
|
+
pre.style.backgroundColor = "#ffffff";
|
|
3116
|
+
pre.style.width = "816px";
|
|
3117
|
+
pre.style.minHeight = "1056px";
|
|
3118
|
+
pre.style.padding = "72px 56px";
|
|
3119
|
+
pre.style.boxSizing = "border-box";
|
|
3120
|
+
pre.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)";
|
|
3121
|
+
pre.style.borderRadius = "4px";
|
|
3122
|
+
pre.style.transformOrigin = "top center";
|
|
3123
|
+
} else {
|
|
3124
|
+
container.style.backgroundColor = "#1e1e1e";
|
|
3125
|
+
container.style.color = "#d4d4d4";
|
|
3126
|
+
container.style.padding = "16px";
|
|
3127
|
+
container.style.boxSizing = "border-box";
|
|
3128
|
+
pre.style.margin = "0";
|
|
3129
|
+
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
3130
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3131
|
+
pre.style.lineHeight = "1.5";
|
|
3132
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3133
|
+
pre.style.wordBreak = "break-all";
|
|
3134
|
+
pre.style.transformOrigin = "top left";
|
|
3135
|
+
}
|
|
2958
3136
|
const ext = (ctx.metadata.extension || "").replace(".", "");
|
|
2959
3137
|
const renderCodePage = (text) => {
|
|
2960
|
-
|
|
2961
|
-
if (ext && hljs.getLanguage(ext)) {
|
|
2962
|
-
code.innerHTML = hljs.highlight(text, { language: ext }).value;
|
|
2963
|
-
} else {
|
|
2964
|
-
code.innerHTML = hljs.highlightAuto(text).value;
|
|
2965
|
-
}
|
|
2966
|
-
} catch {
|
|
3138
|
+
if (isTxt) {
|
|
2967
3139
|
code.textContent = text;
|
|
3140
|
+
} else {
|
|
3141
|
+
try {
|
|
3142
|
+
if (ext && hljs.getLanguage(ext)) {
|
|
3143
|
+
code.innerHTML = hljs.highlight(text, { language: ext }).value;
|
|
3144
|
+
} else {
|
|
3145
|
+
code.innerHTML = hljs.highlightAuto(text).value;
|
|
3146
|
+
}
|
|
3147
|
+
} catch {
|
|
3148
|
+
code.textContent = text;
|
|
3149
|
+
}
|
|
2968
3150
|
}
|
|
2969
3151
|
};
|
|
2970
|
-
renderCodePage(rawPages[0] || fullText);
|
|
3152
|
+
renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
|
|
2971
3153
|
pre.appendChild(code);
|
|
2972
3154
|
container.appendChild(pre);
|
|
2973
3155
|
let indicator = null;
|
|
@@ -2976,15 +3158,22 @@ var CodePlugin = class {
|
|
|
2976
3158
|
indicator.className = "fp-code-page-indicator";
|
|
2977
3159
|
indicator.style.position = "sticky";
|
|
2978
3160
|
indicator.style.bottom = "16px";
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
3161
|
+
if (isTxt) {
|
|
3162
|
+
indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
3163
|
+
indicator.style.color = "#334155";
|
|
3164
|
+
indicator.style.border = "1px solid #e2e8f0";
|
|
3165
|
+
indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
|
|
3166
|
+
} else {
|
|
3167
|
+
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3168
|
+
indicator.style.color = "#f8fafc";
|
|
3169
|
+
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3170
|
+
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3171
|
+
indicator.style.backdropFilter = "blur(8px)";
|
|
3172
|
+
}
|
|
2982
3173
|
indicator.style.fontSize = "12px";
|
|
2983
3174
|
indicator.style.fontWeight = "600";
|
|
2984
3175
|
indicator.style.padding = "5px 14px";
|
|
2985
3176
|
indicator.style.borderRadius = "20px";
|
|
2986
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
2987
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
2988
3177
|
indicator.style.zIndex = "10";
|
|
2989
3178
|
indicator.style.userSelect = "none";
|
|
2990
3179
|
indicator.style.pointerEvents = "none";
|
|
@@ -2995,7 +3184,7 @@ var CodePlugin = class {
|
|
|
2995
3184
|
}
|
|
2996
3185
|
const showPage = (pageNum) => {
|
|
2997
3186
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
2998
|
-
renderCodePage(rawPages[currentPage - 1] || fullText);
|
|
3187
|
+
renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
|
|
2999
3188
|
if (indicator) {
|
|
3000
3189
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
3001
3190
|
}
|
|
@@ -3011,39 +3200,57 @@ var CodePlugin = class {
|
|
|
3011
3200
|
ctx.container.innerHTML = "";
|
|
3012
3201
|
};
|
|
3013
3202
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3203
|
+
const updateTransform = () => {
|
|
3204
|
+
if (isTxt) {
|
|
3205
|
+
pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
|
|
3206
|
+
} else {
|
|
3207
|
+
pre.style.transform = `rotate(${rotation}deg)`;
|
|
3208
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3209
|
+
}
|
|
3210
|
+
};
|
|
3014
3211
|
return {
|
|
3015
3212
|
destroy: cleanup,
|
|
3016
3213
|
getPageCount: () => totalPages,
|
|
3017
3214
|
getCurrentPage: () => currentPage,
|
|
3018
3215
|
goToPage: (page) => showPage(page),
|
|
3019
3216
|
zoomIn: () => {
|
|
3020
|
-
|
|
3021
|
-
|
|
3217
|
+
if (isTxt) {
|
|
3218
|
+
zoomLevel = Math.min(3, zoomLevel + 0.1);
|
|
3219
|
+
} else {
|
|
3220
|
+
fontSize = Math.min(32, fontSize + 2);
|
|
3221
|
+
}
|
|
3222
|
+
updateTransform();
|
|
3022
3223
|
},
|
|
3023
3224
|
zoomOut: () => {
|
|
3024
|
-
|
|
3025
|
-
|
|
3225
|
+
if (isTxt) {
|
|
3226
|
+
zoomLevel = Math.max(0.1, zoomLevel - 0.1);
|
|
3227
|
+
} else {
|
|
3228
|
+
fontSize = Math.max(8, fontSize - 2);
|
|
3229
|
+
}
|
|
3230
|
+
updateTransform();
|
|
3026
3231
|
},
|
|
3027
|
-
getZoom: () => fontSize / 13,
|
|
3232
|
+
getZoom: () => isTxt ? zoomLevel : fontSize / 13,
|
|
3028
3233
|
setZoom: (level) => {
|
|
3029
|
-
|
|
3030
|
-
|
|
3234
|
+
if (isTxt) {
|
|
3235
|
+
zoomLevel = level;
|
|
3236
|
+
} else {
|
|
3237
|
+
fontSize = Math.round(13 * level);
|
|
3238
|
+
}
|
|
3239
|
+
updateTransform();
|
|
3031
3240
|
},
|
|
3032
3241
|
fitToPage: () => {
|
|
3033
3242
|
fontSize = 13;
|
|
3034
3243
|
rotation = 0;
|
|
3035
|
-
|
|
3036
|
-
|
|
3244
|
+
zoomLevel = isTxt ? Math.max(0.65, Math.min(1.05, (container.clientWidth - 48) / 816)) : 1;
|
|
3245
|
+
updateTransform();
|
|
3037
3246
|
},
|
|
3038
3247
|
rotateCW: () => {
|
|
3039
3248
|
rotation = (rotation + 90) % 360;
|
|
3040
|
-
|
|
3041
|
-
pre.style.transformOrigin = "top left";
|
|
3249
|
+
updateTransform();
|
|
3042
3250
|
},
|
|
3043
3251
|
rotateCCW: () => {
|
|
3044
3252
|
rotation = (rotation - 90 + 360) % 360;
|
|
3045
|
-
|
|
3046
|
-
pre.style.transformOrigin = "top left";
|
|
3253
|
+
updateTransform();
|
|
3047
3254
|
},
|
|
3048
3255
|
download: () => {
|
|
3049
3256
|
const mimeType = ctx.metadata.mimeType || "text/plain";
|
|
@@ -3342,7 +3549,7 @@ var MarkdownPlugin = class {
|
|
|
3342
3549
|
gfm: true,
|
|
3343
3550
|
breaks: true
|
|
3344
3551
|
});
|
|
3345
|
-
const cleanHtml =
|
|
3552
|
+
const cleanHtml = DOMPurify6.sanitize(rawHtml, {
|
|
3346
3553
|
USE_PROFILES: { html: true }
|
|
3347
3554
|
});
|
|
3348
3555
|
const wrapper = document.createElement("div");
|
|
@@ -3978,6 +4185,14 @@ var RtfPlugin = class {
|
|
|
3978
4185
|
group: "actions",
|
|
3979
4186
|
execute: () => instance.download?.()
|
|
3980
4187
|
},
|
|
4188
|
+
{
|
|
4189
|
+
id: "copy",
|
|
4190
|
+
icon: "copy",
|
|
4191
|
+
label: "Copy Text",
|
|
4192
|
+
type: "button",
|
|
4193
|
+
group: "actions",
|
|
4194
|
+
execute: () => instance.copy?.()
|
|
4195
|
+
},
|
|
3981
4196
|
{
|
|
3982
4197
|
id: "print",
|
|
3983
4198
|
icon: "print",
|
|
@@ -4008,20 +4223,27 @@ var RtfPlugin = class {
|
|
|
4008
4223
|
let scale = 1;
|
|
4009
4224
|
let rotation = 0;
|
|
4010
4225
|
let pageElements = [];
|
|
4011
|
-
|
|
4226
|
+
let fitMode = "width";
|
|
4227
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
4012
4228
|
const activeEl = pageElements[currentPage - 1] || wrapper;
|
|
4013
4229
|
const elW = activeEl.offsetWidth || 850;
|
|
4014
|
-
const
|
|
4015
|
-
const availW = Math.max(
|
|
4016
|
-
const availH = Math.max(
|
|
4017
|
-
|
|
4230
|
+
const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
4231
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
4232
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
4233
|
+
const sW = availW / elW;
|
|
4234
|
+
const sH = availH / singlePageH;
|
|
4235
|
+
if (mode === "page") {
|
|
4236
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
4237
|
+
}
|
|
4238
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
4018
4239
|
};
|
|
4019
4240
|
const applyTransform = () => {
|
|
4020
4241
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4021
4242
|
wrapper.style.transformOrigin = "top center";
|
|
4022
4243
|
};
|
|
4023
4244
|
setTimeout(() => {
|
|
4024
|
-
|
|
4245
|
+
fitMode = "width";
|
|
4246
|
+
scale = calculateFitScale("width");
|
|
4025
4247
|
applyTransform();
|
|
4026
4248
|
}, 60);
|
|
4027
4249
|
try {
|
|
@@ -4039,14 +4261,31 @@ var RtfPlugin = class {
|
|
|
4039
4261
|
} catch (err) {
|
|
4040
4262
|
console.warn("[RtfPlugin] RTF render error, fallback text:", err);
|
|
4041
4263
|
const text = new TextDecoder("latin1").decode(ctx.buffer);
|
|
4042
|
-
const
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4264
|
+
const rawPages = text.split(/\\page\b/).map((segment) => {
|
|
4265
|
+
return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
|
|
4266
|
+
}).filter((p) => p.length > 0);
|
|
4267
|
+
const pages = rawPages.length > 0 ? rawPages : [text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim()];
|
|
4268
|
+
for (let i = 0; i < pages.length; i++) {
|
|
4269
|
+
const pageCard = document.createElement("div");
|
|
4270
|
+
pageCard.className = "fp-rtf-page-card";
|
|
4271
|
+
pageCard.style.backgroundColor = "#ffffff";
|
|
4272
|
+
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4273
|
+
pageCard.style.borderRadius = "4px";
|
|
4274
|
+
pageCard.style.padding = "72px 56px";
|
|
4275
|
+
pageCard.style.width = "816px";
|
|
4276
|
+
pageCard.style.minHeight = "1056px";
|
|
4277
|
+
pageCard.style.maxWidth = "100%";
|
|
4278
|
+
pageCard.style.boxSizing = "border-box";
|
|
4279
|
+
pageCard.style.fontFamily = "serif";
|
|
4280
|
+
pageCard.style.fontSize = "12pt";
|
|
4281
|
+
pageCard.style.lineHeight = "1.6";
|
|
4282
|
+
pageCard.style.color = "#1e293b";
|
|
4283
|
+
pageCard.style.whiteSpace = "pre-wrap";
|
|
4284
|
+
pageCard.style.display = i === 0 ? "block" : "none";
|
|
4285
|
+
pageCard.textContent = pages[i];
|
|
4286
|
+
wrapper.appendChild(pageCard);
|
|
4287
|
+
pageElements.push(pageCard);
|
|
4288
|
+
}
|
|
4050
4289
|
}
|
|
4051
4290
|
const totalPages = Math.max(1, pageElements.length);
|
|
4052
4291
|
let currentPage = 1;
|
|
@@ -4113,7 +4352,8 @@ var RtfPlugin = class {
|
|
|
4113
4352
|
applyTransform();
|
|
4114
4353
|
},
|
|
4115
4354
|
fitToPage: () => {
|
|
4116
|
-
|
|
4355
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
4356
|
+
scale = calculateFitScale(fitMode);
|
|
4117
4357
|
rotation = 0;
|
|
4118
4358
|
applyTransform();
|
|
4119
4359
|
},
|
|
@@ -4134,6 +4374,10 @@ var RtfPlugin = class {
|
|
|
4134
4374
|
a.click();
|
|
4135
4375
|
URL.revokeObjectURL(url);
|
|
4136
4376
|
},
|
|
4377
|
+
copy: () => {
|
|
4378
|
+
const text = wrapper.textContent || "";
|
|
4379
|
+
navigator.clipboard?.writeText(text);
|
|
4380
|
+
},
|
|
4137
4381
|
print: () => {
|
|
4138
4382
|
window.print();
|
|
4139
4383
|
}
|
|
@@ -4208,7 +4452,7 @@ var HtmlPreviewPlugin = class {
|
|
|
4208
4452
|
}
|
|
4209
4453
|
async render(ctx) {
|
|
4210
4454
|
const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
|
|
4211
|
-
const sanitized =
|
|
4455
|
+
const sanitized = DOMPurify6.sanitize(rawHtml, {
|
|
4212
4456
|
WHOLE_DOCUMENT: true,
|
|
4213
4457
|
ADD_TAGS: ["style", "link"],
|
|
4214
4458
|
ADD_ATTR: ["target", "rel"]
|
|
@@ -4428,19 +4672,29 @@ var OpenDocumentPlugin = class {
|
|
|
4428
4672
|
ctx.container.appendChild(container);
|
|
4429
4673
|
let scale = 1;
|
|
4430
4674
|
let rotation = 0;
|
|
4431
|
-
|
|
4675
|
+
let fitMode = "width";
|
|
4676
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
4432
4677
|
const elW = wrapper.offsetWidth || 850;
|
|
4433
|
-
const
|
|
4434
|
-
const availW = Math.max(
|
|
4435
|
-
const availH = Math.max(
|
|
4436
|
-
|
|
4678
|
+
const singlePageH = Math.min(wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
4679
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
4680
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
4681
|
+
const sW = availW / elW;
|
|
4682
|
+
const sH = availH / (isPresentation ? 540 : singlePageH);
|
|
4683
|
+
if (isPresentation) {
|
|
4684
|
+
return Math.min(1, Math.min(sW, sH));
|
|
4685
|
+
}
|
|
4686
|
+
if (mode === "page") {
|
|
4687
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
4688
|
+
}
|
|
4689
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
4437
4690
|
};
|
|
4438
4691
|
const applyTransform = () => {
|
|
4439
4692
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4440
4693
|
wrapper.style.transformOrigin = "top center";
|
|
4441
4694
|
};
|
|
4442
4695
|
setTimeout(() => {
|
|
4443
|
-
|
|
4696
|
+
fitMode = "width";
|
|
4697
|
+
scale = calculateFitScale("width");
|
|
4444
4698
|
applyTransform();
|
|
4445
4699
|
}, 60);
|
|
4446
4700
|
let currentPage = 1;
|
|
@@ -4474,14 +4728,97 @@ var OpenDocumentPlugin = class {
|
|
|
4474
4728
|
wrapper.textContent = contentDoc.documentElement.textContent || "Formula content";
|
|
4475
4729
|
}
|
|
4476
4730
|
} else {
|
|
4477
|
-
wrapper.style.maxWidth = "
|
|
4478
|
-
wrapper.style.padding = "
|
|
4731
|
+
wrapper.style.maxWidth = "none";
|
|
4732
|
+
wrapper.style.padding = "0";
|
|
4479
4733
|
wrapper.style.minHeight = "100%";
|
|
4734
|
+
wrapper.style.backgroundColor = "transparent";
|
|
4735
|
+
wrapper.style.boxShadow = "none";
|
|
4736
|
+
wrapper.style.position = "relative";
|
|
4737
|
+
const dims = this.getPageDimensions(stylesDoc, contentDoc);
|
|
4480
4738
|
const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
|
|
4481
|
-
|
|
4482
|
-
|
|
4739
|
+
const tempDiv = document.createElement("div");
|
|
4740
|
+
tempDiv.style.width = `${dims.width - dims.marginLeft - dims.marginRight}px`;
|
|
4741
|
+
tempDiv.style.position = "absolute";
|
|
4742
|
+
tempDiv.style.visibility = "hidden";
|
|
4743
|
+
tempDiv.innerHTML = DOMPurify6.sanitize(bodyHtml, {
|
|
4744
|
+
ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub", "hr"],
|
|
4483
4745
|
ADD_ATTR: ["style", "colspan", "rowspan"]
|
|
4484
4746
|
});
|
|
4747
|
+
document.body.appendChild(tempDiv);
|
|
4748
|
+
const contentHeight = dims.height - dims.marginTop - dims.marginBottom;
|
|
4749
|
+
const pageElements = [[]];
|
|
4750
|
+
let currentHeight = 0;
|
|
4751
|
+
let currentPageIdx = 0;
|
|
4752
|
+
Array.from(tempDiv.children).forEach((child) => {
|
|
4753
|
+
const el = child;
|
|
4754
|
+
const style = el.getAttribute("style") || "";
|
|
4755
|
+
const isBreakBefore = style.includes("page-break-before: always");
|
|
4756
|
+
const isBreakAfter = style.includes("page-break-after: always");
|
|
4757
|
+
const isSoftBreak = el.classList.contains("odf-page-break");
|
|
4758
|
+
if (isBreakBefore) {
|
|
4759
|
+
if (pageElements[currentPageIdx].length > 0) {
|
|
4760
|
+
currentPageIdx++;
|
|
4761
|
+
pageElements.push([]);
|
|
4762
|
+
currentHeight = 0;
|
|
4763
|
+
}
|
|
4764
|
+
}
|
|
4765
|
+
const h2 = el.offsetHeight || 0;
|
|
4766
|
+
if (currentHeight + h2 > contentHeight && pageElements[currentPageIdx].length > 0 && !isSoftBreak) {
|
|
4767
|
+
currentPageIdx++;
|
|
4768
|
+
pageElements.push([]);
|
|
4769
|
+
currentHeight = 0;
|
|
4770
|
+
}
|
|
4771
|
+
if (!isSoftBreak) {
|
|
4772
|
+
pageElements[currentPageIdx].push(el.cloneNode(true));
|
|
4773
|
+
currentHeight += h2;
|
|
4774
|
+
}
|
|
4775
|
+
if (isBreakAfter || isSoftBreak) {
|
|
4776
|
+
currentPageIdx++;
|
|
4777
|
+
pageElements.push([]);
|
|
4778
|
+
currentHeight = 0;
|
|
4779
|
+
}
|
|
4780
|
+
});
|
|
4781
|
+
document.body.removeChild(tempDiv);
|
|
4782
|
+
if (pageElements.length > 1 && pageElements[pageElements.length - 1].length === 0) {
|
|
4783
|
+
pageElements.pop();
|
|
4784
|
+
}
|
|
4785
|
+
totalPages = Math.max(1, pageElements.length);
|
|
4786
|
+
pageElements.forEach((elements, idx) => {
|
|
4787
|
+
const page = document.createElement("div");
|
|
4788
|
+
page.className = `fp-odt-page fp-odt-page-${idx + 1}`;
|
|
4789
|
+
page.style.width = `${dims.width}px`;
|
|
4790
|
+
page.style.minHeight = `${dims.height}px`;
|
|
4791
|
+
page.style.padding = `${dims.marginTop}px ${dims.marginRight}px ${dims.marginBottom}px ${dims.marginLeft}px`;
|
|
4792
|
+
page.style.margin = "0 auto";
|
|
4793
|
+
page.style.backgroundColor = "#ffffff";
|
|
4794
|
+
page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
4795
|
+
page.style.borderRadius = "4px";
|
|
4796
|
+
page.style.boxSizing = "border-box";
|
|
4797
|
+
page.style.display = idx === 0 ? "block" : "none";
|
|
4798
|
+
page.style.position = "absolute";
|
|
4799
|
+
page.style.top = "0";
|
|
4800
|
+
page.style.left = "50%";
|
|
4801
|
+
page.style.transform = "translateX(-50%)";
|
|
4802
|
+
elements.forEach((el) => page.appendChild(el));
|
|
4803
|
+
wrapper.appendChild(page);
|
|
4804
|
+
slides.push(page);
|
|
4805
|
+
});
|
|
4806
|
+
const pageIndicator = document.createElement("div");
|
|
4807
|
+
pageIndicator.className = "fp-odt-page-indicator";
|
|
4808
|
+
pageIndicator.style.position = "sticky";
|
|
4809
|
+
pageIndicator.style.bottom = "16px";
|
|
4810
|
+
pageIndicator.style.left = "50%";
|
|
4811
|
+
pageIndicator.style.transform = "translateX(-50%)";
|
|
4812
|
+
pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
|
4813
|
+
pageIndicator.style.color = "#fff";
|
|
4814
|
+
pageIndicator.style.padding = "6px 12px";
|
|
4815
|
+
pageIndicator.style.borderRadius = "16px";
|
|
4816
|
+
pageIndicator.style.fontSize = "12px";
|
|
4817
|
+
pageIndicator.style.zIndex = "100";
|
|
4818
|
+
pageIndicator.style.display = "inline-block";
|
|
4819
|
+
pageIndicator.style.width = "fit-content";
|
|
4820
|
+
pageIndicator.textContent = `Page 1 of ${totalPages}`;
|
|
4821
|
+
container.appendChild(pageIndicator);
|
|
4485
4822
|
}
|
|
4486
4823
|
const cleanup = () => {
|
|
4487
4824
|
imageUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
@@ -4490,11 +4827,15 @@ var OpenDocumentPlugin = class {
|
|
|
4490
4827
|
};
|
|
4491
4828
|
ctx.signal.addEventListener("abort", cleanup);
|
|
4492
4829
|
const goToPage = (page) => {
|
|
4493
|
-
if (
|
|
4830
|
+
if (page < 1 || page > totalPages) return;
|
|
4494
4831
|
currentPage = page;
|
|
4495
4832
|
slides.forEach((s, idx) => {
|
|
4496
4833
|
s.style.display = idx === page - 1 ? "block" : "none";
|
|
4497
4834
|
});
|
|
4835
|
+
const indicator = container.querySelector(".fp-odt-page-indicator");
|
|
4836
|
+
if (indicator) {
|
|
4837
|
+
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4838
|
+
}
|
|
4498
4839
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4499
4840
|
};
|
|
4500
4841
|
return {
|
|
@@ -4514,7 +4855,8 @@ var OpenDocumentPlugin = class {
|
|
|
4514
4855
|
applyTransform();
|
|
4515
4856
|
},
|
|
4516
4857
|
fitToPage: () => {
|
|
4517
|
-
|
|
4858
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
4859
|
+
scale = calculateFitScale(fitMode);
|
|
4518
4860
|
rotation = 0;
|
|
4519
4861
|
applyTransform();
|
|
4520
4862
|
},
|
|
@@ -4563,6 +4905,43 @@ var OpenDocumentPlugin = class {
|
|
|
4563
4905
|
}
|
|
4564
4906
|
};
|
|
4565
4907
|
}
|
|
4908
|
+
getPageDimensions(stylesDoc, contentDoc) {
|
|
4909
|
+
let width = 850;
|
|
4910
|
+
let height = 1123;
|
|
4911
|
+
let marginTop = 48;
|
|
4912
|
+
let marginBottom = 48;
|
|
4913
|
+
let marginLeft = 48;
|
|
4914
|
+
let marginRight = 48;
|
|
4915
|
+
const parseUnit = (val) => {
|
|
4916
|
+
if (!val) return null;
|
|
4917
|
+
if (val.endsWith("cm")) return parseFloat(val) * 37.8;
|
|
4918
|
+
if (val.endsWith("mm")) return parseFloat(val) * 3.78;
|
|
4919
|
+
if (val.endsWith("in")) return parseFloat(val) * 96;
|
|
4920
|
+
if (val.endsWith("pt")) return parseFloat(val) * 1.33;
|
|
4921
|
+
if (val.endsWith("px")) return parseFloat(val);
|
|
4922
|
+
return parseFloat(val);
|
|
4923
|
+
};
|
|
4924
|
+
const docs = [stylesDoc, contentDoc].filter(Boolean);
|
|
4925
|
+
for (const doc of docs) {
|
|
4926
|
+
const pageLayout = doc.querySelector("page-layout-properties, [page-width]");
|
|
4927
|
+
if (pageLayout) {
|
|
4928
|
+
const w = parseUnit(pageLayout.getAttribute("fo:page-width") || pageLayout.getAttribute("page-width"));
|
|
4929
|
+
const h2 = parseUnit(pageLayout.getAttribute("fo:page-height") || pageLayout.getAttribute("page-height"));
|
|
4930
|
+
const mt = parseUnit(pageLayout.getAttribute("fo:margin-top") || pageLayout.getAttribute("margin-top"));
|
|
4931
|
+
const mb = parseUnit(pageLayout.getAttribute("fo:margin-bottom") || pageLayout.getAttribute("margin-bottom"));
|
|
4932
|
+
const ml = parseUnit(pageLayout.getAttribute("fo:margin-left") || pageLayout.getAttribute("margin-left"));
|
|
4933
|
+
const mr = parseUnit(pageLayout.getAttribute("fo:margin-right") || pageLayout.getAttribute("margin-right"));
|
|
4934
|
+
if (w !== null) width = w;
|
|
4935
|
+
if (h2 !== null) height = h2;
|
|
4936
|
+
if (mt !== null) marginTop = mt;
|
|
4937
|
+
if (mb !== null) marginBottom = mb;
|
|
4938
|
+
if (ml !== null) marginLeft = ml;
|
|
4939
|
+
if (mr !== null) marginRight = mr;
|
|
4940
|
+
break;
|
|
4941
|
+
}
|
|
4942
|
+
}
|
|
4943
|
+
return { width, height, marginTop, marginBottom, marginLeft, marginRight };
|
|
4944
|
+
}
|
|
4566
4945
|
extractStyles(stylesDoc, contentDoc) {
|
|
4567
4946
|
const map = /* @__PURE__ */ new Map();
|
|
4568
4947
|
const styleNodes = [];
|
|
@@ -4585,14 +4964,21 @@ var OpenDocumentPlugin = class {
|
|
|
4585
4964
|
if (color) css += `color: ${color}; `;
|
|
4586
4965
|
if (size) css += `font-size: ${size}; `;
|
|
4587
4966
|
}
|
|
4588
|
-
|
|
4967
|
+
let paraProp = node.querySelector("paragraph-properties, [text-align]");
|
|
4968
|
+
if (!paraProp) {
|
|
4969
|
+
paraProp = Array.from(node.children).find((c) => c.tagName.includes("paragraph-properties")) || null;
|
|
4970
|
+
}
|
|
4589
4971
|
if (paraProp) {
|
|
4590
4972
|
const align = paraProp.getAttribute("fo:text-align") || paraProp.getAttribute("text-align");
|
|
4591
4973
|
const mt = paraProp.getAttribute("fo:margin-top") || paraProp.getAttribute("margin-top");
|
|
4592
4974
|
const mb = paraProp.getAttribute("fo:margin-bottom") || paraProp.getAttribute("margin-bottom");
|
|
4975
|
+
const breakBefore = paraProp.getAttribute("fo:break-before") || paraProp.getAttribute("break-before");
|
|
4976
|
+
const breakAfter = paraProp.getAttribute("fo:break-after") || paraProp.getAttribute("break-after");
|
|
4593
4977
|
if (align) css += `text-align: ${align}; `;
|
|
4594
4978
|
if (mt) css += `margin-top: ${mt}; `;
|
|
4595
4979
|
if (mb) css += `margin-bottom: ${mb}; `;
|
|
4980
|
+
if (breakBefore === "page") css += "page-break-before: always; ";
|
|
4981
|
+
if (breakAfter === "page") css += "page-break-after: always; ";
|
|
4596
4982
|
}
|
|
4597
4983
|
if (css) map.set(name, css);
|
|
4598
4984
|
}
|
|
@@ -4677,6 +5063,8 @@ var OpenDocumentPlugin = class {
|
|
|
4677
5063
|
result += " ";
|
|
4678
5064
|
} else if (tag === "line-break") {
|
|
4679
5065
|
result += "<br/>";
|
|
5066
|
+
} else if (tag === "soft-page-break") {
|
|
5067
|
+
result += '<hr class="odf-page-break" style="page-break-after: always; border: none; margin: 0; padding: 0; height: 0;" />';
|
|
4680
5068
|
} else {
|
|
4681
5069
|
result += el.textContent || "";
|
|
4682
5070
|
}
|
|
@@ -4837,20 +5225,9 @@ var DocPlugin = class {
|
|
|
4837
5225
|
container.style.overflow = "auto";
|
|
4838
5226
|
container.style.padding = "32px 16px";
|
|
4839
5227
|
container.style.backgroundColor = "#f1f5f9";
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
wrapper.style.margin = "0 auto";
|
|
4844
|
-
wrapper.style.backgroundColor = "#ffffff";
|
|
4845
|
-
wrapper.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4846
|
-
wrapper.style.borderRadius = "4px";
|
|
4847
|
-
wrapper.style.padding = "56px 48px";
|
|
4848
|
-
wrapper.style.minHeight = "100%";
|
|
4849
|
-
wrapper.style.transformOrigin = "top center";
|
|
4850
|
-
wrapper.style.transition = "transform 0.2s ease";
|
|
4851
|
-
wrapper.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4852
|
-
wrapper.style.color = "#1e293b";
|
|
4853
|
-
container.appendChild(wrapper);
|
|
5228
|
+
container.style.display = "flex";
|
|
5229
|
+
container.style.justifyContent = "center";
|
|
5230
|
+
container.style.alignItems = "flex-start";
|
|
4854
5231
|
ctx.container.appendChild(container);
|
|
4855
5232
|
let scale = 1;
|
|
4856
5233
|
let extractedRawText = "";
|
|
@@ -4877,21 +5254,27 @@ var DocPlugin = class {
|
|
|
4877
5254
|
const rawPages = this.splitIntoPages(extractedRawText);
|
|
4878
5255
|
const totalPages = Math.max(1, rawPages.length);
|
|
4879
5256
|
let currentPage = 1;
|
|
4880
|
-
wrapper.innerHTML = "";
|
|
4881
5257
|
const pageCards = [];
|
|
4882
5258
|
for (let i = 0; i < totalPages; i++) {
|
|
4883
5259
|
const pageCard = document.createElement("div");
|
|
4884
5260
|
pageCard.className = "fp-doc-page-card";
|
|
5261
|
+
pageCard.style.width = "816px";
|
|
5262
|
+
pageCard.style.height = "1056px";
|
|
4885
5263
|
pageCard.style.backgroundColor = "#ffffff";
|
|
4886
5264
|
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4887
5265
|
pageCard.style.borderRadius = "4px";
|
|
4888
|
-
pageCard.style.padding = "
|
|
4889
|
-
pageCard.style.
|
|
5266
|
+
pageCard.style.padding = "96px 72px";
|
|
5267
|
+
pageCard.style.boxSizing = "border-box";
|
|
5268
|
+
pageCard.style.overflow = "hidden";
|
|
4890
5269
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5270
|
+
pageCard.style.transformOrigin = "top center";
|
|
5271
|
+
pageCard.style.transition = "transform 0.2s ease";
|
|
5272
|
+
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
5273
|
+
pageCard.style.color = "#1e293b";
|
|
4891
5274
|
if (isFallback && i === 0) {
|
|
4892
5275
|
pageCard.innerHTML = `
|
|
4893
5276
|
<div style="border-bottom: 1px solid #e2e8f0; padding-bottom: 12px; margin-bottom: 24px;">
|
|
4894
|
-
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${
|
|
5277
|
+
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify6.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
|
|
4895
5278
|
<span style="font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 4px;">Legacy Word 97-2003 Binary Preview</span>
|
|
4896
5279
|
</div>
|
|
4897
5280
|
${this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document")}
|
|
@@ -4899,15 +5282,17 @@ var DocPlugin = class {
|
|
|
4899
5282
|
} else {
|
|
4900
5283
|
pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
|
|
4901
5284
|
}
|
|
4902
|
-
|
|
5285
|
+
container.appendChild(pageCard);
|
|
4903
5286
|
pageCards.push(pageCard);
|
|
4904
5287
|
}
|
|
4905
5288
|
let indicator = null;
|
|
4906
5289
|
if (totalPages > 1) {
|
|
4907
5290
|
indicator = document.createElement("div");
|
|
4908
5291
|
indicator.className = "fp-doc-page-indicator";
|
|
4909
|
-
indicator.style.position = "
|
|
5292
|
+
indicator.style.position = "fixed";
|
|
4910
5293
|
indicator.style.bottom = "16px";
|
|
5294
|
+
indicator.style.left = "50%";
|
|
5295
|
+
indicator.style.transform = "translateX(-50%)";
|
|
4911
5296
|
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4912
5297
|
indicator.style.backdropFilter = "blur(8px)";
|
|
4913
5298
|
indicator.style.color = "#f8fafc";
|
|
@@ -4921,17 +5306,25 @@ var DocPlugin = class {
|
|
|
4921
5306
|
indicator.style.userSelect = "none";
|
|
4922
5307
|
indicator.style.pointerEvents = "none";
|
|
4923
5308
|
indicator.style.textAlign = "center";
|
|
4924
|
-
indicator.style.width = "fit-content";
|
|
4925
|
-
indicator.style.margin = "16px auto 0";
|
|
4926
5309
|
container.appendChild(indicator);
|
|
4927
5310
|
}
|
|
5311
|
+
let rotation = 0;
|
|
5312
|
+
const applyTransform = () => {
|
|
5313
|
+
const activeCard = pageCards[currentPage - 1];
|
|
5314
|
+
if (activeCard) {
|
|
5315
|
+
activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5316
|
+
}
|
|
5317
|
+
};
|
|
4928
5318
|
const showPage = (pageNum) => {
|
|
4929
5319
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
card.style.display =
|
|
4933
|
-
|
|
4934
|
-
|
|
5320
|
+
pageCards.forEach((card, idx) => {
|
|
5321
|
+
if (idx + 1 === currentPage) {
|
|
5322
|
+
card.style.display = "block";
|
|
5323
|
+
card.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5324
|
+
} else {
|
|
5325
|
+
card.style.display = "none";
|
|
5326
|
+
}
|
|
5327
|
+
});
|
|
4935
5328
|
if (indicator) {
|
|
4936
5329
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4937
5330
|
}
|
|
@@ -4940,21 +5333,22 @@ var DocPlugin = class {
|
|
|
4940
5333
|
if (totalPages > 1) {
|
|
4941
5334
|
showPage(1);
|
|
4942
5335
|
}
|
|
4943
|
-
let
|
|
4944
|
-
const calculateFitScale = () => {
|
|
4945
|
-
const
|
|
4946
|
-
const
|
|
4947
|
-
const
|
|
4948
|
-
const
|
|
4949
|
-
const
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
5336
|
+
let fitMode = "width";
|
|
5337
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
5338
|
+
const elW = 816;
|
|
5339
|
+
const elH = 1056;
|
|
5340
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
5341
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
5342
|
+
const sW = availW / elW;
|
|
5343
|
+
const sH = availH / elH;
|
|
5344
|
+
if (mode === "page") {
|
|
5345
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
5346
|
+
}
|
|
5347
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
4955
5348
|
};
|
|
4956
5349
|
setTimeout(() => {
|
|
4957
|
-
|
|
5350
|
+
fitMode = "width";
|
|
5351
|
+
scale = calculateFitScale("width");
|
|
4958
5352
|
applyTransform();
|
|
4959
5353
|
}, 60);
|
|
4960
5354
|
const cleanup = () => {
|
|
@@ -4982,7 +5376,8 @@ var DocPlugin = class {
|
|
|
4982
5376
|
applyTransform();
|
|
4983
5377
|
},
|
|
4984
5378
|
fitToPage: () => {
|
|
4985
|
-
|
|
5379
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
5380
|
+
scale = calculateFitScale(fitMode);
|
|
4986
5381
|
rotation = 0;
|
|
4987
5382
|
applyTransform();
|
|
4988
5383
|
},
|
|
@@ -5110,8 +5505,28 @@ var DocPlugin = class {
|
|
|
5110
5505
|
}
|
|
5111
5506
|
splitIntoPages(text) {
|
|
5112
5507
|
if (!text) return [""];
|
|
5113
|
-
const
|
|
5114
|
-
|
|
5508
|
+
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);
|
|
5509
|
+
if (explicitParts.length === 0) explicitParts.push(text);
|
|
5510
|
+
const maxLinesPerPage = 48;
|
|
5511
|
+
const finalPages = [];
|
|
5512
|
+
for (const part of explicitParts) {
|
|
5513
|
+
const lines = part.split(/\r?\n/);
|
|
5514
|
+
let currentLines = [];
|
|
5515
|
+
let count = 0;
|
|
5516
|
+
for (const line of lines) {
|
|
5517
|
+
currentLines.push(line);
|
|
5518
|
+
count++;
|
|
5519
|
+
if (count >= maxLinesPerPage) {
|
|
5520
|
+
finalPages.push(currentLines.join("\n"));
|
|
5521
|
+
currentLines = [];
|
|
5522
|
+
count = 0;
|
|
5523
|
+
}
|
|
5524
|
+
}
|
|
5525
|
+
if (currentLines.length > 0) {
|
|
5526
|
+
finalPages.push(currentLines.join("\n"));
|
|
5527
|
+
}
|
|
5528
|
+
}
|
|
5529
|
+
return finalPages.length > 0 ? finalPages : [text];
|
|
5115
5530
|
}
|
|
5116
5531
|
/**
|
|
5117
5532
|
* Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
|
|
@@ -5120,17 +5535,65 @@ var DocPlugin = class {
|
|
|
5120
5535
|
const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
|
|
5121
5536
|
let html = "";
|
|
5122
5537
|
let inList = false;
|
|
5123
|
-
|
|
5124
|
-
|
|
5538
|
+
let tableLines = [];
|
|
5539
|
+
const flushTable = () => {
|
|
5540
|
+
if (tableLines.length > 0) {
|
|
5541
|
+
html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
|
|
5542
|
+
for (const tLine of tableLines) {
|
|
5543
|
+
html += "<tr>";
|
|
5544
|
+
const cols = tLine.split(" ");
|
|
5545
|
+
for (const col of cols) {
|
|
5546
|
+
html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6.sanitize(col.trim())}</td>`;
|
|
5547
|
+
}
|
|
5548
|
+
html += "</tr>";
|
|
5549
|
+
}
|
|
5550
|
+
html += "</table>";
|
|
5551
|
+
tableLines = [];
|
|
5552
|
+
}
|
|
5553
|
+
};
|
|
5554
|
+
let i = 0;
|
|
5555
|
+
while (i < lines.length) {
|
|
5556
|
+
let line = lines[i];
|
|
5557
|
+
let tabCount = (line.match(/\t/g) || []).length;
|
|
5558
|
+
if (tabCount > 0) {
|
|
5559
|
+
let consecutiveTableLines = 1;
|
|
5560
|
+
let j = i + 1;
|
|
5561
|
+
while (j < lines.length) {
|
|
5562
|
+
const nextTabCount = (lines[j].match(/\t/g) || []).length;
|
|
5563
|
+
if (nextTabCount === tabCount) {
|
|
5564
|
+
consecutiveTableLines++;
|
|
5565
|
+
j++;
|
|
5566
|
+
} else {
|
|
5567
|
+
break;
|
|
5568
|
+
}
|
|
5569
|
+
}
|
|
5570
|
+
if (consecutiveTableLines >= 3) {
|
|
5571
|
+
if (inList) {
|
|
5572
|
+
html += "</ul>";
|
|
5573
|
+
inList = false;
|
|
5574
|
+
}
|
|
5575
|
+
tableLines = lines.slice(i, j);
|
|
5576
|
+
flushTable();
|
|
5577
|
+
i = j;
|
|
5578
|
+
continue;
|
|
5579
|
+
}
|
|
5580
|
+
}
|
|
5581
|
+
line = line.trim();
|
|
5125
5582
|
if (!line) {
|
|
5126
5583
|
if (inList) {
|
|
5127
5584
|
html += "</ul>";
|
|
5128
5585
|
inList = false;
|
|
5129
5586
|
}
|
|
5587
|
+
html += '<div style="height: 1.15em;"></div>';
|
|
5588
|
+
i++;
|
|
5589
|
+
continue;
|
|
5590
|
+
}
|
|
5591
|
+
if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line)) {
|
|
5592
|
+
i++;
|
|
5130
5593
|
continue;
|
|
5131
5594
|
}
|
|
5132
|
-
if (
|
|
5133
|
-
|
|
5595
|
+
if ((line.includes("Normal.dot") || line.includes("Microsoft Word") || line.includes("Times New Roman")) && line.length < 30) {
|
|
5596
|
+
i++;
|
|
5134
5597
|
continue;
|
|
5135
5598
|
}
|
|
5136
5599
|
if (line.length < 60 && !line.endsWith(".") && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#"))) {
|
|
@@ -5138,24 +5601,26 @@ var DocPlugin = class {
|
|
|
5138
5601
|
html += "</ul>";
|
|
5139
5602
|
inList = false;
|
|
5140
5603
|
}
|
|
5141
|
-
html += `<h2 style="font-size:
|
|
5604
|
+
html += `<h2 style="font-size: 16px; font-weight: 700; color: #1e3a8a; margin: 16px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify6.sanitize(line)}</h2>`;
|
|
5142
5605
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
5143
5606
|
if (!inList) {
|
|
5144
5607
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
5145
5608
|
inList = true;
|
|
5146
5609
|
}
|
|
5147
5610
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
5148
|
-
html += `<li style="margin: 4px 0; line-height: 1.
|
|
5611
|
+
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6.sanitize(bulletText)}</li>`;
|
|
5149
5612
|
} else {
|
|
5150
5613
|
if (inList) {
|
|
5151
5614
|
html += "</ul>";
|
|
5152
5615
|
inList = false;
|
|
5153
5616
|
}
|
|
5154
|
-
html += `<p style="line-height: 1.
|
|
5617
|
+
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6.sanitize(line)}</p>`;
|
|
5155
5618
|
}
|
|
5619
|
+
i++;
|
|
5156
5620
|
}
|
|
5157
5621
|
if (inList) html += "</ul>";
|
|
5158
|
-
|
|
5622
|
+
flushTable();
|
|
5623
|
+
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6.sanitize(filename)})</p>`;
|
|
5159
5624
|
}
|
|
5160
5625
|
};
|
|
5161
5626
|
function docPlugin() {
|
|
@@ -5333,7 +5798,7 @@ var PptPlugin = class {
|
|
|
5333
5798
|
if (s.pictureUrl) {
|
|
5334
5799
|
contentHtml = `
|
|
5335
5800
|
<div style="flex: 1; display: flex; justify-content: center; align-items: center; padding: 12px; overflow: hidden;">
|
|
5336
|
-
<img src="${s.pictureUrl}" alt="${
|
|
5801
|
+
<img src="${s.pictureUrl}" alt="${DOMPurify6.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;" />
|
|
5337
5802
|
</div>
|
|
5338
5803
|
`;
|
|
5339
5804
|
} else if (s.tableColumns.length > 0) {
|
|
@@ -5343,7 +5808,7 @@ var PptPlugin = class {
|
|
|
5343
5808
|
<table style="width: 100%; border-collapse: collapse; border: 1px solid #cbd5e1; border-radius: 6px; overflow: hidden; background: #ffffff;">
|
|
5344
5809
|
<thead>
|
|
5345
5810
|
<tr style="background: #e2e8f0; color: #1e293b; font-weight: 600; font-size: 14px;">
|
|
5346
|
-
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${
|
|
5811
|
+
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${DOMPurify6.sanitize(c)}</th>`).join("")}
|
|
5347
5812
|
</tr>
|
|
5348
5813
|
</thead>
|
|
5349
5814
|
<tbody>
|
|
@@ -5359,7 +5824,7 @@ var PptPlugin = class {
|
|
|
5359
5824
|
} else {
|
|
5360
5825
|
const pTags = s.paragraphs.map((p) => {
|
|
5361
5826
|
const lines = p.split(/[\r\n]+/).map((l) => l.trim()).filter(Boolean);
|
|
5362
|
-
return lines.map((l) => `<p style="margin: 0 0 14px; font-size: 14px; line-height: 1.65; color: #334155; text-align: justify;">${
|
|
5827
|
+
return lines.map((l) => `<p style="margin: 0 0 14px; font-size: 14px; line-height: 1.65; color: #334155; text-align: justify;">${DOMPurify6.sanitize(l)}</p>`).join("");
|
|
5363
5828
|
}).join("");
|
|
5364
5829
|
contentHtml = `
|
|
5365
5830
|
<div style="flex: 1; overflow: auto; padding: 4px 8px; display: flex; flex-direction: column; justify-content: flex-start;">
|
|
@@ -5372,11 +5837,11 @@ var PptPlugin = class {
|
|
|
5372
5837
|
<!-- Header Banner matching PowerPoint design -->
|
|
5373
5838
|
<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;">
|
|
5374
5839
|
<h1 style="margin: 0; font-size: 26px; font-weight: 700; color: #1e293b; letter-spacing: -0.3px;">
|
|
5375
|
-
${
|
|
5840
|
+
${DOMPurify6.sanitize(s.title)}
|
|
5376
5841
|
</h1>
|
|
5377
5842
|
${s.subtitle ? `
|
|
5378
5843
|
<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);">
|
|
5379
|
-
${
|
|
5844
|
+
${DOMPurify6.sanitize(s.subtitle)}
|
|
5380
5845
|
</span>
|
|
5381
5846
|
` : `
|
|
5382
5847
|
<span style="font-size: 12px; color: #365314; font-weight: 600;">
|