@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/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var DOMPurify6 = require('dompurify');
|
|
4
4
|
var pdfjsLib = require('pdfjs-dist');
|
|
5
5
|
var docx = require('docx-preview');
|
|
6
6
|
var fflate = require('fflate');
|
|
@@ -34,7 +34,7 @@ function _interopNamespace(e) {
|
|
|
34
34
|
return Object.freeze(n);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
var
|
|
37
|
+
var DOMPurify6__default = /*#__PURE__*/_interopDefault(DOMPurify6);
|
|
38
38
|
var pdfjsLib__namespace = /*#__PURE__*/_interopNamespace(pdfjsLib);
|
|
39
39
|
var docx__namespace = /*#__PURE__*/_interopNamespace(docx);
|
|
40
40
|
var XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
|
|
@@ -386,7 +386,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
386
386
|
if (magicMime === "application/zip") {
|
|
387
387
|
const ooxmlMime = detectOoxmlType(buffer);
|
|
388
388
|
if (ooxmlMime && ooxmlMime !== "application/zip") {
|
|
389
|
-
metadata.mimeType = ooxmlMime;
|
|
389
|
+
metadata.mimeType = metadata.mimeType ?? ooxmlMime;
|
|
390
390
|
if (ooxmlMime.includes("wordprocessing")) metadata.extension = metadata.extension ?? ".docx";
|
|
391
391
|
else if (ooxmlMime.includes("spreadsheet")) metadata.extension = metadata.extension ?? ".xlsx";
|
|
392
392
|
else if (ooxmlMime.includes("presentation")) metadata.extension = metadata.extension ?? ".pptx";
|
|
@@ -415,12 +415,12 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
415
415
|
return { buffer, metadata };
|
|
416
416
|
}
|
|
417
417
|
function sanitizeHTML(html) {
|
|
418
|
-
return
|
|
418
|
+
return DOMPurify6__default.default.sanitize(html, {
|
|
419
419
|
USE_PROFILES: { html: true }
|
|
420
420
|
});
|
|
421
421
|
}
|
|
422
422
|
function sanitizeSVG(svg) {
|
|
423
|
-
return
|
|
423
|
+
return DOMPurify6__default.default.sanitize(svg, {
|
|
424
424
|
USE_PROFILES: { svg: true, svgFilters: true }
|
|
425
425
|
});
|
|
426
426
|
}
|
|
@@ -506,7 +506,8 @@ function createElement(tag, attrs, ...children) {
|
|
|
506
506
|
}
|
|
507
507
|
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>`;
|
|
508
508
|
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>`;
|
|
509
|
-
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"><
|
|
509
|
+
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>`;
|
|
510
|
+
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>`;
|
|
510
511
|
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>`;
|
|
511
512
|
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>`;
|
|
512
513
|
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>`;
|
|
@@ -526,6 +527,7 @@ var ICON_MAP = {
|
|
|
526
527
|
"zoom-in": ICON_ZOOM_IN,
|
|
527
528
|
"zoom-out": ICON_ZOOM_OUT,
|
|
528
529
|
"fit-page": ICON_FIT_PAGE,
|
|
530
|
+
"fit-width": ICON_FIT_WIDTH,
|
|
529
531
|
"fit-slide": ICON_FIT_PAGE,
|
|
530
532
|
"rotate-cw": ICON_ROTATE_CW,
|
|
531
533
|
"rotate-ccw": ICON_ROTATE_CCW,
|
|
@@ -1472,6 +1474,7 @@ var PdfPlugin = class {
|
|
|
1472
1474
|
let currentPage = 1;
|
|
1473
1475
|
let zoomScale = 1;
|
|
1474
1476
|
let rotation = 0;
|
|
1477
|
+
let fitMode = "width";
|
|
1475
1478
|
let currentRenderTask = null;
|
|
1476
1479
|
const renderPage = async (pageNum) => {
|
|
1477
1480
|
if (currentRenderTask) {
|
|
@@ -1491,11 +1494,16 @@ var PdfPlugin = class {
|
|
|
1491
1494
|
const containerWidth = container.clientWidth || 900;
|
|
1492
1495
|
const containerHeight = container.clientHeight || 700;
|
|
1493
1496
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1494
|
-
const availWidth = Math.max(
|
|
1495
|
-
const availHeight = Math.max(
|
|
1497
|
+
const availWidth = Math.max(280, containerWidth - 48);
|
|
1498
|
+
const availHeight = Math.max(280, containerHeight - 88);
|
|
1496
1499
|
const scaleW = availWidth / unscaledVp.width;
|
|
1497
1500
|
const scaleH = availHeight / unscaledVp.height;
|
|
1498
|
-
|
|
1501
|
+
let fitScale;
|
|
1502
|
+
if (fitMode === "page") {
|
|
1503
|
+
fitScale = Math.max(0.5, Math.min(scaleW, scaleH));
|
|
1504
|
+
} else {
|
|
1505
|
+
fitScale = Math.max(0.65, Math.min(1.15, scaleW));
|
|
1506
|
+
}
|
|
1499
1507
|
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1500
1508
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
1501
1509
|
const viewport = page.getViewport({ scale: effectiveScale, rotation });
|
|
@@ -1521,7 +1529,19 @@ var PdfPlugin = class {
|
|
|
1521
1529
|
}
|
|
1522
1530
|
};
|
|
1523
1531
|
await renderPage(1);
|
|
1532
|
+
let resizeTimer = null;
|
|
1533
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
1534
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1535
|
+
resizeTimer = setTimeout(() => {
|
|
1536
|
+
if (Math.abs(zoomScale - 1) < 0.05) {
|
|
1537
|
+
renderPage(currentPage);
|
|
1538
|
+
}
|
|
1539
|
+
}, 150);
|
|
1540
|
+
});
|
|
1541
|
+
resizeObserver.observe(container);
|
|
1524
1542
|
const cleanup = () => {
|
|
1543
|
+
resizeObserver.disconnect();
|
|
1544
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1525
1545
|
if (currentRenderTask) {
|
|
1526
1546
|
try {
|
|
1527
1547
|
currentRenderTask.cancel();
|
|
@@ -1552,6 +1572,7 @@ var PdfPlugin = class {
|
|
|
1552
1572
|
renderPage(currentPage);
|
|
1553
1573
|
},
|
|
1554
1574
|
fitToPage: () => {
|
|
1575
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
1555
1576
|
zoomScale = 1;
|
|
1556
1577
|
rotation = 0;
|
|
1557
1578
|
renderPage(currentPage);
|
|
@@ -2105,8 +2126,53 @@ var DocxPlugin = class {
|
|
|
2105
2126
|
}
|
|
2106
2127
|
}
|
|
2107
2128
|
}
|
|
2108
|
-
|
|
2109
|
-
const cards = wrapper.querySelectorAll(".fp-docx-page-card");
|
|
2129
|
+
let sections = Array.from(wrapper.querySelectorAll("section.docx"));
|
|
2130
|
+
const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
|
|
2131
|
+
if (sections.length === 1 && cards.length === 0) {
|
|
2132
|
+
const singleSec = sections[0];
|
|
2133
|
+
const pageH = 1056;
|
|
2134
|
+
const secH = singleSec.offsetHeight || singleSec.scrollHeight;
|
|
2135
|
+
if (secH > pageH * 1.25) {
|
|
2136
|
+
const children = Array.from(singleSec.children);
|
|
2137
|
+
if (children.length > 1) {
|
|
2138
|
+
const parent = singleSec.parentElement || wrapper;
|
|
2139
|
+
const newSections = [singleSec];
|
|
2140
|
+
singleSec.innerHTML = "";
|
|
2141
|
+
singleSec.style.minHeight = `${pageH}px`;
|
|
2142
|
+
singleSec.style.maxHeight = `${pageH}px`;
|
|
2143
|
+
singleSec.style.overflow = "hidden";
|
|
2144
|
+
singleSec.style.boxSizing = "border-box";
|
|
2145
|
+
let curSec = singleSec;
|
|
2146
|
+
let curH = 0;
|
|
2147
|
+
const maxH = pageH - 96;
|
|
2148
|
+
for (let i = 0; i < children.length; i++) {
|
|
2149
|
+
const child = children[i];
|
|
2150
|
+
curSec.appendChild(child);
|
|
2151
|
+
const chH = child.offsetHeight || 28;
|
|
2152
|
+
curH += chH;
|
|
2153
|
+
if (curH >= maxH && i < children.length - 1) {
|
|
2154
|
+
const nextSec = document.createElement("section");
|
|
2155
|
+
nextSec.className = singleSec.className;
|
|
2156
|
+
nextSec.style.cssText = singleSec.style.cssText;
|
|
2157
|
+
nextSec.style.width = singleSec.style.width || "816px";
|
|
2158
|
+
nextSec.style.minHeight = `${pageH}px`;
|
|
2159
|
+
nextSec.style.maxHeight = `${pageH}px`;
|
|
2160
|
+
nextSec.style.overflow = "hidden";
|
|
2161
|
+
nextSec.style.boxSizing = "border-box";
|
|
2162
|
+
nextSec.style.backgroundColor = "#ffffff";
|
|
2163
|
+
nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
|
|
2164
|
+
nextSec.style.borderRadius = "4px";
|
|
2165
|
+
nextSec.style.marginBottom = "24px";
|
|
2166
|
+
parent.appendChild(nextSec);
|
|
2167
|
+
newSections.push(nextSec);
|
|
2168
|
+
curSec = nextSec;
|
|
2169
|
+
curH = 0;
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
sections = newSections;
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2110
2176
|
const pageElements = sections.length > 0 ? sections : cards;
|
|
2111
2177
|
const totalPages = Math.max(1, pageElements.length);
|
|
2112
2178
|
let currentPage = 1;
|
|
@@ -2150,22 +2216,27 @@ var DocxPlugin = class {
|
|
|
2150
2216
|
}
|
|
2151
2217
|
scale = 1;
|
|
2152
2218
|
let rotation = 0;
|
|
2153
|
-
|
|
2219
|
+
let fitMode = "width";
|
|
2220
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
2154
2221
|
const activeEl = pageElements[currentPage - 1] || wrapper.firstElementChild || wrapper;
|
|
2155
2222
|
const elW = activeEl.offsetWidth || 816;
|
|
2156
|
-
const
|
|
2157
|
-
const availW = Math.max(
|
|
2158
|
-
const availH = Math.max(
|
|
2223
|
+
const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
2224
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
2225
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
2159
2226
|
const sW = availW / elW;
|
|
2160
|
-
const sH = availH /
|
|
2161
|
-
|
|
2227
|
+
const sH = availH / singlePageH;
|
|
2228
|
+
if (mode === "page") {
|
|
2229
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
2230
|
+
}
|
|
2231
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
2162
2232
|
};
|
|
2163
2233
|
const applyTransform = () => {
|
|
2164
2234
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
2165
2235
|
wrapper.style.transformOrigin = "top center";
|
|
2166
2236
|
};
|
|
2167
2237
|
setTimeout(() => {
|
|
2168
|
-
|
|
2238
|
+
fitMode = "width";
|
|
2239
|
+
scale = calculateFitScale("width");
|
|
2169
2240
|
applyTransform();
|
|
2170
2241
|
}, 60);
|
|
2171
2242
|
const cleanup = () => {
|
|
@@ -2199,7 +2270,8 @@ var DocxPlugin = class {
|
|
|
2199
2270
|
applyTransform();
|
|
2200
2271
|
},
|
|
2201
2272
|
fitToPage: () => {
|
|
2202
|
-
|
|
2273
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
2274
|
+
scale = calculateFitScale(fitMode);
|
|
2203
2275
|
rotation = 0;
|
|
2204
2276
|
applyTransform();
|
|
2205
2277
|
},
|
|
@@ -2269,90 +2341,149 @@ var DocxPlugin = class {
|
|
|
2269
2341
|
console.warn("[DocxPlugin] Error parsing relationships:", relsErr);
|
|
2270
2342
|
}
|
|
2271
2343
|
}
|
|
2272
|
-
const
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2344
|
+
const sectPrs = Array.from(doc.getElementsByTagNameNS("*", "sectPr"));
|
|
2345
|
+
const lastSectPr = sectPrs[sectPrs.length - 1];
|
|
2346
|
+
let defaultW = 12240;
|
|
2347
|
+
let defaultH = 15840;
|
|
2348
|
+
let margins = { top: 1440, right: 1440, bottom: 1440, left: 1440 };
|
|
2349
|
+
if (lastSectPr) {
|
|
2350
|
+
const pgSz = lastSectPr.getElementsByTagNameNS("*", "pgSz")[0];
|
|
2351
|
+
if (pgSz) {
|
|
2352
|
+
defaultW = parseInt(pgSz.getAttribute("w:w") || pgSz.getAttribute("w") || "12240", 10);
|
|
2353
|
+
defaultH = parseInt(pgSz.getAttribute("w:h") || pgSz.getAttribute("h") || "15840", 10);
|
|
2354
|
+
}
|
|
2355
|
+
const pgMar = lastSectPr.getElementsByTagNameNS("*", "pgMar")[0];
|
|
2356
|
+
if (pgMar) {
|
|
2357
|
+
margins.top = parseInt(pgMar.getAttribute("w:top") || pgMar.getAttribute("top") || "1440", 10);
|
|
2358
|
+
margins.bottom = parseInt(pgMar.getAttribute("w:bottom") || pgMar.getAttribute("bottom") || "1440", 10);
|
|
2359
|
+
margins.left = parseInt(pgMar.getAttribute("w:left") || pgMar.getAttribute("left") || "1440", 10);
|
|
2360
|
+
margins.right = parseInt(pgMar.getAttribute("w:right") || pgMar.getAttribute("right") || "1440", 10);
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
const createPageCard = () => {
|
|
2364
|
+
const card = document.createElement("div");
|
|
2365
|
+
card.className = "fp-docx-page-card";
|
|
2366
|
+
card.style.backgroundColor = "#ffffff";
|
|
2367
|
+
card.style.borderRadius = "4px";
|
|
2368
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
2369
|
+
card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2370
|
+
card.style.color = "#1e293b";
|
|
2371
|
+
card.style.lineHeight = "1.6";
|
|
2372
|
+
card.style.boxSizing = "border-box";
|
|
2373
|
+
card.style.overflow = "hidden";
|
|
2374
|
+
card.style.position = "relative";
|
|
2375
|
+
card.style.marginBottom = "24px";
|
|
2376
|
+
card.style.width = `${defaultW / 15}px`;
|
|
2377
|
+
card.style.height = `${defaultH / 15}px`;
|
|
2378
|
+
card.style.padding = `${margins.top / 15}px ${margins.right / 15}px ${margins.bottom / 15}px ${margins.left / 15}px`;
|
|
2379
|
+
return card;
|
|
2380
|
+
};
|
|
2381
|
+
let currentCard = createPageCard();
|
|
2382
|
+
let currentHtml = "";
|
|
2383
|
+
const pages = [{ card: currentCard, html: "" }];
|
|
2384
|
+
const flushHtml = () => {
|
|
2385
|
+
pages[pages.length - 1].html += currentHtml;
|
|
2386
|
+
currentHtml = "";
|
|
2387
|
+
};
|
|
2388
|
+
const newPage = () => {
|
|
2389
|
+
flushHtml();
|
|
2390
|
+
currentCard = createPageCard();
|
|
2391
|
+
pages.push({ card: currentCard, html: "" });
|
|
2392
|
+
};
|
|
2281
2393
|
const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
|
|
2282
|
-
let html = "";
|
|
2283
2394
|
for (const child of Array.from(body.children)) {
|
|
2284
2395
|
const tag = child.localName || child.nodeName.split(":").pop();
|
|
2285
2396
|
if (tag === "p") {
|
|
2286
2397
|
const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
|
|
2287
2398
|
const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
|
|
2288
2399
|
const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
|
|
2289
|
-
const
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2400
|
+
const chunks = this.extractParagraphChunks(child, imageMap);
|
|
2401
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
2402
|
+
if (i > 0) {
|
|
2403
|
+
newPage();
|
|
2404
|
+
}
|
|
2405
|
+
const textContent = chunks[i];
|
|
2406
|
+
if (!textContent.trim() && !textContent.includes("<img")) {
|
|
2407
|
+
currentHtml += '<div style="height: 10px;"></div>';
|
|
2408
|
+
continue;
|
|
2409
|
+
}
|
|
2410
|
+
const lowerStyle = styleVal.toLowerCase();
|
|
2411
|
+
if (lowerStyle.includes("title")) {
|
|
2412
|
+
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>`;
|
|
2413
|
+
} else if (lowerStyle.includes("heading1") || styleVal === "1") {
|
|
2414
|
+
currentHtml += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
|
|
2415
|
+
} else if (lowerStyle.includes("heading2") || styleVal === "2") {
|
|
2416
|
+
currentHtml += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
|
|
2417
|
+
} else if (lowerStyle.includes("heading3") || styleVal === "3") {
|
|
2418
|
+
currentHtml += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
|
|
2419
|
+
} else if (numPr) {
|
|
2420
|
+
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>`;
|
|
2421
|
+
} else {
|
|
2422
|
+
currentHtml += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
|
|
2423
|
+
}
|
|
2307
2424
|
}
|
|
2308
2425
|
} else if (tag === "tbl") {
|
|
2309
|
-
|
|
2426
|
+
currentHtml += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
|
|
2310
2427
|
const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
|
|
2311
2428
|
rows.forEach((tr, rIdx) => {
|
|
2312
|
-
|
|
2429
|
+
currentHtml += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
2313
2430
|
const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
|
|
2314
2431
|
cells.forEach((tc) => {
|
|
2315
2432
|
const cellText = this.extractParagraphHtml(tc, imageMap);
|
|
2316
|
-
|
|
2433
|
+
currentHtml += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || " "}</td>`;
|
|
2317
2434
|
});
|
|
2318
|
-
|
|
2435
|
+
currentHtml += "</tr>";
|
|
2319
2436
|
});
|
|
2320
|
-
|
|
2437
|
+
currentHtml += "</table>";
|
|
2321
2438
|
}
|
|
2322
2439
|
}
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2440
|
+
flushHtml();
|
|
2441
|
+
for (const page of pages) {
|
|
2442
|
+
page.card.innerHTML = DOMPurify6__default.default.sanitize(page.html, {
|
|
2443
|
+
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
|
|
2444
|
+
ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
|
|
2445
|
+
});
|
|
2446
|
+
wrapper.appendChild(page.card);
|
|
2447
|
+
}
|
|
2328
2448
|
}
|
|
2329
2449
|
extractParagraphHtml(pElement, imageMap = {}) {
|
|
2330
|
-
|
|
2450
|
+
return this.extractParagraphChunks(pElement, imageMap).join("<br/>");
|
|
2451
|
+
}
|
|
2452
|
+
extractParagraphChunks(pElement, imageMap = {}) {
|
|
2453
|
+
const chunks = [""];
|
|
2454
|
+
let currentChunkIndex = 0;
|
|
2331
2455
|
const drawings = Array.from(pElement.getElementsByTagNameNS("*", "drawing"));
|
|
2332
2456
|
for (const drawing of drawings) {
|
|
2333
2457
|
const blip = drawing.getElementsByTagNameNS("*", "blip")[0];
|
|
2334
2458
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2335
2459
|
if (rId && imageMap[rId]) {
|
|
2336
|
-
|
|
2460
|
+
chunks[currentChunkIndex] += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
|
|
2337
2461
|
}
|
|
2338
2462
|
}
|
|
2339
2463
|
const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
|
|
2340
|
-
if (runs.length === 0 && !
|
|
2341
|
-
|
|
2464
|
+
if (runs.length === 0 && !chunks[currentChunkIndex]) {
|
|
2465
|
+
chunks[currentChunkIndex] = DOMPurify6__default.default.sanitize(pElement.textContent || "");
|
|
2466
|
+
return chunks;
|
|
2342
2467
|
}
|
|
2343
2468
|
for (const r of runs) {
|
|
2344
2469
|
const blip = r.getElementsByTagNameNS("*", "blip")[0] || r.getElementsByTagNameNS("*", "imagedata")[0];
|
|
2345
2470
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2346
2471
|
if (rId && imageMap[rId]) {
|
|
2347
|
-
|
|
2472
|
+
chunks[currentChunkIndex] += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
|
|
2348
2473
|
}
|
|
2349
|
-
const brs = r.getElementsByTagNameNS("*", "br");
|
|
2350
|
-
for (
|
|
2351
|
-
|
|
2474
|
+
const brs = Array.from(r.getElementsByTagNameNS("*", "br"));
|
|
2475
|
+
for (const br of brs) {
|
|
2476
|
+
const type = br.getAttribute("w:type") || br.getAttribute("type");
|
|
2477
|
+
if (type === "page") {
|
|
2478
|
+
chunks.push("");
|
|
2479
|
+
currentChunkIndex++;
|
|
2480
|
+
} else {
|
|
2481
|
+
chunks[currentChunkIndex] += "<br/>";
|
|
2482
|
+
}
|
|
2352
2483
|
}
|
|
2353
2484
|
const tabs = r.getElementsByTagNameNS("*", "tab");
|
|
2354
2485
|
if (tabs.length > 0) {
|
|
2355
|
-
|
|
2486
|
+
chunks[currentChunkIndex] += " ";
|
|
2356
2487
|
}
|
|
2357
2488
|
const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
|
|
2358
2489
|
const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
|
|
@@ -2366,7 +2497,7 @@ var DocxPlugin = class {
|
|
|
2366
2497
|
const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
|
|
2367
2498
|
let text = texts.map((t) => t.textContent || "").join("");
|
|
2368
2499
|
if (!text) continue;
|
|
2369
|
-
text =
|
|
2500
|
+
text = DOMPurify6__default.default.sanitize(text);
|
|
2370
2501
|
let styles = "";
|
|
2371
2502
|
if (isBold) styles += "font-weight: bold; ";
|
|
2372
2503
|
if (isItalic) styles += "font-style: italic; ";
|
|
@@ -2378,12 +2509,12 @@ var DocxPlugin = class {
|
|
|
2378
2509
|
if (!isNaN(pt) && pt > 0) styles += `font-size: ${pt}pt; `;
|
|
2379
2510
|
}
|
|
2380
2511
|
if (styles) {
|
|
2381
|
-
|
|
2512
|
+
chunks[currentChunkIndex] += `<span style="${styles}">${text}</span>`;
|
|
2382
2513
|
} else {
|
|
2383
|
-
|
|
2514
|
+
chunks[currentChunkIndex] += text;
|
|
2384
2515
|
}
|
|
2385
2516
|
}
|
|
2386
|
-
return
|
|
2517
|
+
return chunks;
|
|
2387
2518
|
}
|
|
2388
2519
|
renderBinaryDocFallback(ctx, wrapper) {
|
|
2389
2520
|
const card = document.createElement("div");
|
|
@@ -2400,14 +2531,14 @@ var DocxPlugin = class {
|
|
|
2400
2531
|
const wordDocStream = cfbf.readStream("WordDocument");
|
|
2401
2532
|
if (wordDocStream && wordDocStream.length >= 512) {
|
|
2402
2533
|
const text2 = this.extractReadableStrings(wordDocStream);
|
|
2403
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2534
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text2)}</div>`;
|
|
2404
2535
|
wrapper.appendChild(card);
|
|
2405
2536
|
return;
|
|
2406
2537
|
}
|
|
2407
2538
|
} catch {
|
|
2408
2539
|
}
|
|
2409
2540
|
const text = this.extractReadableStrings(new Uint8Array(ctx.buffer));
|
|
2410
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2541
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text)}</div>`;
|
|
2411
2542
|
wrapper.appendChild(card);
|
|
2412
2543
|
}
|
|
2413
2544
|
extractReadableStrings(bytes) {
|
|
@@ -2584,11 +2715,9 @@ var ExcelPlugin = class {
|
|
|
2584
2715
|
const calculateFitScale = () => {
|
|
2585
2716
|
const table = contentArea.querySelector("table");
|
|
2586
2717
|
if (!table) return 1;
|
|
2587
|
-
const availW = Math.max(
|
|
2588
|
-
const availH = Math.max(200, container.clientHeight - 80);
|
|
2718
|
+
const availW = Math.max(280, container.clientWidth - 48);
|
|
2589
2719
|
const tW = table.offsetWidth || 800;
|
|
2590
|
-
|
|
2591
|
-
return Math.min(1, Math.min(availW / tW, availH / tH));
|
|
2720
|
+
return Math.max(0.65, Math.min(1, availW / tW));
|
|
2592
2721
|
};
|
|
2593
2722
|
try {
|
|
2594
2723
|
wb = XLSX__namespace.read(new Uint8Array(ctx.buffer), { type: "array", cellDates: true });
|
|
@@ -3006,41 +3135,94 @@ var CodePlugin = class {
|
|
|
3006
3135
|
async render(ctx) {
|
|
3007
3136
|
const decoder = new TextDecoder("utf-8");
|
|
3008
3137
|
const fullText = decoder.decode(ctx.buffer);
|
|
3009
|
-
const
|
|
3010
|
-
const
|
|
3138
|
+
const extRaw = ctx.metadata.extension?.toLowerCase();
|
|
3139
|
+
const mimeRaw = ctx.metadata.mimeType?.toLowerCase();
|
|
3140
|
+
const isTxt = extRaw === ".txt" || mimeRaw === "text/plain" && (!extRaw || !this.extensions.filter((e) => e !== ".txt").includes(extRaw));
|
|
3141
|
+
let rawPages = [];
|
|
3142
|
+
if (isTxt) {
|
|
3143
|
+
const explicitPages = fullText.split(/(?:\f|\x0C)/);
|
|
3144
|
+
for (const ep of explicitPages) {
|
|
3145
|
+
const lines = ep.split(/\r?\n/);
|
|
3146
|
+
let currentChunk = [];
|
|
3147
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3148
|
+
currentChunk.push(lines[i]);
|
|
3149
|
+
if (currentChunk.length >= 46) {
|
|
3150
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3151
|
+
currentChunk = [];
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
if (currentChunk.length > 0 || lines.length === 0) {
|
|
3155
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
if (rawPages.length === 0) rawPages = [""];
|
|
3159
|
+
} else {
|
|
3160
|
+
const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
|
|
3161
|
+
rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
3162
|
+
}
|
|
3011
3163
|
const totalPages = Math.max(1, rawPages.length);
|
|
3012
3164
|
let currentPage = 1;
|
|
3013
3165
|
const container = document.createElement("div");
|
|
3014
3166
|
container.style.width = "100%";
|
|
3015
3167
|
container.style.height = "100%";
|
|
3016
3168
|
container.style.overflow = "auto";
|
|
3017
|
-
container.style.backgroundColor = "#1e1e1e";
|
|
3018
|
-
container.style.color = "#d4d4d4";
|
|
3019
|
-
container.style.padding = "16px";
|
|
3020
|
-
container.style.boxSizing = "border-box";
|
|
3021
3169
|
let fontSize = 13;
|
|
3022
3170
|
let rotation = 0;
|
|
3171
|
+
let zoomLevel = 1;
|
|
3023
3172
|
const pre = document.createElement("pre");
|
|
3024
|
-
pre.style.margin = "0";
|
|
3025
|
-
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
3026
|
-
pre.style.fontSize = `${fontSize}px`;
|
|
3027
|
-
pre.style.lineHeight = "1.5";
|
|
3028
|
-
pre.style.whiteSpace = "pre-wrap";
|
|
3029
|
-
pre.style.wordBreak = "break-all";
|
|
3030
3173
|
const code = document.createElement("code");
|
|
3174
|
+
if (isTxt) {
|
|
3175
|
+
container.style.backgroundColor = "#f1f5f9";
|
|
3176
|
+
container.style.padding = "32px";
|
|
3177
|
+
container.style.boxSizing = "border-box";
|
|
3178
|
+
container.style.display = "flex";
|
|
3179
|
+
container.style.flexDirection = "column";
|
|
3180
|
+
container.style.alignItems = "center";
|
|
3181
|
+
pre.style.margin = "0";
|
|
3182
|
+
pre.style.fontFamily = "Consolas, 'Courier New', monospace";
|
|
3183
|
+
pre.style.fontSize = "13px";
|
|
3184
|
+
pre.style.color = "#1e293b";
|
|
3185
|
+
pre.style.lineHeight = "1.5";
|
|
3186
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3187
|
+
pre.style.wordBreak = "break-word";
|
|
3188
|
+
pre.style.backgroundColor = "#ffffff";
|
|
3189
|
+
pre.style.width = "816px";
|
|
3190
|
+
pre.style.minHeight = "1056px";
|
|
3191
|
+
pre.style.padding = "72px 56px";
|
|
3192
|
+
pre.style.boxSizing = "border-box";
|
|
3193
|
+
pre.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)";
|
|
3194
|
+
pre.style.borderRadius = "4px";
|
|
3195
|
+
pre.style.transformOrigin = "top center";
|
|
3196
|
+
} else {
|
|
3197
|
+
container.style.backgroundColor = "#1e1e1e";
|
|
3198
|
+
container.style.color = "#d4d4d4";
|
|
3199
|
+
container.style.padding = "16px";
|
|
3200
|
+
container.style.boxSizing = "border-box";
|
|
3201
|
+
pre.style.margin = "0";
|
|
3202
|
+
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
3203
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3204
|
+
pre.style.lineHeight = "1.5";
|
|
3205
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3206
|
+
pre.style.wordBreak = "break-all";
|
|
3207
|
+
pre.style.transformOrigin = "top left";
|
|
3208
|
+
}
|
|
3031
3209
|
const ext = (ctx.metadata.extension || "").replace(".", "");
|
|
3032
3210
|
const renderCodePage = (text) => {
|
|
3033
|
-
|
|
3034
|
-
if (ext && hljs__default.default.getLanguage(ext)) {
|
|
3035
|
-
code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
|
|
3036
|
-
} else {
|
|
3037
|
-
code.innerHTML = hljs__default.default.highlightAuto(text).value;
|
|
3038
|
-
}
|
|
3039
|
-
} catch {
|
|
3211
|
+
if (isTxt) {
|
|
3040
3212
|
code.textContent = text;
|
|
3213
|
+
} else {
|
|
3214
|
+
try {
|
|
3215
|
+
if (ext && hljs__default.default.getLanguage(ext)) {
|
|
3216
|
+
code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
|
|
3217
|
+
} else {
|
|
3218
|
+
code.innerHTML = hljs__default.default.highlightAuto(text).value;
|
|
3219
|
+
}
|
|
3220
|
+
} catch {
|
|
3221
|
+
code.textContent = text;
|
|
3222
|
+
}
|
|
3041
3223
|
}
|
|
3042
3224
|
};
|
|
3043
|
-
renderCodePage(rawPages[0] || fullText);
|
|
3225
|
+
renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
|
|
3044
3226
|
pre.appendChild(code);
|
|
3045
3227
|
container.appendChild(pre);
|
|
3046
3228
|
let indicator = null;
|
|
@@ -3049,15 +3231,22 @@ var CodePlugin = class {
|
|
|
3049
3231
|
indicator.className = "fp-code-page-indicator";
|
|
3050
3232
|
indicator.style.position = "sticky";
|
|
3051
3233
|
indicator.style.bottom = "16px";
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3234
|
+
if (isTxt) {
|
|
3235
|
+
indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
3236
|
+
indicator.style.color = "#334155";
|
|
3237
|
+
indicator.style.border = "1px solid #e2e8f0";
|
|
3238
|
+
indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
|
|
3239
|
+
} else {
|
|
3240
|
+
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3241
|
+
indicator.style.color = "#f8fafc";
|
|
3242
|
+
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3243
|
+
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3244
|
+
indicator.style.backdropFilter = "blur(8px)";
|
|
3245
|
+
}
|
|
3055
3246
|
indicator.style.fontSize = "12px";
|
|
3056
3247
|
indicator.style.fontWeight = "600";
|
|
3057
3248
|
indicator.style.padding = "5px 14px";
|
|
3058
3249
|
indicator.style.borderRadius = "20px";
|
|
3059
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3060
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3061
3250
|
indicator.style.zIndex = "10";
|
|
3062
3251
|
indicator.style.userSelect = "none";
|
|
3063
3252
|
indicator.style.pointerEvents = "none";
|
|
@@ -3068,7 +3257,7 @@ var CodePlugin = class {
|
|
|
3068
3257
|
}
|
|
3069
3258
|
const showPage = (pageNum) => {
|
|
3070
3259
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3071
|
-
renderCodePage(rawPages[currentPage - 1] || fullText);
|
|
3260
|
+
renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
|
|
3072
3261
|
if (indicator) {
|
|
3073
3262
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
3074
3263
|
}
|
|
@@ -3084,39 +3273,57 @@ var CodePlugin = class {
|
|
|
3084
3273
|
ctx.container.innerHTML = "";
|
|
3085
3274
|
};
|
|
3086
3275
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3276
|
+
const updateTransform = () => {
|
|
3277
|
+
if (isTxt) {
|
|
3278
|
+
pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
|
|
3279
|
+
} else {
|
|
3280
|
+
pre.style.transform = `rotate(${rotation}deg)`;
|
|
3281
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3282
|
+
}
|
|
3283
|
+
};
|
|
3087
3284
|
return {
|
|
3088
3285
|
destroy: cleanup,
|
|
3089
3286
|
getPageCount: () => totalPages,
|
|
3090
3287
|
getCurrentPage: () => currentPage,
|
|
3091
3288
|
goToPage: (page) => showPage(page),
|
|
3092
3289
|
zoomIn: () => {
|
|
3093
|
-
|
|
3094
|
-
|
|
3290
|
+
if (isTxt) {
|
|
3291
|
+
zoomLevel = Math.min(3, zoomLevel + 0.1);
|
|
3292
|
+
} else {
|
|
3293
|
+
fontSize = Math.min(32, fontSize + 2);
|
|
3294
|
+
}
|
|
3295
|
+
updateTransform();
|
|
3095
3296
|
},
|
|
3096
3297
|
zoomOut: () => {
|
|
3097
|
-
|
|
3098
|
-
|
|
3298
|
+
if (isTxt) {
|
|
3299
|
+
zoomLevel = Math.max(0.1, zoomLevel - 0.1);
|
|
3300
|
+
} else {
|
|
3301
|
+
fontSize = Math.max(8, fontSize - 2);
|
|
3302
|
+
}
|
|
3303
|
+
updateTransform();
|
|
3099
3304
|
},
|
|
3100
|
-
getZoom: () => fontSize / 13,
|
|
3305
|
+
getZoom: () => isTxt ? zoomLevel : fontSize / 13,
|
|
3101
3306
|
setZoom: (level) => {
|
|
3102
|
-
|
|
3103
|
-
|
|
3307
|
+
if (isTxt) {
|
|
3308
|
+
zoomLevel = level;
|
|
3309
|
+
} else {
|
|
3310
|
+
fontSize = Math.round(13 * level);
|
|
3311
|
+
}
|
|
3312
|
+
updateTransform();
|
|
3104
3313
|
},
|
|
3105
3314
|
fitToPage: () => {
|
|
3106
3315
|
fontSize = 13;
|
|
3107
3316
|
rotation = 0;
|
|
3108
|
-
|
|
3109
|
-
|
|
3317
|
+
zoomLevel = isTxt ? Math.max(0.65, Math.min(1.05, (container.clientWidth - 48) / 816)) : 1;
|
|
3318
|
+
updateTransform();
|
|
3110
3319
|
},
|
|
3111
3320
|
rotateCW: () => {
|
|
3112
3321
|
rotation = (rotation + 90) % 360;
|
|
3113
|
-
|
|
3114
|
-
pre.style.transformOrigin = "top left";
|
|
3322
|
+
updateTransform();
|
|
3115
3323
|
},
|
|
3116
3324
|
rotateCCW: () => {
|
|
3117
3325
|
rotation = (rotation - 90 + 360) % 360;
|
|
3118
|
-
|
|
3119
|
-
pre.style.transformOrigin = "top left";
|
|
3326
|
+
updateTransform();
|
|
3120
3327
|
},
|
|
3121
3328
|
download: () => {
|
|
3122
3329
|
const mimeType = ctx.metadata.mimeType || "text/plain";
|
|
@@ -3415,7 +3622,7 @@ var MarkdownPlugin = class {
|
|
|
3415
3622
|
gfm: true,
|
|
3416
3623
|
breaks: true
|
|
3417
3624
|
});
|
|
3418
|
-
const cleanHtml =
|
|
3625
|
+
const cleanHtml = DOMPurify6__default.default.sanitize(rawHtml, {
|
|
3419
3626
|
USE_PROFILES: { html: true }
|
|
3420
3627
|
});
|
|
3421
3628
|
const wrapper = document.createElement("div");
|
|
@@ -4051,6 +4258,14 @@ var RtfPlugin = class {
|
|
|
4051
4258
|
group: "actions",
|
|
4052
4259
|
execute: () => instance.download?.()
|
|
4053
4260
|
},
|
|
4261
|
+
{
|
|
4262
|
+
id: "copy",
|
|
4263
|
+
icon: "copy",
|
|
4264
|
+
label: "Copy Text",
|
|
4265
|
+
type: "button",
|
|
4266
|
+
group: "actions",
|
|
4267
|
+
execute: () => instance.copy?.()
|
|
4268
|
+
},
|
|
4054
4269
|
{
|
|
4055
4270
|
id: "print",
|
|
4056
4271
|
icon: "print",
|
|
@@ -4081,20 +4296,27 @@ var RtfPlugin = class {
|
|
|
4081
4296
|
let scale = 1;
|
|
4082
4297
|
let rotation = 0;
|
|
4083
4298
|
let pageElements = [];
|
|
4084
|
-
|
|
4299
|
+
let fitMode = "width";
|
|
4300
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
4085
4301
|
const activeEl = pageElements[currentPage - 1] || wrapper;
|
|
4086
4302
|
const elW = activeEl.offsetWidth || 850;
|
|
4087
|
-
const
|
|
4088
|
-
const availW = Math.max(
|
|
4089
|
-
const availH = Math.max(
|
|
4090
|
-
|
|
4303
|
+
const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
4304
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
4305
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
4306
|
+
const sW = availW / elW;
|
|
4307
|
+
const sH = availH / singlePageH;
|
|
4308
|
+
if (mode === "page") {
|
|
4309
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
4310
|
+
}
|
|
4311
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
4091
4312
|
};
|
|
4092
4313
|
const applyTransform = () => {
|
|
4093
4314
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4094
4315
|
wrapper.style.transformOrigin = "top center";
|
|
4095
4316
|
};
|
|
4096
4317
|
setTimeout(() => {
|
|
4097
|
-
|
|
4318
|
+
fitMode = "width";
|
|
4319
|
+
scale = calculateFitScale("width");
|
|
4098
4320
|
applyTransform();
|
|
4099
4321
|
}, 60);
|
|
4100
4322
|
try {
|
|
@@ -4112,14 +4334,31 @@ var RtfPlugin = class {
|
|
|
4112
4334
|
} catch (err) {
|
|
4113
4335
|
console.warn("[RtfPlugin] RTF render error, fallback text:", err);
|
|
4114
4336
|
const text = new TextDecoder("latin1").decode(ctx.buffer);
|
|
4115
|
-
const
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4337
|
+
const rawPages = text.split(/\\page\b/).map((segment) => {
|
|
4338
|
+
return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
|
|
4339
|
+
}).filter((p) => p.length > 0);
|
|
4340
|
+
const pages = rawPages.length > 0 ? rawPages : [text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim()];
|
|
4341
|
+
for (let i = 0; i < pages.length; i++) {
|
|
4342
|
+
const pageCard = document.createElement("div");
|
|
4343
|
+
pageCard.className = "fp-rtf-page-card";
|
|
4344
|
+
pageCard.style.backgroundColor = "#ffffff";
|
|
4345
|
+
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4346
|
+
pageCard.style.borderRadius = "4px";
|
|
4347
|
+
pageCard.style.padding = "72px 56px";
|
|
4348
|
+
pageCard.style.width = "816px";
|
|
4349
|
+
pageCard.style.minHeight = "1056px";
|
|
4350
|
+
pageCard.style.maxWidth = "100%";
|
|
4351
|
+
pageCard.style.boxSizing = "border-box";
|
|
4352
|
+
pageCard.style.fontFamily = "serif";
|
|
4353
|
+
pageCard.style.fontSize = "12pt";
|
|
4354
|
+
pageCard.style.lineHeight = "1.6";
|
|
4355
|
+
pageCard.style.color = "#1e293b";
|
|
4356
|
+
pageCard.style.whiteSpace = "pre-wrap";
|
|
4357
|
+
pageCard.style.display = i === 0 ? "block" : "none";
|
|
4358
|
+
pageCard.textContent = pages[i];
|
|
4359
|
+
wrapper.appendChild(pageCard);
|
|
4360
|
+
pageElements.push(pageCard);
|
|
4361
|
+
}
|
|
4123
4362
|
}
|
|
4124
4363
|
const totalPages = Math.max(1, pageElements.length);
|
|
4125
4364
|
let currentPage = 1;
|
|
@@ -4186,7 +4425,8 @@ var RtfPlugin = class {
|
|
|
4186
4425
|
applyTransform();
|
|
4187
4426
|
},
|
|
4188
4427
|
fitToPage: () => {
|
|
4189
|
-
|
|
4428
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
4429
|
+
scale = calculateFitScale(fitMode);
|
|
4190
4430
|
rotation = 0;
|
|
4191
4431
|
applyTransform();
|
|
4192
4432
|
},
|
|
@@ -4207,6 +4447,10 @@ var RtfPlugin = class {
|
|
|
4207
4447
|
a.click();
|
|
4208
4448
|
URL.revokeObjectURL(url);
|
|
4209
4449
|
},
|
|
4450
|
+
copy: () => {
|
|
4451
|
+
const text = wrapper.textContent || "";
|
|
4452
|
+
navigator.clipboard?.writeText(text);
|
|
4453
|
+
},
|
|
4210
4454
|
print: () => {
|
|
4211
4455
|
window.print();
|
|
4212
4456
|
}
|
|
@@ -4281,7 +4525,7 @@ var HtmlPreviewPlugin = class {
|
|
|
4281
4525
|
}
|
|
4282
4526
|
async render(ctx) {
|
|
4283
4527
|
const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
|
|
4284
|
-
const sanitized =
|
|
4528
|
+
const sanitized = DOMPurify6__default.default.sanitize(rawHtml, {
|
|
4285
4529
|
WHOLE_DOCUMENT: true,
|
|
4286
4530
|
ADD_TAGS: ["style", "link"],
|
|
4287
4531
|
ADD_ATTR: ["target", "rel"]
|
|
@@ -4501,19 +4745,29 @@ var OpenDocumentPlugin = class {
|
|
|
4501
4745
|
ctx.container.appendChild(container);
|
|
4502
4746
|
let scale = 1;
|
|
4503
4747
|
let rotation = 0;
|
|
4504
|
-
|
|
4748
|
+
let fitMode = "width";
|
|
4749
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
4505
4750
|
const elW = wrapper.offsetWidth || 850;
|
|
4506
|
-
const
|
|
4507
|
-
const availW = Math.max(
|
|
4508
|
-
const availH = Math.max(
|
|
4509
|
-
|
|
4751
|
+
const singlePageH = Math.min(wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
4752
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
4753
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
4754
|
+
const sW = availW / elW;
|
|
4755
|
+
const sH = availH / (isPresentation ? 540 : singlePageH);
|
|
4756
|
+
if (isPresentation) {
|
|
4757
|
+
return Math.min(1, Math.min(sW, sH));
|
|
4758
|
+
}
|
|
4759
|
+
if (mode === "page") {
|
|
4760
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
4761
|
+
}
|
|
4762
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
4510
4763
|
};
|
|
4511
4764
|
const applyTransform = () => {
|
|
4512
4765
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4513
4766
|
wrapper.style.transformOrigin = "top center";
|
|
4514
4767
|
};
|
|
4515
4768
|
setTimeout(() => {
|
|
4516
|
-
|
|
4769
|
+
fitMode = "width";
|
|
4770
|
+
scale = calculateFitScale("width");
|
|
4517
4771
|
applyTransform();
|
|
4518
4772
|
}, 60);
|
|
4519
4773
|
let currentPage = 1;
|
|
@@ -4547,14 +4801,97 @@ var OpenDocumentPlugin = class {
|
|
|
4547
4801
|
wrapper.textContent = contentDoc.documentElement.textContent || "Formula content";
|
|
4548
4802
|
}
|
|
4549
4803
|
} else {
|
|
4550
|
-
wrapper.style.maxWidth = "
|
|
4551
|
-
wrapper.style.padding = "
|
|
4804
|
+
wrapper.style.maxWidth = "none";
|
|
4805
|
+
wrapper.style.padding = "0";
|
|
4552
4806
|
wrapper.style.minHeight = "100%";
|
|
4807
|
+
wrapper.style.backgroundColor = "transparent";
|
|
4808
|
+
wrapper.style.boxShadow = "none";
|
|
4809
|
+
wrapper.style.position = "relative";
|
|
4810
|
+
const dims = this.getPageDimensions(stylesDoc, contentDoc);
|
|
4553
4811
|
const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
|
|
4554
|
-
|
|
4555
|
-
|
|
4812
|
+
const tempDiv = document.createElement("div");
|
|
4813
|
+
tempDiv.style.width = `${dims.width - dims.marginLeft - dims.marginRight}px`;
|
|
4814
|
+
tempDiv.style.position = "absolute";
|
|
4815
|
+
tempDiv.style.visibility = "hidden";
|
|
4816
|
+
tempDiv.innerHTML = DOMPurify6__default.default.sanitize(bodyHtml, {
|
|
4817
|
+
ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub", "hr"],
|
|
4556
4818
|
ADD_ATTR: ["style", "colspan", "rowspan"]
|
|
4557
4819
|
});
|
|
4820
|
+
document.body.appendChild(tempDiv);
|
|
4821
|
+
const contentHeight = dims.height - dims.marginTop - dims.marginBottom;
|
|
4822
|
+
const pageElements = [[]];
|
|
4823
|
+
let currentHeight = 0;
|
|
4824
|
+
let currentPageIdx = 0;
|
|
4825
|
+
Array.from(tempDiv.children).forEach((child) => {
|
|
4826
|
+
const el = child;
|
|
4827
|
+
const style = el.getAttribute("style") || "";
|
|
4828
|
+
const isBreakBefore = style.includes("page-break-before: always");
|
|
4829
|
+
const isBreakAfter = style.includes("page-break-after: always");
|
|
4830
|
+
const isSoftBreak = el.classList.contains("odf-page-break");
|
|
4831
|
+
if (isBreakBefore) {
|
|
4832
|
+
if (pageElements[currentPageIdx].length > 0) {
|
|
4833
|
+
currentPageIdx++;
|
|
4834
|
+
pageElements.push([]);
|
|
4835
|
+
currentHeight = 0;
|
|
4836
|
+
}
|
|
4837
|
+
}
|
|
4838
|
+
const h = el.offsetHeight || 0;
|
|
4839
|
+
if (currentHeight + h > contentHeight && pageElements[currentPageIdx].length > 0 && !isSoftBreak) {
|
|
4840
|
+
currentPageIdx++;
|
|
4841
|
+
pageElements.push([]);
|
|
4842
|
+
currentHeight = 0;
|
|
4843
|
+
}
|
|
4844
|
+
if (!isSoftBreak) {
|
|
4845
|
+
pageElements[currentPageIdx].push(el.cloneNode(true));
|
|
4846
|
+
currentHeight += h;
|
|
4847
|
+
}
|
|
4848
|
+
if (isBreakAfter || isSoftBreak) {
|
|
4849
|
+
currentPageIdx++;
|
|
4850
|
+
pageElements.push([]);
|
|
4851
|
+
currentHeight = 0;
|
|
4852
|
+
}
|
|
4853
|
+
});
|
|
4854
|
+
document.body.removeChild(tempDiv);
|
|
4855
|
+
if (pageElements.length > 1 && pageElements[pageElements.length - 1].length === 0) {
|
|
4856
|
+
pageElements.pop();
|
|
4857
|
+
}
|
|
4858
|
+
totalPages = Math.max(1, pageElements.length);
|
|
4859
|
+
pageElements.forEach((elements, idx) => {
|
|
4860
|
+
const page = document.createElement("div");
|
|
4861
|
+
page.className = `fp-odt-page fp-odt-page-${idx + 1}`;
|
|
4862
|
+
page.style.width = `${dims.width}px`;
|
|
4863
|
+
page.style.minHeight = `${dims.height}px`;
|
|
4864
|
+
page.style.padding = `${dims.marginTop}px ${dims.marginRight}px ${dims.marginBottom}px ${dims.marginLeft}px`;
|
|
4865
|
+
page.style.margin = "0 auto";
|
|
4866
|
+
page.style.backgroundColor = "#ffffff";
|
|
4867
|
+
page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
4868
|
+
page.style.borderRadius = "4px";
|
|
4869
|
+
page.style.boxSizing = "border-box";
|
|
4870
|
+
page.style.display = idx === 0 ? "block" : "none";
|
|
4871
|
+
page.style.position = "absolute";
|
|
4872
|
+
page.style.top = "0";
|
|
4873
|
+
page.style.left = "50%";
|
|
4874
|
+
page.style.transform = "translateX(-50%)";
|
|
4875
|
+
elements.forEach((el) => page.appendChild(el));
|
|
4876
|
+
wrapper.appendChild(page);
|
|
4877
|
+
slides.push(page);
|
|
4878
|
+
});
|
|
4879
|
+
const pageIndicator = document.createElement("div");
|
|
4880
|
+
pageIndicator.className = "fp-odt-page-indicator";
|
|
4881
|
+
pageIndicator.style.position = "sticky";
|
|
4882
|
+
pageIndicator.style.bottom = "16px";
|
|
4883
|
+
pageIndicator.style.left = "50%";
|
|
4884
|
+
pageIndicator.style.transform = "translateX(-50%)";
|
|
4885
|
+
pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
|
4886
|
+
pageIndicator.style.color = "#fff";
|
|
4887
|
+
pageIndicator.style.padding = "6px 12px";
|
|
4888
|
+
pageIndicator.style.borderRadius = "16px";
|
|
4889
|
+
pageIndicator.style.fontSize = "12px";
|
|
4890
|
+
pageIndicator.style.zIndex = "100";
|
|
4891
|
+
pageIndicator.style.display = "inline-block";
|
|
4892
|
+
pageIndicator.style.width = "fit-content";
|
|
4893
|
+
pageIndicator.textContent = `Page 1 of ${totalPages}`;
|
|
4894
|
+
container.appendChild(pageIndicator);
|
|
4558
4895
|
}
|
|
4559
4896
|
const cleanup = () => {
|
|
4560
4897
|
imageUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
@@ -4563,11 +4900,15 @@ var OpenDocumentPlugin = class {
|
|
|
4563
4900
|
};
|
|
4564
4901
|
ctx.signal.addEventListener("abort", cleanup);
|
|
4565
4902
|
const goToPage = (page) => {
|
|
4566
|
-
if (
|
|
4903
|
+
if (page < 1 || page > totalPages) return;
|
|
4567
4904
|
currentPage = page;
|
|
4568
4905
|
slides.forEach((s, idx) => {
|
|
4569
4906
|
s.style.display = idx === page - 1 ? "block" : "none";
|
|
4570
4907
|
});
|
|
4908
|
+
const indicator = container.querySelector(".fp-odt-page-indicator");
|
|
4909
|
+
if (indicator) {
|
|
4910
|
+
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4911
|
+
}
|
|
4571
4912
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4572
4913
|
};
|
|
4573
4914
|
return {
|
|
@@ -4587,7 +4928,8 @@ var OpenDocumentPlugin = class {
|
|
|
4587
4928
|
applyTransform();
|
|
4588
4929
|
},
|
|
4589
4930
|
fitToPage: () => {
|
|
4590
|
-
|
|
4931
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
4932
|
+
scale = calculateFitScale(fitMode);
|
|
4591
4933
|
rotation = 0;
|
|
4592
4934
|
applyTransform();
|
|
4593
4935
|
},
|
|
@@ -4636,6 +4978,43 @@ var OpenDocumentPlugin = class {
|
|
|
4636
4978
|
}
|
|
4637
4979
|
};
|
|
4638
4980
|
}
|
|
4981
|
+
getPageDimensions(stylesDoc, contentDoc) {
|
|
4982
|
+
let width = 850;
|
|
4983
|
+
let height = 1123;
|
|
4984
|
+
let marginTop = 48;
|
|
4985
|
+
let marginBottom = 48;
|
|
4986
|
+
let marginLeft = 48;
|
|
4987
|
+
let marginRight = 48;
|
|
4988
|
+
const parseUnit = (val) => {
|
|
4989
|
+
if (!val) return null;
|
|
4990
|
+
if (val.endsWith("cm")) return parseFloat(val) * 37.8;
|
|
4991
|
+
if (val.endsWith("mm")) return parseFloat(val) * 3.78;
|
|
4992
|
+
if (val.endsWith("in")) return parseFloat(val) * 96;
|
|
4993
|
+
if (val.endsWith("pt")) return parseFloat(val) * 1.33;
|
|
4994
|
+
if (val.endsWith("px")) return parseFloat(val);
|
|
4995
|
+
return parseFloat(val);
|
|
4996
|
+
};
|
|
4997
|
+
const docs = [stylesDoc, contentDoc].filter(Boolean);
|
|
4998
|
+
for (const doc of docs) {
|
|
4999
|
+
const pageLayout = doc.querySelector("page-layout-properties, [page-width]");
|
|
5000
|
+
if (pageLayout) {
|
|
5001
|
+
const w = parseUnit(pageLayout.getAttribute("fo:page-width") || pageLayout.getAttribute("page-width"));
|
|
5002
|
+
const h = parseUnit(pageLayout.getAttribute("fo:page-height") || pageLayout.getAttribute("page-height"));
|
|
5003
|
+
const mt = parseUnit(pageLayout.getAttribute("fo:margin-top") || pageLayout.getAttribute("margin-top"));
|
|
5004
|
+
const mb = parseUnit(pageLayout.getAttribute("fo:margin-bottom") || pageLayout.getAttribute("margin-bottom"));
|
|
5005
|
+
const ml = parseUnit(pageLayout.getAttribute("fo:margin-left") || pageLayout.getAttribute("margin-left"));
|
|
5006
|
+
const mr = parseUnit(pageLayout.getAttribute("fo:margin-right") || pageLayout.getAttribute("margin-right"));
|
|
5007
|
+
if (w !== null) width = w;
|
|
5008
|
+
if (h !== null) height = h;
|
|
5009
|
+
if (mt !== null) marginTop = mt;
|
|
5010
|
+
if (mb !== null) marginBottom = mb;
|
|
5011
|
+
if (ml !== null) marginLeft = ml;
|
|
5012
|
+
if (mr !== null) marginRight = mr;
|
|
5013
|
+
break;
|
|
5014
|
+
}
|
|
5015
|
+
}
|
|
5016
|
+
return { width, height, marginTop, marginBottom, marginLeft, marginRight };
|
|
5017
|
+
}
|
|
4639
5018
|
extractStyles(stylesDoc, contentDoc) {
|
|
4640
5019
|
const map = /* @__PURE__ */ new Map();
|
|
4641
5020
|
const styleNodes = [];
|
|
@@ -4658,14 +5037,21 @@ var OpenDocumentPlugin = class {
|
|
|
4658
5037
|
if (color) css += `color: ${color}; `;
|
|
4659
5038
|
if (size) css += `font-size: ${size}; `;
|
|
4660
5039
|
}
|
|
4661
|
-
|
|
5040
|
+
let paraProp = node.querySelector("paragraph-properties, [text-align]");
|
|
5041
|
+
if (!paraProp) {
|
|
5042
|
+
paraProp = Array.from(node.children).find((c) => c.tagName.includes("paragraph-properties")) || null;
|
|
5043
|
+
}
|
|
4662
5044
|
if (paraProp) {
|
|
4663
5045
|
const align = paraProp.getAttribute("fo:text-align") || paraProp.getAttribute("text-align");
|
|
4664
5046
|
const mt = paraProp.getAttribute("fo:margin-top") || paraProp.getAttribute("margin-top");
|
|
4665
5047
|
const mb = paraProp.getAttribute("fo:margin-bottom") || paraProp.getAttribute("margin-bottom");
|
|
5048
|
+
const breakBefore = paraProp.getAttribute("fo:break-before") || paraProp.getAttribute("break-before");
|
|
5049
|
+
const breakAfter = paraProp.getAttribute("fo:break-after") || paraProp.getAttribute("break-after");
|
|
4666
5050
|
if (align) css += `text-align: ${align}; `;
|
|
4667
5051
|
if (mt) css += `margin-top: ${mt}; `;
|
|
4668
5052
|
if (mb) css += `margin-bottom: ${mb}; `;
|
|
5053
|
+
if (breakBefore === "page") css += "page-break-before: always; ";
|
|
5054
|
+
if (breakAfter === "page") css += "page-break-after: always; ";
|
|
4669
5055
|
}
|
|
4670
5056
|
if (css) map.set(name, css);
|
|
4671
5057
|
}
|
|
@@ -4750,6 +5136,8 @@ var OpenDocumentPlugin = class {
|
|
|
4750
5136
|
result += " ";
|
|
4751
5137
|
} else if (tag === "line-break") {
|
|
4752
5138
|
result += "<br/>";
|
|
5139
|
+
} else if (tag === "soft-page-break") {
|
|
5140
|
+
result += '<hr class="odf-page-break" style="page-break-after: always; border: none; margin: 0; padding: 0; height: 0;" />';
|
|
4753
5141
|
} else {
|
|
4754
5142
|
result += el.textContent || "";
|
|
4755
5143
|
}
|
|
@@ -4910,20 +5298,9 @@ var DocPlugin = class {
|
|
|
4910
5298
|
container.style.overflow = "auto";
|
|
4911
5299
|
container.style.padding = "32px 16px";
|
|
4912
5300
|
container.style.backgroundColor = "#f1f5f9";
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
4916
|
-
wrapper.style.margin = "0 auto";
|
|
4917
|
-
wrapper.style.backgroundColor = "#ffffff";
|
|
4918
|
-
wrapper.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4919
|
-
wrapper.style.borderRadius = "4px";
|
|
4920
|
-
wrapper.style.padding = "56px 48px";
|
|
4921
|
-
wrapper.style.minHeight = "100%";
|
|
4922
|
-
wrapper.style.transformOrigin = "top center";
|
|
4923
|
-
wrapper.style.transition = "transform 0.2s ease";
|
|
4924
|
-
wrapper.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4925
|
-
wrapper.style.color = "#1e293b";
|
|
4926
|
-
container.appendChild(wrapper);
|
|
5301
|
+
container.style.display = "flex";
|
|
5302
|
+
container.style.justifyContent = "center";
|
|
5303
|
+
container.style.alignItems = "flex-start";
|
|
4927
5304
|
ctx.container.appendChild(container);
|
|
4928
5305
|
let scale = 1;
|
|
4929
5306
|
let extractedRawText = "";
|
|
@@ -4950,21 +5327,27 @@ var DocPlugin = class {
|
|
|
4950
5327
|
const rawPages = this.splitIntoPages(extractedRawText);
|
|
4951
5328
|
const totalPages = Math.max(1, rawPages.length);
|
|
4952
5329
|
let currentPage = 1;
|
|
4953
|
-
wrapper.innerHTML = "";
|
|
4954
5330
|
const pageCards = [];
|
|
4955
5331
|
for (let i = 0; i < totalPages; i++) {
|
|
4956
5332
|
const pageCard = document.createElement("div");
|
|
4957
5333
|
pageCard.className = "fp-doc-page-card";
|
|
5334
|
+
pageCard.style.width = "816px";
|
|
5335
|
+
pageCard.style.height = "1056px";
|
|
4958
5336
|
pageCard.style.backgroundColor = "#ffffff";
|
|
4959
5337
|
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4960
5338
|
pageCard.style.borderRadius = "4px";
|
|
4961
|
-
pageCard.style.padding = "
|
|
4962
|
-
pageCard.style.
|
|
5339
|
+
pageCard.style.padding = "96px 72px";
|
|
5340
|
+
pageCard.style.boxSizing = "border-box";
|
|
5341
|
+
pageCard.style.overflow = "hidden";
|
|
4963
5342
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5343
|
+
pageCard.style.transformOrigin = "top center";
|
|
5344
|
+
pageCard.style.transition = "transform 0.2s ease";
|
|
5345
|
+
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
5346
|
+
pageCard.style.color = "#1e293b";
|
|
4964
5347
|
if (isFallback && i === 0) {
|
|
4965
5348
|
pageCard.innerHTML = `
|
|
4966
5349
|
<div style="border-bottom: 1px solid #e2e8f0; padding-bottom: 12px; margin-bottom: 24px;">
|
|
4967
|
-
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${
|
|
5350
|
+
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify6__default.default.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
|
|
4968
5351
|
<span style="font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 4px;">Legacy Word 97-2003 Binary Preview</span>
|
|
4969
5352
|
</div>
|
|
4970
5353
|
${this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document")}
|
|
@@ -4972,15 +5355,17 @@ var DocPlugin = class {
|
|
|
4972
5355
|
} else {
|
|
4973
5356
|
pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
|
|
4974
5357
|
}
|
|
4975
|
-
|
|
5358
|
+
container.appendChild(pageCard);
|
|
4976
5359
|
pageCards.push(pageCard);
|
|
4977
5360
|
}
|
|
4978
5361
|
let indicator = null;
|
|
4979
5362
|
if (totalPages > 1) {
|
|
4980
5363
|
indicator = document.createElement("div");
|
|
4981
5364
|
indicator.className = "fp-doc-page-indicator";
|
|
4982
|
-
indicator.style.position = "
|
|
5365
|
+
indicator.style.position = "fixed";
|
|
4983
5366
|
indicator.style.bottom = "16px";
|
|
5367
|
+
indicator.style.left = "50%";
|
|
5368
|
+
indicator.style.transform = "translateX(-50%)";
|
|
4984
5369
|
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4985
5370
|
indicator.style.backdropFilter = "blur(8px)";
|
|
4986
5371
|
indicator.style.color = "#f8fafc";
|
|
@@ -4994,17 +5379,25 @@ var DocPlugin = class {
|
|
|
4994
5379
|
indicator.style.userSelect = "none";
|
|
4995
5380
|
indicator.style.pointerEvents = "none";
|
|
4996
5381
|
indicator.style.textAlign = "center";
|
|
4997
|
-
indicator.style.width = "fit-content";
|
|
4998
|
-
indicator.style.margin = "16px auto 0";
|
|
4999
5382
|
container.appendChild(indicator);
|
|
5000
5383
|
}
|
|
5384
|
+
let rotation = 0;
|
|
5385
|
+
const applyTransform = () => {
|
|
5386
|
+
const activeCard = pageCards[currentPage - 1];
|
|
5387
|
+
if (activeCard) {
|
|
5388
|
+
activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5389
|
+
}
|
|
5390
|
+
};
|
|
5001
5391
|
const showPage = (pageNum) => {
|
|
5002
5392
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
card.style.display =
|
|
5006
|
-
|
|
5007
|
-
|
|
5393
|
+
pageCards.forEach((card, idx) => {
|
|
5394
|
+
if (idx + 1 === currentPage) {
|
|
5395
|
+
card.style.display = "block";
|
|
5396
|
+
card.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5397
|
+
} else {
|
|
5398
|
+
card.style.display = "none";
|
|
5399
|
+
}
|
|
5400
|
+
});
|
|
5008
5401
|
if (indicator) {
|
|
5009
5402
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
5010
5403
|
}
|
|
@@ -5013,21 +5406,22 @@ var DocPlugin = class {
|
|
|
5013
5406
|
if (totalPages > 1) {
|
|
5014
5407
|
showPage(1);
|
|
5015
5408
|
}
|
|
5016
|
-
let
|
|
5017
|
-
const calculateFitScale = () => {
|
|
5018
|
-
const
|
|
5019
|
-
const
|
|
5020
|
-
const
|
|
5021
|
-
const
|
|
5022
|
-
const
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5409
|
+
let fitMode = "width";
|
|
5410
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
5411
|
+
const elW = 816;
|
|
5412
|
+
const elH = 1056;
|
|
5413
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
5414
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
5415
|
+
const sW = availW / elW;
|
|
5416
|
+
const sH = availH / elH;
|
|
5417
|
+
if (mode === "page") {
|
|
5418
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
5419
|
+
}
|
|
5420
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
5028
5421
|
};
|
|
5029
5422
|
setTimeout(() => {
|
|
5030
|
-
|
|
5423
|
+
fitMode = "width";
|
|
5424
|
+
scale = calculateFitScale("width");
|
|
5031
5425
|
applyTransform();
|
|
5032
5426
|
}, 60);
|
|
5033
5427
|
const cleanup = () => {
|
|
@@ -5055,7 +5449,8 @@ var DocPlugin = class {
|
|
|
5055
5449
|
applyTransform();
|
|
5056
5450
|
},
|
|
5057
5451
|
fitToPage: () => {
|
|
5058
|
-
|
|
5452
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
5453
|
+
scale = calculateFitScale(fitMode);
|
|
5059
5454
|
rotation = 0;
|
|
5060
5455
|
applyTransform();
|
|
5061
5456
|
},
|
|
@@ -5183,8 +5578,28 @@ var DocPlugin = class {
|
|
|
5183
5578
|
}
|
|
5184
5579
|
splitIntoPages(text) {
|
|
5185
5580
|
if (!text) return [""];
|
|
5186
|
-
const
|
|
5187
|
-
|
|
5581
|
+
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);
|
|
5582
|
+
if (explicitParts.length === 0) explicitParts.push(text);
|
|
5583
|
+
const maxLinesPerPage = 48;
|
|
5584
|
+
const finalPages = [];
|
|
5585
|
+
for (const part of explicitParts) {
|
|
5586
|
+
const lines = part.split(/\r?\n/);
|
|
5587
|
+
let currentLines = [];
|
|
5588
|
+
let count = 0;
|
|
5589
|
+
for (const line of lines) {
|
|
5590
|
+
currentLines.push(line);
|
|
5591
|
+
count++;
|
|
5592
|
+
if (count >= maxLinesPerPage) {
|
|
5593
|
+
finalPages.push(currentLines.join("\n"));
|
|
5594
|
+
currentLines = [];
|
|
5595
|
+
count = 0;
|
|
5596
|
+
}
|
|
5597
|
+
}
|
|
5598
|
+
if (currentLines.length > 0) {
|
|
5599
|
+
finalPages.push(currentLines.join("\n"));
|
|
5600
|
+
}
|
|
5601
|
+
}
|
|
5602
|
+
return finalPages.length > 0 ? finalPages : [text];
|
|
5188
5603
|
}
|
|
5189
5604
|
/**
|
|
5190
5605
|
* Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
|
|
@@ -5193,17 +5608,65 @@ var DocPlugin = class {
|
|
|
5193
5608
|
const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
|
|
5194
5609
|
let html = "";
|
|
5195
5610
|
let inList = false;
|
|
5196
|
-
|
|
5197
|
-
|
|
5611
|
+
let tableLines = [];
|
|
5612
|
+
const flushTable = () => {
|
|
5613
|
+
if (tableLines.length > 0) {
|
|
5614
|
+
html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
|
|
5615
|
+
for (const tLine of tableLines) {
|
|
5616
|
+
html += "<tr>";
|
|
5617
|
+
const cols = tLine.split(" ");
|
|
5618
|
+
for (const col of cols) {
|
|
5619
|
+
html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
|
|
5620
|
+
}
|
|
5621
|
+
html += "</tr>";
|
|
5622
|
+
}
|
|
5623
|
+
html += "</table>";
|
|
5624
|
+
tableLines = [];
|
|
5625
|
+
}
|
|
5626
|
+
};
|
|
5627
|
+
let i = 0;
|
|
5628
|
+
while (i < lines.length) {
|
|
5629
|
+
let line = lines[i];
|
|
5630
|
+
let tabCount = (line.match(/\t/g) || []).length;
|
|
5631
|
+
if (tabCount > 0) {
|
|
5632
|
+
let consecutiveTableLines = 1;
|
|
5633
|
+
let j = i + 1;
|
|
5634
|
+
while (j < lines.length) {
|
|
5635
|
+
const nextTabCount = (lines[j].match(/\t/g) || []).length;
|
|
5636
|
+
if (nextTabCount === tabCount) {
|
|
5637
|
+
consecutiveTableLines++;
|
|
5638
|
+
j++;
|
|
5639
|
+
} else {
|
|
5640
|
+
break;
|
|
5641
|
+
}
|
|
5642
|
+
}
|
|
5643
|
+
if (consecutiveTableLines >= 3) {
|
|
5644
|
+
if (inList) {
|
|
5645
|
+
html += "</ul>";
|
|
5646
|
+
inList = false;
|
|
5647
|
+
}
|
|
5648
|
+
tableLines = lines.slice(i, j);
|
|
5649
|
+
flushTable();
|
|
5650
|
+
i = j;
|
|
5651
|
+
continue;
|
|
5652
|
+
}
|
|
5653
|
+
}
|
|
5654
|
+
line = line.trim();
|
|
5198
5655
|
if (!line) {
|
|
5199
5656
|
if (inList) {
|
|
5200
5657
|
html += "</ul>";
|
|
5201
5658
|
inList = false;
|
|
5202
5659
|
}
|
|
5660
|
+
html += '<div style="height: 1.15em;"></div>';
|
|
5661
|
+
i++;
|
|
5662
|
+
continue;
|
|
5663
|
+
}
|
|
5664
|
+
if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line)) {
|
|
5665
|
+
i++;
|
|
5203
5666
|
continue;
|
|
5204
5667
|
}
|
|
5205
|
-
if (
|
|
5206
|
-
|
|
5668
|
+
if ((line.includes("Normal.dot") || line.includes("Microsoft Word") || line.includes("Times New Roman")) && line.length < 30) {
|
|
5669
|
+
i++;
|
|
5207
5670
|
continue;
|
|
5208
5671
|
}
|
|
5209
5672
|
if (line.length < 60 && !line.endsWith(".") && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#"))) {
|
|
@@ -5211,24 +5674,26 @@ var DocPlugin = class {
|
|
|
5211
5674
|
html += "</ul>";
|
|
5212
5675
|
inList = false;
|
|
5213
5676
|
}
|
|
5214
|
-
html += `<h2 style="font-size:
|
|
5677
|
+
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>`;
|
|
5215
5678
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
5216
5679
|
if (!inList) {
|
|
5217
5680
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
5218
5681
|
inList = true;
|
|
5219
5682
|
}
|
|
5220
5683
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
5221
|
-
html += `<li style="margin: 4px 0; line-height: 1.
|
|
5684
|
+
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6__default.default.sanitize(bulletText)}</li>`;
|
|
5222
5685
|
} else {
|
|
5223
5686
|
if (inList) {
|
|
5224
5687
|
html += "</ul>";
|
|
5225
5688
|
inList = false;
|
|
5226
5689
|
}
|
|
5227
|
-
html += `<p style="line-height: 1.
|
|
5690
|
+
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6__default.default.sanitize(line)}</p>`;
|
|
5228
5691
|
}
|
|
5692
|
+
i++;
|
|
5229
5693
|
}
|
|
5230
5694
|
if (inList) html += "</ul>";
|
|
5231
|
-
|
|
5695
|
+
flushTable();
|
|
5696
|
+
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6__default.default.sanitize(filename)})</p>`;
|
|
5232
5697
|
}
|
|
5233
5698
|
};
|
|
5234
5699
|
function docPlugin() {
|
|
@@ -5406,7 +5871,7 @@ var PptPlugin = class {
|
|
|
5406
5871
|
if (s.pictureUrl) {
|
|
5407
5872
|
contentHtml = `
|
|
5408
5873
|
<div style="flex: 1; display: flex; justify-content: center; align-items: center; padding: 12px; overflow: hidden;">
|
|
5409
|
-
<img src="${s.pictureUrl}" alt="${
|
|
5874
|
+
<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;" />
|
|
5410
5875
|
</div>
|
|
5411
5876
|
`;
|
|
5412
5877
|
} else if (s.tableColumns.length > 0) {
|
|
@@ -5416,7 +5881,7 @@ var PptPlugin = class {
|
|
|
5416
5881
|
<table style="width: 100%; border-collapse: collapse; border: 1px solid #cbd5e1; border-radius: 6px; overflow: hidden; background: #ffffff;">
|
|
5417
5882
|
<thead>
|
|
5418
5883
|
<tr style="background: #e2e8f0; color: #1e293b; font-weight: 600; font-size: 14px;">
|
|
5419
|
-
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${
|
|
5884
|
+
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${DOMPurify6__default.default.sanitize(c)}</th>`).join("")}
|
|
5420
5885
|
</tr>
|
|
5421
5886
|
</thead>
|
|
5422
5887
|
<tbody>
|
|
@@ -5432,7 +5897,7 @@ var PptPlugin = class {
|
|
|
5432
5897
|
} else {
|
|
5433
5898
|
const pTags = s.paragraphs.map((p) => {
|
|
5434
5899
|
const lines = p.split(/[\r\n]+/).map((l) => l.trim()).filter(Boolean);
|
|
5435
|
-
return lines.map((l) => `<p style="margin: 0 0 14px; font-size: 14px; line-height: 1.65; color: #334155; text-align: justify;">${
|
|
5900
|
+
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("");
|
|
5436
5901
|
}).join("");
|
|
5437
5902
|
contentHtml = `
|
|
5438
5903
|
<div style="flex: 1; overflow: auto; padding: 4px 8px; display: flex; flex-direction: column; justify-content: flex-start;">
|
|
@@ -5445,11 +5910,11 @@ var PptPlugin = class {
|
|
|
5445
5910
|
<!-- Header Banner matching PowerPoint design -->
|
|
5446
5911
|
<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;">
|
|
5447
5912
|
<h1 style="margin: 0; font-size: 26px; font-weight: 700; color: #1e293b; letter-spacing: -0.3px;">
|
|
5448
|
-
${
|
|
5913
|
+
${DOMPurify6__default.default.sanitize(s.title)}
|
|
5449
5914
|
</h1>
|
|
5450
5915
|
${s.subtitle ? `
|
|
5451
5916
|
<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);">
|
|
5452
|
-
${
|
|
5917
|
+
${DOMPurify6__default.default.sanitize(s.subtitle)}
|
|
5453
5918
|
</span>
|
|
5454
5919
|
` : `
|
|
5455
5920
|
<span style="font-size: 12px; color: #365314; font-weight: 600;">
|