@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/angular.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Component, ChangeDetectionStrategy, Input, Output, ViewChild, EventEmitter as EventEmitter$1 } from '@angular/core';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
|
-
import
|
|
3
|
+
import DOMPurify6 from 'dompurify';
|
|
4
4
|
import * as pdfjsLib from 'pdfjs-dist';
|
|
5
5
|
import * as docx from 'docx-preview';
|
|
6
6
|
import { unzipSync, strFromU8, unzip } from 'fflate';
|
|
@@ -405,7 +405,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
405
405
|
if (magicMime === "application/zip") {
|
|
406
406
|
const ooxmlMime = detectOoxmlType(buffer);
|
|
407
407
|
if (ooxmlMime && ooxmlMime !== "application/zip") {
|
|
408
|
-
metadata.mimeType = ooxmlMime;
|
|
408
|
+
metadata.mimeType = metadata.mimeType ?? ooxmlMime;
|
|
409
409
|
if (ooxmlMime.includes("wordprocessing")) metadata.extension = metadata.extension ?? ".docx";
|
|
410
410
|
else if (ooxmlMime.includes("spreadsheet")) metadata.extension = metadata.extension ?? ".xlsx";
|
|
411
411
|
else if (ooxmlMime.includes("presentation")) metadata.extension = metadata.extension ?? ".pptx";
|
|
@@ -434,7 +434,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
434
434
|
return { buffer, metadata };
|
|
435
435
|
}
|
|
436
436
|
function sanitizeSVG(svg) {
|
|
437
|
-
return
|
|
437
|
+
return DOMPurify6.sanitize(svg, {
|
|
438
438
|
USE_PROFILES: { svg: true, svgFilters: true }
|
|
439
439
|
});
|
|
440
440
|
}
|
|
@@ -1496,7 +1496,19 @@ var PdfPlugin = class {
|
|
|
1496
1496
|
}
|
|
1497
1497
|
};
|
|
1498
1498
|
await renderPage(1);
|
|
1499
|
+
let resizeTimer = null;
|
|
1500
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
1501
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1502
|
+
resizeTimer = setTimeout(() => {
|
|
1503
|
+
if (Math.abs(zoomScale - 1) < 0.05) {
|
|
1504
|
+
renderPage(currentPage);
|
|
1505
|
+
}
|
|
1506
|
+
}, 150);
|
|
1507
|
+
});
|
|
1508
|
+
resizeObserver.observe(container);
|
|
1499
1509
|
const cleanup = () => {
|
|
1510
|
+
resizeObserver.disconnect();
|
|
1511
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
1500
1512
|
if (currentRenderTask) {
|
|
1501
1513
|
try {
|
|
1502
1514
|
currentRenderTask.cancel();
|
|
@@ -2244,90 +2256,149 @@ var DocxPlugin = class {
|
|
|
2244
2256
|
console.warn("[DocxPlugin] Error parsing relationships:", relsErr);
|
|
2245
2257
|
}
|
|
2246
2258
|
}
|
|
2247
|
-
const
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2259
|
+
const sectPrs = Array.from(doc.getElementsByTagNameNS("*", "sectPr"));
|
|
2260
|
+
const lastSectPr = sectPrs[sectPrs.length - 1];
|
|
2261
|
+
let defaultW = 12240;
|
|
2262
|
+
let defaultH = 15840;
|
|
2263
|
+
let margins = { top: 1440, right: 1440, bottom: 1440, left: 1440 };
|
|
2264
|
+
if (lastSectPr) {
|
|
2265
|
+
const pgSz = lastSectPr.getElementsByTagNameNS("*", "pgSz")[0];
|
|
2266
|
+
if (pgSz) {
|
|
2267
|
+
defaultW = parseInt(pgSz.getAttribute("w:w") || pgSz.getAttribute("w") || "12240", 10);
|
|
2268
|
+
defaultH = parseInt(pgSz.getAttribute("w:h") || pgSz.getAttribute("h") || "15840", 10);
|
|
2269
|
+
}
|
|
2270
|
+
const pgMar = lastSectPr.getElementsByTagNameNS("*", "pgMar")[0];
|
|
2271
|
+
if (pgMar) {
|
|
2272
|
+
margins.top = parseInt(pgMar.getAttribute("w:top") || pgMar.getAttribute("top") || "1440", 10);
|
|
2273
|
+
margins.bottom = parseInt(pgMar.getAttribute("w:bottom") || pgMar.getAttribute("bottom") || "1440", 10);
|
|
2274
|
+
margins.left = parseInt(pgMar.getAttribute("w:left") || pgMar.getAttribute("left") || "1440", 10);
|
|
2275
|
+
margins.right = parseInt(pgMar.getAttribute("w:right") || pgMar.getAttribute("right") || "1440", 10);
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2278
|
+
const createPageCard = () => {
|
|
2279
|
+
const card = document.createElement("div");
|
|
2280
|
+
card.className = "fp-docx-page-card";
|
|
2281
|
+
card.style.backgroundColor = "#ffffff";
|
|
2282
|
+
card.style.borderRadius = "4px";
|
|
2283
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
2284
|
+
card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2285
|
+
card.style.color = "#1e293b";
|
|
2286
|
+
card.style.lineHeight = "1.6";
|
|
2287
|
+
card.style.boxSizing = "border-box";
|
|
2288
|
+
card.style.overflow = "hidden";
|
|
2289
|
+
card.style.position = "relative";
|
|
2290
|
+
card.style.marginBottom = "24px";
|
|
2291
|
+
card.style.width = `${defaultW / 15}px`;
|
|
2292
|
+
card.style.height = `${defaultH / 15}px`;
|
|
2293
|
+
card.style.padding = `${margins.top / 15}px ${margins.right / 15}px ${margins.bottom / 15}px ${margins.left / 15}px`;
|
|
2294
|
+
return card;
|
|
2295
|
+
};
|
|
2296
|
+
let currentCard = createPageCard();
|
|
2297
|
+
let currentHtml = "";
|
|
2298
|
+
const pages = [{ card: currentCard, html: "" }];
|
|
2299
|
+
const flushHtml = () => {
|
|
2300
|
+
pages[pages.length - 1].html += currentHtml;
|
|
2301
|
+
currentHtml = "";
|
|
2302
|
+
};
|
|
2303
|
+
const newPage = () => {
|
|
2304
|
+
flushHtml();
|
|
2305
|
+
currentCard = createPageCard();
|
|
2306
|
+
pages.push({ card: currentCard, html: "" });
|
|
2307
|
+
};
|
|
2256
2308
|
const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
|
|
2257
|
-
let html = "";
|
|
2258
2309
|
for (const child of Array.from(body.children)) {
|
|
2259
2310
|
const tag = child.localName || child.nodeName.split(":").pop();
|
|
2260
2311
|
if (tag === "p") {
|
|
2261
2312
|
const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
|
|
2262
2313
|
const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
|
|
2263
2314
|
const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
|
|
2264
|
-
const
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2315
|
+
const chunks = this.extractParagraphChunks(child, imageMap);
|
|
2316
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
2317
|
+
if (i > 0) {
|
|
2318
|
+
newPage();
|
|
2319
|
+
}
|
|
2320
|
+
const textContent = chunks[i];
|
|
2321
|
+
if (!textContent.trim() && !textContent.includes("<img")) {
|
|
2322
|
+
currentHtml += '<div style="height: 10px;"></div>';
|
|
2323
|
+
continue;
|
|
2324
|
+
}
|
|
2325
|
+
const lowerStyle = styleVal.toLowerCase();
|
|
2326
|
+
if (lowerStyle.includes("title")) {
|
|
2327
|
+
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>`;
|
|
2328
|
+
} else if (lowerStyle.includes("heading1") || styleVal === "1") {
|
|
2329
|
+
currentHtml += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
|
|
2330
|
+
} else if (lowerStyle.includes("heading2") || styleVal === "2") {
|
|
2331
|
+
currentHtml += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
|
|
2332
|
+
} else if (lowerStyle.includes("heading3") || styleVal === "3") {
|
|
2333
|
+
currentHtml += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
|
|
2334
|
+
} else if (numPr) {
|
|
2335
|
+
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>`;
|
|
2336
|
+
} else {
|
|
2337
|
+
currentHtml += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
|
|
2338
|
+
}
|
|
2282
2339
|
}
|
|
2283
2340
|
} else if (tag === "tbl") {
|
|
2284
|
-
|
|
2341
|
+
currentHtml += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
|
|
2285
2342
|
const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
|
|
2286
2343
|
rows.forEach((tr, rIdx) => {
|
|
2287
|
-
|
|
2344
|
+
currentHtml += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
2288
2345
|
const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
|
|
2289
2346
|
cells.forEach((tc) => {
|
|
2290
2347
|
const cellText = this.extractParagraphHtml(tc, imageMap);
|
|
2291
|
-
|
|
2348
|
+
currentHtml += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || " "}</td>`;
|
|
2292
2349
|
});
|
|
2293
|
-
|
|
2350
|
+
currentHtml += "</tr>";
|
|
2294
2351
|
});
|
|
2295
|
-
|
|
2352
|
+
currentHtml += "</table>";
|
|
2296
2353
|
}
|
|
2297
2354
|
}
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2355
|
+
flushHtml();
|
|
2356
|
+
for (const page of pages) {
|
|
2357
|
+
page.card.innerHTML = DOMPurify6.sanitize(page.html, {
|
|
2358
|
+
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
|
|
2359
|
+
ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
|
|
2360
|
+
});
|
|
2361
|
+
wrapper.appendChild(page.card);
|
|
2362
|
+
}
|
|
2303
2363
|
}
|
|
2304
2364
|
extractParagraphHtml(pElement, imageMap = {}) {
|
|
2305
|
-
|
|
2365
|
+
return this.extractParagraphChunks(pElement, imageMap).join("<br/>");
|
|
2366
|
+
}
|
|
2367
|
+
extractParagraphChunks(pElement, imageMap = {}) {
|
|
2368
|
+
const chunks = [""];
|
|
2369
|
+
let currentChunkIndex = 0;
|
|
2306
2370
|
const drawings = Array.from(pElement.getElementsByTagNameNS("*", "drawing"));
|
|
2307
2371
|
for (const drawing of drawings) {
|
|
2308
2372
|
const blip = drawing.getElementsByTagNameNS("*", "blip")[0];
|
|
2309
2373
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2310
2374
|
if (rId && imageMap[rId]) {
|
|
2311
|
-
|
|
2375
|
+
chunks[currentChunkIndex] += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
|
|
2312
2376
|
}
|
|
2313
2377
|
}
|
|
2314
2378
|
const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
|
|
2315
|
-
if (runs.length === 0 && !
|
|
2316
|
-
|
|
2379
|
+
if (runs.length === 0 && !chunks[currentChunkIndex]) {
|
|
2380
|
+
chunks[currentChunkIndex] = DOMPurify6.sanitize(pElement.textContent || "");
|
|
2381
|
+
return chunks;
|
|
2317
2382
|
}
|
|
2318
2383
|
for (const r of runs) {
|
|
2319
2384
|
const blip = r.getElementsByTagNameNS("*", "blip")[0] || r.getElementsByTagNameNS("*", "imagedata")[0];
|
|
2320
2385
|
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
2321
2386
|
if (rId && imageMap[rId]) {
|
|
2322
|
-
|
|
2387
|
+
chunks[currentChunkIndex] += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
|
|
2323
2388
|
}
|
|
2324
|
-
const brs = r.getElementsByTagNameNS("*", "br");
|
|
2325
|
-
for (
|
|
2326
|
-
|
|
2389
|
+
const brs = Array.from(r.getElementsByTagNameNS("*", "br"));
|
|
2390
|
+
for (const br of brs) {
|
|
2391
|
+
const type = br.getAttribute("w:type") || br.getAttribute("type");
|
|
2392
|
+
if (type === "page") {
|
|
2393
|
+
chunks.push("");
|
|
2394
|
+
currentChunkIndex++;
|
|
2395
|
+
} else {
|
|
2396
|
+
chunks[currentChunkIndex] += "<br/>";
|
|
2397
|
+
}
|
|
2327
2398
|
}
|
|
2328
2399
|
const tabs = r.getElementsByTagNameNS("*", "tab");
|
|
2329
2400
|
if (tabs.length > 0) {
|
|
2330
|
-
|
|
2401
|
+
chunks[currentChunkIndex] += " ";
|
|
2331
2402
|
}
|
|
2332
2403
|
const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
|
|
2333
2404
|
const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
|
|
@@ -2341,7 +2412,7 @@ var DocxPlugin = class {
|
|
|
2341
2412
|
const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
|
|
2342
2413
|
let text = texts.map((t) => t.textContent || "").join("");
|
|
2343
2414
|
if (!text) continue;
|
|
2344
|
-
text =
|
|
2415
|
+
text = DOMPurify6.sanitize(text);
|
|
2345
2416
|
let styles = "";
|
|
2346
2417
|
if (isBold) styles += "font-weight: bold; ";
|
|
2347
2418
|
if (isItalic) styles += "font-style: italic; ";
|
|
@@ -2353,12 +2424,12 @@ var DocxPlugin = class {
|
|
|
2353
2424
|
if (!isNaN(pt) && pt > 0) styles += `font-size: ${pt}pt; `;
|
|
2354
2425
|
}
|
|
2355
2426
|
if (styles) {
|
|
2356
|
-
|
|
2427
|
+
chunks[currentChunkIndex] += `<span style="${styles}">${text}</span>`;
|
|
2357
2428
|
} else {
|
|
2358
|
-
|
|
2429
|
+
chunks[currentChunkIndex] += text;
|
|
2359
2430
|
}
|
|
2360
2431
|
}
|
|
2361
|
-
return
|
|
2432
|
+
return chunks;
|
|
2362
2433
|
}
|
|
2363
2434
|
renderBinaryDocFallback(ctx, wrapper) {
|
|
2364
2435
|
const card = document.createElement("div");
|
|
@@ -2375,14 +2446,14 @@ var DocxPlugin = class {
|
|
|
2375
2446
|
const wordDocStream = cfbf.readStream("WordDocument");
|
|
2376
2447
|
if (wordDocStream && wordDocStream.length >= 512) {
|
|
2377
2448
|
const text2 = this.extractReadableStrings(wordDocStream);
|
|
2378
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2449
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6.sanitize(text2)}</div>`;
|
|
2379
2450
|
wrapper.appendChild(card);
|
|
2380
2451
|
return;
|
|
2381
2452
|
}
|
|
2382
2453
|
} catch {
|
|
2383
2454
|
}
|
|
2384
2455
|
const text = this.extractReadableStrings(new Uint8Array(ctx.buffer));
|
|
2385
|
-
card.innerHTML = `<div style="white-space: pre-wrap;">${
|
|
2456
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6.sanitize(text)}</div>`;
|
|
2386
2457
|
wrapper.appendChild(card);
|
|
2387
2458
|
}
|
|
2388
2459
|
extractReadableStrings(bytes) {
|
|
@@ -2981,41 +3052,94 @@ var CodePlugin = class {
|
|
|
2981
3052
|
async render(ctx) {
|
|
2982
3053
|
const decoder = new TextDecoder("utf-8");
|
|
2983
3054
|
const fullText = decoder.decode(ctx.buffer);
|
|
2984
|
-
const
|
|
2985
|
-
const
|
|
3055
|
+
const extRaw = ctx.metadata.extension?.toLowerCase();
|
|
3056
|
+
const mimeRaw = ctx.metadata.mimeType?.toLowerCase();
|
|
3057
|
+
const isTxt = extRaw === ".txt" || mimeRaw === "text/plain" && (!extRaw || !this.extensions.filter((e) => e !== ".txt").includes(extRaw));
|
|
3058
|
+
let rawPages = [];
|
|
3059
|
+
if (isTxt) {
|
|
3060
|
+
const explicitPages = fullText.split(/(?:\f|\x0C)/);
|
|
3061
|
+
for (const ep of explicitPages) {
|
|
3062
|
+
const lines = ep.split(/\r?\n/);
|
|
3063
|
+
let currentChunk = [];
|
|
3064
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3065
|
+
currentChunk.push(lines[i]);
|
|
3066
|
+
if (currentChunk.length >= 46) {
|
|
3067
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3068
|
+
currentChunk = [];
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
if (currentChunk.length > 0 || lines.length === 0) {
|
|
3072
|
+
rawPages.push(currentChunk.join("\n"));
|
|
3073
|
+
}
|
|
3074
|
+
}
|
|
3075
|
+
if (rawPages.length === 0) rawPages = [""];
|
|
3076
|
+
} else {
|
|
3077
|
+
const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
|
|
3078
|
+
rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
3079
|
+
}
|
|
2986
3080
|
const totalPages = Math.max(1, rawPages.length);
|
|
2987
3081
|
let currentPage = 1;
|
|
2988
3082
|
const container = document.createElement("div");
|
|
2989
3083
|
container.style.width = "100%";
|
|
2990
3084
|
container.style.height = "100%";
|
|
2991
3085
|
container.style.overflow = "auto";
|
|
2992
|
-
container.style.backgroundColor = "#1e1e1e";
|
|
2993
|
-
container.style.color = "#d4d4d4";
|
|
2994
|
-
container.style.padding = "16px";
|
|
2995
|
-
container.style.boxSizing = "border-box";
|
|
2996
3086
|
let fontSize = 13;
|
|
2997
3087
|
let rotation = 0;
|
|
3088
|
+
let zoomLevel = 1;
|
|
2998
3089
|
const pre = document.createElement("pre");
|
|
2999
|
-
pre.style.margin = "0";
|
|
3000
|
-
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
3001
|
-
pre.style.fontSize = `${fontSize}px`;
|
|
3002
|
-
pre.style.lineHeight = "1.5";
|
|
3003
|
-
pre.style.whiteSpace = "pre-wrap";
|
|
3004
|
-
pre.style.wordBreak = "break-all";
|
|
3005
3090
|
const code = document.createElement("code");
|
|
3091
|
+
if (isTxt) {
|
|
3092
|
+
container.style.backgroundColor = "#f1f5f9";
|
|
3093
|
+
container.style.padding = "32px";
|
|
3094
|
+
container.style.boxSizing = "border-box";
|
|
3095
|
+
container.style.display = "flex";
|
|
3096
|
+
container.style.flexDirection = "column";
|
|
3097
|
+
container.style.alignItems = "center";
|
|
3098
|
+
pre.style.margin = "0";
|
|
3099
|
+
pre.style.fontFamily = "Consolas, 'Courier New', monospace";
|
|
3100
|
+
pre.style.fontSize = "13px";
|
|
3101
|
+
pre.style.color = "#1e293b";
|
|
3102
|
+
pre.style.lineHeight = "1.5";
|
|
3103
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3104
|
+
pre.style.wordBreak = "break-word";
|
|
3105
|
+
pre.style.backgroundColor = "#ffffff";
|
|
3106
|
+
pre.style.width = "816px";
|
|
3107
|
+
pre.style.minHeight = "1056px";
|
|
3108
|
+
pre.style.padding = "72px 56px";
|
|
3109
|
+
pre.style.boxSizing = "border-box";
|
|
3110
|
+
pre.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)";
|
|
3111
|
+
pre.style.borderRadius = "4px";
|
|
3112
|
+
pre.style.transformOrigin = "top center";
|
|
3113
|
+
} else {
|
|
3114
|
+
container.style.backgroundColor = "#1e1e1e";
|
|
3115
|
+
container.style.color = "#d4d4d4";
|
|
3116
|
+
container.style.padding = "16px";
|
|
3117
|
+
container.style.boxSizing = "border-box";
|
|
3118
|
+
pre.style.margin = "0";
|
|
3119
|
+
pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
|
|
3120
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3121
|
+
pre.style.lineHeight = "1.5";
|
|
3122
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
3123
|
+
pre.style.wordBreak = "break-all";
|
|
3124
|
+
pre.style.transformOrigin = "top left";
|
|
3125
|
+
}
|
|
3006
3126
|
const ext = (ctx.metadata.extension || "").replace(".", "");
|
|
3007
3127
|
const renderCodePage = (text) => {
|
|
3008
|
-
|
|
3009
|
-
if (ext && hljs.getLanguage(ext)) {
|
|
3010
|
-
code.innerHTML = hljs.highlight(text, { language: ext }).value;
|
|
3011
|
-
} else {
|
|
3012
|
-
code.innerHTML = hljs.highlightAuto(text).value;
|
|
3013
|
-
}
|
|
3014
|
-
} catch {
|
|
3128
|
+
if (isTxt) {
|
|
3015
3129
|
code.textContent = text;
|
|
3130
|
+
} else {
|
|
3131
|
+
try {
|
|
3132
|
+
if (ext && hljs.getLanguage(ext)) {
|
|
3133
|
+
code.innerHTML = hljs.highlight(text, { language: ext }).value;
|
|
3134
|
+
} else {
|
|
3135
|
+
code.innerHTML = hljs.highlightAuto(text).value;
|
|
3136
|
+
}
|
|
3137
|
+
} catch {
|
|
3138
|
+
code.textContent = text;
|
|
3139
|
+
}
|
|
3016
3140
|
}
|
|
3017
3141
|
};
|
|
3018
|
-
renderCodePage(rawPages[0] || fullText);
|
|
3142
|
+
renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
|
|
3019
3143
|
pre.appendChild(code);
|
|
3020
3144
|
container.appendChild(pre);
|
|
3021
3145
|
let indicator = null;
|
|
@@ -3024,15 +3148,22 @@ var CodePlugin = class {
|
|
|
3024
3148
|
indicator.className = "fp-code-page-indicator";
|
|
3025
3149
|
indicator.style.position = "sticky";
|
|
3026
3150
|
indicator.style.bottom = "16px";
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3151
|
+
if (isTxt) {
|
|
3152
|
+
indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
3153
|
+
indicator.style.color = "#334155";
|
|
3154
|
+
indicator.style.border = "1px solid #e2e8f0";
|
|
3155
|
+
indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
|
|
3156
|
+
} else {
|
|
3157
|
+
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
3158
|
+
indicator.style.color = "#f8fafc";
|
|
3159
|
+
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3160
|
+
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3161
|
+
indicator.style.backdropFilter = "blur(8px)";
|
|
3162
|
+
}
|
|
3030
3163
|
indicator.style.fontSize = "12px";
|
|
3031
3164
|
indicator.style.fontWeight = "600";
|
|
3032
3165
|
indicator.style.padding = "5px 14px";
|
|
3033
3166
|
indicator.style.borderRadius = "20px";
|
|
3034
|
-
indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
3035
|
-
indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
|
|
3036
3167
|
indicator.style.zIndex = "10";
|
|
3037
3168
|
indicator.style.userSelect = "none";
|
|
3038
3169
|
indicator.style.pointerEvents = "none";
|
|
@@ -3043,7 +3174,7 @@ var CodePlugin = class {
|
|
|
3043
3174
|
}
|
|
3044
3175
|
const showPage = (pageNum) => {
|
|
3045
3176
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
3046
|
-
renderCodePage(rawPages[currentPage - 1] || fullText);
|
|
3177
|
+
renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
|
|
3047
3178
|
if (indicator) {
|
|
3048
3179
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
3049
3180
|
}
|
|
@@ -3059,39 +3190,57 @@ var CodePlugin = class {
|
|
|
3059
3190
|
ctx.container.innerHTML = "";
|
|
3060
3191
|
};
|
|
3061
3192
|
ctx.signal.addEventListener("abort", cleanup);
|
|
3193
|
+
const updateTransform = () => {
|
|
3194
|
+
if (isTxt) {
|
|
3195
|
+
pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
|
|
3196
|
+
} else {
|
|
3197
|
+
pre.style.transform = `rotate(${rotation}deg)`;
|
|
3198
|
+
pre.style.fontSize = `${fontSize}px`;
|
|
3199
|
+
}
|
|
3200
|
+
};
|
|
3062
3201
|
return {
|
|
3063
3202
|
destroy: cleanup,
|
|
3064
3203
|
getPageCount: () => totalPages,
|
|
3065
3204
|
getCurrentPage: () => currentPage,
|
|
3066
3205
|
goToPage: (page) => showPage(page),
|
|
3067
3206
|
zoomIn: () => {
|
|
3068
|
-
|
|
3069
|
-
|
|
3207
|
+
if (isTxt) {
|
|
3208
|
+
zoomLevel = Math.min(3, zoomLevel + 0.1);
|
|
3209
|
+
} else {
|
|
3210
|
+
fontSize = Math.min(32, fontSize + 2);
|
|
3211
|
+
}
|
|
3212
|
+
updateTransform();
|
|
3070
3213
|
},
|
|
3071
3214
|
zoomOut: () => {
|
|
3072
|
-
|
|
3073
|
-
|
|
3215
|
+
if (isTxt) {
|
|
3216
|
+
zoomLevel = Math.max(0.1, zoomLevel - 0.1);
|
|
3217
|
+
} else {
|
|
3218
|
+
fontSize = Math.max(8, fontSize - 2);
|
|
3219
|
+
}
|
|
3220
|
+
updateTransform();
|
|
3074
3221
|
},
|
|
3075
|
-
getZoom: () => fontSize / 13,
|
|
3222
|
+
getZoom: () => isTxt ? zoomLevel : fontSize / 13,
|
|
3076
3223
|
setZoom: (level) => {
|
|
3077
|
-
|
|
3078
|
-
|
|
3224
|
+
if (isTxt) {
|
|
3225
|
+
zoomLevel = level;
|
|
3226
|
+
} else {
|
|
3227
|
+
fontSize = Math.round(13 * level);
|
|
3228
|
+
}
|
|
3229
|
+
updateTransform();
|
|
3079
3230
|
},
|
|
3080
3231
|
fitToPage: () => {
|
|
3081
3232
|
fontSize = 13;
|
|
3082
3233
|
rotation = 0;
|
|
3083
|
-
|
|
3084
|
-
|
|
3234
|
+
zoomLevel = 1;
|
|
3235
|
+
updateTransform();
|
|
3085
3236
|
},
|
|
3086
3237
|
rotateCW: () => {
|
|
3087
3238
|
rotation = (rotation + 90) % 360;
|
|
3088
|
-
|
|
3089
|
-
pre.style.transformOrigin = "top left";
|
|
3239
|
+
updateTransform();
|
|
3090
3240
|
},
|
|
3091
3241
|
rotateCCW: () => {
|
|
3092
3242
|
rotation = (rotation - 90 + 360) % 360;
|
|
3093
|
-
|
|
3094
|
-
pre.style.transformOrigin = "top left";
|
|
3243
|
+
updateTransform();
|
|
3095
3244
|
},
|
|
3096
3245
|
download: () => {
|
|
3097
3246
|
const mimeType = ctx.metadata.mimeType || "text/plain";
|
|
@@ -3390,7 +3539,7 @@ var MarkdownPlugin = class {
|
|
|
3390
3539
|
gfm: true,
|
|
3391
3540
|
breaks: true
|
|
3392
3541
|
});
|
|
3393
|
-
const cleanHtml =
|
|
3542
|
+
const cleanHtml = DOMPurify6.sanitize(rawHtml, {
|
|
3394
3543
|
USE_PROFILES: { html: true }
|
|
3395
3544
|
});
|
|
3396
3545
|
const wrapper = document.createElement("div");
|
|
@@ -4026,6 +4175,14 @@ var RtfPlugin = class {
|
|
|
4026
4175
|
group: "actions",
|
|
4027
4176
|
execute: () => instance.download?.()
|
|
4028
4177
|
},
|
|
4178
|
+
{
|
|
4179
|
+
id: "copy",
|
|
4180
|
+
icon: "copy",
|
|
4181
|
+
label: "Copy Text",
|
|
4182
|
+
type: "button",
|
|
4183
|
+
group: "actions",
|
|
4184
|
+
execute: () => instance.copy?.()
|
|
4185
|
+
},
|
|
4029
4186
|
{
|
|
4030
4187
|
id: "print",
|
|
4031
4188
|
icon: "print",
|
|
@@ -4087,14 +4244,31 @@ var RtfPlugin = class {
|
|
|
4087
4244
|
} catch (err) {
|
|
4088
4245
|
console.warn("[RtfPlugin] RTF render error, fallback text:", err);
|
|
4089
4246
|
const text = new TextDecoder("latin1").decode(ctx.buffer);
|
|
4090
|
-
const
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4247
|
+
const rawPages = text.split(/\\page\b/).map((segment) => {
|
|
4248
|
+
return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
|
|
4249
|
+
}).filter((p) => p.length > 0);
|
|
4250
|
+
const pages = rawPages.length > 0 ? rawPages : [text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim()];
|
|
4251
|
+
for (let i = 0; i < pages.length; i++) {
|
|
4252
|
+
const pageCard = document.createElement("div");
|
|
4253
|
+
pageCard.className = "fp-rtf-page-card";
|
|
4254
|
+
pageCard.style.backgroundColor = "#ffffff";
|
|
4255
|
+
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4256
|
+
pageCard.style.borderRadius = "4px";
|
|
4257
|
+
pageCard.style.padding = "72px 56px";
|
|
4258
|
+
pageCard.style.width = "816px";
|
|
4259
|
+
pageCard.style.minHeight = "1056px";
|
|
4260
|
+
pageCard.style.maxWidth = "100%";
|
|
4261
|
+
pageCard.style.boxSizing = "border-box";
|
|
4262
|
+
pageCard.style.fontFamily = "serif";
|
|
4263
|
+
pageCard.style.fontSize = "12pt";
|
|
4264
|
+
pageCard.style.lineHeight = "1.6";
|
|
4265
|
+
pageCard.style.color = "#1e293b";
|
|
4266
|
+
pageCard.style.whiteSpace = "pre-wrap";
|
|
4267
|
+
pageCard.style.display = i === 0 ? "block" : "none";
|
|
4268
|
+
pageCard.textContent = pages[i];
|
|
4269
|
+
wrapper.appendChild(pageCard);
|
|
4270
|
+
pageElements.push(pageCard);
|
|
4271
|
+
}
|
|
4098
4272
|
}
|
|
4099
4273
|
const totalPages = Math.max(1, pageElements.length);
|
|
4100
4274
|
let currentPage = 1;
|
|
@@ -4182,6 +4356,10 @@ var RtfPlugin = class {
|
|
|
4182
4356
|
a.click();
|
|
4183
4357
|
URL.revokeObjectURL(url);
|
|
4184
4358
|
},
|
|
4359
|
+
copy: () => {
|
|
4360
|
+
const text = wrapper.textContent || "";
|
|
4361
|
+
navigator.clipboard?.writeText(text);
|
|
4362
|
+
},
|
|
4185
4363
|
print: () => {
|
|
4186
4364
|
window.print();
|
|
4187
4365
|
}
|
|
@@ -4256,7 +4434,7 @@ var HtmlPreviewPlugin = class {
|
|
|
4256
4434
|
}
|
|
4257
4435
|
async render(ctx) {
|
|
4258
4436
|
const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
|
|
4259
|
-
const sanitized =
|
|
4437
|
+
const sanitized = DOMPurify6.sanitize(rawHtml, {
|
|
4260
4438
|
WHOLE_DOCUMENT: true,
|
|
4261
4439
|
ADD_TAGS: ["style", "link"],
|
|
4262
4440
|
ADD_ATTR: ["target", "rel"]
|
|
@@ -4522,14 +4700,97 @@ var OpenDocumentPlugin = class {
|
|
|
4522
4700
|
wrapper.textContent = contentDoc.documentElement.textContent || "Formula content";
|
|
4523
4701
|
}
|
|
4524
4702
|
} else {
|
|
4525
|
-
wrapper.style.maxWidth = "
|
|
4526
|
-
wrapper.style.padding = "
|
|
4703
|
+
wrapper.style.maxWidth = "none";
|
|
4704
|
+
wrapper.style.padding = "0";
|
|
4527
4705
|
wrapper.style.minHeight = "100%";
|
|
4706
|
+
wrapper.style.backgroundColor = "transparent";
|
|
4707
|
+
wrapper.style.boxShadow = "none";
|
|
4708
|
+
wrapper.style.position = "relative";
|
|
4709
|
+
const dims = this.getPageDimensions(stylesDoc, contentDoc);
|
|
4528
4710
|
const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
|
|
4529
|
-
|
|
4530
|
-
|
|
4711
|
+
const tempDiv = document.createElement("div");
|
|
4712
|
+
tempDiv.style.width = `${dims.width - dims.marginLeft - dims.marginRight}px`;
|
|
4713
|
+
tempDiv.style.position = "absolute";
|
|
4714
|
+
tempDiv.style.visibility = "hidden";
|
|
4715
|
+
tempDiv.innerHTML = DOMPurify6.sanitize(bodyHtml, {
|
|
4716
|
+
ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub", "hr"],
|
|
4531
4717
|
ADD_ATTR: ["style", "colspan", "rowspan"]
|
|
4532
4718
|
});
|
|
4719
|
+
document.body.appendChild(tempDiv);
|
|
4720
|
+
const contentHeight = dims.height - dims.marginTop - dims.marginBottom;
|
|
4721
|
+
const pageElements = [[]];
|
|
4722
|
+
let currentHeight = 0;
|
|
4723
|
+
let currentPageIdx = 0;
|
|
4724
|
+
Array.from(tempDiv.children).forEach((child) => {
|
|
4725
|
+
const el = child;
|
|
4726
|
+
const style = el.getAttribute("style") || "";
|
|
4727
|
+
const isBreakBefore = style.includes("page-break-before: always");
|
|
4728
|
+
const isBreakAfter = style.includes("page-break-after: always");
|
|
4729
|
+
const isSoftBreak = el.classList.contains("odf-page-break");
|
|
4730
|
+
if (isBreakBefore) {
|
|
4731
|
+
if (pageElements[currentPageIdx].length > 0) {
|
|
4732
|
+
currentPageIdx++;
|
|
4733
|
+
pageElements.push([]);
|
|
4734
|
+
currentHeight = 0;
|
|
4735
|
+
}
|
|
4736
|
+
}
|
|
4737
|
+
const h = el.offsetHeight || 0;
|
|
4738
|
+
if (currentHeight + h > contentHeight && pageElements[currentPageIdx].length > 0 && !isSoftBreak) {
|
|
4739
|
+
currentPageIdx++;
|
|
4740
|
+
pageElements.push([]);
|
|
4741
|
+
currentHeight = 0;
|
|
4742
|
+
}
|
|
4743
|
+
if (!isSoftBreak) {
|
|
4744
|
+
pageElements[currentPageIdx].push(el.cloneNode(true));
|
|
4745
|
+
currentHeight += h;
|
|
4746
|
+
}
|
|
4747
|
+
if (isBreakAfter || isSoftBreak) {
|
|
4748
|
+
currentPageIdx++;
|
|
4749
|
+
pageElements.push([]);
|
|
4750
|
+
currentHeight = 0;
|
|
4751
|
+
}
|
|
4752
|
+
});
|
|
4753
|
+
document.body.removeChild(tempDiv);
|
|
4754
|
+
if (pageElements.length > 1 && pageElements[pageElements.length - 1].length === 0) {
|
|
4755
|
+
pageElements.pop();
|
|
4756
|
+
}
|
|
4757
|
+
totalPages = Math.max(1, pageElements.length);
|
|
4758
|
+
pageElements.forEach((elements, idx) => {
|
|
4759
|
+
const page = document.createElement("div");
|
|
4760
|
+
page.className = `fp-odt-page fp-odt-page-${idx + 1}`;
|
|
4761
|
+
page.style.width = `${dims.width}px`;
|
|
4762
|
+
page.style.minHeight = `${dims.height}px`;
|
|
4763
|
+
page.style.padding = `${dims.marginTop}px ${dims.marginRight}px ${dims.marginBottom}px ${dims.marginLeft}px`;
|
|
4764
|
+
page.style.margin = "0 auto";
|
|
4765
|
+
page.style.backgroundColor = "#ffffff";
|
|
4766
|
+
page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
|
|
4767
|
+
page.style.borderRadius = "4px";
|
|
4768
|
+
page.style.boxSizing = "border-box";
|
|
4769
|
+
page.style.display = idx === 0 ? "block" : "none";
|
|
4770
|
+
page.style.position = "absolute";
|
|
4771
|
+
page.style.top = "0";
|
|
4772
|
+
page.style.left = "50%";
|
|
4773
|
+
page.style.transform = "translateX(-50%)";
|
|
4774
|
+
elements.forEach((el) => page.appendChild(el));
|
|
4775
|
+
wrapper.appendChild(page);
|
|
4776
|
+
slides.push(page);
|
|
4777
|
+
});
|
|
4778
|
+
const pageIndicator = document.createElement("div");
|
|
4779
|
+
pageIndicator.className = "fp-odt-page-indicator";
|
|
4780
|
+
pageIndicator.style.position = "sticky";
|
|
4781
|
+
pageIndicator.style.bottom = "16px";
|
|
4782
|
+
pageIndicator.style.left = "50%";
|
|
4783
|
+
pageIndicator.style.transform = "translateX(-50%)";
|
|
4784
|
+
pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
|
|
4785
|
+
pageIndicator.style.color = "#fff";
|
|
4786
|
+
pageIndicator.style.padding = "6px 12px";
|
|
4787
|
+
pageIndicator.style.borderRadius = "16px";
|
|
4788
|
+
pageIndicator.style.fontSize = "12px";
|
|
4789
|
+
pageIndicator.style.zIndex = "100";
|
|
4790
|
+
pageIndicator.style.display = "inline-block";
|
|
4791
|
+
pageIndicator.style.width = "fit-content";
|
|
4792
|
+
pageIndicator.textContent = `Page 1 of ${totalPages}`;
|
|
4793
|
+
container.appendChild(pageIndicator);
|
|
4533
4794
|
}
|
|
4534
4795
|
const cleanup = () => {
|
|
4535
4796
|
imageUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
@@ -4538,11 +4799,15 @@ var OpenDocumentPlugin = class {
|
|
|
4538
4799
|
};
|
|
4539
4800
|
ctx.signal.addEventListener("abort", cleanup);
|
|
4540
4801
|
const goToPage = (page) => {
|
|
4541
|
-
if (
|
|
4802
|
+
if (page < 1 || page > totalPages) return;
|
|
4542
4803
|
currentPage = page;
|
|
4543
4804
|
slides.forEach((s, idx) => {
|
|
4544
4805
|
s.style.display = idx === page - 1 ? "block" : "none";
|
|
4545
4806
|
});
|
|
4807
|
+
const indicator = container.querySelector(".fp-odt-page-indicator");
|
|
4808
|
+
if (indicator) {
|
|
4809
|
+
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4810
|
+
}
|
|
4546
4811
|
ctx.emit("page-change", { page: currentPage, total: totalPages });
|
|
4547
4812
|
};
|
|
4548
4813
|
return {
|
|
@@ -4611,6 +4876,43 @@ var OpenDocumentPlugin = class {
|
|
|
4611
4876
|
}
|
|
4612
4877
|
};
|
|
4613
4878
|
}
|
|
4879
|
+
getPageDimensions(stylesDoc, contentDoc) {
|
|
4880
|
+
let width = 850;
|
|
4881
|
+
let height = 1123;
|
|
4882
|
+
let marginTop = 48;
|
|
4883
|
+
let marginBottom = 48;
|
|
4884
|
+
let marginLeft = 48;
|
|
4885
|
+
let marginRight = 48;
|
|
4886
|
+
const parseUnit = (val) => {
|
|
4887
|
+
if (!val) return null;
|
|
4888
|
+
if (val.endsWith("cm")) return parseFloat(val) * 37.8;
|
|
4889
|
+
if (val.endsWith("mm")) return parseFloat(val) * 3.78;
|
|
4890
|
+
if (val.endsWith("in")) return parseFloat(val) * 96;
|
|
4891
|
+
if (val.endsWith("pt")) return parseFloat(val) * 1.33;
|
|
4892
|
+
if (val.endsWith("px")) return parseFloat(val);
|
|
4893
|
+
return parseFloat(val);
|
|
4894
|
+
};
|
|
4895
|
+
const docs = [stylesDoc, contentDoc].filter(Boolean);
|
|
4896
|
+
for (const doc of docs) {
|
|
4897
|
+
const pageLayout = doc.querySelector("page-layout-properties, [page-width]");
|
|
4898
|
+
if (pageLayout) {
|
|
4899
|
+
const w = parseUnit(pageLayout.getAttribute("fo:page-width") || pageLayout.getAttribute("page-width"));
|
|
4900
|
+
const h = parseUnit(pageLayout.getAttribute("fo:page-height") || pageLayout.getAttribute("page-height"));
|
|
4901
|
+
const mt = parseUnit(pageLayout.getAttribute("fo:margin-top") || pageLayout.getAttribute("margin-top"));
|
|
4902
|
+
const mb = parseUnit(pageLayout.getAttribute("fo:margin-bottom") || pageLayout.getAttribute("margin-bottom"));
|
|
4903
|
+
const ml = parseUnit(pageLayout.getAttribute("fo:margin-left") || pageLayout.getAttribute("margin-left"));
|
|
4904
|
+
const mr = parseUnit(pageLayout.getAttribute("fo:margin-right") || pageLayout.getAttribute("margin-right"));
|
|
4905
|
+
if (w !== null) width = w;
|
|
4906
|
+
if (h !== null) height = h;
|
|
4907
|
+
if (mt !== null) marginTop = mt;
|
|
4908
|
+
if (mb !== null) marginBottom = mb;
|
|
4909
|
+
if (ml !== null) marginLeft = ml;
|
|
4910
|
+
if (mr !== null) marginRight = mr;
|
|
4911
|
+
break;
|
|
4912
|
+
}
|
|
4913
|
+
}
|
|
4914
|
+
return { width, height, marginTop, marginBottom, marginLeft, marginRight };
|
|
4915
|
+
}
|
|
4614
4916
|
extractStyles(stylesDoc, contentDoc) {
|
|
4615
4917
|
const map = /* @__PURE__ */ new Map();
|
|
4616
4918
|
const styleNodes = [];
|
|
@@ -4633,14 +4935,21 @@ var OpenDocumentPlugin = class {
|
|
|
4633
4935
|
if (color) css += `color: ${color}; `;
|
|
4634
4936
|
if (size) css += `font-size: ${size}; `;
|
|
4635
4937
|
}
|
|
4636
|
-
|
|
4938
|
+
let paraProp = node.querySelector("paragraph-properties, [text-align]");
|
|
4939
|
+
if (!paraProp) {
|
|
4940
|
+
paraProp = Array.from(node.children).find((c) => c.tagName.includes("paragraph-properties")) || null;
|
|
4941
|
+
}
|
|
4637
4942
|
if (paraProp) {
|
|
4638
4943
|
const align = paraProp.getAttribute("fo:text-align") || paraProp.getAttribute("text-align");
|
|
4639
4944
|
const mt = paraProp.getAttribute("fo:margin-top") || paraProp.getAttribute("margin-top");
|
|
4640
4945
|
const mb = paraProp.getAttribute("fo:margin-bottom") || paraProp.getAttribute("margin-bottom");
|
|
4946
|
+
const breakBefore = paraProp.getAttribute("fo:break-before") || paraProp.getAttribute("break-before");
|
|
4947
|
+
const breakAfter = paraProp.getAttribute("fo:break-after") || paraProp.getAttribute("break-after");
|
|
4641
4948
|
if (align) css += `text-align: ${align}; `;
|
|
4642
4949
|
if (mt) css += `margin-top: ${mt}; `;
|
|
4643
4950
|
if (mb) css += `margin-bottom: ${mb}; `;
|
|
4951
|
+
if (breakBefore === "page") css += "page-break-before: always; ";
|
|
4952
|
+
if (breakAfter === "page") css += "page-break-after: always; ";
|
|
4644
4953
|
}
|
|
4645
4954
|
if (css) map.set(name, css);
|
|
4646
4955
|
}
|
|
@@ -4725,6 +5034,8 @@ var OpenDocumentPlugin = class {
|
|
|
4725
5034
|
result += " ";
|
|
4726
5035
|
} else if (tag === "line-break") {
|
|
4727
5036
|
result += "<br/>";
|
|
5037
|
+
} else if (tag === "soft-page-break") {
|
|
5038
|
+
result += '<hr class="odf-page-break" style="page-break-after: always; border: none; margin: 0; padding: 0; height: 0;" />';
|
|
4728
5039
|
} else {
|
|
4729
5040
|
result += el.textContent || "";
|
|
4730
5041
|
}
|
|
@@ -4885,20 +5196,9 @@ var DocPlugin = class {
|
|
|
4885
5196
|
container.style.overflow = "auto";
|
|
4886
5197
|
container.style.padding = "32px 16px";
|
|
4887
5198
|
container.style.backgroundColor = "#f1f5f9";
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
wrapper.style.margin = "0 auto";
|
|
4892
|
-
wrapper.style.backgroundColor = "#ffffff";
|
|
4893
|
-
wrapper.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4894
|
-
wrapper.style.borderRadius = "4px";
|
|
4895
|
-
wrapper.style.padding = "56px 48px";
|
|
4896
|
-
wrapper.style.minHeight = "100%";
|
|
4897
|
-
wrapper.style.transformOrigin = "top center";
|
|
4898
|
-
wrapper.style.transition = "transform 0.2s ease";
|
|
4899
|
-
wrapper.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
4900
|
-
wrapper.style.color = "#1e293b";
|
|
4901
|
-
container.appendChild(wrapper);
|
|
5199
|
+
container.style.display = "flex";
|
|
5200
|
+
container.style.justifyContent = "center";
|
|
5201
|
+
container.style.alignItems = "flex-start";
|
|
4902
5202
|
ctx.container.appendChild(container);
|
|
4903
5203
|
let scale = 1;
|
|
4904
5204
|
let extractedRawText = "";
|
|
@@ -4925,21 +5225,27 @@ var DocPlugin = class {
|
|
|
4925
5225
|
const rawPages = this.splitIntoPages(extractedRawText);
|
|
4926
5226
|
const totalPages = Math.max(1, rawPages.length);
|
|
4927
5227
|
let currentPage = 1;
|
|
4928
|
-
wrapper.innerHTML = "";
|
|
4929
5228
|
const pageCards = [];
|
|
4930
5229
|
for (let i = 0; i < totalPages; i++) {
|
|
4931
5230
|
const pageCard = document.createElement("div");
|
|
4932
5231
|
pageCard.className = "fp-doc-page-card";
|
|
5232
|
+
pageCard.style.width = "816px";
|
|
5233
|
+
pageCard.style.height = "1056px";
|
|
4933
5234
|
pageCard.style.backgroundColor = "#ffffff";
|
|
4934
5235
|
pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
|
|
4935
5236
|
pageCard.style.borderRadius = "4px";
|
|
4936
|
-
pageCard.style.padding = "
|
|
4937
|
-
pageCard.style.
|
|
5237
|
+
pageCard.style.padding = "96px 72px";
|
|
5238
|
+
pageCard.style.boxSizing = "border-box";
|
|
5239
|
+
pageCard.style.overflow = "hidden";
|
|
4938
5240
|
pageCard.style.display = i === 0 ? "block" : "none";
|
|
5241
|
+
pageCard.style.transformOrigin = "top center";
|
|
5242
|
+
pageCard.style.transition = "transform 0.2s ease";
|
|
5243
|
+
pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
|
|
5244
|
+
pageCard.style.color = "#1e293b";
|
|
4939
5245
|
if (isFallback && i === 0) {
|
|
4940
5246
|
pageCard.innerHTML = `
|
|
4941
5247
|
<div style="border-bottom: 1px solid #e2e8f0; padding-bottom: 12px; margin-bottom: 24px;">
|
|
4942
|
-
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${
|
|
5248
|
+
<h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify6.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
|
|
4943
5249
|
<span style="font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 4px;">Legacy Word 97-2003 Binary Preview</span>
|
|
4944
5250
|
</div>
|
|
4945
5251
|
${this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document")}
|
|
@@ -4947,15 +5253,17 @@ var DocPlugin = class {
|
|
|
4947
5253
|
} else {
|
|
4948
5254
|
pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
|
|
4949
5255
|
}
|
|
4950
|
-
|
|
5256
|
+
container.appendChild(pageCard);
|
|
4951
5257
|
pageCards.push(pageCard);
|
|
4952
5258
|
}
|
|
4953
5259
|
let indicator = null;
|
|
4954
5260
|
if (totalPages > 1) {
|
|
4955
5261
|
indicator = document.createElement("div");
|
|
4956
5262
|
indicator.className = "fp-doc-page-indicator";
|
|
4957
|
-
indicator.style.position = "
|
|
5263
|
+
indicator.style.position = "fixed";
|
|
4958
5264
|
indicator.style.bottom = "16px";
|
|
5265
|
+
indicator.style.left = "50%";
|
|
5266
|
+
indicator.style.transform = "translateX(-50%)";
|
|
4959
5267
|
indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
|
|
4960
5268
|
indicator.style.backdropFilter = "blur(8px)";
|
|
4961
5269
|
indicator.style.color = "#f8fafc";
|
|
@@ -4969,17 +5277,25 @@ var DocPlugin = class {
|
|
|
4969
5277
|
indicator.style.userSelect = "none";
|
|
4970
5278
|
indicator.style.pointerEvents = "none";
|
|
4971
5279
|
indicator.style.textAlign = "center";
|
|
4972
|
-
indicator.style.width = "fit-content";
|
|
4973
|
-
indicator.style.margin = "16px auto 0";
|
|
4974
5280
|
container.appendChild(indicator);
|
|
4975
5281
|
}
|
|
5282
|
+
let rotation = 0;
|
|
5283
|
+
const applyTransform = () => {
|
|
5284
|
+
const activeCard = pageCards[currentPage - 1];
|
|
5285
|
+
if (activeCard) {
|
|
5286
|
+
activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5287
|
+
}
|
|
5288
|
+
};
|
|
4976
5289
|
const showPage = (pageNum) => {
|
|
4977
5290
|
currentPage = Math.max(1, Math.min(totalPages, pageNum));
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
card.style.display =
|
|
4981
|
-
|
|
4982
|
-
|
|
5291
|
+
pageCards.forEach((card, idx) => {
|
|
5292
|
+
if (idx + 1 === currentPage) {
|
|
5293
|
+
card.style.display = "block";
|
|
5294
|
+
card.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5295
|
+
} else {
|
|
5296
|
+
card.style.display = "none";
|
|
5297
|
+
}
|
|
5298
|
+
});
|
|
4983
5299
|
if (indicator) {
|
|
4984
5300
|
indicator.textContent = `Page ${currentPage} of ${totalPages}`;
|
|
4985
5301
|
}
|
|
@@ -4988,19 +5304,13 @@ var DocPlugin = class {
|
|
|
4988
5304
|
if (totalPages > 1) {
|
|
4989
5305
|
showPage(1);
|
|
4990
5306
|
}
|
|
4991
|
-
let rotation = 0;
|
|
4992
5307
|
const calculateFitScale = () => {
|
|
4993
|
-
const
|
|
4994
|
-
const
|
|
4995
|
-
const elH = activeCard.offsetHeight || 1e3;
|
|
5308
|
+
const elW = 816;
|
|
5309
|
+
const elH = 1056;
|
|
4996
5310
|
const availW = Math.max(200, ctx.container.clientWidth - 48);
|
|
4997
5311
|
const availH = Math.max(200, ctx.container.clientHeight - 80);
|
|
4998
5312
|
return Math.min(1.1, Math.min(availW / elW, availH / elH));
|
|
4999
5313
|
};
|
|
5000
|
-
const applyTransform = () => {
|
|
5001
|
-
wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
|
|
5002
|
-
wrapper.style.transformOrigin = "top center";
|
|
5003
|
-
};
|
|
5004
5314
|
setTimeout(() => {
|
|
5005
5315
|
scale = calculateFitScale();
|
|
5006
5316
|
applyTransform();
|
|
@@ -5158,8 +5468,28 @@ var DocPlugin = class {
|
|
|
5158
5468
|
}
|
|
5159
5469
|
splitIntoPages(text) {
|
|
5160
5470
|
if (!text) return [""];
|
|
5161
|
-
const
|
|
5162
|
-
|
|
5471
|
+
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);
|
|
5472
|
+
if (explicitParts.length === 0) explicitParts.push(text);
|
|
5473
|
+
const maxLinesPerPage = 48;
|
|
5474
|
+
const finalPages = [];
|
|
5475
|
+
for (const part of explicitParts) {
|
|
5476
|
+
const lines = part.split(/\r?\n/);
|
|
5477
|
+
let currentLines = [];
|
|
5478
|
+
let count = 0;
|
|
5479
|
+
for (const line of lines) {
|
|
5480
|
+
currentLines.push(line);
|
|
5481
|
+
count++;
|
|
5482
|
+
if (count >= maxLinesPerPage) {
|
|
5483
|
+
finalPages.push(currentLines.join("\n"));
|
|
5484
|
+
currentLines = [];
|
|
5485
|
+
count = 0;
|
|
5486
|
+
}
|
|
5487
|
+
}
|
|
5488
|
+
if (currentLines.length > 0) {
|
|
5489
|
+
finalPages.push(currentLines.join("\n"));
|
|
5490
|
+
}
|
|
5491
|
+
}
|
|
5492
|
+
return finalPages.length > 0 ? finalPages : [text];
|
|
5163
5493
|
}
|
|
5164
5494
|
/**
|
|
5165
5495
|
* Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
|
|
@@ -5168,17 +5498,65 @@ var DocPlugin = class {
|
|
|
5168
5498
|
const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
|
|
5169
5499
|
let html = "";
|
|
5170
5500
|
let inList = false;
|
|
5171
|
-
|
|
5172
|
-
|
|
5501
|
+
let tableLines = [];
|
|
5502
|
+
const flushTable = () => {
|
|
5503
|
+
if (tableLines.length > 0) {
|
|
5504
|
+
html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
|
|
5505
|
+
for (const tLine of tableLines) {
|
|
5506
|
+
html += "<tr>";
|
|
5507
|
+
const cols = tLine.split(" ");
|
|
5508
|
+
for (const col of cols) {
|
|
5509
|
+
html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6.sanitize(col.trim())}</td>`;
|
|
5510
|
+
}
|
|
5511
|
+
html += "</tr>";
|
|
5512
|
+
}
|
|
5513
|
+
html += "</table>";
|
|
5514
|
+
tableLines = [];
|
|
5515
|
+
}
|
|
5516
|
+
};
|
|
5517
|
+
let i = 0;
|
|
5518
|
+
while (i < lines.length) {
|
|
5519
|
+
let line = lines[i];
|
|
5520
|
+
let tabCount = (line.match(/\t/g) || []).length;
|
|
5521
|
+
if (tabCount > 0) {
|
|
5522
|
+
let consecutiveTableLines = 1;
|
|
5523
|
+
let j = i + 1;
|
|
5524
|
+
while (j < lines.length) {
|
|
5525
|
+
const nextTabCount = (lines[j].match(/\t/g) || []).length;
|
|
5526
|
+
if (nextTabCount === tabCount) {
|
|
5527
|
+
consecutiveTableLines++;
|
|
5528
|
+
j++;
|
|
5529
|
+
} else {
|
|
5530
|
+
break;
|
|
5531
|
+
}
|
|
5532
|
+
}
|
|
5533
|
+
if (consecutiveTableLines >= 3) {
|
|
5534
|
+
if (inList) {
|
|
5535
|
+
html += "</ul>";
|
|
5536
|
+
inList = false;
|
|
5537
|
+
}
|
|
5538
|
+
tableLines = lines.slice(i, j);
|
|
5539
|
+
flushTable();
|
|
5540
|
+
i = j;
|
|
5541
|
+
continue;
|
|
5542
|
+
}
|
|
5543
|
+
}
|
|
5544
|
+
line = line.trim();
|
|
5173
5545
|
if (!line) {
|
|
5174
5546
|
if (inList) {
|
|
5175
5547
|
html += "</ul>";
|
|
5176
5548
|
inList = false;
|
|
5177
5549
|
}
|
|
5550
|
+
html += '<div style="height: 1.15em;"></div>';
|
|
5551
|
+
i++;
|
|
5552
|
+
continue;
|
|
5553
|
+
}
|
|
5554
|
+
if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line)) {
|
|
5555
|
+
i++;
|
|
5178
5556
|
continue;
|
|
5179
5557
|
}
|
|
5180
|
-
if (
|
|
5181
|
-
|
|
5558
|
+
if ((line.includes("Normal.dot") || line.includes("Microsoft Word") || line.includes("Times New Roman")) && line.length < 30) {
|
|
5559
|
+
i++;
|
|
5182
5560
|
continue;
|
|
5183
5561
|
}
|
|
5184
5562
|
if (line.length < 60 && !line.endsWith(".") && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#"))) {
|
|
@@ -5186,24 +5564,26 @@ var DocPlugin = class {
|
|
|
5186
5564
|
html += "</ul>";
|
|
5187
5565
|
inList = false;
|
|
5188
5566
|
}
|
|
5189
|
-
html += `<h2 style="font-size:
|
|
5567
|
+
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>`;
|
|
5190
5568
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
5191
5569
|
if (!inList) {
|
|
5192
5570
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
5193
5571
|
inList = true;
|
|
5194
5572
|
}
|
|
5195
5573
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
5196
|
-
html += `<li style="margin: 4px 0; line-height: 1.
|
|
5574
|
+
html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6.sanitize(bulletText)}</li>`;
|
|
5197
5575
|
} else {
|
|
5198
5576
|
if (inList) {
|
|
5199
5577
|
html += "</ul>";
|
|
5200
5578
|
inList = false;
|
|
5201
5579
|
}
|
|
5202
|
-
html += `<p style="line-height: 1.
|
|
5580
|
+
html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6.sanitize(line)}</p>`;
|
|
5203
5581
|
}
|
|
5582
|
+
i++;
|
|
5204
5583
|
}
|
|
5205
5584
|
if (inList) html += "</ul>";
|
|
5206
|
-
|
|
5585
|
+
flushTable();
|
|
5586
|
+
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6.sanitize(filename)})</p>`;
|
|
5207
5587
|
}
|
|
5208
5588
|
};
|
|
5209
5589
|
function docPlugin() {
|
|
@@ -5381,7 +5761,7 @@ var PptPlugin = class {
|
|
|
5381
5761
|
if (s.pictureUrl) {
|
|
5382
5762
|
contentHtml = `
|
|
5383
5763
|
<div style="flex: 1; display: flex; justify-content: center; align-items: center; padding: 12px; overflow: hidden;">
|
|
5384
|
-
<img src="${s.pictureUrl}" alt="${
|
|
5764
|
+
<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;" />
|
|
5385
5765
|
</div>
|
|
5386
5766
|
`;
|
|
5387
5767
|
} else if (s.tableColumns.length > 0) {
|
|
@@ -5391,7 +5771,7 @@ var PptPlugin = class {
|
|
|
5391
5771
|
<table style="width: 100%; border-collapse: collapse; border: 1px solid #cbd5e1; border-radius: 6px; overflow: hidden; background: #ffffff;">
|
|
5392
5772
|
<thead>
|
|
5393
5773
|
<tr style="background: #e2e8f0; color: #1e293b; font-weight: 600; font-size: 14px;">
|
|
5394
|
-
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${
|
|
5774
|
+
${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${DOMPurify6.sanitize(c)}</th>`).join("")}
|
|
5395
5775
|
</tr>
|
|
5396
5776
|
</thead>
|
|
5397
5777
|
<tbody>
|
|
@@ -5407,7 +5787,7 @@ var PptPlugin = class {
|
|
|
5407
5787
|
} else {
|
|
5408
5788
|
const pTags = s.paragraphs.map((p) => {
|
|
5409
5789
|
const lines = p.split(/[\r\n]+/).map((l) => l.trim()).filter(Boolean);
|
|
5410
|
-
return lines.map((l) => `<p style="margin: 0 0 14px; font-size: 14px; line-height: 1.65; color: #334155; text-align: justify;">${
|
|
5790
|
+
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("");
|
|
5411
5791
|
}).join("");
|
|
5412
5792
|
contentHtml = `
|
|
5413
5793
|
<div style="flex: 1; overflow: auto; padding: 4px 8px; display: flex; flex-direction: column; justify-content: flex-start;">
|
|
@@ -5420,11 +5800,11 @@ var PptPlugin = class {
|
|
|
5420
5800
|
<!-- Header Banner matching PowerPoint design -->
|
|
5421
5801
|
<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;">
|
|
5422
5802
|
<h1 style="margin: 0; font-size: 26px; font-weight: 700; color: #1e293b; letter-spacing: -0.3px;">
|
|
5423
|
-
${
|
|
5803
|
+
${DOMPurify6.sanitize(s.title)}
|
|
5424
5804
|
</h1>
|
|
5425
5805
|
${s.subtitle ? `
|
|
5426
5806
|
<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);">
|
|
5427
|
-
${
|
|
5807
|
+
${DOMPurify6.sanitize(s.subtitle)}
|
|
5428
5808
|
</span>
|
|
5429
5809
|
` : `
|
|
5430
5810
|
<span style="font-size: 12px; color: #365314; font-weight: 600;">
|