@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/angular.cjs
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var core = require('@angular/core');
|
|
6
6
|
var common = require('@angular/common');
|
|
7
|
-
var
|
|
7
|
+
var DOMPurify6 = require('dompurify');
|
|
8
8
|
var pdfjsLib = require('pdfjs-dist');
|
|
9
9
|
var docx = require('docx-preview');
|
|
10
10
|
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);
|
|
@@ -437,7 +437,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
437
437
|
if (magicMime === "application/zip") {
|
|
438
438
|
const ooxmlMime = detectOoxmlType(buffer);
|
|
439
439
|
if (ooxmlMime && ooxmlMime !== "application/zip") {
|
|
440
|
-
metadata.mimeType = ooxmlMime;
|
|
440
|
+
metadata.mimeType = metadata.mimeType ?? ooxmlMime;
|
|
441
441
|
if (ooxmlMime.includes("wordprocessing")) metadata.extension = metadata.extension ?? ".docx";
|
|
442
442
|
else if (ooxmlMime.includes("spreadsheet")) metadata.extension = metadata.extension ?? ".xlsx";
|
|
443
443
|
else if (ooxmlMime.includes("presentation")) metadata.extension = metadata.extension ?? ".pptx";
|
|
@@ -466,7 +466,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
466
466
|
return { buffer, metadata };
|
|
467
467
|
}
|
|
468
468
|
function sanitizeSVG(svg) {
|
|
469
|
-
return
|
|
469
|
+
return DOMPurify6__default.default.sanitize(svg, {
|
|
470
470
|
USE_PROFILES: { svg: true, svgFilters: true }
|
|
471
471
|
});
|
|
472
472
|
}
|
|
@@ -513,7 +513,8 @@ function createElement(tag, attrs, ...children) {
|
|
|
513
513
|
}
|
|
514
514
|
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>`;
|
|
515
515
|
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>`;
|
|
516
|
-
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"><
|
|
516
|
+
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>`;
|
|
517
|
+
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>`;
|
|
517
518
|
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>`;
|
|
518
519
|
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>`;
|
|
519
520
|
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>`;
|
|
@@ -533,6 +534,7 @@ var ICON_MAP = {
|
|
|
533
534
|
"zoom-in": ICON_ZOOM_IN,
|
|
534
535
|
"zoom-out": ICON_ZOOM_OUT,
|
|
535
536
|
"fit-page": ICON_FIT_PAGE,
|
|
537
|
+
"fit-width": ICON_FIT_WIDTH,
|
|
536
538
|
"fit-slide": ICON_FIT_PAGE,
|
|
537
539
|
"rotate-cw": ICON_ROTATE_CW,
|
|
538
540
|
"rotate-ccw": ICON_ROTATE_CCW,
|
|
@@ -1479,6 +1481,7 @@ var PdfPlugin = class {
|
|
|
1479
1481
|
let currentPage = 1;
|
|
1480
1482
|
let zoomScale = 1;
|
|
1481
1483
|
let rotation = 0;
|
|
1484
|
+
let fitMode = "width";
|
|
1482
1485
|
let currentRenderTask = null;
|
|
1483
1486
|
const renderPage = async (pageNum) => {
|
|
1484
1487
|
if (currentRenderTask) {
|
|
@@ -1498,11 +1501,16 @@ var PdfPlugin = class {
|
|
|
1498
1501
|
const containerWidth = container.clientWidth || 900;
|
|
1499
1502
|
const containerHeight = container.clientHeight || 700;
|
|
1500
1503
|
const unscaledVp = page.getViewport({ scale: 1, rotation });
|
|
1501
|
-
const availWidth = Math.max(
|
|
1502
|
-
const availHeight = Math.max(
|
|
1504
|
+
const availWidth = Math.max(280, containerWidth - 48);
|
|
1505
|
+
const availHeight = Math.max(280, containerHeight - 88);
|
|
1503
1506
|
const scaleW = availWidth / unscaledVp.width;
|
|
1504
1507
|
const scaleH = availHeight / unscaledVp.height;
|
|
1505
|
-
|
|
1508
|
+
let fitScale;
|
|
1509
|
+
if (fitMode === "page") {
|
|
1510
|
+
fitScale = Math.max(0.5, Math.min(scaleW, scaleH));
|
|
1511
|
+
} else {
|
|
1512
|
+
fitScale = Math.max(0.65, Math.min(1.15, scaleW));
|
|
1513
|
+
}
|
|
1506
1514
|
const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
|
|
1507
1515
|
const pixelRatio = window.devicePixelRatio || 1;
|
|
1508
1516
|
const viewport = page.getViewport({ scale: effectiveScale, rotation });
|
|
@@ -1528,7 +1536,19 @@ var PdfPlugin = class {
|
|
|
1528
1536
|
}
|
|
1529
1537
|
};
|
|
1530
1538
|
await renderPage(1);
|
|
1539
|
+
let resizeTimer = null;
|
|
1540
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
1541
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1542
|
+
resizeTimer = setTimeout(() => {
|
|
1543
|
+
if (Math.abs(zoomScale - 1) < 0.05) {
|
|
1544
|
+
renderPage(currentPage);
|
|
1545
|
+
}
|
|
1546
|
+
}, 150);
|
|
1547
|
+
});
|
|
1548
|
+
resizeObserver.observe(container);
|
|
1531
1549
|
const cleanup = () => {
|
|
1550
|
+
resizeObserver.disconnect();
|
|
1551
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1532
1552
|
if (currentRenderTask) {
|
|
1533
1553
|
try {
|
|
1534
1554
|
currentRenderTask.cancel();
|
|
@@ -1559,6 +1579,7 @@ var PdfPlugin = class {
|
|
|
1559
1579
|
renderPage(currentPage);
|
|
1560
1580
|
},
|
|
1561
1581
|
fitToPage: () => {
|
|
1582
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
1562
1583
|
zoomScale = 1;
|
|
1563
1584
|
rotation = 0;
|
|
1564
1585
|
renderPage(currentPage);
|
|
@@ -2112,8 +2133,53 @@ var DocxPlugin = class {
|
|
|
2112
2133
|
}
|
|
2113
2134
|
}
|
|
2114
2135
|
}
|
|
2115
|
-
|
|
2116
|
-
const cards = wrapper.querySelectorAll(".fp-docx-page-card");
|
|
2136
|
+
let sections = Array.from(wrapper.querySelectorAll("section.docx"));
|
|
2137
|
+
const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
|
|
2138
|
+
if (sections.length === 1 && cards.length === 0) {
|
|
2139
|
+
const singleSec = sections[0];
|
|
2140
|
+
const pageH = 1056;
|
|
2141
|
+
const secH = singleSec.offsetHeight || singleSec.scrollHeight;
|
|
2142
|
+
if (secH > pageH * 1.25) {
|
|
2143
|
+
const children = Array.from(singleSec.children);
|
|
2144
|
+
if (children.length > 1) {
|
|
2145
|
+
const parent = singleSec.parentElement || wrapper;
|
|
2146
|
+
const newSections = [singleSec];
|
|
2147
|
+
singleSec.innerHTML = "";
|
|
2148
|
+
singleSec.style.minHeight = `${pageH}px`;
|
|
2149
|
+
singleSec.style.maxHeight = `${pageH}px`;
|
|
2150
|
+
singleSec.style.overflow = "hidden";
|
|
2151
|
+
singleSec.style.boxSizing = "border-box";
|
|
2152
|
+
let curSec = singleSec;
|
|
2153
|
+
let curH = 0;
|
|
2154
|
+
const maxH = pageH - 96;
|
|
2155
|
+
for (let i = 0; i < children.length; i++) {
|
|
2156
|
+
const child = children[i];
|
|
2157
|
+
curSec.appendChild(child);
|
|
2158
|
+
const chH = child.offsetHeight || 28;
|
|
2159
|
+
curH += chH;
|
|
2160
|
+
if (curH >= maxH && i < children.length - 1) {
|
|
2161
|
+
const nextSec = document.createElement("section");
|
|
2162
|
+
nextSec.className = singleSec.className;
|
|
2163
|
+
nextSec.style.cssText = singleSec.style.cssText;
|
|
2164
|
+
nextSec.style.width = singleSec.style.width || "816px";
|
|
2165
|
+
nextSec.style.minHeight = `${pageH}px`;
|
|
2166
|
+
nextSec.style.maxHeight = `${pageH}px`;
|
|
2167
|
+
nextSec.style.overflow = "hidden";
|
|
2168
|
+
nextSec.style.boxSizing = "border-box";
|
|
2169
|
+
nextSec.style.backgroundColor = "#ffffff";
|
|
2170
|
+
nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
|
|
2171
|
+
nextSec.style.borderRadius = "4px";
|
|
2172
|
+
nextSec.style.marginBottom = "24px";
|
|
2173
|
+
parent.appendChild(nextSec);
|
|
2174
|
+
newSections.push(nextSec);
|
|
2175
|
+
curSec = nextSec;
|
|
2176
|
+
curH = 0;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
sections = newSections;
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2117
2183
|
const pageElements = sections.length > 0 ? sections : cards;
|
|
2118
2184
|
const totalPages = Math.max(1, pageElements.length);
|
|
2119
2185
|
let currentPage = 1;
|
|
@@ -2157,22 +2223,27 @@ var DocxPlugin = class {
|
|
|
2157
2223
|
}
|
|
2158
2224
|
scale = 1;
|
|
2159
2225
|
let rotation = 0;
|
|
2160
|
-
|
|
2226
|
+
let fitMode = "width";
|
|
2227
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
2161
2228
|
const activeEl = pageElements[currentPage - 1] || wrapper.firstElementChild || wrapper;
|
|
2162
2229
|
const elW = activeEl.offsetWidth || 816;
|
|
2163
|
-
const
|
|
2164
|
-
const availW = Math.max(
|
|
2165
|
-
const availH = Math.max(
|
|
2230
|
+
const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
2231
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
2232
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
2166
2233
|
const sW = availW / elW;
|
|
2167
|
-
const sH = availH /
|
|
2168
|
-
|
|
2234
|
+
const sH = availH / singlePageH;
|
|
2235
|
+
if (mode === "page") {
|
|
2236
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
2237
|
+
}
|
|
2238
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
2169
2239
|
};
|
|
2170
2240
|
const applyTransform = () => {
|
|
2171
2241
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
2172
2242
|
wrapper.style.transformOrigin = "top center";
|
|
2173
2243
|
};
|
|
2174
2244
|
setTimeout(() => {
|
|
2175
|
-
|
|
2245
|
+
fitMode = "width";
|
|
2246
|
+
scale = calculateFitScale("width");
|
|
2176
2247
|
applyTransform();
|
|
2177
2248
|
}, 60);
|
|
2178
2249
|
const cleanup = () => {
|
|
@@ -2206,7 +2277,8 @@ var DocxPlugin = class {
|
|
|
2206
2277
|
applyTransform();
|
|
2207
2278
|
},
|
|
2208
2279
|
fitToPage: () => {
|
|
2209
|
-
|
|
2280
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
2281
|
+
scale = calculateFitScale(fitMode);
|
|
2210
2282
|
rotation = 0;
|
|
2211
2283
|
applyTransform();
|
|
2212
2284
|
},
|
|
@@ -2276,90 +2348,149 @@ var DocxPlugin = class {
|
|
|
2276
2348
|
console.warn("[DocxPlugin] Error parsing relationships:", relsErr);
|
|
2277
2349
|
}
|
|
2278
2350
|
}
|
|
2279
|
-
const
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2351
|
+
const sectPrs = Array.from(doc.getElementsByTagNameNS("*", "sectPr"));
|
|
2352
|
+
const lastSectPr = sectPrs[sectPrs.length - 1];
|
|
2353
|
+
let defaultW = 12240;
|
|
2354
|
+
let defaultH = 15840;
|
|
2355
|
+
let margins = { top: 1440, right: 1440, bottom: 1440, left: 1440 };
|
|
2356
|
+
if (lastSectPr) {
|
|
2357
|
+
const pgSz = lastSectPr.getElementsByTagNameNS("*", "pgSz")[0];
|
|
2358
|
+
if (pgSz) {
|
|
2359
|
+
defaultW = parseInt(pgSz.getAttribute("w:w") || pgSz.getAttribute("w") || "12240", 10);
|
|
2360
|
+
defaultH = parseInt(pgSz.getAttribute("w:h") || pgSz.getAttribute("h") || "15840", 10);
|
|
2361
|
+
}
|
|
2362
|
+
const pgMar = lastSectPr.getElementsByTagNameNS("*", "pgMar")[0];
|
|
2363
|
+
if (pgMar) {
|
|
2364
|
+
margins.top = parseInt(pgMar.getAttribute("w:top") || pgMar.getAttribute("top") || "1440", 10);
|
|
2365
|
+
margins.bottom = parseInt(pgMar.getAttribute("w:bottom") || pgMar.getAttribute("bottom") || "1440", 10);
|
|
2366
|
+
margins.left = parseInt(pgMar.getAttribute("w:left") || pgMar.getAttribute("left") || "1440", 10);
|
|
2367
|
+
margins.right = parseInt(pgMar.getAttribute("w:right") || pgMar.getAttribute("right") || "1440", 10);
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
const createPageCard = () => {
|
|
2371
|
+
const card = document.createElement("div");
|
|
2372
|
+
card.className = "fp-docx-page-card";
|
|
2373
|
+
card.style.backgroundColor = "#ffffff";
|
|
2374
|
+
card.style.borderRadius = "4px";
|
|
2375
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
2376
|
+
card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2377
|
+
card.style.color = "#1e293b";
|
|
2378
|
+
card.style.lineHeight = "1.6";
|
|
2379
|
+
card.style.boxSizing = "border-box";
|
|
2380
|
+
card.style.overflow = "hidden";
|
|
2381
|
+
card.style.position = "relative";
|
|
2382
|
+
card.style.marginBottom = "24px";
|
|
2383
|
+
card.style.width = `${defaultW / 15}px`;
|
|
2384
|
+
card.style.height = `${defaultH / 15}px`;
|
|
2385
|
+
card.style.padding = `${margins.top / 15}px ${margins.right / 15}px ${margins.bottom / 15}px ${margins.left / 15}px`;
|
|
2386
|
+
return card;
|
|
2387
|
+
};
|
|
2388
|
+
let currentCard = createPageCard();
|
|
2389
|
+
let currentHtml = "";
|
|
2390
|
+
const pages = [{ card: currentCard, html: "" }];
|
|
2391
|
+
const flushHtml = () => {
|
|
2392
|
+
pages[pages.length - 1].html += currentHtml;
|
|
2393
|
+
currentHtml = "";
|
|
2394
|
+
};
|
|
2395
|
+
const newPage = () => {
|
|
2396
|
+
flushHtml();
|
|
2397
|
+
currentCard = createPageCard();
|
|
2398
|
+
pages.push({ card: currentCard, html: "" });
|
|
2399
|
+
};
|
|
2288
2400
|
const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
|
|
2289
|
-
let html = "";
|
|
2290
2401
|
for (const child of Array.from(body.children)) {
|
|
2291
2402
|
const tag = child.localName || child.nodeName.split(":").pop();
|
|
2292
2403
|
if (tag === "p") {
|
|
2293
2404
|
const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
|
|
2294
2405
|
const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
|
|
2295
2406
|
const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
|
|
2296
|
-
const
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2407
|
+
const chunks = this.extractParagraphChunks(child, imageMap);
|
|
2408
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
2409
|
+
if (i > 0) {
|
|
2410
|
+
newPage();
|
|
2411
|
+
}
|
|
2412
|
+
const textContent = chunks[i];
|
|
2413
|
+
if (!textContent.trim() && !textContent.includes("<img")) {
|
|
2414
|
+
currentHtml += '<div style="height: 10px;"></div>';
|
|
2415
|
+
continue;
|
|
2416
|
+
}
|
|
2417
|
+
const lowerStyle = styleVal.toLowerCase();
|
|
2418
|
+
if (lowerStyle.includes("title")) {
|
|
2419
|
+
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>`;
|
|
2420
|
+
} else if (lowerStyle.includes("heading1") || styleVal === "1") {
|
|
2421
|
+
currentHtml += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
|
|
2422
|
+
} else if (lowerStyle.includes("heading2") || styleVal === "2") {
|
|
2423
|
+
currentHtml += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
|
|
2424
|
+
} else if (lowerStyle.includes("heading3") || styleVal === "3") {
|
|
2425
|
+
currentHtml += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
|
|
2426
|
+
} else if (numPr) {
|
|
2427
|
+
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>`;
|
|
2428
|
+
} else {
|
|
2429
|
+
currentHtml += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
|
|
2430
|
+
}
|
|
2314
2431
|
}
|
|
2315
2432
|
} else if (tag === "tbl") {
|
|
2316
|
-
|
|
2433
|
+
currentHtml += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
|
|
2317
2434
|
const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
|
|
2318
2435
|
rows.forEach((tr, rIdx) => {
|
|
2319
|
-
|
|
2436
|
+
currentHtml += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
2320
2437
|
const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
|
|
2321
2438
|
cells.forEach((tc) => {
|
|
2322
2439
|
const cellText = this.extractParagraphHtml(tc, imageMap);
|
|
2323
|
-
|
|
2440
|
+
currentHtml += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || " "}</td>`;
|
|
2324
2441
|
});
|
|
2325
|
-
|
|
2442
|
+
currentHtml += "</tr>";
|
|
2326
2443
|
});
|
|
2327
|
-
|
|
2444
|
+
currentHtml += "</table>";
|
|
2328
2445
|
}
|
|
2329
2446
|
}
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2447
|
+
flushHtml();
|
|
2448
|
+
for (const page of pages) {
|
|
2449
|
+
page.card.innerHTML = DOMPurify6__default.default.sanitize(page.html, {
|
|
2450
|
+
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
|
|
2451
|
+
ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
|
|
2452
|
+
});
|
|
2453
|
+
wrapper.appendChild(page.card);
|
|
2454
|
+
}
|
|
2335
2455
|
}
|
|
2336
2456
|
extractParagraphHtml(pElement, imageMap = {}) {
|
|
2337
|
-
|
|
2457
|
+
return this.extractParagraphChunks(pElement, imageMap).join("<br/>");
|
|
2458
|
+
}
|
|
2459
|
+
extractParagraphChunks(pElement, imageMap = {}) {
|
|
2460
|
+
const chunks = [""];
|
|
2461
|
+
let currentChunkIndex = 0;
|
|
2338
2462
|
const drawings = Array.from(pElement.getElementsByTagNameNS("*", "drawing"));
|
|
2339
2463
|
for (const drawing of drawings) {
|
|
2340
2464
|
const blip = drawing.getElementsByTagNameNS("*", "blip")[0];
|
|
2341
2465
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2342
2466
|
if (rId && imageMap[rId]) {
|
|
2343
|
-
|
|
2467
|
+
chunks[currentChunkIndex] += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
|
|
2344
2468
|
}
|
|
2345
2469
|
}
|
|
2346
2470
|
const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
|
|
2347
|
-
if (runs.length === 0 && !
|
|
2348
|
-
|
|
2471
|
+
if (runs.length === 0 && !chunks[currentChunkIndex]) {
|
|
2472
|
+
chunks[currentChunkIndex] = DOMPurify6__default.default.sanitize(pElement.textContent || "");
|
|
2473
|
+
return chunks;
|
|
2349
2474
|
}
|
|
2350
2475
|
for (const r of runs) {
|
|
2351
2476
|
const blip = r.getElementsByTagNameNS("*", "blip")[0] || r.getElementsByTagNameNS("*", "imagedata")[0];
|
|
2352
2477
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2353
2478
|
if (rId && imageMap[rId]) {
|
|
2354
|
-
|
|
2479
|
+
chunks[currentChunkIndex] += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
|
|
2355
2480
|
}
|
|
2356
|
-
const brs = r.getElementsByTagNameNS("*", "br");
|
|
2357
|
-
for (
|
|
2358
|
-
|
|
2481
|
+
const brs = Array.from(r.getElementsByTagNameNS("*", "br"));
|
|
2482
|
+
for (const br of brs) {
|
|
2483
|
+
const type = br.getAttribute("w:type") || br.getAttribute("type");
|
|
2484
|
+
if (type === "page") {
|
|
2485
|
+
chunks.push("");
|
|
2486
|
+
currentChunkIndex++;
|
|
2487
|
+
} else {
|
|
2488
|
+
chunks[currentChunkIndex] += "<br/>";
|
|
2489
|
+
}
|
|
2359
2490
|
}
|
|
2360
2491
|
const tabs = r.getElementsByTagNameNS("*", "tab");
|
|
2361
2492
|
if (tabs.length > 0) {
|
|
2362
|
-
|
|
2493
|
+
chunks[currentChunkIndex] += " ";
|
|
2363
2494
|
}
|
|
2364
2495
|
const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
|
|
2365
2496
|
const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
|
|
@@ -2373,7 +2504,7 @@ var DocxPlugin = class {
|
|
|
2373
2504
|
const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
|
|
2374
2505
|
let text = texts.map((t) => t.textContent || "").join("");
|
|
2375
2506
|
if (!text) continue;
|
|
2376
|
-
text =
|
|
2507
|
+
text = DOMPurify6__default.default.sanitize(text);
|
|
2377
2508
|
let styles = "";
|
|
2378
2509
|
if (isBold) styles += "font-weight: bold; ";
|
|
2379
2510
|
if (isItalic) styles += "font-style: italic; ";
|
|
@@ -2385,12 +2516,12 @@ var DocxPlugin = class {
|
|
|
2385
2516
|
if (!isNaN(pt) && pt > 0) styles += `font-size: ${pt}pt; `;
|
|
2386
2517
|
}
|
|
2387
2518
|
if (styles) {
|
|
2388
|
-
|
|
2519
|
+
chunks[currentChunkIndex] += `<span style="${styles}">${text}</span>`;
|
|
2389
2520
|
} else {
|
|
2390
|
-
|
|
2521
|
+
chunks[currentChunkIndex] += text;
|
|
2391
2522
|
}
|
|
2392
2523
|
}
|
|
2393
|
-
return
|
|
2524
|
+
return chunks;
|
|
2394
2525
|
}
|
|
2395
2526
|
renderBinaryDocFallback(ctx, wrapper) {
|
|
2396
2527
|
const card = document.createElement("div");
|
|
@@ -2407,14 +2538,14 @@ var DocxPlugin = class {
|
|
|
2407
2538
|
const wordDocStream = cfbf.readStream("WordDocument");
|
|
2408
2539
|
if (wordDocStream && wordDocStream.length >= 512) {
|
|
2409
2540
|
const text2 = this.extractReadableStrings(wordDocStream);
|
|
2410
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2541
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text2)}</div>`;
|
|
2411
2542
|
wrapper.appendChild(card);
|
|
2412
2543
|
return;
|
|
2413
2544
|
}
|
|
2414
2545
|
} catch {
|
|
2415
2546
|
}
|
|
2416
2547
|
const text = this.extractReadableStrings(new Uint8Array(ctx.buffer));
|
|
2417
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2548
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text)}</div>`;
|
|
2418
2549
|
wrapper.appendChild(card);
|
|
2419
2550
|
}
|
|
2420
2551
|
extractReadableStrings(bytes) {
|
|
@@ -2591,11 +2722,9 @@ var ExcelPlugin = class {
|
|
|
2591
2722
|
const calculateFitScale = () => {
|
|
2592
2723
|
const table = contentArea.querySelector("table");
|
|
2593
2724
|
if (!table) return 1;
|
|
2594
|
-
const availW = Math.max(
|
|
2595
|
-
const availH = Math.max(200, container.clientHeight - 80);
|
|
2725
|
+
const availW = Math.max(280, container.clientWidth - 48);
|
|
2596
2726
|
const tW = table.offsetWidth || 800;
|
|
2597
|
-
|
|
2598
|
-
return Math.min(1, Math.min(availW / tW, availH / tH));
|
|
2727
|
+
return Math.max(0.65, Math.min(1, availW / tW));
|
|
2599
2728
|
};
|
|
2600
2729
|
try {
|
|
2601
2730
|
wb = XLSX__namespace.read(new Uint8Array(ctx.buffer), { type: "array", cellDates: true });
|
|
@@ -3013,41 +3142,94 @@ var CodePlugin = class {
|
|
|
3013
3142
|
async render(ctx) {
|
|
3014
3143
|
const decoder = new TextDecoder("utf-8");
|
|
3015
3144
|
const fullText = decoder.decode(ctx.buffer);
|
|
3016
|
-
const
|
|
3017
|
-
const
|
|
3145
|
+
const extRaw = ctx.metadata.extension?.toLowerCase();
|
|
3146
|
+
const mimeRaw = ctx.metadata.mimeType?.toLowerCase();
|
|
3147
|
+
const isTxt = extRaw === ".txt" || mimeRaw === "text/plain" && (!extRaw || !this.extensions.filter((e) => e !== ".txt").includes(extRaw));
|
|
3148
|
+
let rawPages = [];
|
|
3149
|
+
if (isTxt) {
|
|
3150
|
+
const explicitPages = fullText.split(/(?:\f|\x0C)/);
|
|
3151
|
+
for (const ep of explicitPages) {
|
|
3152
|
+
const lines = ep.split(/\r?\n/);
|
|
3153
|
+
let currentChunk = [];
|
|
3154
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3155
|
+
currentChunk.push(lines[i]);
|
|
3156
|
+
if (currentChunk.length >= 46) {
|
|
3157
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3158
|
+
currentChunk = [];
|
|
3159
|
+
}
|
|
3160
|
+
}
|
|
3161
|
+
if (currentChunk.length > 0 || lines.length === 0) {
|
|
3162
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3165
|
+
if (rawPages.length === 0) rawPages = [""];
|
|
3166
|
+
} else {
|
|
3167
|
+
const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
|
|
3168
|
+
rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
3169
|
+
}
|
|
3018
3170
|
const totalPages = Math.max(1, rawPages.length);
|
|
3019
3171
|
let currentPage = 1;
|
|
3020
3172
|
const container = document.createElement("div");
|
|
3021
3173
|
container.style.width = "100%";
|
|
3022
3174
|
container.style.height = "100%";
|
|
3023
3175
|
container.style.overflow = "auto";
|
|
3024
|
-
container.style.backgroundColor = "#1e1e1e";
|
|
3025
|
-
container.style.color = "#d4d4d4";
|
|
3026
|
-
container.style.padding = "16px";
|
|
3027
|
-
container.style.boxSizing = "border-box";
|
|
3028
3176
|
let fontSize = 13;
|
|
3029
3177
|
let rotation = 0;
|
|
3178
|
+
let zoomLevel = 1;
|
|
3030
3179
|
const pre = document.createElement("pre");
|
|
3031
|
-
pre.style.margin = "0";
|
|
3032
|
-
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
3033
|
-
pre.style.fontSize = `${fontSize}px`;
|
|
3034
|
-
pre.style.lineHeight = "1.5";
|
|
3035
|
-
pre.style.whiteSpace = "pre-wrap";
|
|
3036
|
-
pre.style.wordBreak = "break-all";
|
|
3037
3180
|
const code = document.createElement("code");
|
|
3181
|
+
if (isTxt) {
|
|
3182
|
+
container.style.backgroundColor = "#f1f5f9";
|
|
3183
|
+
container.style.padding = "32px";
|
|
3184
|
+
container.style.boxSizing = "border-box";
|
|
3185
|
+
container.style.display = "flex";
|
|
3186
|
+
container.style.flexDirection = "column";
|
|
3187
|
+
container.style.alignItems = "center";
|
|
3188
|
+
pre.style.margin = "0";
|
|
3189
|
+
pre.style.fontFamily = "Consolas, 'Courier New', monospace";
|
|
3190
|
+
pre.style.fontSize = "13px";
|
|
3191
|
+
pre.style.color = "#1e293b";
|
|
3192
|
+
pre.style.lineHeight = "1.5";
|
|
3193
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3194
|
+
pre.style.wordBreak = "break-word";
|
|
3195
|
+
pre.style.backgroundColor = "#ffffff";
|
|
3196
|
+
pre.style.width = "816px";
|
|
3197
|
+
pre.style.minHeight = "1056px";
|
|
3198
|
+
pre.style.padding = "72px 56px";
|
|
3199
|
+
pre.style.boxSizing = "border-box";
|
|
3200
|
+
pre.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)";
|
|
3201
|
+
pre.style.borderRadius = "4px";
|
|
3202
|
+
pre.style.transformOrigin = "top center";
|
|
3203
|
+
} else {
|
|
3204
|
+
container.style.backgroundColor = "#1e1e1e";
|
|
3205
|
+
container.style.color = "#d4d4d4";
|
|
3206
|
+
container.style.padding = "16px";
|
|
3207
|
+
container.style.boxSizing = "border-box";
|
|
3208
|
+
pre.style.margin = "0";
|
|
3209
|
+
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
3210
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3211
|
+
pre.style.lineHeight = "1.5";
|
|
3212
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3213
|
+
pre.style.wordBreak = "break-all";
|
|
3214
|
+
pre.style.transformOrigin = "top left";
|
|
3215
|
+
}
|
|
3038
3216
|
const ext = (ctx.metadata.extension || "").replace(".", "");
|
|
3039
3217
|
const renderCodePage = (text) => {
|
|
3040
|
-
|
|
3041
|
-
if (ext && hljs__default.default.getLanguage(ext)) {
|
|
3042
|
-
code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
|
|
3043
|
-
} else {
|
|
3044
|
-
code.innerHTML = hljs__default.default.highlightAuto(text).value;
|
|
3045
|
-
}
|
|
3046
|
-
} catch {
|
|
3218
|
+
if (isTxt) {
|
|
3047
3219
|
code.textContent = text;
|
|
3220
|
+
} else {
|
|
3221
|
+
try {
|
|
3222
|
+
if (ext && hljs__default.default.getLanguage(ext)) {
|
|
3223
|
+
code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
|
|
3224
|
+
} else {
|
|
3225
|
+
code.innerHTML = hljs__default.default.highlightAuto(text).value;
|
|
3226
|
+
}
|
|
3227
|
+
} catch {
|
|
3228
|
+
code.textContent = text;
|
|
3229
|
+
}
|
|
3048
3230
|
}
|
|
3049
3231
|
};
|
|
3050
|
-
renderCodePage(rawPages[0] || fullText);
|
|
3232
|
+
renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
|
|
3051
3233
|
pre.appendChild(code);
|
|
3052
3234
|
container.appendChild(pre);
|
|
3053
3235
|
let indicator = null;
|
|
@@ -3056,15 +3238,22 @@ var CodePlugin = class {
|
|
|
3056
3238
|
indicator.className = "fp-code-page-indicator";
|
|
3057
3239
|
indicator.style.position = "sticky";
|
|
3058
3240
|
indicator.style.bottom = "16px";
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3241
|
+
if (isTxt) {
|
|
3242
|
+
indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
3243
|
+
indicator.style.color = "#334155";
|
|
3244
|
+
indicator.style.border = "1px solid #e2e8f0";
|
|
3245
|
+
indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
|
|
3246
|
+
} else {
|
|
3247
|
+
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3248
|
+
indicator.style.color = "#f8fafc";
|
|
3249
|
+
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3250
|
+
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3251
|
+
indicator.style.backdropFilter = "blur(8px)";
|
|
3252
|
+
}
|
|
3062
3253
|
indicator.style.fontSize = "12px";
|
|
3063
3254
|
indicator.style.fontWeight = "600";
|
|
3064
3255
|
indicator.style.padding = "5px 14px";
|
|
3065
3256
|
indicator.style.borderRadius = "20px";
|
|
3066
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3067
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3068
3257
|
indicator.style.zIndex = "10";
|
|
3069
3258
|
indicator.style.userSelect = "none";
|
|
3070
3259
|
indicator.style.pointerEvents = "none";
|
|
@@ -3075,7 +3264,7 @@ var CodePlugin = class {
|
|
|
3075
3264
|
}
|
|
3076
3265
|
const showPage = (pageNum) => {
|
|
3077
3266
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3078
|
-
renderCodePage(rawPages[currentPage - 1] || fullText);
|
|
3267
|
+
renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
|
|
3079
3268
|
if (indicator) {
|
|
3080
3269
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
3081
3270
|
}
|
|
@@ -3091,39 +3280,57 @@ var CodePlugin = class {
|
|
|
3091
3280
|
ctx.container.innerHTML = "";
|
|
3092
3281
|
};
|
|
3093
3282
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3283
|
+
const updateTransform = () => {
|
|
3284
|
+
if (isTxt) {
|
|
3285
|
+
pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
|
|
3286
|
+
} else {
|
|
3287
|
+
pre.style.transform = `rotate(${rotation}deg)`;
|
|
3288
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3289
|
+
}
|
|
3290
|
+
};
|
|
3094
3291
|
return {
|
|
3095
3292
|
destroy: cleanup,
|
|
3096
3293
|
getPageCount: () => totalPages,
|
|
3097
3294
|
getCurrentPage: () => currentPage,
|
|
3098
3295
|
goToPage: (page) => showPage(page),
|
|
3099
3296
|
zoomIn: () => {
|
|
3100
|
-
|
|
3101
|
-
|
|
3297
|
+
if (isTxt) {
|
|
3298
|
+
zoomLevel = Math.min(3, zoomLevel + 0.1);
|
|
3299
|
+
} else {
|
|
3300
|
+
fontSize = Math.min(32, fontSize + 2);
|
|
3301
|
+
}
|
|
3302
|
+
updateTransform();
|
|
3102
3303
|
},
|
|
3103
3304
|
zoomOut: () => {
|
|
3104
|
-
|
|
3105
|
-
|
|
3305
|
+
if (isTxt) {
|
|
3306
|
+
zoomLevel = Math.max(0.1, zoomLevel - 0.1);
|
|
3307
|
+
} else {
|
|
3308
|
+
fontSize = Math.max(8, fontSize - 2);
|
|
3309
|
+
}
|
|
3310
|
+
updateTransform();
|
|
3106
3311
|
},
|
|
3107
|
-
getZoom: () => fontSize / 13,
|
|
3312
|
+
getZoom: () => isTxt ? zoomLevel : fontSize / 13,
|
|
3108
3313
|
setZoom: (level) => {
|
|
3109
|
-
|
|
3110
|
-
|
|
3314
|
+
if (isTxt) {
|
|
3315
|
+
zoomLevel = level;
|
|
3316
|
+
} else {
|
|
3317
|
+
fontSize = Math.round(13 * level);
|
|
3318
|
+
}
|
|
3319
|
+
updateTransform();
|
|
3111
3320
|
},
|
|
3112
3321
|
fitToPage: () => {
|
|
3113
3322
|
fontSize = 13;
|
|
3114
3323
|
rotation = 0;
|
|
3115
|
-
|
|
3116
|
-
|
|
3324
|
+
zoomLevel = isTxt ? Math.max(0.65, Math.min(1.05, (container.clientWidth - 48) / 816)) : 1;
|
|
3325
|
+
updateTransform();
|
|
3117
3326
|
},
|
|
3118
3327
|
rotateCW: () => {
|
|
3119
3328
|
rotation = (rotation + 90) % 360;
|
|
3120
|
-
|
|
3121
|
-
pre.style.transformOrigin = "top left";
|
|
3329
|
+
updateTransform();
|
|
3122
3330
|
},
|
|
3123
3331
|
rotateCCW: () => {
|
|
3124
3332
|
rotation = (rotation - 90 + 360) % 360;
|
|
3125
|
-
|
|
3126
|
-
pre.style.transformOrigin = "top left";
|
|
3333
|
+
updateTransform();
|
|
3127
3334
|
},
|
|
3128
3335
|
download: () => {
|
|
3129
3336
|
const mimeType = ctx.metadata.mimeType || "text/plain";
|
|
@@ -3422,7 +3629,7 @@ var MarkdownPlugin = class {
|
|
|
3422
3629
|
gfm: true,
|
|
3423
3630
|
breaks: true
|
|
3424
3631
|
});
|
|
3425
|
-
const cleanHtml =
|
|
3632
|
+
const cleanHtml = DOMPurify6__default.default.sanitize(rawHtml, {
|
|
3426
3633
|
USE_PROFILES: { html: true }
|
|
3427
3634
|
});
|
|
3428
3635
|
const wrapper = document.createElement("div");
|
|
@@ -4058,6 +4265,14 @@ var RtfPlugin = class {
|
|
|
4058
4265
|
group: "actions",
|
|
4059
4266
|
execute: () => instance.download?.()
|
|
4060
4267
|
},
|
|
4268
|
+
{
|
|
4269
|
+
id: "copy",
|
|
4270
|
+
icon: "copy",
|
|
4271
|
+
label: "Copy Text",
|
|
4272
|
+
type: "button",
|
|
4273
|
+
group: "actions",
|
|
4274
|
+
execute: () => instance.copy?.()
|
|
4275
|
+
},
|
|
4061
4276
|
{
|
|
4062
4277
|
id: "print",
|
|
4063
4278
|
icon: "print",
|
|
@@ -4088,20 +4303,27 @@ var RtfPlugin = class {
|
|
|
4088
4303
|
let scale = 1;
|
|
4089
4304
|
let rotation = 0;
|
|
4090
4305
|
let pageElements = [];
|
|
4091
|
-
|
|
4306
|
+
let fitMode = "width";
|
|
4307
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
4092
4308
|
const activeEl = pageElements[currentPage - 1] || wrapper;
|
|
4093
4309
|
const elW = activeEl.offsetWidth || 850;
|
|
4094
|
-
const
|
|
4095
|
-
const availW = Math.max(
|
|
4096
|
-
const availH = Math.max(
|
|
4097
|
-
|
|
4310
|
+
const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
4311
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
4312
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
4313
|
+
const sW = availW / elW;
|
|
4314
|
+
const sH = availH / singlePageH;
|
|
4315
|
+
if (mode === "page") {
|
|
4316
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
4317
|
+
}
|
|
4318
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
4098
4319
|
};
|
|
4099
4320
|
const applyTransform = () => {
|
|
4100
4321
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4101
4322
|
wrapper.style.transformOrigin = "top center";
|
|
4102
4323
|
};
|
|
4103
4324
|
setTimeout(() => {
|
|
4104
|
-
|
|
4325
|
+
fitMode = "width";
|
|
4326
|
+
scale = calculateFitScale("width");
|
|
4105
4327
|
applyTransform();
|
|
4106
4328
|
}, 60);
|
|
4107
4329
|
try {
|
|
@@ -4119,14 +4341,31 @@ var RtfPlugin = class {
|
|
|
4119
4341
|
} catch (err) {
|
|
4120
4342
|
console.warn("[RtfPlugin] RTF render error, fallback text:", err);
|
|
4121
4343
|
const text = new TextDecoder("latin1").decode(ctx.buffer);
|
|
4122
|
-
const
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4344
|
+
const rawPages = text.split(/\\page\b/).map((segment) => {
|
|
4345
|
+
return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
|
|
4346
|
+
}).filter((p) => p.length > 0);
|
|
4347
|
+
const pages = rawPages.length > 0 ? rawPages : [text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim()];
|
|
4348
|
+
for (let i = 0; i < pages.length; i++) {
|
|
4349
|
+
const pageCard = document.createElement("div");
|
|
4350
|
+
pageCard.className = "fp-rtf-page-card";
|
|
4351
|
+
pageCard.style.backgroundColor = "#ffffff";
|
|
4352
|
+
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4353
|
+
pageCard.style.borderRadius = "4px";
|
|
4354
|
+
pageCard.style.padding = "72px 56px";
|
|
4355
|
+
pageCard.style.width = "816px";
|
|
4356
|
+
pageCard.style.minHeight = "1056px";
|
|
4357
|
+
pageCard.style.maxWidth = "100%";
|
|
4358
|
+
pageCard.style.boxSizing = "border-box";
|
|
4359
|
+
pageCard.style.fontFamily = "serif";
|
|
4360
|
+
pageCard.style.fontSize = "12pt";
|
|
4361
|
+
pageCard.style.lineHeight = "1.6";
|
|
4362
|
+
pageCard.style.color = "#1e293b";
|
|
4363
|
+
pageCard.style.whiteSpace = "pre-wrap";
|
|
4364
|
+
pageCard.style.display = i === 0 ? "block" : "none";
|
|
4365
|
+
pageCard.textContent = pages[i];
|
|
4366
|
+
wrapper.appendChild(pageCard);
|
|
4367
|
+
pageElements.push(pageCard);
|
|
4368
|
+
}
|
|
4130
4369
|
}
|
|
4131
4370
|
const totalPages = Math.max(1, pageElements.length);
|
|
4132
4371
|
let currentPage = 1;
|
|
@@ -4193,7 +4432,8 @@ var RtfPlugin = class {
|
|
|
4193
4432
|
applyTransform();
|
|
4194
4433
|
},
|
|
4195
4434
|
fitToPage: () => {
|
|
4196
|
-
|
|
4435
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
4436
|
+
scale = calculateFitScale(fitMode);
|
|
4197
4437
|
rotation = 0;
|
|
4198
4438
|
applyTransform();
|
|
4199
4439
|
},
|
|
@@ -4214,6 +4454,10 @@ var RtfPlugin = class {
|
|
|
4214
4454
|
a.click();
|
|
4215
4455
|
URL.revokeObjectURL(url);
|
|
4216
4456
|
},
|
|
4457
|
+
copy: () => {
|
|
4458
|
+
const text = wrapper.textContent || "";
|
|
4459
|
+
navigator.clipboard?.writeText(text);
|
|
4460
|
+
},
|
|
4217
4461
|
print: () => {
|
|
4218
4462
|
window.print();
|
|
4219
4463
|
}
|
|
@@ -4288,7 +4532,7 @@ var HtmlPreviewPlugin = class {
|
|
|
4288
4532
|
}
|
|
4289
4533
|
async render(ctx) {
|
|
4290
4534
|
const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
|
|
4291
|
-
const sanitized =
|
|
4535
|
+
const sanitized = DOMPurify6__default.default.sanitize(rawHtml, {
|
|
4292
4536
|
WHOLE_DOCUMENT: true,
|
|
4293
4537
|
ADD_TAGS: ["style", "link"],
|
|
4294
4538
|
ADD_ATTR: ["target", "rel"]
|
|
@@ -4508,19 +4752,29 @@ var OpenDocumentPlugin = class {
|
|
|
4508
4752
|
ctx.container.appendChild(container);
|
|
4509
4753
|
let scale = 1;
|
|
4510
4754
|
let rotation = 0;
|
|
4511
|
-
|
|
4755
|
+
let fitMode = "width";
|
|
4756
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
4512
4757
|
const elW = wrapper.offsetWidth || 850;
|
|
4513
|
-
const
|
|
4514
|
-
const availW = Math.max(
|
|
4515
|
-
const availH = Math.max(
|
|
4516
|
-
|
|
4758
|
+
const singlePageH = Math.min(wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
|
|
4759
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
4760
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
4761
|
+
const sW = availW / elW;
|
|
4762
|
+
const sH = availH / (isPresentation ? 540 : singlePageH);
|
|
4763
|
+
if (isPresentation) {
|
|
4764
|
+
return Math.min(1, Math.min(sW, sH));
|
|
4765
|
+
}
|
|
4766
|
+
if (mode === "page") {
|
|
4767
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
4768
|
+
}
|
|
4769
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
4517
4770
|
};
|
|
4518
4771
|
const applyTransform = () => {
|
|
4519
4772
|
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4520
4773
|
wrapper.style.transformOrigin = "top center";
|
|
4521
4774
|
};
|
|
4522
4775
|
setTimeout(() => {
|
|
4523
|
-
|
|
4776
|
+
fitMode = "width";
|
|
4777
|
+
scale = calculateFitScale("width");
|
|
4524
4778
|
applyTransform();
|
|
4525
4779
|
}, 60);
|
|
4526
4780
|
let currentPage = 1;
|
|
@@ -4554,14 +4808,97 @@ var OpenDocumentPlugin = class {
|
|
|
4554
4808
|
wrapper.textContent = contentDoc.documentElement.textContent || "Formula content";
|
|
4555
4809
|
}
|
|
4556
4810
|
} else {
|
|
4557
|
-
wrapper.style.maxWidth = "
|
|
4558
|
-
wrapper.style.padding = "
|
|
4811
|
+
wrapper.style.maxWidth = "none";
|
|
4812
|
+
wrapper.style.padding = "0";
|
|
4559
4813
|
wrapper.style.minHeight = "100%";
|
|
4814
|
+
wrapper.style.backgroundColor = "transparent";
|
|
4815
|
+
wrapper.style.boxShadow = "none";
|
|
4816
|
+
wrapper.style.position = "relative";
|
|
4817
|
+
const dims = this.getPageDimensions(stylesDoc, contentDoc);
|
|
4560
4818
|
const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
|
|
4561
|
-
|
|
4562
|
-
|
|
4819
|
+
const tempDiv = document.createElement("div");
|
|
4820
|
+
tempDiv.style.width = `${dims.width - dims.marginLeft - dims.marginRight}px`;
|
|
4821
|
+
tempDiv.style.position = "absolute";
|
|
4822
|
+
tempDiv.style.visibility = "hidden";
|
|
4823
|
+
tempDiv.innerHTML = DOMPurify6__default.default.sanitize(bodyHtml, {
|
|
4824
|
+
ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub", "hr"],
|
|
4563
4825
|
ADD_ATTR: ["style", "colspan", "rowspan"]
|
|
4564
4826
|
});
|
|
4827
|
+
document.body.appendChild(tempDiv);
|
|
4828
|
+
const contentHeight = dims.height - dims.marginTop - dims.marginBottom;
|
|
4829
|
+
const pageElements = [[]];
|
|
4830
|
+
let currentHeight = 0;
|
|
4831
|
+
let currentPageIdx = 0;
|
|
4832
|
+
Array.from(tempDiv.children).forEach((child) => {
|
|
4833
|
+
const el = child;
|
|
4834
|
+
const style = el.getAttribute("style") || "";
|
|
4835
|
+
const isBreakBefore = style.includes("page-break-before: always");
|
|
4836
|
+
const isBreakAfter = style.includes("page-break-after: always");
|
|
4837
|
+
const isSoftBreak = el.classList.contains("odf-page-break");
|
|
4838
|
+
if (isBreakBefore) {
|
|
4839
|
+
if (pageElements[currentPageIdx].length > 0) {
|
|
4840
|
+
currentPageIdx++;
|
|
4841
|
+
pageElements.push([]);
|
|
4842
|
+
currentHeight = 0;
|
|
4843
|
+
}
|
|
4844
|
+
}
|
|
4845
|
+
const h = el.offsetHeight || 0;
|
|
4846
|
+
if (currentHeight + h > contentHeight && pageElements[currentPageIdx].length > 0 && !isSoftBreak) {
|
|
4847
|
+
currentPageIdx++;
|
|
4848
|
+
pageElements.push([]);
|
|
4849
|
+
currentHeight = 0;
|
|
4850
|
+
}
|
|
4851
|
+
if (!isSoftBreak) {
|
|
4852
|
+
pageElements[currentPageIdx].push(el.cloneNode(true));
|
|
4853
|
+
currentHeight += h;
|
|
4854
|
+
}
|
|
4855
|
+
if (isBreakAfter || isSoftBreak) {
|
|
4856
|
+
currentPageIdx++;
|
|
4857
|
+
pageElements.push([]);
|
|
4858
|
+
currentHeight = 0;
|
|
4859
|
+
}
|
|
4860
|
+
});
|
|
4861
|
+
document.body.removeChild(tempDiv);
|
|
4862
|
+
if (pageElements.length > 1 && pageElements[pageElements.length - 1].length === 0) {
|
|
4863
|
+
pageElements.pop();
|
|
4864
|
+
}
|
|
4865
|
+
totalPages = Math.max(1, pageElements.length);
|
|
4866
|
+
pageElements.forEach((elements, idx) => {
|
|
4867
|
+
const page = document.createElement("div");
|
|
4868
|
+
page.className = `fp-odt-page fp-odt-page-${idx + 1}`;
|
|
4869
|
+
page.style.width = `${dims.width}px`;
|
|
4870
|
+
page.style.minHeight = `${dims.height}px`;
|
|
4871
|
+
page.style.padding = `${dims.marginTop}px ${dims.marginRight}px ${dims.marginBottom}px ${dims.marginLeft}px`;
|
|
4872
|
+
page.style.margin = "0 auto";
|
|
4873
|
+
page.style.backgroundColor = "#ffffff";
|
|
4874
|
+
page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
4875
|
+
page.style.borderRadius = "4px";
|
|
4876
|
+
page.style.boxSizing = "border-box";
|
|
4877
|
+
page.style.display = idx === 0 ? "block" : "none";
|
|
4878
|
+
page.style.position = "absolute";
|
|
4879
|
+
page.style.top = "0";
|
|
4880
|
+
page.style.left = "50%";
|
|
4881
|
+
page.style.transform = "translateX(-50%)";
|
|
4882
|
+
elements.forEach((el) => page.appendChild(el));
|
|
4883
|
+
wrapper.appendChild(page);
|
|
4884
|
+
slides.push(page);
|
|
4885
|
+
});
|
|
4886
|
+
const pageIndicator = document.createElement("div");
|
|
4887
|
+
pageIndicator.className = "fp-odt-page-indicator";
|
|
4888
|
+
pageIndicator.style.position = "sticky";
|
|
4889
|
+
pageIndicator.style.bottom = "16px";
|
|
4890
|
+
pageIndicator.style.left = "50%";
|
|
4891
|
+
pageIndicator.style.transform = "translateX(-50%)";
|
|
4892
|
+
pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
|
4893
|
+
pageIndicator.style.color = "#fff";
|
|
4894
|
+
pageIndicator.style.padding = "6px 12px";
|
|
4895
|
+
pageIndicator.style.borderRadius = "16px";
|
|
4896
|
+
pageIndicator.style.fontSize = "12px";
|
|
4897
|
+
pageIndicator.style.zIndex = "100";
|
|
4898
|
+
pageIndicator.style.display = "inline-block";
|
|
4899
|
+
pageIndicator.style.width = "fit-content";
|
|
4900
|
+
pageIndicator.textContent = `Page 1 of ${totalPages}`;
|
|
4901
|
+
container.appendChild(pageIndicator);
|
|
4565
4902
|
}
|
|
4566
4903
|
const cleanup = () => {
|
|
4567
4904
|
imageUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
@@ -4570,11 +4907,15 @@ var OpenDocumentPlugin = class {
|
|
|
4570
4907
|
};
|
|
4571
4908
|
ctx.signal.addEventListener("abort", cleanup);
|
|
4572
4909
|
const goToPage = (page) => {
|
|
4573
|
-
if (
|
|
4910
|
+
if (page < 1 || page > totalPages) return;
|
|
4574
4911
|
currentPage = page;
|
|
4575
4912
|
slides.forEach((s, idx) => {
|
|
4576
4913
|
s.style.display = idx === page - 1 ? "block" : "none";
|
|
4577
4914
|
});
|
|
4915
|
+
const indicator = container.querySelector(".fp-odt-page-indicator");
|
|
4916
|
+
if (indicator) {
|
|
4917
|
+
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4918
|
+
}
|
|
4578
4919
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4579
4920
|
};
|
|
4580
4921
|
return {
|
|
@@ -4594,7 +4935,8 @@ var OpenDocumentPlugin = class {
|
|
|
4594
4935
|
applyTransform();
|
|
4595
4936
|
},
|
|
4596
4937
|
fitToPage: () => {
|
|
4597
|
-
|
|
4938
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
4939
|
+
scale = calculateFitScale(fitMode);
|
|
4598
4940
|
rotation = 0;
|
|
4599
4941
|
applyTransform();
|
|
4600
4942
|
},
|
|
@@ -4643,6 +4985,43 @@ var OpenDocumentPlugin = class {
|
|
|
4643
4985
|
}
|
|
4644
4986
|
};
|
|
4645
4987
|
}
|
|
4988
|
+
getPageDimensions(stylesDoc, contentDoc) {
|
|
4989
|
+
let width = 850;
|
|
4990
|
+
let height = 1123;
|
|
4991
|
+
let marginTop = 48;
|
|
4992
|
+
let marginBottom = 48;
|
|
4993
|
+
let marginLeft = 48;
|
|
4994
|
+
let marginRight = 48;
|
|
4995
|
+
const parseUnit = (val) => {
|
|
4996
|
+
if (!val) return null;
|
|
4997
|
+
if (val.endsWith("cm")) return parseFloat(val) * 37.8;
|
|
4998
|
+
if (val.endsWith("mm")) return parseFloat(val) * 3.78;
|
|
4999
|
+
if (val.endsWith("in")) return parseFloat(val) * 96;
|
|
5000
|
+
if (val.endsWith("pt")) return parseFloat(val) * 1.33;
|
|
5001
|
+
if (val.endsWith("px")) return parseFloat(val);
|
|
5002
|
+
return parseFloat(val);
|
|
5003
|
+
};
|
|
5004
|
+
const docs = [stylesDoc, contentDoc].filter(Boolean);
|
|
5005
|
+
for (const doc of docs) {
|
|
5006
|
+
const pageLayout = doc.querySelector("page-layout-properties, [page-width]");
|
|
5007
|
+
if (pageLayout) {
|
|
5008
|
+
const w = parseUnit(pageLayout.getAttribute("fo:page-width") || pageLayout.getAttribute("page-width"));
|
|
5009
|
+
const h = parseUnit(pageLayout.getAttribute("fo:page-height") || pageLayout.getAttribute("page-height"));
|
|
5010
|
+
const mt = parseUnit(pageLayout.getAttribute("fo:margin-top") || pageLayout.getAttribute("margin-top"));
|
|
5011
|
+
const mb = parseUnit(pageLayout.getAttribute("fo:margin-bottom") || pageLayout.getAttribute("margin-bottom"));
|
|
5012
|
+
const ml = parseUnit(pageLayout.getAttribute("fo:margin-left") || pageLayout.getAttribute("margin-left"));
|
|
5013
|
+
const mr = parseUnit(pageLayout.getAttribute("fo:margin-right") || pageLayout.getAttribute("margin-right"));
|
|
5014
|
+
if (w !== null) width = w;
|
|
5015
|
+
if (h !== null) height = h;
|
|
5016
|
+
if (mt !== null) marginTop = mt;
|
|
5017
|
+
if (mb !== null) marginBottom = mb;
|
|
5018
|
+
if (ml !== null) marginLeft = ml;
|
|
5019
|
+
if (mr !== null) marginRight = mr;
|
|
5020
|
+
break;
|
|
5021
|
+
}
|
|
5022
|
+
}
|
|
5023
|
+
return { width, height, marginTop, marginBottom, marginLeft, marginRight };
|
|
5024
|
+
}
|
|
4646
5025
|
extractStyles(stylesDoc, contentDoc) {
|
|
4647
5026
|
const map = /* @__PURE__ */ new Map();
|
|
4648
5027
|
const styleNodes = [];
|
|
@@ -4665,14 +5044,21 @@ var OpenDocumentPlugin = class {
|
|
|
4665
5044
|
if (color) css += `color: ${color}; `;
|
|
4666
5045
|
if (size) css += `font-size: ${size}; `;
|
|
4667
5046
|
}
|
|
4668
|
-
|
|
5047
|
+
let paraProp = node.querySelector("paragraph-properties, [text-align]");
|
|
5048
|
+
if (!paraProp) {
|
|
5049
|
+
paraProp = Array.from(node.children).find((c) => c.tagName.includes("paragraph-properties")) || null;
|
|
5050
|
+
}
|
|
4669
5051
|
if (paraProp) {
|
|
4670
5052
|
const align = paraProp.getAttribute("fo:text-align") || paraProp.getAttribute("text-align");
|
|
4671
5053
|
const mt = paraProp.getAttribute("fo:margin-top") || paraProp.getAttribute("margin-top");
|
|
4672
5054
|
const mb = paraProp.getAttribute("fo:margin-bottom") || paraProp.getAttribute("margin-bottom");
|
|
5055
|
+
const breakBefore = paraProp.getAttribute("fo:break-before") || paraProp.getAttribute("break-before");
|
|
5056
|
+
const breakAfter = paraProp.getAttribute("fo:break-after") || paraProp.getAttribute("break-after");
|
|
4673
5057
|
if (align) css += `text-align: ${align}; `;
|
|
4674
5058
|
if (mt) css += `margin-top: ${mt}; `;
|
|
4675
5059
|
if (mb) css += `margin-bottom: ${mb}; `;
|
|
5060
|
+
if (breakBefore === "page") css += "page-break-before: always; ";
|
|
5061
|
+
if (breakAfter === "page") css += "page-break-after: always; ";
|
|
4676
5062
|
}
|
|
4677
5063
|
if (css) map.set(name, css);
|
|
4678
5064
|
}
|
|
@@ -4757,6 +5143,8 @@ var OpenDocumentPlugin = class {
|
|
|
4757
5143
|
result += " ";
|
|
4758
5144
|
} else if (tag === "line-break") {
|
|
4759
5145
|
result += "<br/>";
|
|
5146
|
+
} else if (tag === "soft-page-break") {
|
|
5147
|
+
result += '<hr class="odf-page-break" style="page-break-after: always; border: none; margin: 0; padding: 0; height: 0;" />';
|
|
4760
5148
|
} else {
|
|
4761
5149
|
result += el.textContent || "";
|
|
4762
5150
|
}
|
|
@@ -4917,20 +5305,9 @@ var DocPlugin = class {
|
|
|
4917
5305
|
container.style.overflow = "auto";
|
|
4918
5306
|
container.style.padding = "32px 16px";
|
|
4919
5307
|
container.style.backgroundColor = "#f1f5f9";
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
wrapper.style.margin = "0 auto";
|
|
4924
|
-
wrapper.style.backgroundColor = "#ffffff";
|
|
4925
|
-
wrapper.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4926
|
-
wrapper.style.borderRadius = "4px";
|
|
4927
|
-
wrapper.style.padding = "56px 48px";
|
|
4928
|
-
wrapper.style.minHeight = "100%";
|
|
4929
|
-
wrapper.style.transformOrigin = "top center";
|
|
4930
|
-
wrapper.style.transition = "transform 0.2s ease";
|
|
4931
|
-
wrapper.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4932
|
-
wrapper.style.color = "#1e293b";
|
|
4933
|
-
container.appendChild(wrapper);
|
|
5308
|
+
container.style.display = "flex";
|
|
5309
|
+
container.style.justifyContent = "center";
|
|
5310
|
+
container.style.alignItems = "flex-start";
|
|
4934
5311
|
ctx.container.appendChild(container);
|
|
4935
5312
|
let scale = 1;
|
|
4936
5313
|
let extractedRawText = "";
|
|
@@ -4957,21 +5334,27 @@ var DocPlugin = class {
|
|
|
4957
5334
|
const rawPages = this.splitIntoPages(extractedRawText);
|
|
4958
5335
|
const totalPages = Math.max(1, rawPages.length);
|
|
4959
5336
|
let currentPage = 1;
|
|
4960
|
-
wrapper.innerHTML = "";
|
|
4961
5337
|
const pageCards = [];
|
|
4962
5338
|
for (let i = 0; i < totalPages; i++) {
|
|
4963
5339
|
const pageCard = document.createElement("div");
|
|
4964
5340
|
pageCard.className = "fp-doc-page-card";
|
|
5341
|
+
pageCard.style.width = "816px";
|
|
5342
|
+
pageCard.style.height = "1056px";
|
|
4965
5343
|
pageCard.style.backgroundColor = "#ffffff";
|
|
4966
5344
|
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4967
5345
|
pageCard.style.borderRadius = "4px";
|
|
4968
|
-
pageCard.style.padding = "
|
|
4969
|
-
pageCard.style.
|
|
5346
|
+
pageCard.style.padding = "96px 72px";
|
|
5347
|
+
pageCard.style.boxSizing = "border-box";
|
|
5348
|
+
pageCard.style.overflow = "hidden";
|
|
4970
5349
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5350
|
+
pageCard.style.transformOrigin = "top center";
|
|
5351
|
+
pageCard.style.transition = "transform 0.2s ease";
|
|
5352
|
+
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
5353
|
+
pageCard.style.color = "#1e293b";
|
|
4971
5354
|
if (isFallback && i === 0) {
|
|
4972
5355
|
pageCard.innerHTML = `
|
|
4973
5356
|
<div style="border-bottom: 1px solid #e2e8f0; padding-bottom: 12px; margin-bottom: 24px;">
|
|
4974
|
-
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${
|
|
5357
|
+
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify6__default.default.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
|
|
4975
5358
|
<span style="font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 4px;">Legacy Word 97-2003 Binary Preview</span>
|
|
4976
5359
|
</div>
|
|
4977
5360
|
${this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document")}
|
|
@@ -4979,15 +5362,17 @@ var DocPlugin = class {
|
|
|
4979
5362
|
} else {
|
|
4980
5363
|
pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
|
|
4981
5364
|
}
|
|
4982
|
-
|
|
5365
|
+
container.appendChild(pageCard);
|
|
4983
5366
|
pageCards.push(pageCard);
|
|
4984
5367
|
}
|
|
4985
5368
|
let indicator = null;
|
|
4986
5369
|
if (totalPages > 1) {
|
|
4987
5370
|
indicator = document.createElement("div");
|
|
4988
5371
|
indicator.className = "fp-doc-page-indicator";
|
|
4989
|
-
indicator.style.position = "
|
|
5372
|
+
indicator.style.position = "fixed";
|
|
4990
5373
|
indicator.style.bottom = "16px";
|
|
5374
|
+
indicator.style.left = "50%";
|
|
5375
|
+
indicator.style.transform = "translateX(-50%)";
|
|
4991
5376
|
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4992
5377
|
indicator.style.backdropFilter = "blur(8px)";
|
|
4993
5378
|
indicator.style.color = "#f8fafc";
|
|
@@ -5001,17 +5386,25 @@ var DocPlugin = class {
|
|
|
5001
5386
|
indicator.style.userSelect = "none";
|
|
5002
5387
|
indicator.style.pointerEvents = "none";
|
|
5003
5388
|
indicator.style.textAlign = "center";
|
|
5004
|
-
indicator.style.width = "fit-content";
|
|
5005
|
-
indicator.style.margin = "16px auto 0";
|
|
5006
5389
|
container.appendChild(indicator);
|
|
5007
5390
|
}
|
|
5391
|
+
let rotation = 0;
|
|
5392
|
+
const applyTransform = () => {
|
|
5393
|
+
const activeCard = pageCards[currentPage - 1];
|
|
5394
|
+
if (activeCard) {
|
|
5395
|
+
activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5396
|
+
}
|
|
5397
|
+
};
|
|
5008
5398
|
const showPage = (pageNum) => {
|
|
5009
5399
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
card.style.display =
|
|
5013
|
-
|
|
5014
|
-
|
|
5400
|
+
pageCards.forEach((card, idx) => {
|
|
5401
|
+
if (idx + 1 === currentPage) {
|
|
5402
|
+
card.style.display = "block";
|
|
5403
|
+
card.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5404
|
+
} else {
|
|
5405
|
+
card.style.display = "none";
|
|
5406
|
+
}
|
|
5407
|
+
});
|
|
5015
5408
|
if (indicator) {
|
|
5016
5409
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
5017
5410
|
}
|
|
@@ -5020,21 +5413,22 @@ var DocPlugin = class {
|
|
|
5020
5413
|
if (totalPages > 1) {
|
|
5021
5414
|
showPage(1);
|
|
5022
5415
|
}
|
|
5023
|
-
let
|
|
5024
|
-
const calculateFitScale = () => {
|
|
5025
|
-
const
|
|
5026
|
-
const
|
|
5027
|
-
const
|
|
5028
|
-
const
|
|
5029
|
-
const
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5416
|
+
let fitMode = "width";
|
|
5417
|
+
const calculateFitScale = (mode = fitMode) => {
|
|
5418
|
+
const elW = 816;
|
|
5419
|
+
const elH = 1056;
|
|
5420
|
+
const availW = Math.max(280, ctx.container.clientWidth - 48);
|
|
5421
|
+
const availH = Math.max(280, ctx.container.clientHeight - 80);
|
|
5422
|
+
const sW = availW / elW;
|
|
5423
|
+
const sH = availH / elH;
|
|
5424
|
+
if (mode === "page") {
|
|
5425
|
+
return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
|
|
5426
|
+
}
|
|
5427
|
+
return Math.max(0.65, Math.min(1.05, sW));
|
|
5035
5428
|
};
|
|
5036
5429
|
setTimeout(() => {
|
|
5037
|
-
|
|
5430
|
+
fitMode = "width";
|
|
5431
|
+
scale = calculateFitScale("width");
|
|
5038
5432
|
applyTransform();
|
|
5039
5433
|
}, 60);
|
|
5040
5434
|
const cleanup = () => {
|
|
@@ -5062,7 +5456,8 @@ var DocPlugin = class {
|
|
|
5062
5456
|
applyTransform();
|
|
5063
5457
|
},
|
|
5064
5458
|
fitToPage: () => {
|
|
5065
|
-
|
|
5459
|
+
fitMode = fitMode === "width" ? "page" : "width";
|
|
5460
|
+
scale = calculateFitScale(fitMode);
|
|
5066
5461
|
rotation = 0;
|
|
5067
5462
|
applyTransform();
|
|
5068
5463
|
},
|
|
@@ -5190,8 +5585,28 @@ var DocPlugin = class {
|
|
|
5190
5585
|
}
|
|
5191
5586
|
splitIntoPages(text) {
|
|
5192
5587
|
if (!text) return [""];
|
|
5193
|
-
const
|
|
5194
|
-
|
|
5588
|
+
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);
|
|
5589
|
+
if (explicitParts.length === 0) explicitParts.push(text);
|
|
5590
|
+
const maxLinesPerPage = 48;
|
|
5591
|
+
const finalPages = [];
|
|
5592
|
+
for (const part of explicitParts) {
|
|
5593
|
+
const lines = part.split(/\r?\n/);
|
|
5594
|
+
let currentLines = [];
|
|
5595
|
+
let count = 0;
|
|
5596
|
+
for (const line of lines) {
|
|
5597
|
+
currentLines.push(line);
|
|
5598
|
+
count++;
|
|
5599
|
+
if (count >= maxLinesPerPage) {
|
|
5600
|
+
finalPages.push(currentLines.join("\n"));
|
|
5601
|
+
currentLines = [];
|
|
5602
|
+
count = 0;
|
|
5603
|
+
}
|
|
5604
|
+
}
|
|
5605
|
+
if (currentLines.length > 0) {
|
|
5606
|
+
finalPages.push(currentLines.join("\n"));
|
|
5607
|
+
}
|
|
5608
|
+
}
|
|
5609
|
+
return finalPages.length > 0 ? finalPages : [text];
|
|
5195
5610
|
}
|
|
5196
5611
|
/**
|
|
5197
5612
|
* Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
|
|
@@ -5200,17 +5615,65 @@ var DocPlugin = class {
|
|
|
5200
5615
|
const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
|
|
5201
5616
|
let html = "";
|
|
5202
5617
|
let inList = false;
|
|
5203
|
-
|
|
5204
|
-
|
|
5618
|
+
let tableLines = [];
|
|
5619
|
+
const flushTable = () => {
|
|
5620
|
+
if (tableLines.length > 0) {
|
|
5621
|
+
html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
|
|
5622
|
+
for (const tLine of tableLines) {
|
|
5623
|
+
html += "<tr>";
|
|
5624
|
+
const cols = tLine.split(" ");
|
|
5625
|
+
for (const col of cols) {
|
|
5626
|
+
html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
|
|
5627
|
+
}
|
|
5628
|
+
html += "</tr>";
|
|
5629
|
+
}
|
|
5630
|
+
html += "</table>";
|
|
5631
|
+
tableLines = [];
|
|
5632
|
+
}
|
|
5633
|
+
};
|
|
5634
|
+
let i = 0;
|
|
5635
|
+
while (i < lines.length) {
|
|
5636
|
+
let line = lines[i];
|
|
5637
|
+
let tabCount = (line.match(/\t/g) || []).length;
|
|
5638
|
+
if (tabCount > 0) {
|
|
5639
|
+
let consecutiveTableLines = 1;
|
|
5640
|
+
let j = i + 1;
|
|
5641
|
+
while (j < lines.length) {
|
|
5642
|
+
const nextTabCount = (lines[j].match(/\t/g) || []).length;
|
|
5643
|
+
if (nextTabCount === tabCount) {
|
|
5644
|
+
consecutiveTableLines++;
|
|
5645
|
+
j++;
|
|
5646
|
+
} else {
|
|
5647
|
+
break;
|
|
5648
|
+
}
|
|
5649
|
+
}
|
|
5650
|
+
if (consecutiveTableLines >= 3) {
|
|
5651
|
+
if (inList) {
|
|
5652
|
+
html += "</ul>";
|
|
5653
|
+
inList = false;
|
|
5654
|
+
}
|
|
5655
|
+
tableLines = lines.slice(i, j);
|
|
5656
|
+
flushTable();
|
|
5657
|
+
i = j;
|
|
5658
|
+
continue;
|
|
5659
|
+
}
|
|
5660
|
+
}
|
|
5661
|
+
line = line.trim();
|
|
5205
5662
|
if (!line) {
|
|
5206
5663
|
if (inList) {
|
|
5207
5664
|
html += "</ul>";
|
|
5208
5665
|
inList = false;
|
|
5209
5666
|
}
|
|
5667
|
+
html += '<div style="height: 1.15em;"></div>';
|
|
5668
|
+
i++;
|
|
5669
|
+
continue;
|
|
5670
|
+
}
|
|
5671
|
+
if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line)) {
|
|
5672
|
+
i++;
|
|
5210
5673
|
continue;
|
|
5211
5674
|
}
|
|
5212
|
-
if (
|
|
5213
|
-
|
|
5675
|
+
if ((line.includes("Normal.dot") || line.includes("Microsoft Word") || line.includes("Times New Roman")) && line.length < 30) {
|
|
5676
|
+
i++;
|
|
5214
5677
|
continue;
|
|
5215
5678
|
}
|
|
5216
5679
|
if (line.length < 60 && !line.endsWith(".") && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#"))) {
|
|
@@ -5218,24 +5681,26 @@ var DocPlugin = class {
|
|
|
5218
5681
|
html += "</ul>";
|
|
5219
5682
|
inList = false;
|
|
5220
5683
|
}
|
|
5221
|
-
html += `<h2 style="font-size:
|
|
5684
|
+
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>`;
|
|
5222
5685
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
5223
5686
|
if (!inList) {
|
|
5224
5687
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
5225
5688
|
inList = true;
|
|
5226
5689
|
}
|
|
5227
5690
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
5228
|
-
html += `<li style="margin: 4px 0; line-height: 1.
|
|
5691
|
+
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6__default.default.sanitize(bulletText)}</li>`;
|
|
5229
5692
|
} else {
|
|
5230
5693
|
if (inList) {
|
|
5231
5694
|
html += "</ul>";
|
|
5232
5695
|
inList = false;
|
|
5233
5696
|
}
|
|
5234
|
-
html += `<p style="line-height: 1.
|
|
5697
|
+
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6__default.default.sanitize(line)}</p>`;
|
|
5235
5698
|
}
|
|
5699
|
+
i++;
|
|
5236
5700
|
}
|
|
5237
5701
|
if (inList) html += "</ul>";
|
|
5238
|
-
|
|
5702
|
+
flushTable();
|
|
5703
|
+
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6__default.default.sanitize(filename)})</p>`;
|
|
5239
5704
|
}
|
|
5240
5705
|
};
|
|
5241
5706
|
function docPlugin() {
|
|
@@ -5413,7 +5878,7 @@ var PptPlugin = class {
|
|
|
5413
5878
|
if (s.pictureUrl) {
|
|
5414
5879
|
contentHtml = `
|
|
5415
5880
|
<div style="flex: 1; display: flex; justify-content: center; align-items: center; padding: 12px; overflow: hidden;">
|
|
5416
|
-
<img src="${s.pictureUrl}" alt="${
|
|
5881
|
+
<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;" />
|
|
5417
5882
|
</div>
|
|
5418
5883
|
`;
|
|
5419
5884
|
} else if (s.tableColumns.length > 0) {
|
|
@@ -5423,7 +5888,7 @@ var PptPlugin = class {
|
|
|
5423
5888
|
<table style="width: 100%; border-collapse: collapse; border: 1px solid #cbd5e1; border-radius: 6px; overflow: hidden; background: #ffffff;">
|
|
5424
5889
|
<thead>
|
|
5425
5890
|
<tr style="background: #e2e8f0; color: #1e293b; font-weight: 600; font-size: 14px;">
|
|
5426
|
-
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${
|
|
5891
|
+
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${DOMPurify6__default.default.sanitize(c)}</th>`).join("")}
|
|
5427
5892
|
</tr>
|
|
5428
5893
|
</thead>
|
|
5429
5894
|
<tbody>
|
|
@@ -5439,7 +5904,7 @@ var PptPlugin = class {
|
|
|
5439
5904
|
} else {
|
|
5440
5905
|
const pTags = s.paragraphs.map((p) => {
|
|
5441
5906
|
const lines = p.split(/[\r\n]+/).map((l) => l.trim()).filter(Boolean);
|
|
5442
|
-
return lines.map((l) => `<p style="margin: 0 0 14px; font-size: 14px; line-height: 1.65; color: #334155; text-align: justify;">${
|
|
5907
|
+
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("");
|
|
5443
5908
|
}).join("");
|
|
5444
5909
|
contentHtml = `
|
|
5445
5910
|
<div style="flex: 1; overflow: auto; padding: 4px 8px; display: flex; flex-direction: column; justify-content: flex-start;">
|
|
@@ -5452,11 +5917,11 @@ var PptPlugin = class {
|
|
|
5452
5917
|
<!-- Header Banner matching PowerPoint design -->
|
|
5453
5918
|
<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;">
|
|
5454
5919
|
<h1 style="margin: 0; font-size: 26px; font-weight: 700; color: #1e293b; letter-spacing: -0.3px;">
|
|
5455
|
-
${
|
|
5920
|
+
${DOMPurify6__default.default.sanitize(s.title)}
|
|
5456
5921
|
</h1>
|
|
5457
5922
|
${s.subtitle ? `
|
|
5458
5923
|
<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);">
|
|
5459
|
-
${
|
|
5924
|
+
${DOMPurify6__default.default.sanitize(s.subtitle)}
|
|
5460
5925
|
</span>
|
|
5461
5926
|
` : `
|
|
5462
5927
|
<span style="font-size: 12px; color: #365314; font-weight: 600;">
|