@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/react.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var react = require('react');
|
|
6
|
-
var
|
|
6
|
+
var DOMPurify6 = require('dompurify');
|
|
7
7
|
var pdfjsLib = require('pdfjs-dist');
|
|
8
8
|
var docx = require('docx-preview');
|
|
9
9
|
var fflate = require('fflate');
|
|
@@ -38,7 +38,7 @@ function _interopNamespace(e) {
|
|
|
38
38
|
return Object.freeze(n);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
var
|
|
41
|
+
var DOMPurify6__default = /*#__PURE__*/_interopDefault(DOMPurify6);
|
|
42
42
|
var pdfjsLib__namespace = /*#__PURE__*/_interopNamespace(pdfjsLib);
|
|
43
43
|
var docx__namespace = /*#__PURE__*/_interopNamespace(docx);
|
|
44
44
|
var XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
|
|
@@ -390,7 +390,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
390
390
|
if (magicMime === "application/zip") {
|
|
391
391
|
const ooxmlMime = detectOoxmlType(buffer);
|
|
392
392
|
if (ooxmlMime && ooxmlMime !== "application/zip") {
|
|
393
|
-
metadata.mimeType = ooxmlMime;
|
|
393
|
+
metadata.mimeType = metadata.mimeType ?? ooxmlMime;
|
|
394
394
|
if (ooxmlMime.includes("wordprocessing")) metadata.extension = metadata.extension ?? ".docx";
|
|
395
395
|
else if (ooxmlMime.includes("spreadsheet")) metadata.extension = metadata.extension ?? ".xlsx";
|
|
396
396
|
else if (ooxmlMime.includes("presentation")) metadata.extension = metadata.extension ?? ".pptx";
|
|
@@ -419,7 +419,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
419
419
|
return { buffer, metadata };
|
|
420
420
|
}
|
|
421
421
|
function sanitizeSVG(svg) {
|
|
422
|
-
return
|
|
422
|
+
return DOMPurify6__default.default.sanitize(svg, {
|
|
423
423
|
USE_PROFILES: { svg: true, svgFilters: true }
|
|
424
424
|
});
|
|
425
425
|
}
|
|
@@ -466,7 +466,8 @@ function createElement(tag, attrs, ...children) {
|
|
|
466
466
|
}
|
|
467
467
|
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>`;
|
|
468
468
|
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>`;
|
|
469
|
-
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"><
|
|
469
|
+
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>`;
|
|
470
|
+
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>`;
|
|
470
471
|
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>`;
|
|
471
472
|
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>`;
|
|
472
473
|
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>`;
|
|
@@ -486,6 +487,7 @@ var ICON_MAP = {
|
|
|
486
487
|
"zoom-in": ICON_ZOOM_IN,
|
|
487
488
|
"zoom-out": ICON_ZOOM_OUT,
|
|
488
489
|
"fit-page": ICON_FIT_PAGE,
|
|
490
|
+
"fit-width": ICON_FIT_WIDTH,
|
|
489
491
|
"fit-slide": ICON_FIT_PAGE,
|
|
490
492
|
"rotate-cw": ICON_ROTATE_CW,
|
|
491
493
|
"rotate-ccw": ICON_ROTATE_CCW,
|
|
@@ -1432,6 +1434,7 @@ var PdfPlugin = class {
|
|
|
1432
1434
|
let currentPage = 1;
|
|
1433
1435
|
let zoomScale = 1;
|
|
1434
1436
|
let rotation = 0;
|
|
1437
|
+
let fitMode = "width";
|
|
1435
1438
|
let currentRenderTask = null;
|
|
1436
1439
|
const renderPage = async (pageNum) => {
|
|
1437
1440
|
if (currentRenderTask) {
|
|
@@ -1451,11 +1454,16 @@ var PdfPlugin = class {
|
|
|
1451
1454
|
const containerWidth = container.clientWidth || 900;
|
|
1452
1455
|
const containerHeight = container.clientHeight || 700;
|
|
1453
1456
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1454
|
-
const availWidth = Math.max(
|
|
1455
|
-
const availHeight = Math.max(
|
|
1457
|
+
const availWidth = Math.max(280, containerWidth - 48);
|
|
1458
|
+
const availHeight = Math.max(280, containerHeight - 88);
|
|
1456
1459
|
const scaleW = availWidth / unscaledVp.width;
|
|
1457
1460
|
const scaleH = availHeight / unscaledVp.height;
|
|
1458
|
-
|
|
1461
|
+
let fitScale;
|
|
1462
|
+
if (fitMode === "page") {
|
|
1463
|
+
fitScale = Math.max(0.5, Math.min(scaleW, scaleH));
|
|
1464
|
+
} else {
|
|
1465
|
+
fitScale = Math.max(0.65, Math.min(1.15, scaleW));
|
|
1466
|
+
}
|
|
1459
1467
|
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1460
1468
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
1461
1469
|
const viewport = page.getViewport({ scale: effectiveScale, rotation });
|
|
@@ -1481,7 +1489,19 @@ var PdfPlugin = class {
|
|
|
1481
1489
|
}
|
|
1482
1490
|
};
|
|
1483
1491
|
await renderPage(1);
|
|
1492
|
+
let resizeTimer = null;
|
|
1493
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
1494
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1495
|
+
resizeTimer = setTimeout(() => {
|
|
1496
|
+
if (Math.abs(zoomScale - 1) < 0.05) {
|
|
1497
|
+
renderPage(currentPage);
|
|
1498
|
+
}
|
|
1499
|
+
}, 150);
|
|
1500
|
+
});
|
|
1501
|
+
resizeObserver.observe(container);
|
|
1484
1502
|
const cleanup = () => {
|
|
1503
|
+
resizeObserver.disconnect();
|
|
1504
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1485
1505
|
if (currentRenderTask) {
|
|
1486
1506
|
try {
|
|
1487
1507
|
currentRenderTask.cancel();
|
|
@@ -1512,6 +1532,7 @@ var PdfPlugin = class {
|
|
|
1512
1532
|
renderPage(currentPage);
|
|
1513
1533
|
},
|
|
1514
1534
|
fitToPage: () => {
|
|
1535
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
1515
1536
|
zoomScale = 1;
|
|
1516
1537
|
rotation = 0;
|
|
1517
1538
|
renderPage(currentPage);
|
|
@@ -2065,8 +2086,53 @@ var DocxPlugin = class {
|
|
|
2065
2086
|
}
|
|
2066
2087
|
}
|
|
2067
2088
|
}
|
|
2068
|
-
|
|
2069
|
-
const cards = wrapper.querySelectorAll(".fp-docx-page-card");
|
|
2089
|
+
let sections = Array.from(wrapper.querySelectorAll("section.docx"));
|
|
2090
|
+
const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
|
|
2091
|
+
if (sections.length === 1 && cards.length === 0) {
|
|
2092
|
+
const singleSec = sections[0];
|
|
2093
|
+
const pageH = 1056;
|
|
2094
|
+
const secH = singleSec.offsetHeight || singleSec.scrollHeight;
|
|
2095
|
+
if (secH > pageH * 1.25) {
|
|
2096
|
+
const children = Array.from(singleSec.children);
|
|
2097
|
+
if (children.length > 1) {
|
|
2098
|
+
const parent = singleSec.parentElement || wrapper;
|
|
2099
|
+
const newSections = [singleSec];
|
|
2100
|
+
singleSec.innerHTML = "";
|
|
2101
|
+
singleSec.style.minHeight = `${pageH}px`;
|
|
2102
|
+
singleSec.style.maxHeight = `${pageH}px`;
|
|
2103
|
+
singleSec.style.overflow = "hidden";
|
|
2104
|
+
singleSec.style.boxSizing = "border-box";
|
|
2105
|
+
let curSec = singleSec;
|
|
2106
|
+
let curH = 0;
|
|
2107
|
+
const maxH = pageH - 96;
|
|
2108
|
+
for (let i = 0; i < children.length; i++) {
|
|
2109
|
+
const child = children[i];
|
|
2110
|
+
curSec.appendChild(child);
|
|
2111
|
+
const chH = child.offsetHeight || 28;
|
|
2112
|
+
curH += chH;
|
|
2113
|
+
if (curH >= maxH && i < children.length - 1) {
|
|
2114
|
+
const nextSec = document.createElement("section");
|
|
2115
|
+
nextSec.className = singleSec.className;
|
|
2116
|
+
nextSec.style.cssText = singleSec.style.cssText;
|
|
2117
|
+
nextSec.style.width = singleSec.style.width || "816px";
|
|
2118
|
+
nextSec.style.minHeight = `${pageH}px`;
|
|
2119
|
+
nextSec.style.maxHeight = `${pageH}px`;
|
|
2120
|
+
nextSec.style.overflow = "hidden";
|
|
2121
|
+
nextSec.style.boxSizing = "border-box";
|
|
2122
|
+
nextSec.style.backgroundColor = "#ffffff";
|
|
2123
|
+
nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
|
|
2124
|
+
nextSec.style.borderRadius = "4px";
|
|
2125
|
+
nextSec.style.marginBottom = "24px";
|
|
2126
|
+
parent.appendChild(nextSec);
|
|
2127
|
+
newSections.push(nextSec);
|
|
2128
|
+
curSec = nextSec;
|
|
2129
|
+
curH = 0;
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
sections = newSections;
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2070
2136
|
const pageElements = sections.length > 0 ? sections : cards;
|
|
2071
2137
|
const totalPages = Math.max(1, pageElements.length);
|
|
2072
2138
|
let currentPage = 1;
|
|
@@ -2110,22 +2176,27 @@ var DocxPlugin = class {
|
|
|
2110
2176
|
}
|
|
2111
2177
|
scale = 1;
|
|
2112
2178
|
let rotation = 0;
|
|
2113
|
-
|
|
2179
|
+
let fitMode = "width";
|
|
2180
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
2114
2181
|
const activeEl = pageElements[currentPage - 1] || wrapper.firstElementChild || wrapper;
|
|
2115
2182
|
const elW = activeEl.offsetWidth || 816;
|
|
2116
|
-
const
|
|
2117
|
-
const availW = Math.max(
|
|
2118
|
-
const availH = Math.max(
|
|
2183
|
+
const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
2184
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
2185
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
2119
2186
|
const sW = availW / elW;
|
|
2120
|
-
const sH = availH /
|
|
2121
|
-
|
|
2187
|
+
const sH = availH / singlePageH;
|
|
2188
|
+
if (mode === "page") {
|
|
2189
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
2190
|
+
}
|
|
2191
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
2122
2192
|
};
|
|
2123
2193
|
const applyTransform = () => {
|
|
2124
2194
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
2125
2195
|
wrapper.style.transformOrigin = "top center";
|
|
2126
2196
|
};
|
|
2127
2197
|
setTimeout(() => {
|
|
2128
|
-
|
|
2198
|
+
fitMode = "width";
|
|
2199
|
+
scale = calculateFitScale("width");
|
|
2129
2200
|
applyTransform();
|
|
2130
2201
|
}, 60);
|
|
2131
2202
|
const cleanup = () => {
|
|
@@ -2159,7 +2230,8 @@ var DocxPlugin = class {
|
|
|
2159
2230
|
applyTransform();
|
|
2160
2231
|
},
|
|
2161
2232
|
fitToPage: () => {
|
|
2162
|
-
|
|
2233
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
2234
|
+
scale = calculateFitScale(fitMode);
|
|
2163
2235
|
rotation = 0;
|
|
2164
2236
|
applyTransform();
|
|
2165
2237
|
},
|
|
@@ -2229,90 +2301,149 @@ var DocxPlugin = class {
|
|
|
2229
2301
|
console.warn("[DocxPlugin] Error parsing relationships:", relsErr);
|
|
2230
2302
|
}
|
|
2231
2303
|
}
|
|
2232
|
-
const
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2304
|
+
const sectPrs = Array.from(doc.getElementsByTagNameNS("*", "sectPr"));
|
|
2305
|
+
const lastSectPr = sectPrs[sectPrs.length - 1];
|
|
2306
|
+
let defaultW = 12240;
|
|
2307
|
+
let defaultH = 15840;
|
|
2308
|
+
let margins = { top: 1440, right: 1440, bottom: 1440, left: 1440 };
|
|
2309
|
+
if (lastSectPr) {
|
|
2310
|
+
const pgSz = lastSectPr.getElementsByTagNameNS("*", "pgSz")[0];
|
|
2311
|
+
if (pgSz) {
|
|
2312
|
+
defaultW = parseInt(pgSz.getAttribute("w:w") || pgSz.getAttribute("w") || "12240", 10);
|
|
2313
|
+
defaultH = parseInt(pgSz.getAttribute("w:h") || pgSz.getAttribute("h") || "15840", 10);
|
|
2314
|
+
}
|
|
2315
|
+
const pgMar = lastSectPr.getElementsByTagNameNS("*", "pgMar")[0];
|
|
2316
|
+
if (pgMar) {
|
|
2317
|
+
margins.top = parseInt(pgMar.getAttribute("w:top") || pgMar.getAttribute("top") || "1440", 10);
|
|
2318
|
+
margins.bottom = parseInt(pgMar.getAttribute("w:bottom") || pgMar.getAttribute("bottom") || "1440", 10);
|
|
2319
|
+
margins.left = parseInt(pgMar.getAttribute("w:left") || pgMar.getAttribute("left") || "1440", 10);
|
|
2320
|
+
margins.right = parseInt(pgMar.getAttribute("w:right") || pgMar.getAttribute("right") || "1440", 10);
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
const createPageCard = () => {
|
|
2324
|
+
const card = document.createElement("div");
|
|
2325
|
+
card.className = "fp-docx-page-card";
|
|
2326
|
+
card.style.backgroundColor = "#ffffff";
|
|
2327
|
+
card.style.borderRadius = "4px";
|
|
2328
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
2329
|
+
card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2330
|
+
card.style.color = "#1e293b";
|
|
2331
|
+
card.style.lineHeight = "1.6";
|
|
2332
|
+
card.style.boxSizing = "border-box";
|
|
2333
|
+
card.style.overflow = "hidden";
|
|
2334
|
+
card.style.position = "relative";
|
|
2335
|
+
card.style.marginBottom = "24px";
|
|
2336
|
+
card.style.width = `${defaultW / 15}px`;
|
|
2337
|
+
card.style.height = `${defaultH / 15}px`;
|
|
2338
|
+
card.style.padding = `${margins.top / 15}px ${margins.right / 15}px ${margins.bottom / 15}px ${margins.left / 15}px`;
|
|
2339
|
+
return card;
|
|
2340
|
+
};
|
|
2341
|
+
let currentCard = createPageCard();
|
|
2342
|
+
let currentHtml = "";
|
|
2343
|
+
const pages = [{ card: currentCard, html: "" }];
|
|
2344
|
+
const flushHtml = () => {
|
|
2345
|
+
pages[pages.length - 1].html += currentHtml;
|
|
2346
|
+
currentHtml = "";
|
|
2347
|
+
};
|
|
2348
|
+
const newPage = () => {
|
|
2349
|
+
flushHtml();
|
|
2350
|
+
currentCard = createPageCard();
|
|
2351
|
+
pages.push({ card: currentCard, html: "" });
|
|
2352
|
+
};
|
|
2241
2353
|
const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
|
|
2242
|
-
let html = "";
|
|
2243
2354
|
for (const child of Array.from(body.children)) {
|
|
2244
2355
|
const tag = child.localName || child.nodeName.split(":").pop();
|
|
2245
2356
|
if (tag === "p") {
|
|
2246
2357
|
const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
|
|
2247
2358
|
const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
|
|
2248
2359
|
const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
|
|
2249
|
-
const
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2360
|
+
const chunks = this.extractParagraphChunks(child, imageMap);
|
|
2361
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
2362
|
+
if (i > 0) {
|
|
2363
|
+
newPage();
|
|
2364
|
+
}
|
|
2365
|
+
const textContent = chunks[i];
|
|
2366
|
+
if (!textContent.trim() && !textContent.includes("<img")) {
|
|
2367
|
+
currentHtml += '<div style="height: 10px;"></div>';
|
|
2368
|
+
continue;
|
|
2369
|
+
}
|
|
2370
|
+
const lowerStyle = styleVal.toLowerCase();
|
|
2371
|
+
if (lowerStyle.includes("title")) {
|
|
2372
|
+
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>`;
|
|
2373
|
+
} else if (lowerStyle.includes("heading1") || styleVal === "1") {
|
|
2374
|
+
currentHtml += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
|
|
2375
|
+
} else if (lowerStyle.includes("heading2") || styleVal === "2") {
|
|
2376
|
+
currentHtml += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
|
|
2377
|
+
} else if (lowerStyle.includes("heading3") || styleVal === "3") {
|
|
2378
|
+
currentHtml += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
|
|
2379
|
+
} else if (numPr) {
|
|
2380
|
+
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>`;
|
|
2381
|
+
} else {
|
|
2382
|
+
currentHtml += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
|
|
2383
|
+
}
|
|
2267
2384
|
}
|
|
2268
2385
|
} else if (tag === "tbl") {
|
|
2269
|
-
|
|
2386
|
+
currentHtml += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
|
|
2270
2387
|
const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
|
|
2271
2388
|
rows.forEach((tr, rIdx) => {
|
|
2272
|
-
|
|
2389
|
+
currentHtml += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
2273
2390
|
const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
|
|
2274
2391
|
cells.forEach((tc) => {
|
|
2275
2392
|
const cellText = this.extractParagraphHtml(tc, imageMap);
|
|
2276
|
-
|
|
2393
|
+
currentHtml += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || " "}</td>`;
|
|
2277
2394
|
});
|
|
2278
|
-
|
|
2395
|
+
currentHtml += "</tr>";
|
|
2279
2396
|
});
|
|
2280
|
-
|
|
2397
|
+
currentHtml += "</table>";
|
|
2281
2398
|
}
|
|
2282
2399
|
}
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2400
|
+
flushHtml();
|
|
2401
|
+
for (const page of pages) {
|
|
2402
|
+
page.card.innerHTML = DOMPurify6__default.default.sanitize(page.html, {
|
|
2403
|
+
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
|
|
2404
|
+
ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
|
|
2405
|
+
});
|
|
2406
|
+
wrapper.appendChild(page.card);
|
|
2407
|
+
}
|
|
2288
2408
|
}
|
|
2289
2409
|
extractParagraphHtml(pElement, imageMap = {}) {
|
|
2290
|
-
|
|
2410
|
+
return this.extractParagraphChunks(pElement, imageMap).join("<br/>");
|
|
2411
|
+
}
|
|
2412
|
+
extractParagraphChunks(pElement, imageMap = {}) {
|
|
2413
|
+
const chunks = [""];
|
|
2414
|
+
let currentChunkIndex = 0;
|
|
2291
2415
|
const drawings = Array.from(pElement.getElementsByTagNameNS("*", "drawing"));
|
|
2292
2416
|
for (const drawing of drawings) {
|
|
2293
2417
|
const blip = drawing.getElementsByTagNameNS("*", "blip")[0];
|
|
2294
2418
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2295
2419
|
if (rId && imageMap[rId]) {
|
|
2296
|
-
|
|
2420
|
+
chunks[currentChunkIndex] += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
|
|
2297
2421
|
}
|
|
2298
2422
|
}
|
|
2299
2423
|
const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
|
|
2300
|
-
if (runs.length === 0 && !
|
|
2301
|
-
|
|
2424
|
+
if (runs.length === 0 && !chunks[currentChunkIndex]) {
|
|
2425
|
+
chunks[currentChunkIndex] = DOMPurify6__default.default.sanitize(pElement.textContent || "");
|
|
2426
|
+
return chunks;
|
|
2302
2427
|
}
|
|
2303
2428
|
for (const r of runs) {
|
|
2304
2429
|
const blip = r.getElementsByTagNameNS("*", "blip")[0] || r.getElementsByTagNameNS("*", "imagedata")[0];
|
|
2305
2430
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2306
2431
|
if (rId && imageMap[rId]) {
|
|
2307
|
-
|
|
2432
|
+
chunks[currentChunkIndex] += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
|
|
2308
2433
|
}
|
|
2309
|
-
const brs = r.getElementsByTagNameNS("*", "br");
|
|
2310
|
-
for (
|
|
2311
|
-
|
|
2434
|
+
const brs = Array.from(r.getElementsByTagNameNS("*", "br"));
|
|
2435
|
+
for (const br of brs) {
|
|
2436
|
+
const type = br.getAttribute("w:type") || br.getAttribute("type");
|
|
2437
|
+
if (type === "page") {
|
|
2438
|
+
chunks.push("");
|
|
2439
|
+
currentChunkIndex++;
|
|
2440
|
+
} else {
|
|
2441
|
+
chunks[currentChunkIndex] += "<br/>";
|
|
2442
|
+
}
|
|
2312
2443
|
}
|
|
2313
2444
|
const tabs = r.getElementsByTagNameNS("*", "tab");
|
|
2314
2445
|
if (tabs.length > 0) {
|
|
2315
|
-
|
|
2446
|
+
chunks[currentChunkIndex] += " ";
|
|
2316
2447
|
}
|
|
2317
2448
|
const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
|
|
2318
2449
|
const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
|
|
@@ -2326,7 +2457,7 @@ var DocxPlugin = class {
|
|
|
2326
2457
|
const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
|
|
2327
2458
|
let text = texts.map((t) => t.textContent || "").join("");
|
|
2328
2459
|
if (!text) continue;
|
|
2329
|
-
text =
|
|
2460
|
+
text = DOMPurify6__default.default.sanitize(text);
|
|
2330
2461
|
let styles = "";
|
|
2331
2462
|
if (isBold) styles += "font-weight: bold; ";
|
|
2332
2463
|
if (isItalic) styles += "font-style: italic; ";
|
|
@@ -2338,12 +2469,12 @@ var DocxPlugin = class {
|
|
|
2338
2469
|
if (!isNaN(pt) && pt > 0) styles += `font-size: ${pt}pt; `;
|
|
2339
2470
|
}
|
|
2340
2471
|
if (styles) {
|
|
2341
|
-
|
|
2472
|
+
chunks[currentChunkIndex] += `<span style="${styles}">${text}</span>`;
|
|
2342
2473
|
} else {
|
|
2343
|
-
|
|
2474
|
+
chunks[currentChunkIndex] += text;
|
|
2344
2475
|
}
|
|
2345
2476
|
}
|
|
2346
|
-
return
|
|
2477
|
+
return chunks;
|
|
2347
2478
|
}
|
|
2348
2479
|
renderBinaryDocFallback(ctx, wrapper) {
|
|
2349
2480
|
const card = document.createElement("div");
|
|
@@ -2360,14 +2491,14 @@ var DocxPlugin = class {
|
|
|
2360
2491
|
const wordDocStream = cfbf.readStream("WordDocument");
|
|
2361
2492
|
if (wordDocStream && wordDocStream.length >= 512) {
|
|
2362
2493
|
const text2 = this.extractReadableStrings(wordDocStream);
|
|
2363
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2494
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text2)}</div>`;
|
|
2364
2495
|
wrapper.appendChild(card);
|
|
2365
2496
|
return;
|
|
2366
2497
|
}
|
|
2367
2498
|
} catch {
|
|
2368
2499
|
}
|
|
2369
2500
|
const text = this.extractReadableStrings(new Uint8Array(ctx.buffer));
|
|
2370
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2501
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text)}</div>`;
|
|
2371
2502
|
wrapper.appendChild(card);
|
|
2372
2503
|
}
|
|
2373
2504
|
extractReadableStrings(bytes) {
|
|
@@ -2544,11 +2675,9 @@ var ExcelPlugin = class {
|
|
|
2544
2675
|
const calculateFitScale = () => {
|
|
2545
2676
|
const table = contentArea.querySelector("table");
|
|
2546
2677
|
if (!table) return 1;
|
|
2547
|
-
const availW = Math.max(
|
|
2548
|
-
const availH = Math.max(200, container.clientHeight - 80);
|
|
2678
|
+
const availW = Math.max(280, container.clientWidth - 48);
|
|
2549
2679
|
const tW = table.offsetWidth || 800;
|
|
2550
|
-
|
|
2551
|
-
return Math.min(1, Math.min(availW / tW, availH / tH));
|
|
2680
|
+
return Math.max(0.65, Math.min(1, availW / tW));
|
|
2552
2681
|
};
|
|
2553
2682
|
try {
|
|
2554
2683
|
wb = XLSX__namespace.read(new Uint8Array(ctx.buffer), { type: "array", cellDates: true });
|
|
@@ -2966,41 +3095,94 @@ var CodePlugin = class {
|
|
|
2966
3095
|
async render(ctx) {
|
|
2967
3096
|
const decoder = new TextDecoder("utf-8");
|
|
2968
3097
|
const fullText = decoder.decode(ctx.buffer);
|
|
2969
|
-
const
|
|
2970
|
-
const
|
|
3098
|
+
const extRaw = ctx.metadata.extension?.toLowerCase();
|
|
3099
|
+
const mimeRaw = ctx.metadata.mimeType?.toLowerCase();
|
|
3100
|
+
const isTxt = extRaw === ".txt" || mimeRaw === "text/plain" && (!extRaw || !this.extensions.filter((e) => e !== ".txt").includes(extRaw));
|
|
3101
|
+
let rawPages = [];
|
|
3102
|
+
if (isTxt) {
|
|
3103
|
+
const explicitPages = fullText.split(/(?:\f|\x0C)/);
|
|
3104
|
+
for (const ep of explicitPages) {
|
|
3105
|
+
const lines = ep.split(/\r?\n/);
|
|
3106
|
+
let currentChunk = [];
|
|
3107
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3108
|
+
currentChunk.push(lines[i]);
|
|
3109
|
+
if (currentChunk.length >= 46) {
|
|
3110
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3111
|
+
currentChunk = [];
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3114
|
+
if (currentChunk.length > 0 || lines.length === 0) {
|
|
3115
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
if (rawPages.length === 0) rawPages = [""];
|
|
3119
|
+
} else {
|
|
3120
|
+
const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
|
|
3121
|
+
rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
3122
|
+
}
|
|
2971
3123
|
const totalPages = Math.max(1, rawPages.length);
|
|
2972
3124
|
let currentPage = 1;
|
|
2973
3125
|
const container = document.createElement("div");
|
|
2974
3126
|
container.style.width = "100%";
|
|
2975
3127
|
container.style.height = "100%";
|
|
2976
3128
|
container.style.overflow = "auto";
|
|
2977
|
-
container.style.backgroundColor = "#1e1e1e";
|
|
2978
|
-
container.style.color = "#d4d4d4";
|
|
2979
|
-
container.style.padding = "16px";
|
|
2980
|
-
container.style.boxSizing = "border-box";
|
|
2981
3129
|
let fontSize = 13;
|
|
2982
3130
|
let rotation = 0;
|
|
3131
|
+
let zoomLevel = 1;
|
|
2983
3132
|
const pre = document.createElement("pre");
|
|
2984
|
-
pre.style.margin = "0";
|
|
2985
|
-
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
2986
|
-
pre.style.fontSize = `${fontSize}px`;
|
|
2987
|
-
pre.style.lineHeight = "1.5";
|
|
2988
|
-
pre.style.whiteSpace = "pre-wrap";
|
|
2989
|
-
pre.style.wordBreak = "break-all";
|
|
2990
3133
|
const code = document.createElement("code");
|
|
3134
|
+
if (isTxt) {
|
|
3135
|
+
container.style.backgroundColor = "#f1f5f9";
|
|
3136
|
+
container.style.padding = "32px";
|
|
3137
|
+
container.style.boxSizing = "border-box";
|
|
3138
|
+
container.style.display = "flex";
|
|
3139
|
+
container.style.flexDirection = "column";
|
|
3140
|
+
container.style.alignItems = "center";
|
|
3141
|
+
pre.style.margin = "0";
|
|
3142
|
+
pre.style.fontFamily = "Consolas, 'Courier New', monospace";
|
|
3143
|
+
pre.style.fontSize = "13px";
|
|
3144
|
+
pre.style.color = "#1e293b";
|
|
3145
|
+
pre.style.lineHeight = "1.5";
|
|
3146
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3147
|
+
pre.style.wordBreak = "break-word";
|
|
3148
|
+
pre.style.backgroundColor = "#ffffff";
|
|
3149
|
+
pre.style.width = "816px";
|
|
3150
|
+
pre.style.minHeight = "1056px";
|
|
3151
|
+
pre.style.padding = "72px 56px";
|
|
3152
|
+
pre.style.boxSizing = "border-box";
|
|
3153
|
+
pre.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)";
|
|
3154
|
+
pre.style.borderRadius = "4px";
|
|
3155
|
+
pre.style.transformOrigin = "top center";
|
|
3156
|
+
} else {
|
|
3157
|
+
container.style.backgroundColor = "#1e1e1e";
|
|
3158
|
+
container.style.color = "#d4d4d4";
|
|
3159
|
+
container.style.padding = "16px";
|
|
3160
|
+
container.style.boxSizing = "border-box";
|
|
3161
|
+
pre.style.margin = "0";
|
|
3162
|
+
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
3163
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3164
|
+
pre.style.lineHeight = "1.5";
|
|
3165
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3166
|
+
pre.style.wordBreak = "break-all";
|
|
3167
|
+
pre.style.transformOrigin = "top left";
|
|
3168
|
+
}
|
|
2991
3169
|
const ext = (ctx.metadata.extension || "").replace(".", "");
|
|
2992
3170
|
const renderCodePage = (text) => {
|
|
2993
|
-
|
|
2994
|
-
if (ext && hljs__default.default.getLanguage(ext)) {
|
|
2995
|
-
code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
|
|
2996
|
-
} else {
|
|
2997
|
-
code.innerHTML = hljs__default.default.highlightAuto(text).value;
|
|
2998
|
-
}
|
|
2999
|
-
} catch {
|
|
3171
|
+
if (isTxt) {
|
|
3000
3172
|
code.textContent = text;
|
|
3173
|
+
} else {
|
|
3174
|
+
try {
|
|
3175
|
+
if (ext && hljs__default.default.getLanguage(ext)) {
|
|
3176
|
+
code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
|
|
3177
|
+
} else {
|
|
3178
|
+
code.innerHTML = hljs__default.default.highlightAuto(text).value;
|
|
3179
|
+
}
|
|
3180
|
+
} catch {
|
|
3181
|
+
code.textContent = text;
|
|
3182
|
+
}
|
|
3001
3183
|
}
|
|
3002
3184
|
};
|
|
3003
|
-
renderCodePage(rawPages[0] || fullText);
|
|
3185
|
+
renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
|
|
3004
3186
|
pre.appendChild(code);
|
|
3005
3187
|
container.appendChild(pre);
|
|
3006
3188
|
let indicator = null;
|
|
@@ -3009,15 +3191,22 @@ var CodePlugin = class {
|
|
|
3009
3191
|
indicator.className = "fp-code-page-indicator";
|
|
3010
3192
|
indicator.style.position = "sticky";
|
|
3011
3193
|
indicator.style.bottom = "16px";
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3194
|
+
if (isTxt) {
|
|
3195
|
+
indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
3196
|
+
indicator.style.color = "#334155";
|
|
3197
|
+
indicator.style.border = "1px solid #e2e8f0";
|
|
3198
|
+
indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
|
|
3199
|
+
} else {
|
|
3200
|
+
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3201
|
+
indicator.style.color = "#f8fafc";
|
|
3202
|
+
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3203
|
+
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3204
|
+
indicator.style.backdropFilter = "blur(8px)";
|
|
3205
|
+
}
|
|
3015
3206
|
indicator.style.fontSize = "12px";
|
|
3016
3207
|
indicator.style.fontWeight = "600";
|
|
3017
3208
|
indicator.style.padding = "5px 14px";
|
|
3018
3209
|
indicator.style.borderRadius = "20px";
|
|
3019
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3020
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3021
3210
|
indicator.style.zIndex = "10";
|
|
3022
3211
|
indicator.style.userSelect = "none";
|
|
3023
3212
|
indicator.style.pointerEvents = "none";
|
|
@@ -3028,7 +3217,7 @@ var CodePlugin = class {
|
|
|
3028
3217
|
}
|
|
3029
3218
|
const showPage = (pageNum) => {
|
|
3030
3219
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3031
|
-
renderCodePage(rawPages[currentPage - 1] || fullText);
|
|
3220
|
+
renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
|
|
3032
3221
|
if (indicator) {
|
|
3033
3222
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
3034
3223
|
}
|
|
@@ -3044,39 +3233,57 @@ var CodePlugin = class {
|
|
|
3044
3233
|
ctx.container.innerHTML = "";
|
|
3045
3234
|
};
|
|
3046
3235
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3236
|
+
const updateTransform = () => {
|
|
3237
|
+
if (isTxt) {
|
|
3238
|
+
pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
|
|
3239
|
+
} else {
|
|
3240
|
+
pre.style.transform = `rotate(${rotation}deg)`;
|
|
3241
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3242
|
+
}
|
|
3243
|
+
};
|
|
3047
3244
|
return {
|
|
3048
3245
|
destroy: cleanup,
|
|
3049
3246
|
getPageCount: () => totalPages,
|
|
3050
3247
|
getCurrentPage: () => currentPage,
|
|
3051
3248
|
goToPage: (page) => showPage(page),
|
|
3052
3249
|
zoomIn: () => {
|
|
3053
|
-
|
|
3054
|
-
|
|
3250
|
+
if (isTxt) {
|
|
3251
|
+
zoomLevel = Math.min(3, zoomLevel + 0.1);
|
|
3252
|
+
} else {
|
|
3253
|
+
fontSize = Math.min(32, fontSize + 2);
|
|
3254
|
+
}
|
|
3255
|
+
updateTransform();
|
|
3055
3256
|
},
|
|
3056
3257
|
zoomOut: () => {
|
|
3057
|
-
|
|
3058
|
-
|
|
3258
|
+
if (isTxt) {
|
|
3259
|
+
zoomLevel = Math.max(0.1, zoomLevel - 0.1);
|
|
3260
|
+
} else {
|
|
3261
|
+
fontSize = Math.max(8, fontSize - 2);
|
|
3262
|
+
}
|
|
3263
|
+
updateTransform();
|
|
3059
3264
|
},
|
|
3060
|
-
getZoom: () => fontSize / 13,
|
|
3265
|
+
getZoom: () => isTxt ? zoomLevel : fontSize / 13,
|
|
3061
3266
|
setZoom: (level) => {
|
|
3062
|
-
|
|
3063
|
-
|
|
3267
|
+
if (isTxt) {
|
|
3268
|
+
zoomLevel = level;
|
|
3269
|
+
} else {
|
|
3270
|
+
fontSize = Math.round(13 * level);
|
|
3271
|
+
}
|
|
3272
|
+
updateTransform();
|
|
3064
3273
|
},
|
|
3065
3274
|
fitToPage: () => {
|
|
3066
3275
|
fontSize = 13;
|
|
3067
3276
|
rotation = 0;
|
|
3068
|
-
|
|
3069
|
-
|
|
3277
|
+
zoomLevel = isTxt ? Math.max(0.65, Math.min(1.05, (container.clientWidth - 48) / 816)) : 1;
|
|
3278
|
+
updateTransform();
|
|
3070
3279
|
},
|
|
3071
3280
|
rotateCW: () => {
|
|
3072
3281
|
rotation = (rotation + 90) % 360;
|
|
3073
|
-
|
|
3074
|
-
pre.style.transformOrigin = "top left";
|
|
3282
|
+
updateTransform();
|
|
3075
3283
|
},
|
|
3076
3284
|
rotateCCW: () => {
|
|
3077
3285
|
rotation = (rotation - 90 + 360) % 360;
|
|
3078
|
-
|
|
3079
|
-
pre.style.transformOrigin = "top left";
|
|
3286
|
+
updateTransform();
|
|
3080
3287
|
},
|
|
3081
3288
|
download: () => {
|
|
3082
3289
|
const mimeType = ctx.metadata.mimeType || "text/plain";
|
|
@@ -3375,7 +3582,7 @@ var MarkdownPlugin = class {
|
|
|
3375
3582
|
gfm: true,
|
|
3376
3583
|
breaks: true
|
|
3377
3584
|
});
|
|
3378
|
-
const cleanHtml =
|
|
3585
|
+
const cleanHtml = DOMPurify6__default.default.sanitize(rawHtml, {
|
|
3379
3586
|
USE_PROFILES: { html: true }
|
|
3380
3587
|
});
|
|
3381
3588
|
const wrapper = document.createElement("div");
|
|
@@ -4011,6 +4218,14 @@ var RtfPlugin = class {
|
|
|
4011
4218
|
group: "actions",
|
|
4012
4219
|
execute: () => instance.download?.()
|
|
4013
4220
|
},
|
|
4221
|
+
{
|
|
4222
|
+
id: "copy",
|
|
4223
|
+
icon: "copy",
|
|
4224
|
+
label: "Copy Text",
|
|
4225
|
+
type: "button",
|
|
4226
|
+
group: "actions",
|
|
4227
|
+
execute: () => instance.copy?.()
|
|
4228
|
+
},
|
|
4014
4229
|
{
|
|
4015
4230
|
id: "print",
|
|
4016
4231
|
icon: "print",
|
|
@@ -4041,20 +4256,27 @@ var RtfPlugin = class {
|
|
|
4041
4256
|
let scale = 1;
|
|
4042
4257
|
let rotation = 0;
|
|
4043
4258
|
let pageElements = [];
|
|
4044
|
-
|
|
4259
|
+
let fitMode = "width";
|
|
4260
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
4045
4261
|
const activeEl = pageElements[currentPage - 1] || wrapper;
|
|
4046
4262
|
const elW = activeEl.offsetWidth || 850;
|
|
4047
|
-
const
|
|
4048
|
-
const availW = Math.max(
|
|
4049
|
-
const availH = Math.max(
|
|
4050
|
-
|
|
4263
|
+
const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
4264
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
4265
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
4266
|
+
const sW = availW / elW;
|
|
4267
|
+
const sH = availH / singlePageH;
|
|
4268
|
+
if (mode === "page") {
|
|
4269
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
4270
|
+
}
|
|
4271
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
4051
4272
|
};
|
|
4052
4273
|
const applyTransform = () => {
|
|
4053
4274
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4054
4275
|
wrapper.style.transformOrigin = "top center";
|
|
4055
4276
|
};
|
|
4056
4277
|
setTimeout(() => {
|
|
4057
|
-
|
|
4278
|
+
fitMode = "width";
|
|
4279
|
+
scale = calculateFitScale("width");
|
|
4058
4280
|
applyTransform();
|
|
4059
4281
|
}, 60);
|
|
4060
4282
|
try {
|
|
@@ -4072,14 +4294,31 @@ var RtfPlugin = class {
|
|
|
4072
4294
|
} catch (err) {
|
|
4073
4295
|
console.warn("[RtfPlugin] RTF render error, fallback text:", err);
|
|
4074
4296
|
const text = new TextDecoder("latin1").decode(ctx.buffer);
|
|
4075
|
-
const
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4297
|
+
const rawPages = text.split(/\\page\b/).map((segment) => {
|
|
4298
|
+
return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
|
|
4299
|
+
}).filter((p) => p.length > 0);
|
|
4300
|
+
const pages = rawPages.length > 0 ? rawPages : [text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim()];
|
|
4301
|
+
for (let i = 0; i < pages.length; i++) {
|
|
4302
|
+
const pageCard = document.createElement("div");
|
|
4303
|
+
pageCard.className = "fp-rtf-page-card";
|
|
4304
|
+
pageCard.style.backgroundColor = "#ffffff";
|
|
4305
|
+
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4306
|
+
pageCard.style.borderRadius = "4px";
|
|
4307
|
+
pageCard.style.padding = "72px 56px";
|
|
4308
|
+
pageCard.style.width = "816px";
|
|
4309
|
+
pageCard.style.minHeight = "1056px";
|
|
4310
|
+
pageCard.style.maxWidth = "100%";
|
|
4311
|
+
pageCard.style.boxSizing = "border-box";
|
|
4312
|
+
pageCard.style.fontFamily = "serif";
|
|
4313
|
+
pageCard.style.fontSize = "12pt";
|
|
4314
|
+
pageCard.style.lineHeight = "1.6";
|
|
4315
|
+
pageCard.style.color = "#1e293b";
|
|
4316
|
+
pageCard.style.whiteSpace = "pre-wrap";
|
|
4317
|
+
pageCard.style.display = i === 0 ? "block" : "none";
|
|
4318
|
+
pageCard.textContent = pages[i];
|
|
4319
|
+
wrapper.appendChild(pageCard);
|
|
4320
|
+
pageElements.push(pageCard);
|
|
4321
|
+
}
|
|
4083
4322
|
}
|
|
4084
4323
|
const totalPages = Math.max(1, pageElements.length);
|
|
4085
4324
|
let currentPage = 1;
|
|
@@ -4146,7 +4385,8 @@ var RtfPlugin = class {
|
|
|
4146
4385
|
applyTransform();
|
|
4147
4386
|
},
|
|
4148
4387
|
fitToPage: () => {
|
|
4149
|
-
|
|
4388
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
4389
|
+
scale = calculateFitScale(fitMode);
|
|
4150
4390
|
rotation = 0;
|
|
4151
4391
|
applyTransform();
|
|
4152
4392
|
},
|
|
@@ -4167,6 +4407,10 @@ var RtfPlugin = class {
|
|
|
4167
4407
|
a.click();
|
|
4168
4408
|
URL.revokeObjectURL(url);
|
|
4169
4409
|
},
|
|
4410
|
+
copy: () => {
|
|
4411
|
+
const text = wrapper.textContent || "";
|
|
4412
|
+
navigator.clipboard?.writeText(text);
|
|
4413
|
+
},
|
|
4170
4414
|
print: () => {
|
|
4171
4415
|
window.print();
|
|
4172
4416
|
}
|
|
@@ -4241,7 +4485,7 @@ var HtmlPreviewPlugin = class {
|
|
|
4241
4485
|
}
|
|
4242
4486
|
async render(ctx) {
|
|
4243
4487
|
const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
|
|
4244
|
-
const sanitized =
|
|
4488
|
+
const sanitized = DOMPurify6__default.default.sanitize(rawHtml, {
|
|
4245
4489
|
WHOLE_DOCUMENT: true,
|
|
4246
4490
|
ADD_TAGS: ["style", "link"],
|
|
4247
4491
|
ADD_ATTR: ["target", "rel"]
|
|
@@ -4461,19 +4705,29 @@ var OpenDocumentPlugin = class {
|
|
|
4461
4705
|
ctx.container.appendChild(container);
|
|
4462
4706
|
let scale = 1;
|
|
4463
4707
|
let rotation = 0;
|
|
4464
|
-
|
|
4708
|
+
let fitMode = "width";
|
|
4709
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
4465
4710
|
const elW = wrapper.offsetWidth || 850;
|
|
4466
|
-
const
|
|
4467
|
-
const availW = Math.max(
|
|
4468
|
-
const availH = Math.max(
|
|
4469
|
-
|
|
4711
|
+
const singlePageH = Math.min(wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
4712
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
4713
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
4714
|
+
const sW = availW / elW;
|
|
4715
|
+
const sH = availH / (isPresentation ? 540 : singlePageH);
|
|
4716
|
+
if (isPresentation) {
|
|
4717
|
+
return Math.min(1, Math.min(sW, sH));
|
|
4718
|
+
}
|
|
4719
|
+
if (mode === "page") {
|
|
4720
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
4721
|
+
}
|
|
4722
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
4470
4723
|
};
|
|
4471
4724
|
const applyTransform = () => {
|
|
4472
4725
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4473
4726
|
wrapper.style.transformOrigin = "top center";
|
|
4474
4727
|
};
|
|
4475
4728
|
setTimeout(() => {
|
|
4476
|
-
|
|
4729
|
+
fitMode = "width";
|
|
4730
|
+
scale = calculateFitScale("width");
|
|
4477
4731
|
applyTransform();
|
|
4478
4732
|
}, 60);
|
|
4479
4733
|
let currentPage = 1;
|
|
@@ -4507,14 +4761,97 @@ var OpenDocumentPlugin = class {
|
|
|
4507
4761
|
wrapper.textContent = contentDoc.documentElement.textContent || "Formula content";
|
|
4508
4762
|
}
|
|
4509
4763
|
} else {
|
|
4510
|
-
wrapper.style.maxWidth = "
|
|
4511
|
-
wrapper.style.padding = "
|
|
4764
|
+
wrapper.style.maxWidth = "none";
|
|
4765
|
+
wrapper.style.padding = "0";
|
|
4512
4766
|
wrapper.style.minHeight = "100%";
|
|
4767
|
+
wrapper.style.backgroundColor = "transparent";
|
|
4768
|
+
wrapper.style.boxShadow = "none";
|
|
4769
|
+
wrapper.style.position = "relative";
|
|
4770
|
+
const dims = this.getPageDimensions(stylesDoc, contentDoc);
|
|
4513
4771
|
const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
|
|
4514
|
-
|
|
4515
|
-
|
|
4772
|
+
const tempDiv = document.createElement("div");
|
|
4773
|
+
tempDiv.style.width = `${dims.width - dims.marginLeft - dims.marginRight}px`;
|
|
4774
|
+
tempDiv.style.position = "absolute";
|
|
4775
|
+
tempDiv.style.visibility = "hidden";
|
|
4776
|
+
tempDiv.innerHTML = DOMPurify6__default.default.sanitize(bodyHtml, {
|
|
4777
|
+
ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub", "hr"],
|
|
4516
4778
|
ADD_ATTR: ["style", "colspan", "rowspan"]
|
|
4517
4779
|
});
|
|
4780
|
+
document.body.appendChild(tempDiv);
|
|
4781
|
+
const contentHeight = dims.height - dims.marginTop - dims.marginBottom;
|
|
4782
|
+
const pageElements = [[]];
|
|
4783
|
+
let currentHeight = 0;
|
|
4784
|
+
let currentPageIdx = 0;
|
|
4785
|
+
Array.from(tempDiv.children).forEach((child) => {
|
|
4786
|
+
const el = child;
|
|
4787
|
+
const style = el.getAttribute("style") || "";
|
|
4788
|
+
const isBreakBefore = style.includes("page-break-before: always");
|
|
4789
|
+
const isBreakAfter = style.includes("page-break-after: always");
|
|
4790
|
+
const isSoftBreak = el.classList.contains("odf-page-break");
|
|
4791
|
+
if (isBreakBefore) {
|
|
4792
|
+
if (pageElements[currentPageIdx].length > 0) {
|
|
4793
|
+
currentPageIdx++;
|
|
4794
|
+
pageElements.push([]);
|
|
4795
|
+
currentHeight = 0;
|
|
4796
|
+
}
|
|
4797
|
+
}
|
|
4798
|
+
const h = el.offsetHeight || 0;
|
|
4799
|
+
if (currentHeight + h > contentHeight && pageElements[currentPageIdx].length > 0 && !isSoftBreak) {
|
|
4800
|
+
currentPageIdx++;
|
|
4801
|
+
pageElements.push([]);
|
|
4802
|
+
currentHeight = 0;
|
|
4803
|
+
}
|
|
4804
|
+
if (!isSoftBreak) {
|
|
4805
|
+
pageElements[currentPageIdx].push(el.cloneNode(true));
|
|
4806
|
+
currentHeight += h;
|
|
4807
|
+
}
|
|
4808
|
+
if (isBreakAfter || isSoftBreak) {
|
|
4809
|
+
currentPageIdx++;
|
|
4810
|
+
pageElements.push([]);
|
|
4811
|
+
currentHeight = 0;
|
|
4812
|
+
}
|
|
4813
|
+
});
|
|
4814
|
+
document.body.removeChild(tempDiv);
|
|
4815
|
+
if (pageElements.length > 1 && pageElements[pageElements.length - 1].length === 0) {
|
|
4816
|
+
pageElements.pop();
|
|
4817
|
+
}
|
|
4818
|
+
totalPages = Math.max(1, pageElements.length);
|
|
4819
|
+
pageElements.forEach((elements, idx) => {
|
|
4820
|
+
const page = document.createElement("div");
|
|
4821
|
+
page.className = `fp-odt-page fp-odt-page-${idx + 1}`;
|
|
4822
|
+
page.style.width = `${dims.width}px`;
|
|
4823
|
+
page.style.minHeight = `${dims.height}px`;
|
|
4824
|
+
page.style.padding = `${dims.marginTop}px ${dims.marginRight}px ${dims.marginBottom}px ${dims.marginLeft}px`;
|
|
4825
|
+
page.style.margin = "0 auto";
|
|
4826
|
+
page.style.backgroundColor = "#ffffff";
|
|
4827
|
+
page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
4828
|
+
page.style.borderRadius = "4px";
|
|
4829
|
+
page.style.boxSizing = "border-box";
|
|
4830
|
+
page.style.display = idx === 0 ? "block" : "none";
|
|
4831
|
+
page.style.position = "absolute";
|
|
4832
|
+
page.style.top = "0";
|
|
4833
|
+
page.style.left = "50%";
|
|
4834
|
+
page.style.transform = "translateX(-50%)";
|
|
4835
|
+
elements.forEach((el) => page.appendChild(el));
|
|
4836
|
+
wrapper.appendChild(page);
|
|
4837
|
+
slides.push(page);
|
|
4838
|
+
});
|
|
4839
|
+
const pageIndicator = document.createElement("div");
|
|
4840
|
+
pageIndicator.className = "fp-odt-page-indicator";
|
|
4841
|
+
pageIndicator.style.position = "sticky";
|
|
4842
|
+
pageIndicator.style.bottom = "16px";
|
|
4843
|
+
pageIndicator.style.left = "50%";
|
|
4844
|
+
pageIndicator.style.transform = "translateX(-50%)";
|
|
4845
|
+
pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
|
4846
|
+
pageIndicator.style.color = "#fff";
|
|
4847
|
+
pageIndicator.style.padding = "6px 12px";
|
|
4848
|
+
pageIndicator.style.borderRadius = "16px";
|
|
4849
|
+
pageIndicator.style.fontSize = "12px";
|
|
4850
|
+
pageIndicator.style.zIndex = "100";
|
|
4851
|
+
pageIndicator.style.display = "inline-block";
|
|
4852
|
+
pageIndicator.style.width = "fit-content";
|
|
4853
|
+
pageIndicator.textContent = `Page 1 of ${totalPages}`;
|
|
4854
|
+
container.appendChild(pageIndicator);
|
|
4518
4855
|
}
|
|
4519
4856
|
const cleanup = () => {
|
|
4520
4857
|
imageUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
@@ -4523,11 +4860,15 @@ var OpenDocumentPlugin = class {
|
|
|
4523
4860
|
};
|
|
4524
4861
|
ctx.signal.addEventListener("abort", cleanup);
|
|
4525
4862
|
const goToPage = (page) => {
|
|
4526
|
-
if (
|
|
4863
|
+
if (page < 1 || page > totalPages) return;
|
|
4527
4864
|
currentPage = page;
|
|
4528
4865
|
slides.forEach((s, idx) => {
|
|
4529
4866
|
s.style.display = idx === page - 1 ? "block" : "none";
|
|
4530
4867
|
});
|
|
4868
|
+
const indicator = container.querySelector(".fp-odt-page-indicator");
|
|
4869
|
+
if (indicator) {
|
|
4870
|
+
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4871
|
+
}
|
|
4531
4872
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4532
4873
|
};
|
|
4533
4874
|
return {
|
|
@@ -4547,7 +4888,8 @@ var OpenDocumentPlugin = class {
|
|
|
4547
4888
|
applyTransform();
|
|
4548
4889
|
},
|
|
4549
4890
|
fitToPage: () => {
|
|
4550
|
-
|
|
4891
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
4892
|
+
scale = calculateFitScale(fitMode);
|
|
4551
4893
|
rotation = 0;
|
|
4552
4894
|
applyTransform();
|
|
4553
4895
|
},
|
|
@@ -4596,6 +4938,43 @@ var OpenDocumentPlugin = class {
|
|
|
4596
4938
|
}
|
|
4597
4939
|
};
|
|
4598
4940
|
}
|
|
4941
|
+
getPageDimensions(stylesDoc, contentDoc) {
|
|
4942
|
+
let width = 850;
|
|
4943
|
+
let height = 1123;
|
|
4944
|
+
let marginTop = 48;
|
|
4945
|
+
let marginBottom = 48;
|
|
4946
|
+
let marginLeft = 48;
|
|
4947
|
+
let marginRight = 48;
|
|
4948
|
+
const parseUnit = (val) => {
|
|
4949
|
+
if (!val) return null;
|
|
4950
|
+
if (val.endsWith("cm")) return parseFloat(val) * 37.8;
|
|
4951
|
+
if (val.endsWith("mm")) return parseFloat(val) * 3.78;
|
|
4952
|
+
if (val.endsWith("in")) return parseFloat(val) * 96;
|
|
4953
|
+
if (val.endsWith("pt")) return parseFloat(val) * 1.33;
|
|
4954
|
+
if (val.endsWith("px")) return parseFloat(val);
|
|
4955
|
+
return parseFloat(val);
|
|
4956
|
+
};
|
|
4957
|
+
const docs = [stylesDoc, contentDoc].filter(Boolean);
|
|
4958
|
+
for (const doc of docs) {
|
|
4959
|
+
const pageLayout = doc.querySelector("page-layout-properties, [page-width]");
|
|
4960
|
+
if (pageLayout) {
|
|
4961
|
+
const w = parseUnit(pageLayout.getAttribute("fo:page-width") || pageLayout.getAttribute("page-width"));
|
|
4962
|
+
const h = parseUnit(pageLayout.getAttribute("fo:page-height") || pageLayout.getAttribute("page-height"));
|
|
4963
|
+
const mt = parseUnit(pageLayout.getAttribute("fo:margin-top") || pageLayout.getAttribute("margin-top"));
|
|
4964
|
+
const mb = parseUnit(pageLayout.getAttribute("fo:margin-bottom") || pageLayout.getAttribute("margin-bottom"));
|
|
4965
|
+
const ml = parseUnit(pageLayout.getAttribute("fo:margin-left") || pageLayout.getAttribute("margin-left"));
|
|
4966
|
+
const mr = parseUnit(pageLayout.getAttribute("fo:margin-right") || pageLayout.getAttribute("margin-right"));
|
|
4967
|
+
if (w !== null) width = w;
|
|
4968
|
+
if (h !== null) height = h;
|
|
4969
|
+
if (mt !== null) marginTop = mt;
|
|
4970
|
+
if (mb !== null) marginBottom = mb;
|
|
4971
|
+
if (ml !== null) marginLeft = ml;
|
|
4972
|
+
if (mr !== null) marginRight = mr;
|
|
4973
|
+
break;
|
|
4974
|
+
}
|
|
4975
|
+
}
|
|
4976
|
+
return { width, height, marginTop, marginBottom, marginLeft, marginRight };
|
|
4977
|
+
}
|
|
4599
4978
|
extractStyles(stylesDoc, contentDoc) {
|
|
4600
4979
|
const map = /* @__PURE__ */ new Map();
|
|
4601
4980
|
const styleNodes = [];
|
|
@@ -4618,14 +4997,21 @@ var OpenDocumentPlugin = class {
|
|
|
4618
4997
|
if (color) css += `color: ${color}; `;
|
|
4619
4998
|
if (size) css += `font-size: ${size}; `;
|
|
4620
4999
|
}
|
|
4621
|
-
|
|
5000
|
+
let paraProp = node.querySelector("paragraph-properties, [text-align]");
|
|
5001
|
+
if (!paraProp) {
|
|
5002
|
+
paraProp = Array.from(node.children).find((c) => c.tagName.includes("paragraph-properties")) || null;
|
|
5003
|
+
}
|
|
4622
5004
|
if (paraProp) {
|
|
4623
5005
|
const align = paraProp.getAttribute("fo:text-align") || paraProp.getAttribute("text-align");
|
|
4624
5006
|
const mt = paraProp.getAttribute("fo:margin-top") || paraProp.getAttribute("margin-top");
|
|
4625
5007
|
const mb = paraProp.getAttribute("fo:margin-bottom") || paraProp.getAttribute("margin-bottom");
|
|
5008
|
+
const breakBefore = paraProp.getAttribute("fo:break-before") || paraProp.getAttribute("break-before");
|
|
5009
|
+
const breakAfter = paraProp.getAttribute("fo:break-after") || paraProp.getAttribute("break-after");
|
|
4626
5010
|
if (align) css += `text-align: ${align}; `;
|
|
4627
5011
|
if (mt) css += `margin-top: ${mt}; `;
|
|
4628
5012
|
if (mb) css += `margin-bottom: ${mb}; `;
|
|
5013
|
+
if (breakBefore === "page") css += "page-break-before: always; ";
|
|
5014
|
+
if (breakAfter === "page") css += "page-break-after: always; ";
|
|
4629
5015
|
}
|
|
4630
5016
|
if (css) map.set(name, css);
|
|
4631
5017
|
}
|
|
@@ -4710,6 +5096,8 @@ var OpenDocumentPlugin = class {
|
|
|
4710
5096
|
result += " ";
|
|
4711
5097
|
} else if (tag === "line-break") {
|
|
4712
5098
|
result += "<br/>";
|
|
5099
|
+
} else if (tag === "soft-page-break") {
|
|
5100
|
+
result += '<hr class="odf-page-break" style="page-break-after: always; border: none; margin: 0; padding: 0; height: 0;" />';
|
|
4713
5101
|
} else {
|
|
4714
5102
|
result += el.textContent || "";
|
|
4715
5103
|
}
|
|
@@ -4870,20 +5258,9 @@ var DocPlugin = class {
|
|
|
4870
5258
|
container.style.overflow = "auto";
|
|
4871
5259
|
container.style.padding = "32px 16px";
|
|
4872
5260
|
container.style.backgroundColor = "#f1f5f9";
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
wrapper.style.margin = "0 auto";
|
|
4877
|
-
wrapper.style.backgroundColor = "#ffffff";
|
|
4878
|
-
wrapper.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4879
|
-
wrapper.style.borderRadius = "4px";
|
|
4880
|
-
wrapper.style.padding = "56px 48px";
|
|
4881
|
-
wrapper.style.minHeight = "100%";
|
|
4882
|
-
wrapper.style.transformOrigin = "top center";
|
|
4883
|
-
wrapper.style.transition = "transform 0.2s ease";
|
|
4884
|
-
wrapper.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4885
|
-
wrapper.style.color = "#1e293b";
|
|
4886
|
-
container.appendChild(wrapper);
|
|
5261
|
+
container.style.display = "flex";
|
|
5262
|
+
container.style.justifyContent = "center";
|
|
5263
|
+
container.style.alignItems = "flex-start";
|
|
4887
5264
|
ctx.container.appendChild(container);
|
|
4888
5265
|
let scale = 1;
|
|
4889
5266
|
let extractedRawText = "";
|
|
@@ -4910,21 +5287,27 @@ var DocPlugin = class {
|
|
|
4910
5287
|
const rawPages = this.splitIntoPages(extractedRawText);
|
|
4911
5288
|
const totalPages = Math.max(1, rawPages.length);
|
|
4912
5289
|
let currentPage = 1;
|
|
4913
|
-
wrapper.innerHTML = "";
|
|
4914
5290
|
const pageCards = [];
|
|
4915
5291
|
for (let i = 0; i < totalPages; i++) {
|
|
4916
5292
|
const pageCard = document.createElement("div");
|
|
4917
5293
|
pageCard.className = "fp-doc-page-card";
|
|
5294
|
+
pageCard.style.width = "816px";
|
|
5295
|
+
pageCard.style.height = "1056px";
|
|
4918
5296
|
pageCard.style.backgroundColor = "#ffffff";
|
|
4919
5297
|
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4920
5298
|
pageCard.style.borderRadius = "4px";
|
|
4921
|
-
pageCard.style.padding = "
|
|
4922
|
-
pageCard.style.
|
|
5299
|
+
pageCard.style.padding = "96px 72px";
|
|
5300
|
+
pageCard.style.boxSizing = "border-box";
|
|
5301
|
+
pageCard.style.overflow = "hidden";
|
|
4923
5302
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5303
|
+
pageCard.style.transformOrigin = "top center";
|
|
5304
|
+
pageCard.style.transition = "transform 0.2s ease";
|
|
5305
|
+
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
5306
|
+
pageCard.style.color = "#1e293b";
|
|
4924
5307
|
if (isFallback && i === 0) {
|
|
4925
5308
|
pageCard.innerHTML = `
|
|
4926
5309
|
<div style="border-bottom: 1px solid #e2e8f0; padding-bottom: 12px; margin-bottom: 24px;">
|
|
4927
|
-
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${
|
|
5310
|
+
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify6__default.default.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
|
|
4928
5311
|
<span style="font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 4px;">Legacy Word 97-2003 Binary Preview</span>
|
|
4929
5312
|
</div>
|
|
4930
5313
|
${this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document")}
|
|
@@ -4932,15 +5315,17 @@ var DocPlugin = class {
|
|
|
4932
5315
|
} else {
|
|
4933
5316
|
pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
|
|
4934
5317
|
}
|
|
4935
|
-
|
|
5318
|
+
container.appendChild(pageCard);
|
|
4936
5319
|
pageCards.push(pageCard);
|
|
4937
5320
|
}
|
|
4938
5321
|
let indicator = null;
|
|
4939
5322
|
if (totalPages > 1) {
|
|
4940
5323
|
indicator = document.createElement("div");
|
|
4941
5324
|
indicator.className = "fp-doc-page-indicator";
|
|
4942
|
-
indicator.style.position = "
|
|
5325
|
+
indicator.style.position = "fixed";
|
|
4943
5326
|
indicator.style.bottom = "16px";
|
|
5327
|
+
indicator.style.left = "50%";
|
|
5328
|
+
indicator.style.transform = "translateX(-50%)";
|
|
4944
5329
|
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4945
5330
|
indicator.style.backdropFilter = "blur(8px)";
|
|
4946
5331
|
indicator.style.color = "#f8fafc";
|
|
@@ -4954,17 +5339,25 @@ var DocPlugin = class {
|
|
|
4954
5339
|
indicator.style.userSelect = "none";
|
|
4955
5340
|
indicator.style.pointerEvents = "none";
|
|
4956
5341
|
indicator.style.textAlign = "center";
|
|
4957
|
-
indicator.style.width = "fit-content";
|
|
4958
|
-
indicator.style.margin = "16px auto 0";
|
|
4959
5342
|
container.appendChild(indicator);
|
|
4960
5343
|
}
|
|
5344
|
+
let rotation = 0;
|
|
5345
|
+
const applyTransform = () => {
|
|
5346
|
+
const activeCard = pageCards[currentPage - 1];
|
|
5347
|
+
if (activeCard) {
|
|
5348
|
+
activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5349
|
+
}
|
|
5350
|
+
};
|
|
4961
5351
|
const showPage = (pageNum) => {
|
|
4962
5352
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
card.style.display =
|
|
4966
|
-
|
|
4967
|
-
|
|
5353
|
+
pageCards.forEach((card, idx) => {
|
|
5354
|
+
if (idx + 1 === currentPage) {
|
|
5355
|
+
card.style.display = "block";
|
|
5356
|
+
card.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5357
|
+
} else {
|
|
5358
|
+
card.style.display = "none";
|
|
5359
|
+
}
|
|
5360
|
+
});
|
|
4968
5361
|
if (indicator) {
|
|
4969
5362
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4970
5363
|
}
|
|
@@ -4973,21 +5366,22 @@ var DocPlugin = class {
|
|
|
4973
5366
|
if (totalPages > 1) {
|
|
4974
5367
|
showPage(1);
|
|
4975
5368
|
}
|
|
4976
|
-
let
|
|
4977
|
-
const calculateFitScale = () => {
|
|
4978
|
-
const
|
|
4979
|
-
const
|
|
4980
|
-
const
|
|
4981
|
-
const
|
|
4982
|
-
const
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
5369
|
+
let fitMode = "width";
|
|
5370
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
5371
|
+
const elW = 816;
|
|
5372
|
+
const elH = 1056;
|
|
5373
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
5374
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
5375
|
+
const sW = availW / elW;
|
|
5376
|
+
const sH = availH / elH;
|
|
5377
|
+
if (mode === "page") {
|
|
5378
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
5379
|
+
}
|
|
5380
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
4988
5381
|
};
|
|
4989
5382
|
setTimeout(() => {
|
|
4990
|
-
|
|
5383
|
+
fitMode = "width";
|
|
5384
|
+
scale = calculateFitScale("width");
|
|
4991
5385
|
applyTransform();
|
|
4992
5386
|
}, 60);
|
|
4993
5387
|
const cleanup = () => {
|
|
@@ -5015,7 +5409,8 @@ var DocPlugin = class {
|
|
|
5015
5409
|
applyTransform();
|
|
5016
5410
|
},
|
|
5017
5411
|
fitToPage: () => {
|
|
5018
|
-
|
|
5412
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
5413
|
+
scale = calculateFitScale(fitMode);
|
|
5019
5414
|
rotation = 0;
|
|
5020
5415
|
applyTransform();
|
|
5021
5416
|
},
|
|
@@ -5143,8 +5538,28 @@ var DocPlugin = class {
|
|
|
5143
5538
|
}
|
|
5144
5539
|
splitIntoPages(text) {
|
|
5145
5540
|
if (!text) return [""];
|
|
5146
|
-
const
|
|
5147
|
-
|
|
5541
|
+
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);
|
|
5542
|
+
if (explicitParts.length === 0) explicitParts.push(text);
|
|
5543
|
+
const maxLinesPerPage = 48;
|
|
5544
|
+
const finalPages = [];
|
|
5545
|
+
for (const part of explicitParts) {
|
|
5546
|
+
const lines = part.split(/\r?\n/);
|
|
5547
|
+
let currentLines = [];
|
|
5548
|
+
let count = 0;
|
|
5549
|
+
for (const line of lines) {
|
|
5550
|
+
currentLines.push(line);
|
|
5551
|
+
count++;
|
|
5552
|
+
if (count >= maxLinesPerPage) {
|
|
5553
|
+
finalPages.push(currentLines.join("\n"));
|
|
5554
|
+
currentLines = [];
|
|
5555
|
+
count = 0;
|
|
5556
|
+
}
|
|
5557
|
+
}
|
|
5558
|
+
if (currentLines.length > 0) {
|
|
5559
|
+
finalPages.push(currentLines.join("\n"));
|
|
5560
|
+
}
|
|
5561
|
+
}
|
|
5562
|
+
return finalPages.length > 0 ? finalPages : [text];
|
|
5148
5563
|
}
|
|
5149
5564
|
/**
|
|
5150
5565
|
* Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
|
|
@@ -5153,17 +5568,65 @@ var DocPlugin = class {
|
|
|
5153
5568
|
const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
|
|
5154
5569
|
let html = "";
|
|
5155
5570
|
let inList = false;
|
|
5156
|
-
|
|
5157
|
-
|
|
5571
|
+
let tableLines = [];
|
|
5572
|
+
const flushTable = () => {
|
|
5573
|
+
if (tableLines.length > 0) {
|
|
5574
|
+
html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
|
|
5575
|
+
for (const tLine of tableLines) {
|
|
5576
|
+
html += "<tr>";
|
|
5577
|
+
const cols = tLine.split(" ");
|
|
5578
|
+
for (const col of cols) {
|
|
5579
|
+
html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
|
|
5580
|
+
}
|
|
5581
|
+
html += "</tr>";
|
|
5582
|
+
}
|
|
5583
|
+
html += "</table>";
|
|
5584
|
+
tableLines = [];
|
|
5585
|
+
}
|
|
5586
|
+
};
|
|
5587
|
+
let i = 0;
|
|
5588
|
+
while (i < lines.length) {
|
|
5589
|
+
let line = lines[i];
|
|
5590
|
+
let tabCount = (line.match(/\t/g) || []).length;
|
|
5591
|
+
if (tabCount > 0) {
|
|
5592
|
+
let consecutiveTableLines = 1;
|
|
5593
|
+
let j = i + 1;
|
|
5594
|
+
while (j < lines.length) {
|
|
5595
|
+
const nextTabCount = (lines[j].match(/\t/g) || []).length;
|
|
5596
|
+
if (nextTabCount === tabCount) {
|
|
5597
|
+
consecutiveTableLines++;
|
|
5598
|
+
j++;
|
|
5599
|
+
} else {
|
|
5600
|
+
break;
|
|
5601
|
+
}
|
|
5602
|
+
}
|
|
5603
|
+
if (consecutiveTableLines >= 3) {
|
|
5604
|
+
if (inList) {
|
|
5605
|
+
html += "</ul>";
|
|
5606
|
+
inList = false;
|
|
5607
|
+
}
|
|
5608
|
+
tableLines = lines.slice(i, j);
|
|
5609
|
+
flushTable();
|
|
5610
|
+
i = j;
|
|
5611
|
+
continue;
|
|
5612
|
+
}
|
|
5613
|
+
}
|
|
5614
|
+
line = line.trim();
|
|
5158
5615
|
if (!line) {
|
|
5159
5616
|
if (inList) {
|
|
5160
5617
|
html += "</ul>";
|
|
5161
5618
|
inList = false;
|
|
5162
5619
|
}
|
|
5620
|
+
html += '<div style="height: 1.15em;"></div>';
|
|
5621
|
+
i++;
|
|
5622
|
+
continue;
|
|
5623
|
+
}
|
|
5624
|
+
if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line)) {
|
|
5625
|
+
i++;
|
|
5163
5626
|
continue;
|
|
5164
5627
|
}
|
|
5165
|
-
if (
|
|
5166
|
-
|
|
5628
|
+
if ((line.includes("Normal.dot") || line.includes("Microsoft Word") || line.includes("Times New Roman")) && line.length < 30) {
|
|
5629
|
+
i++;
|
|
5167
5630
|
continue;
|
|
5168
5631
|
}
|
|
5169
5632
|
if (line.length < 60 && !line.endsWith(".") && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#"))) {
|
|
@@ -5171,24 +5634,26 @@ var DocPlugin = class {
|
|
|
5171
5634
|
html += "</ul>";
|
|
5172
5635
|
inList = false;
|
|
5173
5636
|
}
|
|
5174
|
-
html += `<h2 style="font-size:
|
|
5637
|
+
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>`;
|
|
5175
5638
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
5176
5639
|
if (!inList) {
|
|
5177
5640
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
5178
5641
|
inList = true;
|
|
5179
5642
|
}
|
|
5180
5643
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
5181
|
-
html += `<li style="margin: 4px 0; line-height: 1.
|
|
5644
|
+
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6__default.default.sanitize(bulletText)}</li>`;
|
|
5182
5645
|
} else {
|
|
5183
5646
|
if (inList) {
|
|
5184
5647
|
html += "</ul>";
|
|
5185
5648
|
inList = false;
|
|
5186
5649
|
}
|
|
5187
|
-
html += `<p style="line-height: 1.
|
|
5650
|
+
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6__default.default.sanitize(line)}</p>`;
|
|
5188
5651
|
}
|
|
5652
|
+
i++;
|
|
5189
5653
|
}
|
|
5190
5654
|
if (inList) html += "</ul>";
|
|
5191
|
-
|
|
5655
|
+
flushTable();
|
|
5656
|
+
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6__default.default.sanitize(filename)})</p>`;
|
|
5192
5657
|
}
|
|
5193
5658
|
};
|
|
5194
5659
|
function docPlugin() {
|
|
@@ -5366,7 +5831,7 @@ var PptPlugin = class {
|
|
|
5366
5831
|
if (s.pictureUrl) {
|
|
5367
5832
|
contentHtml = `
|
|
5368
5833
|
<div style="flex: 1; display: flex; justify-content: center; align-items: center; padding: 12px; overflow: hidden;">
|
|
5369
|
-
<img src="${s.pictureUrl}" alt="${
|
|
5834
|
+
<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;" />
|
|
5370
5835
|
</div>
|
|
5371
5836
|
`;
|
|
5372
5837
|
} else if (s.tableColumns.length > 0) {
|
|
@@ -5376,7 +5841,7 @@ var PptPlugin = class {
|
|
|
5376
5841
|
<table style="width: 100%; border-collapse: collapse; border: 1px solid #cbd5e1; border-radius: 6px; overflow: hidden; background: #ffffff;">
|
|
5377
5842
|
<thead>
|
|
5378
5843
|
<tr style="background: #e2e8f0; color: #1e293b; font-weight: 600; font-size: 14px;">
|
|
5379
|
-
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${
|
|
5844
|
+
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${DOMPurify6__default.default.sanitize(c)}</th>`).join("")}
|
|
5380
5845
|
</tr>
|
|
5381
5846
|
</thead>
|
|
5382
5847
|
<tbody>
|
|
@@ -5392,7 +5857,7 @@ var PptPlugin = class {
|
|
|
5392
5857
|
} else {
|
|
5393
5858
|
const pTags = s.paragraphs.map((p) => {
|
|
5394
5859
|
const lines = p.split(/[\r\n]+/).map((l) => l.trim()).filter(Boolean);
|
|
5395
|
-
return lines.map((l) => `<p style="margin: 0 0 14px; font-size: 14px; line-height: 1.65; color: #334155; text-align: justify;">${
|
|
5860
|
+
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("");
|
|
5396
5861
|
}).join("");
|
|
5397
5862
|
contentHtml = `
|
|
5398
5863
|
<div style="flex: 1; overflow: auto; padding: 4px 8px; display: flex; flex-direction: column; justify-content: flex-start;">
|
|
@@ -5405,11 +5870,11 @@ var PptPlugin = class {
|
|
|
5405
5870
|
<!-- Header Banner matching PowerPoint design -->
|
|
5406
5871
|
<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;">
|
|
5407
5872
|
<h1 style="margin: 0; font-size: 26px; font-weight: 700; color: #1e293b; letter-spacing: -0.3px;">
|
|
5408
|
-
${
|
|
5873
|
+
${DOMPurify6__default.default.sanitize(s.title)}
|
|
5409
5874
|
</h1>
|
|
5410
5875
|
${s.subtitle ? `
|
|
5411
5876
|
<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);">
|
|
5412
|
-
${
|
|
5877
|
+
${DOMPurify6__default.default.sanitize(s.subtitle)}
|
|
5413
5878
|
</span>
|
|
5414
5879
|
` : `
|
|
5415
5880
|
<span style="font-size: 12px; color: #365314; font-weight: 600;">
|