@files-preview-app/preview-file 1.2.6 → 1.2.7
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 +542 -162
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.js +541 -161
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +543 -163
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +542 -162
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +542 -162
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +541 -161
- package/dist/react.js.map +1 -1
- package/dist/vue.cjs +542 -162
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +541 -161
- package/dist/vue.js.map +1 -1
- package/package.json +179 -169
package/dist/react.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { memo, forwardRef, useRef, useImperativeHandle, useEffect } from 'react';
|
|
2
|
-
import
|
|
2
|
+
import DOMPurify6 from 'dompurify';
|
|
3
3
|
import * as pdfjsLib from 'pdfjs-dist';
|
|
4
4
|
import * as docx from 'docx-preview';
|
|
5
5
|
import { unzipSync, strFromU8, unzip } from 'fflate';
|
|
@@ -358,7 +358,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
358
358
|
if (magicMime === "application/zip") {
|
|
359
359
|
const ooxmlMime = detectOoxmlType(buffer);
|
|
360
360
|
if (ooxmlMime && ooxmlMime !== "application/zip") {
|
|
361
|
-
metadata.mimeType = ooxmlMime;
|
|
361
|
+
metadata.mimeType = metadata.mimeType ?? ooxmlMime;
|
|
362
362
|
if (ooxmlMime.includes("wordprocessing")) metadata.extension = metadata.extension ?? ".docx";
|
|
363
363
|
else if (ooxmlMime.includes("spreadsheet")) metadata.extension = metadata.extension ?? ".xlsx";
|
|
364
364
|
else if (ooxmlMime.includes("presentation")) metadata.extension = metadata.extension ?? ".pptx";
|
|
@@ -387,7 +387,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
387
387
|
return { buffer, metadata };
|
|
388
388
|
}
|
|
389
389
|
function sanitizeSVG(svg) {
|
|
390
|
-
return
|
|
390
|
+
return DOMPurify6.sanitize(svg, {
|
|
391
391
|
USE_PROFILES: { svg: true, svgFilters: true }
|
|
392
392
|
});
|
|
393
393
|
}
|
|
@@ -1449,7 +1449,19 @@ var PdfPlugin = class {
|
|
|
1449
1449
|
}
|
|
1450
1450
|
};
|
|
1451
1451
|
await renderPage(1);
|
|
1452
|
+
let resizeTimer = null;
|
|
1453
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
1454
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1455
|
+
resizeTimer = setTimeout(() => {
|
|
1456
|
+
if (Math.abs(zoomScale - 1) < 0.05) {
|
|
1457
|
+
renderPage(currentPage);
|
|
1458
|
+
}
|
|
1459
|
+
}, 150);
|
|
1460
|
+
});
|
|
1461
|
+
resizeObserver.observe(container);
|
|
1452
1462
|
const cleanup = () => {
|
|
1463
|
+
resizeObserver.disconnect();
|
|
1464
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1453
1465
|
if (currentRenderTask) {
|
|
1454
1466
|
try {
|
|
1455
1467
|
currentRenderTask.cancel();
|
|
@@ -2197,90 +2209,149 @@ var DocxPlugin = class {
|
|
|
2197
2209
|
console.warn("[DocxPlugin] Error parsing relationships:", relsErr);
|
|
2198
2210
|
}
|
|
2199
2211
|
}
|
|
2200
|
-
const
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2212
|
+
const sectPrs = Array.from(doc.getElementsByTagNameNS("*", "sectPr"));
|
|
2213
|
+
const lastSectPr = sectPrs[sectPrs.length - 1];
|
|
2214
|
+
let defaultW = 12240;
|
|
2215
|
+
let defaultH = 15840;
|
|
2216
|
+
let margins = { top: 1440, right: 1440, bottom: 1440, left: 1440 };
|
|
2217
|
+
if (lastSectPr) {
|
|
2218
|
+
const pgSz = lastSectPr.getElementsByTagNameNS("*", "pgSz")[0];
|
|
2219
|
+
if (pgSz) {
|
|
2220
|
+
defaultW = parseInt(pgSz.getAttribute("w:w") || pgSz.getAttribute("w") || "12240", 10);
|
|
2221
|
+
defaultH = parseInt(pgSz.getAttribute("w:h") || pgSz.getAttribute("h") || "15840", 10);
|
|
2222
|
+
}
|
|
2223
|
+
const pgMar = lastSectPr.getElementsByTagNameNS("*", "pgMar")[0];
|
|
2224
|
+
if (pgMar) {
|
|
2225
|
+
margins.top = parseInt(pgMar.getAttribute("w:top") || pgMar.getAttribute("top") || "1440", 10);
|
|
2226
|
+
margins.bottom = parseInt(pgMar.getAttribute("w:bottom") || pgMar.getAttribute("bottom") || "1440", 10);
|
|
2227
|
+
margins.left = parseInt(pgMar.getAttribute("w:left") || pgMar.getAttribute("left") || "1440", 10);
|
|
2228
|
+
margins.right = parseInt(pgMar.getAttribute("w:right") || pgMar.getAttribute("right") || "1440", 10);
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
const createPageCard = () => {
|
|
2232
|
+
const card = document.createElement("div");
|
|
2233
|
+
card.className = "fp-docx-page-card";
|
|
2234
|
+
card.style.backgroundColor = "#ffffff";
|
|
2235
|
+
card.style.borderRadius = "4px";
|
|
2236
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
2237
|
+
card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2238
|
+
card.style.color = "#1e293b";
|
|
2239
|
+
card.style.lineHeight = "1.6";
|
|
2240
|
+
card.style.boxSizing = "border-box";
|
|
2241
|
+
card.style.overflow = "hidden";
|
|
2242
|
+
card.style.position = "relative";
|
|
2243
|
+
card.style.marginBottom = "24px";
|
|
2244
|
+
card.style.width = `${defaultW / 15}px`;
|
|
2245
|
+
card.style.height = `${defaultH / 15}px`;
|
|
2246
|
+
card.style.padding = `${margins.top / 15}px ${margins.right / 15}px ${margins.bottom / 15}px ${margins.left / 15}px`;
|
|
2247
|
+
return card;
|
|
2248
|
+
};
|
|
2249
|
+
let currentCard = createPageCard();
|
|
2250
|
+
let currentHtml = "";
|
|
2251
|
+
const pages = [{ card: currentCard, html: "" }];
|
|
2252
|
+
const flushHtml = () => {
|
|
2253
|
+
pages[pages.length - 1].html += currentHtml;
|
|
2254
|
+
currentHtml = "";
|
|
2255
|
+
};
|
|
2256
|
+
const newPage = () => {
|
|
2257
|
+
flushHtml();
|
|
2258
|
+
currentCard = createPageCard();
|
|
2259
|
+
pages.push({ card: currentCard, html: "" });
|
|
2260
|
+
};
|
|
2209
2261
|
const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
|
|
2210
|
-
let html = "";
|
|
2211
2262
|
for (const child of Array.from(body.children)) {
|
|
2212
2263
|
const tag = child.localName || child.nodeName.split(":").pop();
|
|
2213
2264
|
if (tag === "p") {
|
|
2214
2265
|
const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
|
|
2215
2266
|
const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
|
|
2216
2267
|
const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
|
|
2217
|
-
const
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2268
|
+
const chunks = this.extractParagraphChunks(child, imageMap);
|
|
2269
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
2270
|
+
if (i > 0) {
|
|
2271
|
+
newPage();
|
|
2272
|
+
}
|
|
2273
|
+
const textContent = chunks[i];
|
|
2274
|
+
if (!textContent.trim() && !textContent.includes("<img")) {
|
|
2275
|
+
currentHtml += '<div style="height: 10px;"></div>';
|
|
2276
|
+
continue;
|
|
2277
|
+
}
|
|
2278
|
+
const lowerStyle = styleVal.toLowerCase();
|
|
2279
|
+
if (lowerStyle.includes("title")) {
|
|
2280
|
+
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>`;
|
|
2281
|
+
} else if (lowerStyle.includes("heading1") || styleVal === "1") {
|
|
2282
|
+
currentHtml += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
|
|
2283
|
+
} else if (lowerStyle.includes("heading2") || styleVal === "2") {
|
|
2284
|
+
currentHtml += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
|
|
2285
|
+
} else if (lowerStyle.includes("heading3") || styleVal === "3") {
|
|
2286
|
+
currentHtml += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
|
|
2287
|
+
} else if (numPr) {
|
|
2288
|
+
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>`;
|
|
2289
|
+
} else {
|
|
2290
|
+
currentHtml += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
|
|
2291
|
+
}
|
|
2235
2292
|
}
|
|
2236
2293
|
} else if (tag === "tbl") {
|
|
2237
|
-
|
|
2294
|
+
currentHtml += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
|
|
2238
2295
|
const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
|
|
2239
2296
|
rows.forEach((tr, rIdx) => {
|
|
2240
|
-
|
|
2297
|
+
currentHtml += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
2241
2298
|
const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
|
|
2242
2299
|
cells.forEach((tc) => {
|
|
2243
2300
|
const cellText = this.extractParagraphHtml(tc, imageMap);
|
|
2244
|
-
|
|
2301
|
+
currentHtml += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || " "}</td>`;
|
|
2245
2302
|
});
|
|
2246
|
-
|
|
2303
|
+
currentHtml += "</tr>";
|
|
2247
2304
|
});
|
|
2248
|
-
|
|
2305
|
+
currentHtml += "</table>";
|
|
2249
2306
|
}
|
|
2250
2307
|
}
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2308
|
+
flushHtml();
|
|
2309
|
+
for (const page of pages) {
|
|
2310
|
+
page.card.innerHTML = DOMPurify6.sanitize(page.html, {
|
|
2311
|
+
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
|
|
2312
|
+
ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
|
|
2313
|
+
});
|
|
2314
|
+
wrapper.appendChild(page.card);
|
|
2315
|
+
}
|
|
2256
2316
|
}
|
|
2257
2317
|
extractParagraphHtml(pElement, imageMap = {}) {
|
|
2258
|
-
|
|
2318
|
+
return this.extractParagraphChunks(pElement, imageMap).join("<br/>");
|
|
2319
|
+
}
|
|
2320
|
+
extractParagraphChunks(pElement, imageMap = {}) {
|
|
2321
|
+
const chunks = [""];
|
|
2322
|
+
let currentChunkIndex = 0;
|
|
2259
2323
|
const drawings = Array.from(pElement.getElementsByTagNameNS("*", "drawing"));
|
|
2260
2324
|
for (const drawing of drawings) {
|
|
2261
2325
|
const blip = drawing.getElementsByTagNameNS("*", "blip")[0];
|
|
2262
2326
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2263
2327
|
if (rId && imageMap[rId]) {
|
|
2264
|
-
|
|
2328
|
+
chunks[currentChunkIndex] += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
|
|
2265
2329
|
}
|
|
2266
2330
|
}
|
|
2267
2331
|
const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
|
|
2268
|
-
if (runs.length === 0 && !
|
|
2269
|
-
|
|
2332
|
+
if (runs.length === 0 && !chunks[currentChunkIndex]) {
|
|
2333
|
+
chunks[currentChunkIndex] = DOMPurify6.sanitize(pElement.textContent || "");
|
|
2334
|
+
return chunks;
|
|
2270
2335
|
}
|
|
2271
2336
|
for (const r of runs) {
|
|
2272
2337
|
const blip = r.getElementsByTagNameNS("*", "blip")[0] || r.getElementsByTagNameNS("*", "imagedata")[0];
|
|
2273
2338
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2274
2339
|
if (rId && imageMap[rId]) {
|
|
2275
|
-
|
|
2340
|
+
chunks[currentChunkIndex] += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
|
|
2276
2341
|
}
|
|
2277
|
-
const brs = r.getElementsByTagNameNS("*", "br");
|
|
2278
|
-
for (
|
|
2279
|
-
|
|
2342
|
+
const brs = Array.from(r.getElementsByTagNameNS("*", "br"));
|
|
2343
|
+
for (const br of brs) {
|
|
2344
|
+
const type = br.getAttribute("w:type") || br.getAttribute("type");
|
|
2345
|
+
if (type === "page") {
|
|
2346
|
+
chunks.push("");
|
|
2347
|
+
currentChunkIndex++;
|
|
2348
|
+
} else {
|
|
2349
|
+
chunks[currentChunkIndex] += "<br/>";
|
|
2350
|
+
}
|
|
2280
2351
|
}
|
|
2281
2352
|
const tabs = r.getElementsByTagNameNS("*", "tab");
|
|
2282
2353
|
if (tabs.length > 0) {
|
|
2283
|
-
|
|
2354
|
+
chunks[currentChunkIndex] += " ";
|
|
2284
2355
|
}
|
|
2285
2356
|
const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
|
|
2286
2357
|
const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
|
|
@@ -2294,7 +2365,7 @@ var DocxPlugin = class {
|
|
|
2294
2365
|
const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
|
|
2295
2366
|
let text = texts.map((t) => t.textContent || "").join("");
|
|
2296
2367
|
if (!text) continue;
|
|
2297
|
-
text =
|
|
2368
|
+
text = DOMPurify6.sanitize(text);
|
|
2298
2369
|
let styles = "";
|
|
2299
2370
|
if (isBold) styles += "font-weight: bold; ";
|
|
2300
2371
|
if (isItalic) styles += "font-style: italic; ";
|
|
@@ -2306,12 +2377,12 @@ var DocxPlugin = class {
|
|
|
2306
2377
|
if (!isNaN(pt) && pt > 0) styles += `font-size: ${pt}pt; `;
|
|
2307
2378
|
}
|
|
2308
2379
|
if (styles) {
|
|
2309
|
-
|
|
2380
|
+
chunks[currentChunkIndex] += `<span style="${styles}">${text}</span>`;
|
|
2310
2381
|
} else {
|
|
2311
|
-
|
|
2382
|
+
chunks[currentChunkIndex] += text;
|
|
2312
2383
|
}
|
|
2313
2384
|
}
|
|
2314
|
-
return
|
|
2385
|
+
return chunks;
|
|
2315
2386
|
}
|
|
2316
2387
|
renderBinaryDocFallback(ctx, wrapper) {
|
|
2317
2388
|
const card = document.createElement("div");
|
|
@@ -2328,14 +2399,14 @@ var DocxPlugin = class {
|
|
|
2328
2399
|
const wordDocStream = cfbf.readStream("WordDocument");
|
|
2329
2400
|
if (wordDocStream && wordDocStream.length >= 512) {
|
|
2330
2401
|
const text2 = this.extractReadableStrings(wordDocStream);
|
|
2331
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2402
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6.sanitize(text2)}</div>`;
|
|
2332
2403
|
wrapper.appendChild(card);
|
|
2333
2404
|
return;
|
|
2334
2405
|
}
|
|
2335
2406
|
} catch {
|
|
2336
2407
|
}
|
|
2337
2408
|
const text = this.extractReadableStrings(new Uint8Array(ctx.buffer));
|
|
2338
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2409
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6.sanitize(text)}</div>`;
|
|
2339
2410
|
wrapper.appendChild(card);
|
|
2340
2411
|
}
|
|
2341
2412
|
extractReadableStrings(bytes) {
|
|
@@ -2934,41 +3005,94 @@ var CodePlugin = class {
|
|
|
2934
3005
|
async render(ctx) {
|
|
2935
3006
|
const decoder = new TextDecoder("utf-8");
|
|
2936
3007
|
const fullText = decoder.decode(ctx.buffer);
|
|
2937
|
-
const
|
|
2938
|
-
const
|
|
3008
|
+
const extRaw = ctx.metadata.extension?.toLowerCase();
|
|
3009
|
+
const mimeRaw = ctx.metadata.mimeType?.toLowerCase();
|
|
3010
|
+
const isTxt = extRaw === ".txt" || mimeRaw === "text/plain" && (!extRaw || !this.extensions.filter((e) => e !== ".txt").includes(extRaw));
|
|
3011
|
+
let rawPages = [];
|
|
3012
|
+
if (isTxt) {
|
|
3013
|
+
const explicitPages = fullText.split(/(?:\f|\x0C)/);
|
|
3014
|
+
for (const ep of explicitPages) {
|
|
3015
|
+
const lines = ep.split(/\r?\n/);
|
|
3016
|
+
let currentChunk = [];
|
|
3017
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3018
|
+
currentChunk.push(lines[i]);
|
|
3019
|
+
if (currentChunk.length >= 46) {
|
|
3020
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3021
|
+
currentChunk = [];
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
if (currentChunk.length > 0 || lines.length === 0) {
|
|
3025
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
if (rawPages.length === 0) rawPages = [""];
|
|
3029
|
+
} else {
|
|
3030
|
+
const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
|
|
3031
|
+
rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
3032
|
+
}
|
|
2939
3033
|
const totalPages = Math.max(1, rawPages.length);
|
|
2940
3034
|
let currentPage = 1;
|
|
2941
3035
|
const container = document.createElement("div");
|
|
2942
3036
|
container.style.width = "100%";
|
|
2943
3037
|
container.style.height = "100%";
|
|
2944
3038
|
container.style.overflow = "auto";
|
|
2945
|
-
container.style.backgroundColor = "#1e1e1e";
|
|
2946
|
-
container.style.color = "#d4d4d4";
|
|
2947
|
-
container.style.padding = "16px";
|
|
2948
|
-
container.style.boxSizing = "border-box";
|
|
2949
3039
|
let fontSize = 13;
|
|
2950
3040
|
let rotation = 0;
|
|
3041
|
+
let zoomLevel = 1;
|
|
2951
3042
|
const pre = document.createElement("pre");
|
|
2952
|
-
pre.style.margin = "0";
|
|
2953
|
-
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
2954
|
-
pre.style.fontSize = `${fontSize}px`;
|
|
2955
|
-
pre.style.lineHeight = "1.5";
|
|
2956
|
-
pre.style.whiteSpace = "pre-wrap";
|
|
2957
|
-
pre.style.wordBreak = "break-all";
|
|
2958
3043
|
const code = document.createElement("code");
|
|
3044
|
+
if (isTxt) {
|
|
3045
|
+
container.style.backgroundColor = "#f1f5f9";
|
|
3046
|
+
container.style.padding = "32px";
|
|
3047
|
+
container.style.boxSizing = "border-box";
|
|
3048
|
+
container.style.display = "flex";
|
|
3049
|
+
container.style.flexDirection = "column";
|
|
3050
|
+
container.style.alignItems = "center";
|
|
3051
|
+
pre.style.margin = "0";
|
|
3052
|
+
pre.style.fontFamily = "Consolas, 'Courier New', monospace";
|
|
3053
|
+
pre.style.fontSize = "13px";
|
|
3054
|
+
pre.style.color = "#1e293b";
|
|
3055
|
+
pre.style.lineHeight = "1.5";
|
|
3056
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3057
|
+
pre.style.wordBreak = "break-word";
|
|
3058
|
+
pre.style.backgroundColor = "#ffffff";
|
|
3059
|
+
pre.style.width = "816px";
|
|
3060
|
+
pre.style.minHeight = "1056px";
|
|
3061
|
+
pre.style.padding = "72px 56px";
|
|
3062
|
+
pre.style.boxSizing = "border-box";
|
|
3063
|
+
pre.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)";
|
|
3064
|
+
pre.style.borderRadius = "4px";
|
|
3065
|
+
pre.style.transformOrigin = "top center";
|
|
3066
|
+
} else {
|
|
3067
|
+
container.style.backgroundColor = "#1e1e1e";
|
|
3068
|
+
container.style.color = "#d4d4d4";
|
|
3069
|
+
container.style.padding = "16px";
|
|
3070
|
+
container.style.boxSizing = "border-box";
|
|
3071
|
+
pre.style.margin = "0";
|
|
3072
|
+
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
3073
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3074
|
+
pre.style.lineHeight = "1.5";
|
|
3075
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3076
|
+
pre.style.wordBreak = "break-all";
|
|
3077
|
+
pre.style.transformOrigin = "top left";
|
|
3078
|
+
}
|
|
2959
3079
|
const ext = (ctx.metadata.extension || "").replace(".", "");
|
|
2960
3080
|
const renderCodePage = (text) => {
|
|
2961
|
-
|
|
2962
|
-
if (ext && hljs.getLanguage(ext)) {
|
|
2963
|
-
code.innerHTML = hljs.highlight(text, { language: ext }).value;
|
|
2964
|
-
} else {
|
|
2965
|
-
code.innerHTML = hljs.highlightAuto(text).value;
|
|
2966
|
-
}
|
|
2967
|
-
} catch {
|
|
3081
|
+
if (isTxt) {
|
|
2968
3082
|
code.textContent = text;
|
|
3083
|
+
} else {
|
|
3084
|
+
try {
|
|
3085
|
+
if (ext && hljs.getLanguage(ext)) {
|
|
3086
|
+
code.innerHTML = hljs.highlight(text, { language: ext }).value;
|
|
3087
|
+
} else {
|
|
3088
|
+
code.innerHTML = hljs.highlightAuto(text).value;
|
|
3089
|
+
}
|
|
3090
|
+
} catch {
|
|
3091
|
+
code.textContent = text;
|
|
3092
|
+
}
|
|
2969
3093
|
}
|
|
2970
3094
|
};
|
|
2971
|
-
renderCodePage(rawPages[0] || fullText);
|
|
3095
|
+
renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
|
|
2972
3096
|
pre.appendChild(code);
|
|
2973
3097
|
container.appendChild(pre);
|
|
2974
3098
|
let indicator = null;
|
|
@@ -2977,15 +3101,22 @@ var CodePlugin = class {
|
|
|
2977
3101
|
indicator.className = "fp-code-page-indicator";
|
|
2978
3102
|
indicator.style.position = "sticky";
|
|
2979
3103
|
indicator.style.bottom = "16px";
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
3104
|
+
if (isTxt) {
|
|
3105
|
+
indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
3106
|
+
indicator.style.color = "#334155";
|
|
3107
|
+
indicator.style.border = "1px solid #e2e8f0";
|
|
3108
|
+
indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
|
|
3109
|
+
} else {
|
|
3110
|
+
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3111
|
+
indicator.style.color = "#f8fafc";
|
|
3112
|
+
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3113
|
+
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3114
|
+
indicator.style.backdropFilter = "blur(8px)";
|
|
3115
|
+
}
|
|
2983
3116
|
indicator.style.fontSize = "12px";
|
|
2984
3117
|
indicator.style.fontWeight = "600";
|
|
2985
3118
|
indicator.style.padding = "5px 14px";
|
|
2986
3119
|
indicator.style.borderRadius = "20px";
|
|
2987
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
2988
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
2989
3120
|
indicator.style.zIndex = "10";
|
|
2990
3121
|
indicator.style.userSelect = "none";
|
|
2991
3122
|
indicator.style.pointerEvents = "none";
|
|
@@ -2996,7 +3127,7 @@ var CodePlugin = class {
|
|
|
2996
3127
|
}
|
|
2997
3128
|
const showPage = (pageNum) => {
|
|
2998
3129
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
2999
|
-
renderCodePage(rawPages[currentPage - 1] || fullText);
|
|
3130
|
+
renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
|
|
3000
3131
|
if (indicator) {
|
|
3001
3132
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
3002
3133
|
}
|
|
@@ -3012,39 +3143,57 @@ var CodePlugin = class {
|
|
|
3012
3143
|
ctx.container.innerHTML = "";
|
|
3013
3144
|
};
|
|
3014
3145
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3146
|
+
const updateTransform = () => {
|
|
3147
|
+
if (isTxt) {
|
|
3148
|
+
pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
|
|
3149
|
+
} else {
|
|
3150
|
+
pre.style.transform = `rotate(${rotation}deg)`;
|
|
3151
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3152
|
+
}
|
|
3153
|
+
};
|
|
3015
3154
|
return {
|
|
3016
3155
|
destroy: cleanup,
|
|
3017
3156
|
getPageCount: () => totalPages,
|
|
3018
3157
|
getCurrentPage: () => currentPage,
|
|
3019
3158
|
goToPage: (page) => showPage(page),
|
|
3020
3159
|
zoomIn: () => {
|
|
3021
|
-
|
|
3022
|
-
|
|
3160
|
+
if (isTxt) {
|
|
3161
|
+
zoomLevel = Math.min(3, zoomLevel + 0.1);
|
|
3162
|
+
} else {
|
|
3163
|
+
fontSize = Math.min(32, fontSize + 2);
|
|
3164
|
+
}
|
|
3165
|
+
updateTransform();
|
|
3023
3166
|
},
|
|
3024
3167
|
zoomOut: () => {
|
|
3025
|
-
|
|
3026
|
-
|
|
3168
|
+
if (isTxt) {
|
|
3169
|
+
zoomLevel = Math.max(0.1, zoomLevel - 0.1);
|
|
3170
|
+
} else {
|
|
3171
|
+
fontSize = Math.max(8, fontSize - 2);
|
|
3172
|
+
}
|
|
3173
|
+
updateTransform();
|
|
3027
3174
|
},
|
|
3028
|
-
getZoom: () => fontSize / 13,
|
|
3175
|
+
getZoom: () => isTxt ? zoomLevel : fontSize / 13,
|
|
3029
3176
|
setZoom: (level) => {
|
|
3030
|
-
|
|
3031
|
-
|
|
3177
|
+
if (isTxt) {
|
|
3178
|
+
zoomLevel = level;
|
|
3179
|
+
} else {
|
|
3180
|
+
fontSize = Math.round(13 * level);
|
|
3181
|
+
}
|
|
3182
|
+
updateTransform();
|
|
3032
3183
|
},
|
|
3033
3184
|
fitToPage: () => {
|
|
3034
3185
|
fontSize = 13;
|
|
3035
3186
|
rotation = 0;
|
|
3036
|
-
|
|
3037
|
-
|
|
3187
|
+
zoomLevel = 1;
|
|
3188
|
+
updateTransform();
|
|
3038
3189
|
},
|
|
3039
3190
|
rotateCW: () => {
|
|
3040
3191
|
rotation = (rotation + 90) % 360;
|
|
3041
|
-
|
|
3042
|
-
pre.style.transformOrigin = "top left";
|
|
3192
|
+
updateTransform();
|
|
3043
3193
|
},
|
|
3044
3194
|
rotateCCW: () => {
|
|
3045
3195
|
rotation = (rotation - 90 + 360) % 360;
|
|
3046
|
-
|
|
3047
|
-
pre.style.transformOrigin = "top left";
|
|
3196
|
+
updateTransform();
|
|
3048
3197
|
},
|
|
3049
3198
|
download: () => {
|
|
3050
3199
|
const mimeType = ctx.metadata.mimeType || "text/plain";
|
|
@@ -3343,7 +3492,7 @@ var MarkdownPlugin = class {
|
|
|
3343
3492
|
gfm: true,
|
|
3344
3493
|
breaks: true
|
|
3345
3494
|
});
|
|
3346
|
-
const cleanHtml =
|
|
3495
|
+
const cleanHtml = DOMPurify6.sanitize(rawHtml, {
|
|
3347
3496
|
USE_PROFILES: { html: true }
|
|
3348
3497
|
});
|
|
3349
3498
|
const wrapper = document.createElement("div");
|
|
@@ -3979,6 +4128,14 @@ var RtfPlugin = class {
|
|
|
3979
4128
|
group: "actions",
|
|
3980
4129
|
execute: () => instance.download?.()
|
|
3981
4130
|
},
|
|
4131
|
+
{
|
|
4132
|
+
id: "copy",
|
|
4133
|
+
icon: "copy",
|
|
4134
|
+
label: "Copy Text",
|
|
4135
|
+
type: "button",
|
|
4136
|
+
group: "actions",
|
|
4137
|
+
execute: () => instance.copy?.()
|
|
4138
|
+
},
|
|
3982
4139
|
{
|
|
3983
4140
|
id: "print",
|
|
3984
4141
|
icon: "print",
|
|
@@ -4040,14 +4197,31 @@ var RtfPlugin = class {
|
|
|
4040
4197
|
} catch (err) {
|
|
4041
4198
|
console.warn("[RtfPlugin] RTF render error, fallback text:", err);
|
|
4042
4199
|
const text = new TextDecoder("latin1").decode(ctx.buffer);
|
|
4043
|
-
const
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4200
|
+
const rawPages = text.split(/\\page\b/).map((segment) => {
|
|
4201
|
+
return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
|
|
4202
|
+
}).filter((p) => p.length > 0);
|
|
4203
|
+
const pages = rawPages.length > 0 ? rawPages : [text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim()];
|
|
4204
|
+
for (let i = 0; i < pages.length; i++) {
|
|
4205
|
+
const pageCard = document.createElement("div");
|
|
4206
|
+
pageCard.className = "fp-rtf-page-card";
|
|
4207
|
+
pageCard.style.backgroundColor = "#ffffff";
|
|
4208
|
+
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4209
|
+
pageCard.style.borderRadius = "4px";
|
|
4210
|
+
pageCard.style.padding = "72px 56px";
|
|
4211
|
+
pageCard.style.width = "816px";
|
|
4212
|
+
pageCard.style.minHeight = "1056px";
|
|
4213
|
+
pageCard.style.maxWidth = "100%";
|
|
4214
|
+
pageCard.style.boxSizing = "border-box";
|
|
4215
|
+
pageCard.style.fontFamily = "serif";
|
|
4216
|
+
pageCard.style.fontSize = "12pt";
|
|
4217
|
+
pageCard.style.lineHeight = "1.6";
|
|
4218
|
+
pageCard.style.color = "#1e293b";
|
|
4219
|
+
pageCard.style.whiteSpace = "pre-wrap";
|
|
4220
|
+
pageCard.style.display = i === 0 ? "block" : "none";
|
|
4221
|
+
pageCard.textContent = pages[i];
|
|
4222
|
+
wrapper.appendChild(pageCard);
|
|
4223
|
+
pageElements.push(pageCard);
|
|
4224
|
+
}
|
|
4051
4225
|
}
|
|
4052
4226
|
const totalPages = Math.max(1, pageElements.length);
|
|
4053
4227
|
let currentPage = 1;
|
|
@@ -4135,6 +4309,10 @@ var RtfPlugin = class {
|
|
|
4135
4309
|
a.click();
|
|
4136
4310
|
URL.revokeObjectURL(url);
|
|
4137
4311
|
},
|
|
4312
|
+
copy: () => {
|
|
4313
|
+
const text = wrapper.textContent || "";
|
|
4314
|
+
navigator.clipboard?.writeText(text);
|
|
4315
|
+
},
|
|
4138
4316
|
print: () => {
|
|
4139
4317
|
window.print();
|
|
4140
4318
|
}
|
|
@@ -4209,7 +4387,7 @@ var HtmlPreviewPlugin = class {
|
|
|
4209
4387
|
}
|
|
4210
4388
|
async render(ctx) {
|
|
4211
4389
|
const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
|
|
4212
|
-
const sanitized =
|
|
4390
|
+
const sanitized = DOMPurify6.sanitize(rawHtml, {
|
|
4213
4391
|
WHOLE_DOCUMENT: true,
|
|
4214
4392
|
ADD_TAGS: ["style", "link"],
|
|
4215
4393
|
ADD_ATTR: ["target", "rel"]
|
|
@@ -4475,14 +4653,97 @@ var OpenDocumentPlugin = class {
|
|
|
4475
4653
|
wrapper.textContent = contentDoc.documentElement.textContent || "Formula content";
|
|
4476
4654
|
}
|
|
4477
4655
|
} else {
|
|
4478
|
-
wrapper.style.maxWidth = "
|
|
4479
|
-
wrapper.style.padding = "
|
|
4656
|
+
wrapper.style.maxWidth = "none";
|
|
4657
|
+
wrapper.style.padding = "0";
|
|
4480
4658
|
wrapper.style.minHeight = "100%";
|
|
4659
|
+
wrapper.style.backgroundColor = "transparent";
|
|
4660
|
+
wrapper.style.boxShadow = "none";
|
|
4661
|
+
wrapper.style.position = "relative";
|
|
4662
|
+
const dims = this.getPageDimensions(stylesDoc, contentDoc);
|
|
4481
4663
|
const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
|
|
4482
|
-
|
|
4483
|
-
|
|
4664
|
+
const tempDiv = document.createElement("div");
|
|
4665
|
+
tempDiv.style.width = `${dims.width - dims.marginLeft - dims.marginRight}px`;
|
|
4666
|
+
tempDiv.style.position = "absolute";
|
|
4667
|
+
tempDiv.style.visibility = "hidden";
|
|
4668
|
+
tempDiv.innerHTML = DOMPurify6.sanitize(bodyHtml, {
|
|
4669
|
+
ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub", "hr"],
|
|
4484
4670
|
ADD_ATTR: ["style", "colspan", "rowspan"]
|
|
4485
4671
|
});
|
|
4672
|
+
document.body.appendChild(tempDiv);
|
|
4673
|
+
const contentHeight = dims.height - dims.marginTop - dims.marginBottom;
|
|
4674
|
+
const pageElements = [[]];
|
|
4675
|
+
let currentHeight = 0;
|
|
4676
|
+
let currentPageIdx = 0;
|
|
4677
|
+
Array.from(tempDiv.children).forEach((child) => {
|
|
4678
|
+
const el = child;
|
|
4679
|
+
const style = el.getAttribute("style") || "";
|
|
4680
|
+
const isBreakBefore = style.includes("page-break-before: always");
|
|
4681
|
+
const isBreakAfter = style.includes("page-break-after: always");
|
|
4682
|
+
const isSoftBreak = el.classList.contains("odf-page-break");
|
|
4683
|
+
if (isBreakBefore) {
|
|
4684
|
+
if (pageElements[currentPageIdx].length > 0) {
|
|
4685
|
+
currentPageIdx++;
|
|
4686
|
+
pageElements.push([]);
|
|
4687
|
+
currentHeight = 0;
|
|
4688
|
+
}
|
|
4689
|
+
}
|
|
4690
|
+
const h = el.offsetHeight || 0;
|
|
4691
|
+
if (currentHeight + h > contentHeight && pageElements[currentPageIdx].length > 0 && !isSoftBreak) {
|
|
4692
|
+
currentPageIdx++;
|
|
4693
|
+
pageElements.push([]);
|
|
4694
|
+
currentHeight = 0;
|
|
4695
|
+
}
|
|
4696
|
+
if (!isSoftBreak) {
|
|
4697
|
+
pageElements[currentPageIdx].push(el.cloneNode(true));
|
|
4698
|
+
currentHeight += h;
|
|
4699
|
+
}
|
|
4700
|
+
if (isBreakAfter || isSoftBreak) {
|
|
4701
|
+
currentPageIdx++;
|
|
4702
|
+
pageElements.push([]);
|
|
4703
|
+
currentHeight = 0;
|
|
4704
|
+
}
|
|
4705
|
+
});
|
|
4706
|
+
document.body.removeChild(tempDiv);
|
|
4707
|
+
if (pageElements.length > 1 && pageElements[pageElements.length - 1].length === 0) {
|
|
4708
|
+
pageElements.pop();
|
|
4709
|
+
}
|
|
4710
|
+
totalPages = Math.max(1, pageElements.length);
|
|
4711
|
+
pageElements.forEach((elements, idx) => {
|
|
4712
|
+
const page = document.createElement("div");
|
|
4713
|
+
page.className = `fp-odt-page fp-odt-page-${idx + 1}`;
|
|
4714
|
+
page.style.width = `${dims.width}px`;
|
|
4715
|
+
page.style.minHeight = `${dims.height}px`;
|
|
4716
|
+
page.style.padding = `${dims.marginTop}px ${dims.marginRight}px ${dims.marginBottom}px ${dims.marginLeft}px`;
|
|
4717
|
+
page.style.margin = "0 auto";
|
|
4718
|
+
page.style.backgroundColor = "#ffffff";
|
|
4719
|
+
page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
4720
|
+
page.style.borderRadius = "4px";
|
|
4721
|
+
page.style.boxSizing = "border-box";
|
|
4722
|
+
page.style.display = idx === 0 ? "block" : "none";
|
|
4723
|
+
page.style.position = "absolute";
|
|
4724
|
+
page.style.top = "0";
|
|
4725
|
+
page.style.left = "50%";
|
|
4726
|
+
page.style.transform = "translateX(-50%)";
|
|
4727
|
+
elements.forEach((el) => page.appendChild(el));
|
|
4728
|
+
wrapper.appendChild(page);
|
|
4729
|
+
slides.push(page);
|
|
4730
|
+
});
|
|
4731
|
+
const pageIndicator = document.createElement("div");
|
|
4732
|
+
pageIndicator.className = "fp-odt-page-indicator";
|
|
4733
|
+
pageIndicator.style.position = "sticky";
|
|
4734
|
+
pageIndicator.style.bottom = "16px";
|
|
4735
|
+
pageIndicator.style.left = "50%";
|
|
4736
|
+
pageIndicator.style.transform = "translateX(-50%)";
|
|
4737
|
+
pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
|
4738
|
+
pageIndicator.style.color = "#fff";
|
|
4739
|
+
pageIndicator.style.padding = "6px 12px";
|
|
4740
|
+
pageIndicator.style.borderRadius = "16px";
|
|
4741
|
+
pageIndicator.style.fontSize = "12px";
|
|
4742
|
+
pageIndicator.style.zIndex = "100";
|
|
4743
|
+
pageIndicator.style.display = "inline-block";
|
|
4744
|
+
pageIndicator.style.width = "fit-content";
|
|
4745
|
+
pageIndicator.textContent = `Page 1 of ${totalPages}`;
|
|
4746
|
+
container.appendChild(pageIndicator);
|
|
4486
4747
|
}
|
|
4487
4748
|
const cleanup = () => {
|
|
4488
4749
|
imageUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
@@ -4491,11 +4752,15 @@ var OpenDocumentPlugin = class {
|
|
|
4491
4752
|
};
|
|
4492
4753
|
ctx.signal.addEventListener("abort", cleanup);
|
|
4493
4754
|
const goToPage = (page) => {
|
|
4494
|
-
if (
|
|
4755
|
+
if (page < 1 || page > totalPages) return;
|
|
4495
4756
|
currentPage = page;
|
|
4496
4757
|
slides.forEach((s, idx) => {
|
|
4497
4758
|
s.style.display = idx === page - 1 ? "block" : "none";
|
|
4498
4759
|
});
|
|
4760
|
+
const indicator = container.querySelector(".fp-odt-page-indicator");
|
|
4761
|
+
if (indicator) {
|
|
4762
|
+
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4763
|
+
}
|
|
4499
4764
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4500
4765
|
};
|
|
4501
4766
|
return {
|
|
@@ -4564,6 +4829,43 @@ var OpenDocumentPlugin = class {
|
|
|
4564
4829
|
}
|
|
4565
4830
|
};
|
|
4566
4831
|
}
|
|
4832
|
+
getPageDimensions(stylesDoc, contentDoc) {
|
|
4833
|
+
let width = 850;
|
|
4834
|
+
let height = 1123;
|
|
4835
|
+
let marginTop = 48;
|
|
4836
|
+
let marginBottom = 48;
|
|
4837
|
+
let marginLeft = 48;
|
|
4838
|
+
let marginRight = 48;
|
|
4839
|
+
const parseUnit = (val) => {
|
|
4840
|
+
if (!val) return null;
|
|
4841
|
+
if (val.endsWith("cm")) return parseFloat(val) * 37.8;
|
|
4842
|
+
if (val.endsWith("mm")) return parseFloat(val) * 3.78;
|
|
4843
|
+
if (val.endsWith("in")) return parseFloat(val) * 96;
|
|
4844
|
+
if (val.endsWith("pt")) return parseFloat(val) * 1.33;
|
|
4845
|
+
if (val.endsWith("px")) return parseFloat(val);
|
|
4846
|
+
return parseFloat(val);
|
|
4847
|
+
};
|
|
4848
|
+
const docs = [stylesDoc, contentDoc].filter(Boolean);
|
|
4849
|
+
for (const doc of docs) {
|
|
4850
|
+
const pageLayout = doc.querySelector("page-layout-properties, [page-width]");
|
|
4851
|
+
if (pageLayout) {
|
|
4852
|
+
const w = parseUnit(pageLayout.getAttribute("fo:page-width") || pageLayout.getAttribute("page-width"));
|
|
4853
|
+
const h = parseUnit(pageLayout.getAttribute("fo:page-height") || pageLayout.getAttribute("page-height"));
|
|
4854
|
+
const mt = parseUnit(pageLayout.getAttribute("fo:margin-top") || pageLayout.getAttribute("margin-top"));
|
|
4855
|
+
const mb = parseUnit(pageLayout.getAttribute("fo:margin-bottom") || pageLayout.getAttribute("margin-bottom"));
|
|
4856
|
+
const ml = parseUnit(pageLayout.getAttribute("fo:margin-left") || pageLayout.getAttribute("margin-left"));
|
|
4857
|
+
const mr = parseUnit(pageLayout.getAttribute("fo:margin-right") || pageLayout.getAttribute("margin-right"));
|
|
4858
|
+
if (w !== null) width = w;
|
|
4859
|
+
if (h !== null) height = h;
|
|
4860
|
+
if (mt !== null) marginTop = mt;
|
|
4861
|
+
if (mb !== null) marginBottom = mb;
|
|
4862
|
+
if (ml !== null) marginLeft = ml;
|
|
4863
|
+
if (mr !== null) marginRight = mr;
|
|
4864
|
+
break;
|
|
4865
|
+
}
|
|
4866
|
+
}
|
|
4867
|
+
return { width, height, marginTop, marginBottom, marginLeft, marginRight };
|
|
4868
|
+
}
|
|
4567
4869
|
extractStyles(stylesDoc, contentDoc) {
|
|
4568
4870
|
const map = /* @__PURE__ */ new Map();
|
|
4569
4871
|
const styleNodes = [];
|
|
@@ -4586,14 +4888,21 @@ var OpenDocumentPlugin = class {
|
|
|
4586
4888
|
if (color) css += `color: ${color}; `;
|
|
4587
4889
|
if (size) css += `font-size: ${size}; `;
|
|
4588
4890
|
}
|
|
4589
|
-
|
|
4891
|
+
let paraProp = node.querySelector("paragraph-properties, [text-align]");
|
|
4892
|
+
if (!paraProp) {
|
|
4893
|
+
paraProp = Array.from(node.children).find((c) => c.tagName.includes("paragraph-properties")) || null;
|
|
4894
|
+
}
|
|
4590
4895
|
if (paraProp) {
|
|
4591
4896
|
const align = paraProp.getAttribute("fo:text-align") || paraProp.getAttribute("text-align");
|
|
4592
4897
|
const mt = paraProp.getAttribute("fo:margin-top") || paraProp.getAttribute("margin-top");
|
|
4593
4898
|
const mb = paraProp.getAttribute("fo:margin-bottom") || paraProp.getAttribute("margin-bottom");
|
|
4899
|
+
const breakBefore = paraProp.getAttribute("fo:break-before") || paraProp.getAttribute("break-before");
|
|
4900
|
+
const breakAfter = paraProp.getAttribute("fo:break-after") || paraProp.getAttribute("break-after");
|
|
4594
4901
|
if (align) css += `text-align: ${align}; `;
|
|
4595
4902
|
if (mt) css += `margin-top: ${mt}; `;
|
|
4596
4903
|
if (mb) css += `margin-bottom: ${mb}; `;
|
|
4904
|
+
if (breakBefore === "page") css += "page-break-before: always; ";
|
|
4905
|
+
if (breakAfter === "page") css += "page-break-after: always; ";
|
|
4597
4906
|
}
|
|
4598
4907
|
if (css) map.set(name, css);
|
|
4599
4908
|
}
|
|
@@ -4678,6 +4987,8 @@ var OpenDocumentPlugin = class {
|
|
|
4678
4987
|
result += " ";
|
|
4679
4988
|
} else if (tag === "line-break") {
|
|
4680
4989
|
result += "<br/>";
|
|
4990
|
+
} else if (tag === "soft-page-break") {
|
|
4991
|
+
result += '<hr class="odf-page-break" style="page-break-after: always; border: none; margin: 0; padding: 0; height: 0;" />';
|
|
4681
4992
|
} else {
|
|
4682
4993
|
result += el.textContent || "";
|
|
4683
4994
|
}
|
|
@@ -4838,20 +5149,9 @@ var DocPlugin = class {
|
|
|
4838
5149
|
container.style.overflow = "auto";
|
|
4839
5150
|
container.style.padding = "32px 16px";
|
|
4840
5151
|
container.style.backgroundColor = "#f1f5f9";
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
wrapper.style.margin = "0 auto";
|
|
4845
|
-
wrapper.style.backgroundColor = "#ffffff";
|
|
4846
|
-
wrapper.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4847
|
-
wrapper.style.borderRadius = "4px";
|
|
4848
|
-
wrapper.style.padding = "56px 48px";
|
|
4849
|
-
wrapper.style.minHeight = "100%";
|
|
4850
|
-
wrapper.style.transformOrigin = "top center";
|
|
4851
|
-
wrapper.style.transition = "transform 0.2s ease";
|
|
4852
|
-
wrapper.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4853
|
-
wrapper.style.color = "#1e293b";
|
|
4854
|
-
container.appendChild(wrapper);
|
|
5152
|
+
container.style.display = "flex";
|
|
5153
|
+
container.style.justifyContent = "center";
|
|
5154
|
+
container.style.alignItems = "flex-start";
|
|
4855
5155
|
ctx.container.appendChild(container);
|
|
4856
5156
|
let scale = 1;
|
|
4857
5157
|
let extractedRawText = "";
|
|
@@ -4878,21 +5178,27 @@ var DocPlugin = class {
|
|
|
4878
5178
|
const rawPages = this.splitIntoPages(extractedRawText);
|
|
4879
5179
|
const totalPages = Math.max(1, rawPages.length);
|
|
4880
5180
|
let currentPage = 1;
|
|
4881
|
-
wrapper.innerHTML = "";
|
|
4882
5181
|
const pageCards = [];
|
|
4883
5182
|
for (let i = 0; i < totalPages; i++) {
|
|
4884
5183
|
const pageCard = document.createElement("div");
|
|
4885
5184
|
pageCard.className = "fp-doc-page-card";
|
|
5185
|
+
pageCard.style.width = "816px";
|
|
5186
|
+
pageCard.style.height = "1056px";
|
|
4886
5187
|
pageCard.style.backgroundColor = "#ffffff";
|
|
4887
5188
|
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4888
5189
|
pageCard.style.borderRadius = "4px";
|
|
4889
|
-
pageCard.style.padding = "
|
|
4890
|
-
pageCard.style.
|
|
5190
|
+
pageCard.style.padding = "96px 72px";
|
|
5191
|
+
pageCard.style.boxSizing = "border-box";
|
|
5192
|
+
pageCard.style.overflow = "hidden";
|
|
4891
5193
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5194
|
+
pageCard.style.transformOrigin = "top center";
|
|
5195
|
+
pageCard.style.transition = "transform 0.2s ease";
|
|
5196
|
+
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
5197
|
+
pageCard.style.color = "#1e293b";
|
|
4892
5198
|
if (isFallback && i === 0) {
|
|
4893
5199
|
pageCard.innerHTML = `
|
|
4894
5200
|
<div style="border-bottom: 1px solid #e2e8f0; padding-bottom: 12px; margin-bottom: 24px;">
|
|
4895
|
-
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${
|
|
5201
|
+
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify6.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
|
|
4896
5202
|
<span style="font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 4px;">Legacy Word 97-2003 Binary Preview</span>
|
|
4897
5203
|
</div>
|
|
4898
5204
|
${this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document")}
|
|
@@ -4900,15 +5206,17 @@ var DocPlugin = class {
|
|
|
4900
5206
|
} else {
|
|
4901
5207
|
pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
|
|
4902
5208
|
}
|
|
4903
|
-
|
|
5209
|
+
container.appendChild(pageCard);
|
|
4904
5210
|
pageCards.push(pageCard);
|
|
4905
5211
|
}
|
|
4906
5212
|
let indicator = null;
|
|
4907
5213
|
if (totalPages > 1) {
|
|
4908
5214
|
indicator = document.createElement("div");
|
|
4909
5215
|
indicator.className = "fp-doc-page-indicator";
|
|
4910
|
-
indicator.style.position = "
|
|
5216
|
+
indicator.style.position = "fixed";
|
|
4911
5217
|
indicator.style.bottom = "16px";
|
|
5218
|
+
indicator.style.left = "50%";
|
|
5219
|
+
indicator.style.transform = "translateX(-50%)";
|
|
4912
5220
|
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4913
5221
|
indicator.style.backdropFilter = "blur(8px)";
|
|
4914
5222
|
indicator.style.color = "#f8fafc";
|
|
@@ -4922,17 +5230,25 @@ var DocPlugin = class {
|
|
|
4922
5230
|
indicator.style.userSelect = "none";
|
|
4923
5231
|
indicator.style.pointerEvents = "none";
|
|
4924
5232
|
indicator.style.textAlign = "center";
|
|
4925
|
-
indicator.style.width = "fit-content";
|
|
4926
|
-
indicator.style.margin = "16px auto 0";
|
|
4927
5233
|
container.appendChild(indicator);
|
|
4928
5234
|
}
|
|
5235
|
+
let rotation = 0;
|
|
5236
|
+
const applyTransform = () => {
|
|
5237
|
+
const activeCard = pageCards[currentPage - 1];
|
|
5238
|
+
if (activeCard) {
|
|
5239
|
+
activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5240
|
+
}
|
|
5241
|
+
};
|
|
4929
5242
|
const showPage = (pageNum) => {
|
|
4930
5243
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
card.style.display =
|
|
4934
|
-
|
|
4935
|
-
|
|
5244
|
+
pageCards.forEach((card, idx) => {
|
|
5245
|
+
if (idx + 1 === currentPage) {
|
|
5246
|
+
card.style.display = "block";
|
|
5247
|
+
card.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5248
|
+
} else {
|
|
5249
|
+
card.style.display = "none";
|
|
5250
|
+
}
|
|
5251
|
+
});
|
|
4936
5252
|
if (indicator) {
|
|
4937
5253
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4938
5254
|
}
|
|
@@ -4941,19 +5257,13 @@ var DocPlugin = class {
|
|
|
4941
5257
|
if (totalPages > 1) {
|
|
4942
5258
|
showPage(1);
|
|
4943
5259
|
}
|
|
4944
|
-
let rotation = 0;
|
|
4945
5260
|
const calculateFitScale = () => {
|
|
4946
|
-
const
|
|
4947
|
-
const
|
|
4948
|
-
const elH = activeCard.offsetHeight || 1e3;
|
|
5261
|
+
const elW = 816;
|
|
5262
|
+
const elH = 1056;
|
|
4949
5263
|
const availW = Math.max(200, ctx.container.clientWidth - 48);
|
|
4950
5264
|
const availH = Math.max(200, ctx.container.clientHeight - 80);
|
|
4951
5265
|
return Math.min(1.1, Math.min(availW / elW, availH / elH));
|
|
4952
5266
|
};
|
|
4953
|
-
const applyTransform = () => {
|
|
4954
|
-
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
4955
|
-
wrapper.style.transformOrigin = "top center";
|
|
4956
|
-
};
|
|
4957
5267
|
setTimeout(() => {
|
|
4958
5268
|
scale = calculateFitScale();
|
|
4959
5269
|
applyTransform();
|
|
@@ -5111,8 +5421,28 @@ var DocPlugin = class {
|
|
|
5111
5421
|
}
|
|
5112
5422
|
splitIntoPages(text) {
|
|
5113
5423
|
if (!text) return [""];
|
|
5114
|
-
const
|
|
5115
|
-
|
|
5424
|
+
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);
|
|
5425
|
+
if (explicitParts.length === 0) explicitParts.push(text);
|
|
5426
|
+
const maxLinesPerPage = 48;
|
|
5427
|
+
const finalPages = [];
|
|
5428
|
+
for (const part of explicitParts) {
|
|
5429
|
+
const lines = part.split(/\r?\n/);
|
|
5430
|
+
let currentLines = [];
|
|
5431
|
+
let count = 0;
|
|
5432
|
+
for (const line of lines) {
|
|
5433
|
+
currentLines.push(line);
|
|
5434
|
+
count++;
|
|
5435
|
+
if (count >= maxLinesPerPage) {
|
|
5436
|
+
finalPages.push(currentLines.join("\n"));
|
|
5437
|
+
currentLines = [];
|
|
5438
|
+
count = 0;
|
|
5439
|
+
}
|
|
5440
|
+
}
|
|
5441
|
+
if (currentLines.length > 0) {
|
|
5442
|
+
finalPages.push(currentLines.join("\n"));
|
|
5443
|
+
}
|
|
5444
|
+
}
|
|
5445
|
+
return finalPages.length > 0 ? finalPages : [text];
|
|
5116
5446
|
}
|
|
5117
5447
|
/**
|
|
5118
5448
|
* Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
|
|
@@ -5121,17 +5451,65 @@ var DocPlugin = class {
|
|
|
5121
5451
|
const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
|
|
5122
5452
|
let html = "";
|
|
5123
5453
|
let inList = false;
|
|
5124
|
-
|
|
5125
|
-
|
|
5454
|
+
let tableLines = [];
|
|
5455
|
+
const flushTable = () => {
|
|
5456
|
+
if (tableLines.length > 0) {
|
|
5457
|
+
html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
|
|
5458
|
+
for (const tLine of tableLines) {
|
|
5459
|
+
html += "<tr>";
|
|
5460
|
+
const cols = tLine.split(" ");
|
|
5461
|
+
for (const col of cols) {
|
|
5462
|
+
html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6.sanitize(col.trim())}</td>`;
|
|
5463
|
+
}
|
|
5464
|
+
html += "</tr>";
|
|
5465
|
+
}
|
|
5466
|
+
html += "</table>";
|
|
5467
|
+
tableLines = [];
|
|
5468
|
+
}
|
|
5469
|
+
};
|
|
5470
|
+
let i = 0;
|
|
5471
|
+
while (i < lines.length) {
|
|
5472
|
+
let line = lines[i];
|
|
5473
|
+
let tabCount = (line.match(/\t/g) || []).length;
|
|
5474
|
+
if (tabCount > 0) {
|
|
5475
|
+
let consecutiveTableLines = 1;
|
|
5476
|
+
let j = i + 1;
|
|
5477
|
+
while (j < lines.length) {
|
|
5478
|
+
const nextTabCount = (lines[j].match(/\t/g) || []).length;
|
|
5479
|
+
if (nextTabCount === tabCount) {
|
|
5480
|
+
consecutiveTableLines++;
|
|
5481
|
+
j++;
|
|
5482
|
+
} else {
|
|
5483
|
+
break;
|
|
5484
|
+
}
|
|
5485
|
+
}
|
|
5486
|
+
if (consecutiveTableLines >= 3) {
|
|
5487
|
+
if (inList) {
|
|
5488
|
+
html += "</ul>";
|
|
5489
|
+
inList = false;
|
|
5490
|
+
}
|
|
5491
|
+
tableLines = lines.slice(i, j);
|
|
5492
|
+
flushTable();
|
|
5493
|
+
i = j;
|
|
5494
|
+
continue;
|
|
5495
|
+
}
|
|
5496
|
+
}
|
|
5497
|
+
line = line.trim();
|
|
5126
5498
|
if (!line) {
|
|
5127
5499
|
if (inList) {
|
|
5128
5500
|
html += "</ul>";
|
|
5129
5501
|
inList = false;
|
|
5130
5502
|
}
|
|
5503
|
+
html += '<div style="height: 1.15em;"></div>';
|
|
5504
|
+
i++;
|
|
5505
|
+
continue;
|
|
5506
|
+
}
|
|
5507
|
+
if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line)) {
|
|
5508
|
+
i++;
|
|
5131
5509
|
continue;
|
|
5132
5510
|
}
|
|
5133
|
-
if (
|
|
5134
|
-
|
|
5511
|
+
if ((line.includes("Normal.dot") || line.includes("Microsoft Word") || line.includes("Times New Roman")) && line.length < 30) {
|
|
5512
|
+
i++;
|
|
5135
5513
|
continue;
|
|
5136
5514
|
}
|
|
5137
5515
|
if (line.length < 60 && !line.endsWith(".") && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#"))) {
|
|
@@ -5139,24 +5517,26 @@ var DocPlugin = class {
|
|
|
5139
5517
|
html += "</ul>";
|
|
5140
5518
|
inList = false;
|
|
5141
5519
|
}
|
|
5142
|
-
html += `<h2 style="font-size:
|
|
5520
|
+
html += `<h2 style="font-size: 16px; font-weight: 700; color: #1e3a8a; margin: 16px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify6.sanitize(line)}</h2>`;
|
|
5143
5521
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
5144
5522
|
if (!inList) {
|
|
5145
5523
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
5146
5524
|
inList = true;
|
|
5147
5525
|
}
|
|
5148
5526
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
5149
|
-
html += `<li style="margin: 4px 0; line-height: 1.
|
|
5527
|
+
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6.sanitize(bulletText)}</li>`;
|
|
5150
5528
|
} else {
|
|
5151
5529
|
if (inList) {
|
|
5152
5530
|
html += "</ul>";
|
|
5153
5531
|
inList = false;
|
|
5154
5532
|
}
|
|
5155
|
-
html += `<p style="line-height: 1.
|
|
5533
|
+
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6.sanitize(line)}</p>`;
|
|
5156
5534
|
}
|
|
5535
|
+
i++;
|
|
5157
5536
|
}
|
|
5158
5537
|
if (inList) html += "</ul>";
|
|
5159
|
-
|
|
5538
|
+
flushTable();
|
|
5539
|
+
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6.sanitize(filename)})</p>`;
|
|
5160
5540
|
}
|
|
5161
5541
|
};
|
|
5162
5542
|
function docPlugin() {
|
|
@@ -5334,7 +5714,7 @@ var PptPlugin = class {
|
|
|
5334
5714
|
if (s.pictureUrl) {
|
|
5335
5715
|
contentHtml = `
|
|
5336
5716
|
<div style="flex: 1; display: flex; justify-content: center; align-items: center; padding: 12px; overflow: hidden;">
|
|
5337
|
-
<img src="${s.pictureUrl}" alt="${
|
|
5717
|
+
<img src="${s.pictureUrl}" alt="${DOMPurify6.sanitize(s.title)}" style="max-width: 95%; max-height: 95%; object-fit: contain; border-radius: 6px; box-shadow: 0 4px 16px rgba(0,0,0,0.1); background: #ffffff;" />
|
|
5338
5718
|
</div>
|
|
5339
5719
|
`;
|
|
5340
5720
|
} else if (s.tableColumns.length > 0) {
|
|
@@ -5344,7 +5724,7 @@ var PptPlugin = class {
|
|
|
5344
5724
|
<table style="width: 100%; border-collapse: collapse; border: 1px solid #cbd5e1; border-radius: 6px; overflow: hidden; background: #ffffff;">
|
|
5345
5725
|
<thead>
|
|
5346
5726
|
<tr style="background: #e2e8f0; color: #1e293b; font-weight: 600; font-size: 14px;">
|
|
5347
|
-
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${
|
|
5727
|
+
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${DOMPurify6.sanitize(c)}</th>`).join("")}
|
|
5348
5728
|
</tr>
|
|
5349
5729
|
</thead>
|
|
5350
5730
|
<tbody>
|
|
@@ -5360,7 +5740,7 @@ var PptPlugin = class {
|
|
|
5360
5740
|
} else {
|
|
5361
5741
|
const pTags = s.paragraphs.map((p) => {
|
|
5362
5742
|
const lines = p.split(/[\r\n]+/).map((l) => l.trim()).filter(Boolean);
|
|
5363
|
-
return lines.map((l) => `<p style="margin: 0 0 14px; font-size: 14px; line-height: 1.65; color: #334155; text-align: justify;">${
|
|
5743
|
+
return lines.map((l) => `<p style="margin: 0 0 14px; font-size: 14px; line-height: 1.65; color: #334155; text-align: justify;">${DOMPurify6.sanitize(l)}</p>`).join("");
|
|
5364
5744
|
}).join("");
|
|
5365
5745
|
contentHtml = `
|
|
5366
5746
|
<div style="flex: 1; overflow: auto; padding: 4px 8px; display: flex; flex-direction: column; justify-content: flex-start;">
|
|
@@ -5373,11 +5753,11 @@ var PptPlugin = class {
|
|
|
5373
5753
|
<!-- Header Banner matching PowerPoint design -->
|
|
5374
5754
|
<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;">
|
|
5375
5755
|
<h1 style="margin: 0; font-size: 26px; font-weight: 700; color: #1e293b; letter-spacing: -0.3px;">
|
|
5376
|
-
${
|
|
5756
|
+
${DOMPurify6.sanitize(s.title)}
|
|
5377
5757
|
</h1>
|
|
5378
5758
|
${s.subtitle ? `
|
|
5379
5759
|
<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);">
|
|
5380
|
-
${
|
|
5760
|
+
${DOMPurify6.sanitize(s.subtitle)}
|
|
5381
5761
|
</span>
|
|
5382
5762
|
` : `
|
|
5383
5763
|
<span style="font-size: 12px; color: #365314; font-weight: 600;">
|