@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 CHANGED
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var core = require('@angular/core');
6
6
  var common = require('@angular/common');
7
- var DOMPurify2 = require('dompurify');
7
+ var DOMPurify6 = require('dompurify');
8
8
  var pdfjsLib = require('pdfjs-dist');
9
9
  var docx = require('docx-preview');
10
10
  var fflate = require('fflate');
@@ -38,7 +38,7 @@ function _interopNamespace(e) {
38
38
  return Object.freeze(n);
39
39
  }
40
40
 
41
- var DOMPurify2__default = /*#__PURE__*/_interopDefault(DOMPurify2);
41
+ var DOMPurify6__default = /*#__PURE__*/_interopDefault(DOMPurify6);
42
42
  var pdfjsLib__namespace = /*#__PURE__*/_interopNamespace(pdfjsLib);
43
43
  var docx__namespace = /*#__PURE__*/_interopNamespace(docx);
44
44
  var XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
@@ -437,7 +437,7 @@ async function sourceToArrayBuffer(source, signal) {
437
437
  if (magicMime === "application/zip") {
438
438
  const ooxmlMime = detectOoxmlType(buffer);
439
439
  if (ooxmlMime && ooxmlMime !== "application/zip") {
440
- metadata.mimeType = ooxmlMime;
440
+ metadata.mimeType = metadata.mimeType ?? ooxmlMime;
441
441
  if (ooxmlMime.includes("wordprocessing")) metadata.extension = metadata.extension ?? ".docx";
442
442
  else if (ooxmlMime.includes("spreadsheet")) metadata.extension = metadata.extension ?? ".xlsx";
443
443
  else if (ooxmlMime.includes("presentation")) metadata.extension = metadata.extension ?? ".pptx";
@@ -466,7 +466,7 @@ async function sourceToArrayBuffer(source, signal) {
466
466
  return { buffer, metadata };
467
467
  }
468
468
  function sanitizeSVG(svg) {
469
- return DOMPurify2__default.default.sanitize(svg, {
469
+ return DOMPurify6__default.default.sanitize(svg, {
470
470
  USE_PROFILES: { svg: true, svgFilters: true }
471
471
  });
472
472
  }
@@ -1528,7 +1528,19 @@ var PdfPlugin = class {
1528
1528
  }
1529
1529
  };
1530
1530
  await renderPage(1);
1531
+ let resizeTimer = null;
1532
+ const resizeObserver = new ResizeObserver(() => {
1533
+ if (resizeTimer) clearTimeout(resizeTimer);
1534
+ resizeTimer = setTimeout(() => {
1535
+ if (Math.abs(zoomScale - 1) < 0.05) {
1536
+ renderPage(currentPage);
1537
+ }
1538
+ }, 150);
1539
+ });
1540
+ resizeObserver.observe(container);
1531
1541
  const cleanup = () => {
1542
+ resizeObserver.disconnect();
1543
+ if (resizeTimer) clearTimeout(resizeTimer);
1532
1544
  if (currentRenderTask) {
1533
1545
  try {
1534
1546
  currentRenderTask.cancel();
@@ -2276,90 +2288,149 @@ var DocxPlugin = class {
2276
2288
  console.warn("[DocxPlugin] Error parsing relationships:", relsErr);
2277
2289
  }
2278
2290
  }
2279
- const card = document.createElement("div");
2280
- card.className = "fp-docx-page-card";
2281
- card.style.backgroundColor = "#ffffff";
2282
- card.style.borderRadius = "6px";
2283
- card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
2284
- card.style.padding = "48px 56px";
2285
- card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
2286
- card.style.color = "#1e293b";
2287
- card.style.lineHeight = "1.6";
2291
+ const sectPrs = Array.from(doc.getElementsByTagNameNS("*", "sectPr"));
2292
+ const lastSectPr = sectPrs[sectPrs.length - 1];
2293
+ let defaultW = 12240;
2294
+ let defaultH = 15840;
2295
+ let margins = { top: 1440, right: 1440, bottom: 1440, left: 1440 };
2296
+ if (lastSectPr) {
2297
+ const pgSz = lastSectPr.getElementsByTagNameNS("*", "pgSz")[0];
2298
+ if (pgSz) {
2299
+ defaultW = parseInt(pgSz.getAttribute("w:w") || pgSz.getAttribute("w") || "12240", 10);
2300
+ defaultH = parseInt(pgSz.getAttribute("w:h") || pgSz.getAttribute("h") || "15840", 10);
2301
+ }
2302
+ const pgMar = lastSectPr.getElementsByTagNameNS("*", "pgMar")[0];
2303
+ if (pgMar) {
2304
+ margins.top = parseInt(pgMar.getAttribute("w:top") || pgMar.getAttribute("top") || "1440", 10);
2305
+ margins.bottom = parseInt(pgMar.getAttribute("w:bottom") || pgMar.getAttribute("bottom") || "1440", 10);
2306
+ margins.left = parseInt(pgMar.getAttribute("w:left") || pgMar.getAttribute("left") || "1440", 10);
2307
+ margins.right = parseInt(pgMar.getAttribute("w:right") || pgMar.getAttribute("right") || "1440", 10);
2308
+ }
2309
+ }
2310
+ const createPageCard = () => {
2311
+ const card = document.createElement("div");
2312
+ card.className = "fp-docx-page-card";
2313
+ card.style.backgroundColor = "#ffffff";
2314
+ card.style.borderRadius = "4px";
2315
+ card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
2316
+ card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
2317
+ card.style.color = "#1e293b";
2318
+ card.style.lineHeight = "1.6";
2319
+ card.style.boxSizing = "border-box";
2320
+ card.style.overflow = "hidden";
2321
+ card.style.position = "relative";
2322
+ card.style.marginBottom = "24px";
2323
+ card.style.width = `${defaultW / 15}px`;
2324
+ card.style.height = `${defaultH / 15}px`;
2325
+ card.style.padding = `${margins.top / 15}px ${margins.right / 15}px ${margins.bottom / 15}px ${margins.left / 15}px`;
2326
+ return card;
2327
+ };
2328
+ let currentCard = createPageCard();
2329
+ let currentHtml = "";
2330
+ const pages = [{ card: currentCard, html: "" }];
2331
+ const flushHtml = () => {
2332
+ pages[pages.length - 1].html += currentHtml;
2333
+ currentHtml = "";
2334
+ };
2335
+ const newPage = () => {
2336
+ flushHtml();
2337
+ currentCard = createPageCard();
2338
+ pages.push({ card: currentCard, html: "" });
2339
+ };
2288
2340
  const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
2289
- let html = "";
2290
2341
  for (const child of Array.from(body.children)) {
2291
2342
  const tag = child.localName || child.nodeName.split(":").pop();
2292
2343
  if (tag === "p") {
2293
2344
  const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
2294
2345
  const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
2295
2346
  const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
2296
- const textContent = this.extractParagraphHtml(child, imageMap);
2297
- if (!textContent.trim()) {
2298
- html += '<div style="height: 10px;"></div>';
2299
- continue;
2300
- }
2301
- const lowerStyle = styleVal.toLowerCase();
2302
- if (lowerStyle.includes("title")) {
2303
- html += `<h1 style="font-size: 28px; font-weight: 700; color: #1e3a8a; margin: 24px 0 12px; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px;">${textContent}</h1>`;
2304
- } else if (lowerStyle.includes("heading1") || styleVal === "1") {
2305
- html += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
2306
- } else if (lowerStyle.includes("heading2") || styleVal === "2") {
2307
- html += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
2308
- } else if (lowerStyle.includes("heading3") || styleVal === "3") {
2309
- html += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
2310
- } else if (numPr) {
2311
- html += `<div style="display: flex; gap: 8px; margin: 4px 0 4px 20px;"><span style="color: #2563eb; font-weight: bold;">\u2022</span><span>${textContent}</span></div>`;
2312
- } else {
2313
- html += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
2347
+ const chunks = this.extractParagraphChunks(child, imageMap);
2348
+ for (let i = 0; i < chunks.length; i++) {
2349
+ if (i > 0) {
2350
+ newPage();
2351
+ }
2352
+ const textContent = chunks[i];
2353
+ if (!textContent.trim() && !textContent.includes("<img")) {
2354
+ currentHtml += '<div style="height: 10px;"></div>';
2355
+ continue;
2356
+ }
2357
+ const lowerStyle = styleVal.toLowerCase();
2358
+ if (lowerStyle.includes("title")) {
2359
+ 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>`;
2360
+ } else if (lowerStyle.includes("heading1") || styleVal === "1") {
2361
+ currentHtml += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
2362
+ } else if (lowerStyle.includes("heading2") || styleVal === "2") {
2363
+ currentHtml += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
2364
+ } else if (lowerStyle.includes("heading3") || styleVal === "3") {
2365
+ currentHtml += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
2366
+ } else if (numPr) {
2367
+ 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>`;
2368
+ } else {
2369
+ currentHtml += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
2370
+ }
2314
2371
  }
2315
2372
  } else if (tag === "tbl") {
2316
- html += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
2373
+ currentHtml += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
2317
2374
  const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
2318
2375
  rows.forEach((tr, rIdx) => {
2319
- html += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
2376
+ currentHtml += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
2320
2377
  const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
2321
2378
  cells.forEach((tc) => {
2322
2379
  const cellText = this.extractParagraphHtml(tc, imageMap);
2323
- html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || "&nbsp;"}</td>`;
2380
+ currentHtml += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || "&nbsp;"}</td>`;
2324
2381
  });
2325
- html += "</tr>";
2382
+ currentHtml += "</tr>";
2326
2383
  });
2327
- html += "</table>";
2384
+ currentHtml += "</table>";
2328
2385
  }
2329
2386
  }
2330
- card.innerHTML = DOMPurify2__default.default.sanitize(html, {
2331
- ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
2332
- ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
2333
- });
2334
- wrapper.appendChild(card);
2387
+ flushHtml();
2388
+ for (const page of pages) {
2389
+ page.card.innerHTML = DOMPurify6__default.default.sanitize(page.html, {
2390
+ ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
2391
+ ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
2392
+ });
2393
+ wrapper.appendChild(page.card);
2394
+ }
2335
2395
  }
2336
2396
  extractParagraphHtml(pElement, imageMap = {}) {
2337
- let result = "";
2397
+ return this.extractParagraphChunks(pElement, imageMap).join("<br/>");
2398
+ }
2399
+ extractParagraphChunks(pElement, imageMap = {}) {
2400
+ const chunks = [""];
2401
+ let currentChunkIndex = 0;
2338
2402
  const drawings = Array.from(pElement.getElementsByTagNameNS("*", "drawing"));
2339
2403
  for (const drawing of drawings) {
2340
2404
  const blip = drawing.getElementsByTagNameNS("*", "blip")[0];
2341
2405
  const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
2342
2406
  if (rId && imageMap[rId]) {
2343
- result += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
2407
+ chunks[currentChunkIndex] += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
2344
2408
  }
2345
2409
  }
2346
2410
  const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
2347
- if (runs.length === 0 && !result) {
2348
- return DOMPurify2__default.default.sanitize(pElement.textContent || "");
2411
+ if (runs.length === 0 && !chunks[currentChunkIndex]) {
2412
+ chunks[currentChunkIndex] = DOMPurify6__default.default.sanitize(pElement.textContent || "");
2413
+ return chunks;
2349
2414
  }
2350
2415
  for (const r of runs) {
2351
2416
  const blip = r.getElementsByTagNameNS("*", "blip")[0] || r.getElementsByTagNameNS("*", "imagedata")[0];
2352
2417
  const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
2353
2418
  if (rId && imageMap[rId]) {
2354
- result += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
2419
+ chunks[currentChunkIndex] += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
2355
2420
  }
2356
- const brs = r.getElementsByTagNameNS("*", "br");
2357
- for (let i = 0; i < brs.length; i++) {
2358
- result += "<br/>";
2421
+ const brs = Array.from(r.getElementsByTagNameNS("*", "br"));
2422
+ for (const br of brs) {
2423
+ const type = br.getAttribute("w:type") || br.getAttribute("type");
2424
+ if (type === "page") {
2425
+ chunks.push("");
2426
+ currentChunkIndex++;
2427
+ } else {
2428
+ chunks[currentChunkIndex] += "<br/>";
2429
+ }
2359
2430
  }
2360
2431
  const tabs = r.getElementsByTagNameNS("*", "tab");
2361
2432
  if (tabs.length > 0) {
2362
- result += "&emsp;";
2433
+ chunks[currentChunkIndex] += "&emsp;";
2363
2434
  }
2364
2435
  const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
2365
2436
  const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
@@ -2373,7 +2444,7 @@ var DocxPlugin = class {
2373
2444
  const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
2374
2445
  let text = texts.map((t) => t.textContent || "").join("");
2375
2446
  if (!text) continue;
2376
- text = DOMPurify2__default.default.sanitize(text);
2447
+ text = DOMPurify6__default.default.sanitize(text);
2377
2448
  let styles = "";
2378
2449
  if (isBold) styles += "font-weight: bold; ";
2379
2450
  if (isItalic) styles += "font-style: italic; ";
@@ -2385,12 +2456,12 @@ var DocxPlugin = class {
2385
2456
  if (!isNaN(pt) && pt > 0) styles += `font-size: ${pt}pt; `;
2386
2457
  }
2387
2458
  if (styles) {
2388
- result += `<span style="${styles}">${text}</span>`;
2459
+ chunks[currentChunkIndex] += `<span style="${styles}">${text}</span>`;
2389
2460
  } else {
2390
- result += text;
2461
+ chunks[currentChunkIndex] += text;
2391
2462
  }
2392
2463
  }
2393
- return result;
2464
+ return chunks;
2394
2465
  }
2395
2466
  renderBinaryDocFallback(ctx, wrapper) {
2396
2467
  const card = document.createElement("div");
@@ -2407,14 +2478,14 @@ var DocxPlugin = class {
2407
2478
  const wordDocStream = cfbf.readStream("WordDocument");
2408
2479
  if (wordDocStream && wordDocStream.length >= 512) {
2409
2480
  const text2 = this.extractReadableStrings(wordDocStream);
2410
- card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify2__default.default.sanitize(text2)}</div>`;
2481
+ card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text2)}</div>`;
2411
2482
  wrapper.appendChild(card);
2412
2483
  return;
2413
2484
  }
2414
2485
  } catch {
2415
2486
  }
2416
2487
  const text = this.extractReadableStrings(new Uint8Array(ctx.buffer));
2417
- card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify2__default.default.sanitize(text)}</div>`;
2488
+ card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text)}</div>`;
2418
2489
  wrapper.appendChild(card);
2419
2490
  }
2420
2491
  extractReadableStrings(bytes) {
@@ -3013,41 +3084,94 @@ var CodePlugin = class {
3013
3084
  async render(ctx) {
3014
3085
  const decoder = new TextDecoder("utf-8");
3015
3086
  const fullText = decoder.decode(ctx.buffer);
3016
- const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
3017
- const rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
3087
+ const extRaw = ctx.metadata.extension?.toLowerCase();
3088
+ const mimeRaw = ctx.metadata.mimeType?.toLowerCase();
3089
+ const isTxt = extRaw === ".txt" || mimeRaw === "text/plain" && (!extRaw || !this.extensions.filter((e) => e !== ".txt").includes(extRaw));
3090
+ let rawPages = [];
3091
+ if (isTxt) {
3092
+ const explicitPages = fullText.split(/(?:\f|\x0C)/);
3093
+ for (const ep of explicitPages) {
3094
+ const lines = ep.split(/\r?\n/);
3095
+ let currentChunk = [];
3096
+ for (let i = 0; i < lines.length; i++) {
3097
+ currentChunk.push(lines[i]);
3098
+ if (currentChunk.length >= 46) {
3099
+ rawPages.push(currentChunk.join("\n"));
3100
+ currentChunk = [];
3101
+ }
3102
+ }
3103
+ if (currentChunk.length > 0 || lines.length === 0) {
3104
+ rawPages.push(currentChunk.join("\n"));
3105
+ }
3106
+ }
3107
+ if (rawPages.length === 0) rawPages = [""];
3108
+ } else {
3109
+ const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
3110
+ rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
3111
+ }
3018
3112
  const totalPages = Math.max(1, rawPages.length);
3019
3113
  let currentPage = 1;
3020
3114
  const container = document.createElement("div");
3021
3115
  container.style.width = "100%";
3022
3116
  container.style.height = "100%";
3023
3117
  container.style.overflow = "auto";
3024
- container.style.backgroundColor = "#1e1e1e";
3025
- container.style.color = "#d4d4d4";
3026
- container.style.padding = "16px";
3027
- container.style.boxSizing = "border-box";
3028
3118
  let fontSize = 13;
3029
3119
  let rotation = 0;
3120
+ let zoomLevel = 1;
3030
3121
  const pre = document.createElement("pre");
3031
- pre.style.margin = "0";
3032
- pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
3033
- pre.style.fontSize = `${fontSize}px`;
3034
- pre.style.lineHeight = "1.5";
3035
- pre.style.whiteSpace = "pre-wrap";
3036
- pre.style.wordBreak = "break-all";
3037
3122
  const code = document.createElement("code");
3123
+ if (isTxt) {
3124
+ container.style.backgroundColor = "#f1f5f9";
3125
+ container.style.padding = "32px";
3126
+ container.style.boxSizing = "border-box";
3127
+ container.style.display = "flex";
3128
+ container.style.flexDirection = "column";
3129
+ container.style.alignItems = "center";
3130
+ pre.style.margin = "0";
3131
+ pre.style.fontFamily = "Consolas, 'Courier New', monospace";
3132
+ pre.style.fontSize = "13px";
3133
+ pre.style.color = "#1e293b";
3134
+ pre.style.lineHeight = "1.5";
3135
+ pre.style.whiteSpace = "pre-wrap";
3136
+ pre.style.wordBreak = "break-word";
3137
+ pre.style.backgroundColor = "#ffffff";
3138
+ pre.style.width = "816px";
3139
+ pre.style.minHeight = "1056px";
3140
+ pre.style.padding = "72px 56px";
3141
+ pre.style.boxSizing = "border-box";
3142
+ pre.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)";
3143
+ pre.style.borderRadius = "4px";
3144
+ pre.style.transformOrigin = "top center";
3145
+ } else {
3146
+ container.style.backgroundColor = "#1e1e1e";
3147
+ container.style.color = "#d4d4d4";
3148
+ container.style.padding = "16px";
3149
+ container.style.boxSizing = "border-box";
3150
+ pre.style.margin = "0";
3151
+ pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
3152
+ pre.style.fontSize = `${fontSize}px`;
3153
+ pre.style.lineHeight = "1.5";
3154
+ pre.style.whiteSpace = "pre-wrap";
3155
+ pre.style.wordBreak = "break-all";
3156
+ pre.style.transformOrigin = "top left";
3157
+ }
3038
3158
  const ext = (ctx.metadata.extension || "").replace(".", "");
3039
3159
  const renderCodePage = (text) => {
3040
- try {
3041
- if (ext && hljs__default.default.getLanguage(ext)) {
3042
- code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
3043
- } else {
3044
- code.innerHTML = hljs__default.default.highlightAuto(text).value;
3045
- }
3046
- } catch {
3160
+ if (isTxt) {
3047
3161
  code.textContent = text;
3162
+ } else {
3163
+ try {
3164
+ if (ext && hljs__default.default.getLanguage(ext)) {
3165
+ code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
3166
+ } else {
3167
+ code.innerHTML = hljs__default.default.highlightAuto(text).value;
3168
+ }
3169
+ } catch {
3170
+ code.textContent = text;
3171
+ }
3048
3172
  }
3049
3173
  };
3050
- renderCodePage(rawPages[0] || fullText);
3174
+ renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
3051
3175
  pre.appendChild(code);
3052
3176
  container.appendChild(pre);
3053
3177
  let indicator = null;
@@ -3056,15 +3180,22 @@ var CodePlugin = class {
3056
3180
  indicator.className = "fp-code-page-indicator";
3057
3181
  indicator.style.position = "sticky";
3058
3182
  indicator.style.bottom = "16px";
3059
- indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
3060
- indicator.style.backdropFilter = "blur(8px)";
3061
- indicator.style.color = "#f8fafc";
3183
+ if (isTxt) {
3184
+ indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
3185
+ indicator.style.color = "#334155";
3186
+ indicator.style.border = "1px solid #e2e8f0";
3187
+ indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
3188
+ } else {
3189
+ indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
3190
+ indicator.style.color = "#f8fafc";
3191
+ indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
3192
+ indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
3193
+ indicator.style.backdropFilter = "blur(8px)";
3194
+ }
3062
3195
  indicator.style.fontSize = "12px";
3063
3196
  indicator.style.fontWeight = "600";
3064
3197
  indicator.style.padding = "5px 14px";
3065
3198
  indicator.style.borderRadius = "20px";
3066
- indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
3067
- indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
3068
3199
  indicator.style.zIndex = "10";
3069
3200
  indicator.style.userSelect = "none";
3070
3201
  indicator.style.pointerEvents = "none";
@@ -3075,7 +3206,7 @@ var CodePlugin = class {
3075
3206
  }
3076
3207
  const showPage = (pageNum) => {
3077
3208
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
3078
- renderCodePage(rawPages[currentPage - 1] || fullText);
3209
+ renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
3079
3210
  if (indicator) {
3080
3211
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
3081
3212
  }
@@ -3091,39 +3222,57 @@ var CodePlugin = class {
3091
3222
  ctx.container.innerHTML = "";
3092
3223
  };
3093
3224
  ctx.signal.addEventListener("abort", cleanup);
3225
+ const updateTransform = () => {
3226
+ if (isTxt) {
3227
+ pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
3228
+ } else {
3229
+ pre.style.transform = `rotate(${rotation}deg)`;
3230
+ pre.style.fontSize = `${fontSize}px`;
3231
+ }
3232
+ };
3094
3233
  return {
3095
3234
  destroy: cleanup,
3096
3235
  getPageCount: () => totalPages,
3097
3236
  getCurrentPage: () => currentPage,
3098
3237
  goToPage: (page) => showPage(page),
3099
3238
  zoomIn: () => {
3100
- fontSize = Math.min(32, fontSize + 2);
3101
- pre.style.fontSize = `${fontSize}px`;
3239
+ if (isTxt) {
3240
+ zoomLevel = Math.min(3, zoomLevel + 0.1);
3241
+ } else {
3242
+ fontSize = Math.min(32, fontSize + 2);
3243
+ }
3244
+ updateTransform();
3102
3245
  },
3103
3246
  zoomOut: () => {
3104
- fontSize = Math.max(8, fontSize - 2);
3105
- pre.style.fontSize = `${fontSize}px`;
3247
+ if (isTxt) {
3248
+ zoomLevel = Math.max(0.1, zoomLevel - 0.1);
3249
+ } else {
3250
+ fontSize = Math.max(8, fontSize - 2);
3251
+ }
3252
+ updateTransform();
3106
3253
  },
3107
- getZoom: () => fontSize / 13,
3254
+ getZoom: () => isTxt ? zoomLevel : fontSize / 13,
3108
3255
  setZoom: (level) => {
3109
- fontSize = Math.round(13 * level);
3110
- pre.style.fontSize = `${fontSize}px`;
3256
+ if (isTxt) {
3257
+ zoomLevel = level;
3258
+ } else {
3259
+ fontSize = Math.round(13 * level);
3260
+ }
3261
+ updateTransform();
3111
3262
  },
3112
3263
  fitToPage: () => {
3113
3264
  fontSize = 13;
3114
3265
  rotation = 0;
3115
- pre.style.fontSize = "13px";
3116
- pre.style.transform = "none";
3266
+ zoomLevel = 1;
3267
+ updateTransform();
3117
3268
  },
3118
3269
  rotateCW: () => {
3119
3270
  rotation = (rotation + 90) % 360;
3120
- pre.style.transform = `rotate(${rotation}deg)`;
3121
- pre.style.transformOrigin = "top left";
3271
+ updateTransform();
3122
3272
  },
3123
3273
  rotateCCW: () => {
3124
3274
  rotation = (rotation - 90 + 360) % 360;
3125
- pre.style.transform = `rotate(${rotation}deg)`;
3126
- pre.style.transformOrigin = "top left";
3275
+ updateTransform();
3127
3276
  },
3128
3277
  download: () => {
3129
3278
  const mimeType = ctx.metadata.mimeType || "text/plain";
@@ -3422,7 +3571,7 @@ var MarkdownPlugin = class {
3422
3571
  gfm: true,
3423
3572
  breaks: true
3424
3573
  });
3425
- const cleanHtml = DOMPurify2__default.default.sanitize(rawHtml, {
3574
+ const cleanHtml = DOMPurify6__default.default.sanitize(rawHtml, {
3426
3575
  USE_PROFILES: { html: true }
3427
3576
  });
3428
3577
  const wrapper = document.createElement("div");
@@ -4058,6 +4207,14 @@ var RtfPlugin = class {
4058
4207
  group: "actions",
4059
4208
  execute: () => instance.download?.()
4060
4209
  },
4210
+ {
4211
+ id: "copy",
4212
+ icon: "copy",
4213
+ label: "Copy Text",
4214
+ type: "button",
4215
+ group: "actions",
4216
+ execute: () => instance.copy?.()
4217
+ },
4061
4218
  {
4062
4219
  id: "print",
4063
4220
  icon: "print",
@@ -4119,14 +4276,31 @@ var RtfPlugin = class {
4119
4276
  } catch (err) {
4120
4277
  console.warn("[RtfPlugin] RTF render error, fallback text:", err);
4121
4278
  const text = new TextDecoder("latin1").decode(ctx.buffer);
4122
- const clean = text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "");
4123
- const pre = document.createElement("pre");
4124
- pre.style.whiteSpace = "pre-wrap";
4125
- pre.style.fontFamily = "serif";
4126
- pre.style.color = "#333";
4127
- pre.textContent = clean;
4128
- wrapper.appendChild(pre);
4129
- pageElements = [pre];
4279
+ const rawPages = text.split(/\\page\b/).map((segment) => {
4280
+ return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
4281
+ }).filter((p) => p.length > 0);
4282
+ const pages = rawPages.length > 0 ? rawPages : [text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim()];
4283
+ for (let i = 0; i < pages.length; i++) {
4284
+ const pageCard = document.createElement("div");
4285
+ pageCard.className = "fp-rtf-page-card";
4286
+ pageCard.style.backgroundColor = "#ffffff";
4287
+ pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
4288
+ pageCard.style.borderRadius = "4px";
4289
+ pageCard.style.padding = "72px 56px";
4290
+ pageCard.style.width = "816px";
4291
+ pageCard.style.minHeight = "1056px";
4292
+ pageCard.style.maxWidth = "100%";
4293
+ pageCard.style.boxSizing = "border-box";
4294
+ pageCard.style.fontFamily = "serif";
4295
+ pageCard.style.fontSize = "12pt";
4296
+ pageCard.style.lineHeight = "1.6";
4297
+ pageCard.style.color = "#1e293b";
4298
+ pageCard.style.whiteSpace = "pre-wrap";
4299
+ pageCard.style.display = i === 0 ? "block" : "none";
4300
+ pageCard.textContent = pages[i];
4301
+ wrapper.appendChild(pageCard);
4302
+ pageElements.push(pageCard);
4303
+ }
4130
4304
  }
4131
4305
  const totalPages = Math.max(1, pageElements.length);
4132
4306
  let currentPage = 1;
@@ -4214,6 +4388,10 @@ var RtfPlugin = class {
4214
4388
  a.click();
4215
4389
  URL.revokeObjectURL(url);
4216
4390
  },
4391
+ copy: () => {
4392
+ const text = wrapper.textContent || "";
4393
+ navigator.clipboard?.writeText(text);
4394
+ },
4217
4395
  print: () => {
4218
4396
  window.print();
4219
4397
  }
@@ -4288,7 +4466,7 @@ var HtmlPreviewPlugin = class {
4288
4466
  }
4289
4467
  async render(ctx) {
4290
4468
  const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
4291
- const sanitized = DOMPurify2__default.default.sanitize(rawHtml, {
4469
+ const sanitized = DOMPurify6__default.default.sanitize(rawHtml, {
4292
4470
  WHOLE_DOCUMENT: true,
4293
4471
  ADD_TAGS: ["style", "link"],
4294
4472
  ADD_ATTR: ["target", "rel"]
@@ -4554,14 +4732,97 @@ var OpenDocumentPlugin = class {
4554
4732
  wrapper.textContent = contentDoc.documentElement.textContent || "Formula content";
4555
4733
  }
4556
4734
  } else {
4557
- wrapper.style.maxWidth = "850px";
4558
- wrapper.style.padding = "48px";
4735
+ wrapper.style.maxWidth = "none";
4736
+ wrapper.style.padding = "0";
4559
4737
  wrapper.style.minHeight = "100%";
4738
+ wrapper.style.backgroundColor = "transparent";
4739
+ wrapper.style.boxShadow = "none";
4740
+ wrapper.style.position = "relative";
4741
+ const dims = this.getPageDimensions(stylesDoc, contentDoc);
4560
4742
  const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
4561
- wrapper.innerHTML = DOMPurify2__default.default.sanitize(bodyHtml, {
4562
- ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub"],
4743
+ const tempDiv = document.createElement("div");
4744
+ tempDiv.style.width = `${dims.width - dims.marginLeft - dims.marginRight}px`;
4745
+ tempDiv.style.position = "absolute";
4746
+ tempDiv.style.visibility = "hidden";
4747
+ tempDiv.innerHTML = DOMPurify6__default.default.sanitize(bodyHtml, {
4748
+ ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub", "hr"],
4563
4749
  ADD_ATTR: ["style", "colspan", "rowspan"]
4564
4750
  });
4751
+ document.body.appendChild(tempDiv);
4752
+ const contentHeight = dims.height - dims.marginTop - dims.marginBottom;
4753
+ const pageElements = [[]];
4754
+ let currentHeight = 0;
4755
+ let currentPageIdx = 0;
4756
+ Array.from(tempDiv.children).forEach((child) => {
4757
+ const el = child;
4758
+ const style = el.getAttribute("style") || "";
4759
+ const isBreakBefore = style.includes("page-break-before: always");
4760
+ const isBreakAfter = style.includes("page-break-after: always");
4761
+ const isSoftBreak = el.classList.contains("odf-page-break");
4762
+ if (isBreakBefore) {
4763
+ if (pageElements[currentPageIdx].length > 0) {
4764
+ currentPageIdx++;
4765
+ pageElements.push([]);
4766
+ currentHeight = 0;
4767
+ }
4768
+ }
4769
+ const h = el.offsetHeight || 0;
4770
+ if (currentHeight + h > contentHeight && pageElements[currentPageIdx].length > 0 && !isSoftBreak) {
4771
+ currentPageIdx++;
4772
+ pageElements.push([]);
4773
+ currentHeight = 0;
4774
+ }
4775
+ if (!isSoftBreak) {
4776
+ pageElements[currentPageIdx].push(el.cloneNode(true));
4777
+ currentHeight += h;
4778
+ }
4779
+ if (isBreakAfter || isSoftBreak) {
4780
+ currentPageIdx++;
4781
+ pageElements.push([]);
4782
+ currentHeight = 0;
4783
+ }
4784
+ });
4785
+ document.body.removeChild(tempDiv);
4786
+ if (pageElements.length > 1 && pageElements[pageElements.length - 1].length === 0) {
4787
+ pageElements.pop();
4788
+ }
4789
+ totalPages = Math.max(1, pageElements.length);
4790
+ pageElements.forEach((elements, idx) => {
4791
+ const page = document.createElement("div");
4792
+ page.className = `fp-odt-page fp-odt-page-${idx + 1}`;
4793
+ page.style.width = `${dims.width}px`;
4794
+ page.style.minHeight = `${dims.height}px`;
4795
+ page.style.padding = `${dims.marginTop}px ${dims.marginRight}px ${dims.marginBottom}px ${dims.marginLeft}px`;
4796
+ page.style.margin = "0 auto";
4797
+ page.style.backgroundColor = "#ffffff";
4798
+ page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
4799
+ page.style.borderRadius = "4px";
4800
+ page.style.boxSizing = "border-box";
4801
+ page.style.display = idx === 0 ? "block" : "none";
4802
+ page.style.position = "absolute";
4803
+ page.style.top = "0";
4804
+ page.style.left = "50%";
4805
+ page.style.transform = "translateX(-50%)";
4806
+ elements.forEach((el) => page.appendChild(el));
4807
+ wrapper.appendChild(page);
4808
+ slides.push(page);
4809
+ });
4810
+ const pageIndicator = document.createElement("div");
4811
+ pageIndicator.className = "fp-odt-page-indicator";
4812
+ pageIndicator.style.position = "sticky";
4813
+ pageIndicator.style.bottom = "16px";
4814
+ pageIndicator.style.left = "50%";
4815
+ pageIndicator.style.transform = "translateX(-50%)";
4816
+ pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
4817
+ pageIndicator.style.color = "#fff";
4818
+ pageIndicator.style.padding = "6px 12px";
4819
+ pageIndicator.style.borderRadius = "16px";
4820
+ pageIndicator.style.fontSize = "12px";
4821
+ pageIndicator.style.zIndex = "100";
4822
+ pageIndicator.style.display = "inline-block";
4823
+ pageIndicator.style.width = "fit-content";
4824
+ pageIndicator.textContent = `Page 1 of ${totalPages}`;
4825
+ container.appendChild(pageIndicator);
4565
4826
  }
4566
4827
  const cleanup = () => {
4567
4828
  imageUrls.forEach((url) => URL.revokeObjectURL(url));
@@ -4570,11 +4831,15 @@ var OpenDocumentPlugin = class {
4570
4831
  };
4571
4832
  ctx.signal.addEventListener("abort", cleanup);
4572
4833
  const goToPage = (page) => {
4573
- if (!isPresentation || page < 1 || page > totalPages) return;
4834
+ if (page < 1 || page > totalPages) return;
4574
4835
  currentPage = page;
4575
4836
  slides.forEach((s, idx) => {
4576
4837
  s.style.display = idx === page - 1 ? "block" : "none";
4577
4838
  });
4839
+ const indicator = container.querySelector(".fp-odt-page-indicator");
4840
+ if (indicator) {
4841
+ indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4842
+ }
4578
4843
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4579
4844
  };
4580
4845
  return {
@@ -4643,6 +4908,43 @@ var OpenDocumentPlugin = class {
4643
4908
  }
4644
4909
  };
4645
4910
  }
4911
+ getPageDimensions(stylesDoc, contentDoc) {
4912
+ let width = 850;
4913
+ let height = 1123;
4914
+ let marginTop = 48;
4915
+ let marginBottom = 48;
4916
+ let marginLeft = 48;
4917
+ let marginRight = 48;
4918
+ const parseUnit = (val) => {
4919
+ if (!val) return null;
4920
+ if (val.endsWith("cm")) return parseFloat(val) * 37.8;
4921
+ if (val.endsWith("mm")) return parseFloat(val) * 3.78;
4922
+ if (val.endsWith("in")) return parseFloat(val) * 96;
4923
+ if (val.endsWith("pt")) return parseFloat(val) * 1.33;
4924
+ if (val.endsWith("px")) return parseFloat(val);
4925
+ return parseFloat(val);
4926
+ };
4927
+ const docs = [stylesDoc, contentDoc].filter(Boolean);
4928
+ for (const doc of docs) {
4929
+ const pageLayout = doc.querySelector("page-layout-properties, [page-width]");
4930
+ if (pageLayout) {
4931
+ const w = parseUnit(pageLayout.getAttribute("fo:page-width") || pageLayout.getAttribute("page-width"));
4932
+ const h = parseUnit(pageLayout.getAttribute("fo:page-height") || pageLayout.getAttribute("page-height"));
4933
+ const mt = parseUnit(pageLayout.getAttribute("fo:margin-top") || pageLayout.getAttribute("margin-top"));
4934
+ const mb = parseUnit(pageLayout.getAttribute("fo:margin-bottom") || pageLayout.getAttribute("margin-bottom"));
4935
+ const ml = parseUnit(pageLayout.getAttribute("fo:margin-left") || pageLayout.getAttribute("margin-left"));
4936
+ const mr = parseUnit(pageLayout.getAttribute("fo:margin-right") || pageLayout.getAttribute("margin-right"));
4937
+ if (w !== null) width = w;
4938
+ if (h !== null) height = h;
4939
+ if (mt !== null) marginTop = mt;
4940
+ if (mb !== null) marginBottom = mb;
4941
+ if (ml !== null) marginLeft = ml;
4942
+ if (mr !== null) marginRight = mr;
4943
+ break;
4944
+ }
4945
+ }
4946
+ return { width, height, marginTop, marginBottom, marginLeft, marginRight };
4947
+ }
4646
4948
  extractStyles(stylesDoc, contentDoc) {
4647
4949
  const map = /* @__PURE__ */ new Map();
4648
4950
  const styleNodes = [];
@@ -4665,14 +4967,21 @@ var OpenDocumentPlugin = class {
4665
4967
  if (color) css += `color: ${color}; `;
4666
4968
  if (size) css += `font-size: ${size}; `;
4667
4969
  }
4668
- const paraProp = node.querySelector("paragraph-properties, [text-align]");
4970
+ let paraProp = node.querySelector("paragraph-properties, [text-align]");
4971
+ if (!paraProp) {
4972
+ paraProp = Array.from(node.children).find((c) => c.tagName.includes("paragraph-properties")) || null;
4973
+ }
4669
4974
  if (paraProp) {
4670
4975
  const align = paraProp.getAttribute("fo:text-align") || paraProp.getAttribute("text-align");
4671
4976
  const mt = paraProp.getAttribute("fo:margin-top") || paraProp.getAttribute("margin-top");
4672
4977
  const mb = paraProp.getAttribute("fo:margin-bottom") || paraProp.getAttribute("margin-bottom");
4978
+ const breakBefore = paraProp.getAttribute("fo:break-before") || paraProp.getAttribute("break-before");
4979
+ const breakAfter = paraProp.getAttribute("fo:break-after") || paraProp.getAttribute("break-after");
4673
4980
  if (align) css += `text-align: ${align}; `;
4674
4981
  if (mt) css += `margin-top: ${mt}; `;
4675
4982
  if (mb) css += `margin-bottom: ${mb}; `;
4983
+ if (breakBefore === "page") css += "page-break-before: always; ";
4984
+ if (breakAfter === "page") css += "page-break-after: always; ";
4676
4985
  }
4677
4986
  if (css) map.set(name, css);
4678
4987
  }
@@ -4757,6 +5066,8 @@ var OpenDocumentPlugin = class {
4757
5066
  result += "&emsp;";
4758
5067
  } else if (tag === "line-break") {
4759
5068
  result += "<br/>";
5069
+ } else if (tag === "soft-page-break") {
5070
+ result += '<hr class="odf-page-break" style="page-break-after: always; border: none; margin: 0; padding: 0; height: 0;" />';
4760
5071
  } else {
4761
5072
  result += el.textContent || "";
4762
5073
  }
@@ -4917,20 +5228,9 @@ var DocPlugin = class {
4917
5228
  container.style.overflow = "auto";
4918
5229
  container.style.padding = "32px 16px";
4919
5230
  container.style.backgroundColor = "#f1f5f9";
4920
- const wrapper = document.createElement("div");
4921
- wrapper.className = "fp-doc-wrapper";
4922
- wrapper.style.maxWidth = "850px";
4923
- wrapper.style.margin = "0 auto";
4924
- wrapper.style.backgroundColor = "#ffffff";
4925
- wrapper.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
4926
- wrapper.style.borderRadius = "4px";
4927
- wrapper.style.padding = "56px 48px";
4928
- wrapper.style.minHeight = "100%";
4929
- wrapper.style.transformOrigin = "top center";
4930
- wrapper.style.transition = "transform 0.2s ease";
4931
- wrapper.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
4932
- wrapper.style.color = "#1e293b";
4933
- container.appendChild(wrapper);
5231
+ container.style.display = "flex";
5232
+ container.style.justifyContent = "center";
5233
+ container.style.alignItems = "flex-start";
4934
5234
  ctx.container.appendChild(container);
4935
5235
  let scale = 1;
4936
5236
  let extractedRawText = "";
@@ -4957,21 +5257,27 @@ var DocPlugin = class {
4957
5257
  const rawPages = this.splitIntoPages(extractedRawText);
4958
5258
  const totalPages = Math.max(1, rawPages.length);
4959
5259
  let currentPage = 1;
4960
- wrapper.innerHTML = "";
4961
5260
  const pageCards = [];
4962
5261
  for (let i = 0; i < totalPages; i++) {
4963
5262
  const pageCard = document.createElement("div");
4964
5263
  pageCard.className = "fp-doc-page-card";
5264
+ pageCard.style.width = "816px";
5265
+ pageCard.style.height = "1056px";
4965
5266
  pageCard.style.backgroundColor = "#ffffff";
4966
5267
  pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
4967
5268
  pageCard.style.borderRadius = "4px";
4968
- pageCard.style.padding = "56px 48px";
4969
- pageCard.style.minHeight = "100%";
5269
+ pageCard.style.padding = "96px 72px";
5270
+ pageCard.style.boxSizing = "border-box";
5271
+ pageCard.style.overflow = "hidden";
4970
5272
  pageCard.style.display = i === 0 ? "block" : "none";
5273
+ pageCard.style.transformOrigin = "top center";
5274
+ pageCard.style.transition = "transform 0.2s ease";
5275
+ pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
5276
+ pageCard.style.color = "#1e293b";
4971
5277
  if (isFallback && i === 0) {
4972
5278
  pageCard.innerHTML = `
4973
5279
  <div style="border-bottom: 1px solid #e2e8f0; padding-bottom: 12px; margin-bottom: 24px;">
4974
- <h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify2__default.default.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
5280
+ <h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify6__default.default.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
4975
5281
  <span style="font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 4px;">Legacy Word 97-2003 Binary Preview</span>
4976
5282
  </div>
4977
5283
  ${this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document")}
@@ -4979,15 +5285,17 @@ var DocPlugin = class {
4979
5285
  } else {
4980
5286
  pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
4981
5287
  }
4982
- wrapper.appendChild(pageCard);
5288
+ container.appendChild(pageCard);
4983
5289
  pageCards.push(pageCard);
4984
5290
  }
4985
5291
  let indicator = null;
4986
5292
  if (totalPages > 1) {
4987
5293
  indicator = document.createElement("div");
4988
5294
  indicator.className = "fp-doc-page-indicator";
4989
- indicator.style.position = "sticky";
5295
+ indicator.style.position = "fixed";
4990
5296
  indicator.style.bottom = "16px";
5297
+ indicator.style.left = "50%";
5298
+ indicator.style.transform = "translateX(-50%)";
4991
5299
  indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
4992
5300
  indicator.style.backdropFilter = "blur(8px)";
4993
5301
  indicator.style.color = "#f8fafc";
@@ -5001,17 +5309,25 @@ var DocPlugin = class {
5001
5309
  indicator.style.userSelect = "none";
5002
5310
  indicator.style.pointerEvents = "none";
5003
5311
  indicator.style.textAlign = "center";
5004
- indicator.style.width = "fit-content";
5005
- indicator.style.margin = "16px auto 0";
5006
5312
  container.appendChild(indicator);
5007
5313
  }
5314
+ let rotation = 0;
5315
+ const applyTransform = () => {
5316
+ const activeCard = pageCards[currentPage - 1];
5317
+ if (activeCard) {
5318
+ activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
5319
+ }
5320
+ };
5008
5321
  const showPage = (pageNum) => {
5009
5322
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
5010
- if (totalPages > 1) {
5011
- pageCards.forEach((card, idx) => {
5012
- card.style.display = idx + 1 === currentPage ? "block" : "none";
5013
- });
5014
- }
5323
+ pageCards.forEach((card, idx) => {
5324
+ if (idx + 1 === currentPage) {
5325
+ card.style.display = "block";
5326
+ card.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
5327
+ } else {
5328
+ card.style.display = "none";
5329
+ }
5330
+ });
5015
5331
  if (indicator) {
5016
5332
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
5017
5333
  }
@@ -5020,19 +5336,13 @@ var DocPlugin = class {
5020
5336
  if (totalPages > 1) {
5021
5337
  showPage(1);
5022
5338
  }
5023
- let rotation = 0;
5024
5339
  const calculateFitScale = () => {
5025
- const activeCard = pageCards[currentPage - 1] || wrapper;
5026
- const elW = activeCard.offsetWidth || 850;
5027
- const elH = activeCard.offsetHeight || 1e3;
5340
+ const elW = 816;
5341
+ const elH = 1056;
5028
5342
  const availW = Math.max(200, ctx.container.clientWidth - 48);
5029
5343
  const availH = Math.max(200, ctx.container.clientHeight - 80);
5030
5344
  return Math.min(1.1, Math.min(availW / elW, availH / elH));
5031
5345
  };
5032
- const applyTransform = () => {
5033
- wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
5034
- wrapper.style.transformOrigin = "top center";
5035
- };
5036
5346
  setTimeout(() => {
5037
5347
  scale = calculateFitScale();
5038
5348
  applyTransform();
@@ -5190,8 +5500,28 @@ var DocPlugin = class {
5190
5500
  }
5191
5501
  splitIntoPages(text) {
5192
5502
  if (!text) return [""];
5193
- const parts = 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);
5194
- return parts.length > 0 ? parts : [text];
5503
+ 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);
5504
+ if (explicitParts.length === 0) explicitParts.push(text);
5505
+ const maxLinesPerPage = 48;
5506
+ const finalPages = [];
5507
+ for (const part of explicitParts) {
5508
+ const lines = part.split(/\r?\n/);
5509
+ let currentLines = [];
5510
+ let count = 0;
5511
+ for (const line of lines) {
5512
+ currentLines.push(line);
5513
+ count++;
5514
+ if (count >= maxLinesPerPage) {
5515
+ finalPages.push(currentLines.join("\n"));
5516
+ currentLines = [];
5517
+ count = 0;
5518
+ }
5519
+ }
5520
+ if (currentLines.length > 0) {
5521
+ finalPages.push(currentLines.join("\n"));
5522
+ }
5523
+ }
5524
+ return finalPages.length > 0 ? finalPages : [text];
5195
5525
  }
5196
5526
  /**
5197
5527
  * Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
@@ -5200,17 +5530,65 @@ var DocPlugin = class {
5200
5530
  const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
5201
5531
  let html = "";
5202
5532
  let inList = false;
5203
- for (const rawLine of lines) {
5204
- const line = rawLine.trim();
5533
+ let tableLines = [];
5534
+ const flushTable = () => {
5535
+ if (tableLines.length > 0) {
5536
+ html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
5537
+ for (const tLine of tableLines) {
5538
+ html += "<tr>";
5539
+ const cols = tLine.split(" ");
5540
+ for (const col of cols) {
5541
+ html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
5542
+ }
5543
+ html += "</tr>";
5544
+ }
5545
+ html += "</table>";
5546
+ tableLines = [];
5547
+ }
5548
+ };
5549
+ let i = 0;
5550
+ while (i < lines.length) {
5551
+ let line = lines[i];
5552
+ let tabCount = (line.match(/\t/g) || []).length;
5553
+ if (tabCount > 0) {
5554
+ let consecutiveTableLines = 1;
5555
+ let j = i + 1;
5556
+ while (j < lines.length) {
5557
+ const nextTabCount = (lines[j].match(/\t/g) || []).length;
5558
+ if (nextTabCount === tabCount) {
5559
+ consecutiveTableLines++;
5560
+ j++;
5561
+ } else {
5562
+ break;
5563
+ }
5564
+ }
5565
+ if (consecutiveTableLines >= 3) {
5566
+ if (inList) {
5567
+ html += "</ul>";
5568
+ inList = false;
5569
+ }
5570
+ tableLines = lines.slice(i, j);
5571
+ flushTable();
5572
+ i = j;
5573
+ continue;
5574
+ }
5575
+ }
5576
+ line = line.trim();
5205
5577
  if (!line) {
5206
5578
  if (inList) {
5207
5579
  html += "</ul>";
5208
5580
  inList = false;
5209
5581
  }
5582
+ html += '<div style="height: 1.15em;"></div>';
5583
+ i++;
5584
+ continue;
5585
+ }
5586
+ if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line)) {
5587
+ i++;
5210
5588
  continue;
5211
5589
  }
5212
- if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line)) continue;
5213
- if (line.includes("Normal.dot") || line.includes("Microsoft Word") || line.includes("Times New Roman") && line.length < 30) {
5590
+ if ((line.includes("Normal.dot") || line.includes("Microsoft Word") || line.includes("Times New Roman")) && line.length < 30) {
5591
+ i++;
5214
5592
  continue;
5215
5593
  }
5216
5594
  if (line.length < 60 && !line.endsWith(".") && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#"))) {
@@ -5218,24 +5596,26 @@ var DocPlugin = class {
5218
5596
  html += "</ul>";
5219
5597
  inList = false;
5220
5598
  }
5221
- html += `<h2 style="font-size: 18px; font-weight: 700; color: #1e3a8a; margin: 20px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify2__default.default.sanitize(line)}</h2>`;
5599
+ html += `<h2 style="font-size: 16px; font-weight: 700; color: #1e3a8a; margin: 16px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify6__default.default.sanitize(line)}</h2>`;
5222
5600
  } else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
5223
5601
  if (!inList) {
5224
5602
  html += '<ul style="margin: 8px 0; padding-left: 24px;">';
5225
5603
  inList = true;
5226
5604
  }
5227
5605
  const bulletText = line.replace(/^[•\-\*]\s*/, "");
5228
- html += `<li style="margin: 4px 0; line-height: 1.6;">${DOMPurify2__default.default.sanitize(bulletText)}</li>`;
5606
+ html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6__default.default.sanitize(bulletText)}</li>`;
5229
5607
  } else {
5230
5608
  if (inList) {
5231
5609
  html += "</ul>";
5232
5610
  inList = false;
5233
5611
  }
5234
- html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${DOMPurify2__default.default.sanitize(line)}</p>`;
5612
+ html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6__default.default.sanitize(line)}</p>`;
5235
5613
  }
5614
+ i++;
5236
5615
  }
5237
5616
  if (inList) html += "</ul>";
5238
- return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify2__default.default.sanitize(filename)})</p>`;
5617
+ flushTable();
5618
+ return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6__default.default.sanitize(filename)})</p>`;
5239
5619
  }
5240
5620
  };
5241
5621
  function docPlugin() {
@@ -5413,7 +5793,7 @@ var PptPlugin = class {
5413
5793
  if (s.pictureUrl) {
5414
5794
  contentHtml = `
5415
5795
  <div style="flex: 1; display: flex; justify-content: center; align-items: center; padding: 12px; overflow: hidden;">
5416
- <img src="${s.pictureUrl}" alt="${DOMPurify2__default.default.sanitize(s.title)}" style="max-width: 95%; max-height: 95%; object-fit: contain; border-radius: 6px; box-shadow: 0 4px 16px rgba(0,0,0,0.1); background: #ffffff;" />
5796
+ <img src="${s.pictureUrl}" alt="${DOMPurify6__default.default.sanitize(s.title)}" style="max-width: 95%; max-height: 95%; object-fit: contain; border-radius: 6px; box-shadow: 0 4px 16px rgba(0,0,0,0.1); background: #ffffff;" />
5417
5797
  </div>
5418
5798
  `;
5419
5799
  } else if (s.tableColumns.length > 0) {
@@ -5423,7 +5803,7 @@ var PptPlugin = class {
5423
5803
  <table style="width: 100%; border-collapse: collapse; border: 1px solid #cbd5e1; border-radius: 6px; overflow: hidden; background: #ffffff;">
5424
5804
  <thead>
5425
5805
  <tr style="background: #e2e8f0; color: #1e293b; font-weight: 600; font-size: 14px;">
5426
- ${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${DOMPurify2__default.default.sanitize(c)}</th>`).join("")}
5806
+ ${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${DOMPurify6__default.default.sanitize(c)}</th>`).join("")}
5427
5807
  </tr>
5428
5808
  </thead>
5429
5809
  <tbody>
@@ -5439,7 +5819,7 @@ var PptPlugin = class {
5439
5819
  } else {
5440
5820
  const pTags = s.paragraphs.map((p) => {
5441
5821
  const lines = p.split(/[\r\n]+/).map((l) => l.trim()).filter(Boolean);
5442
- return lines.map((l) => `<p style="margin: 0 0 14px; font-size: 14px; line-height: 1.65; color: #334155; text-align: justify;">${DOMPurify2__default.default.sanitize(l)}</p>`).join("");
5822
+ return lines.map((l) => `<p style="margin: 0 0 14px; font-size: 14px; line-height: 1.65; color: #334155; text-align: justify;">${DOMPurify6__default.default.sanitize(l)}</p>`).join("");
5443
5823
  }).join("");
5444
5824
  contentHtml = `
5445
5825
  <div style="flex: 1; overflow: auto; padding: 4px 8px; display: flex; flex-direction: column; justify-content: flex-start;">
@@ -5452,11 +5832,11 @@ var PptPlugin = class {
5452
5832
  <!-- Header Banner matching PowerPoint design -->
5453
5833
  <div style="background: linear-gradient(90deg, #a3e635 0%, #84cc16 100%); padding: 12px 24px; border-radius: 4px; display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); flex-shrink: 0;">
5454
5834
  <h1 style="margin: 0; font-size: 26px; font-weight: 700; color: #1e293b; letter-spacing: -0.3px;">
5455
- ${DOMPurify2__default.default.sanitize(s.title)}
5835
+ ${DOMPurify6__default.default.sanitize(s.title)}
5456
5836
  </h1>
5457
5837
  ${s.subtitle ? `
5458
5838
  <span style="background: #38bdf8; color: #ffffff; padding: 4px 14px; border-radius: 4px; font-weight: 700; font-size: 13px; letter-spacing: 0.5px; box-shadow: 0 1px 4px rgba(0,0,0,0.15);">
5459
- ${DOMPurify2__default.default.sanitize(s.subtitle)}
5839
+ ${DOMPurify6__default.default.sanitize(s.subtitle)}
5460
5840
  </span>
5461
5841
  ` : `
5462
5842
  <span style="font-size: 12px; color: #365314; font-weight: 600;">