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