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