@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/vue.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var vue = require('vue');
6
- var DOMPurify2 = require('dompurify');
6
+ var DOMPurify6 = require('dompurify');
7
7
  var pdfjsLib = require('pdfjs-dist');
8
8
  var docx = require('docx-preview');
9
9
  var fflate = require('fflate');
@@ -37,7 +37,7 @@ function _interopNamespace(e) {
37
37
  return Object.freeze(n);
38
38
  }
39
39
 
40
- var DOMPurify2__default = /*#__PURE__*/_interopDefault(DOMPurify2);
40
+ var DOMPurify6__default = /*#__PURE__*/_interopDefault(DOMPurify6);
41
41
  var pdfjsLib__namespace = /*#__PURE__*/_interopNamespace(pdfjsLib);
42
42
  var docx__namespace = /*#__PURE__*/_interopNamespace(docx);
43
43
  var XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
@@ -389,7 +389,7 @@ async function sourceToArrayBuffer(source, signal) {
389
389
  if (magicMime === "application/zip") {
390
390
  const ooxmlMime = detectOoxmlType(buffer);
391
391
  if (ooxmlMime && ooxmlMime !== "application/zip") {
392
- metadata.mimeType = ooxmlMime;
392
+ metadata.mimeType = metadata.mimeType ?? ooxmlMime;
393
393
  if (ooxmlMime.includes("wordprocessing")) metadata.extension = metadata.extension ?? ".docx";
394
394
  else if (ooxmlMime.includes("spreadsheet")) metadata.extension = metadata.extension ?? ".xlsx";
395
395
  else if (ooxmlMime.includes("presentation")) metadata.extension = metadata.extension ?? ".pptx";
@@ -418,7 +418,7 @@ async function sourceToArrayBuffer(source, signal) {
418
418
  return { buffer, metadata };
419
419
  }
420
420
  function sanitizeSVG(svg) {
421
- return DOMPurify2__default.default.sanitize(svg, {
421
+ return DOMPurify6__default.default.sanitize(svg, {
422
422
  USE_PROFILES: { svg: true, svgFilters: true }
423
423
  });
424
424
  }
@@ -1480,7 +1480,19 @@ var PdfPlugin = class {
1480
1480
  }
1481
1481
  };
1482
1482
  await renderPage(1);
1483
+ let resizeTimer = null;
1484
+ const resizeObserver = new ResizeObserver(() => {
1485
+ if (resizeTimer) clearTimeout(resizeTimer);
1486
+ resizeTimer = setTimeout(() => {
1487
+ if (Math.abs(zoomScale - 1) < 0.05) {
1488
+ renderPage(currentPage);
1489
+ }
1490
+ }, 150);
1491
+ });
1492
+ resizeObserver.observe(container);
1483
1493
  const cleanup = () => {
1494
+ resizeObserver.disconnect();
1495
+ if (resizeTimer) clearTimeout(resizeTimer);
1484
1496
  if (currentRenderTask) {
1485
1497
  try {
1486
1498
  currentRenderTask.cancel();
@@ -2228,90 +2240,149 @@ var DocxPlugin = class {
2228
2240
  console.warn("[DocxPlugin] Error parsing relationships:", relsErr);
2229
2241
  }
2230
2242
  }
2231
- const card = document.createElement("div");
2232
- card.className = "fp-docx-page-card";
2233
- card.style.backgroundColor = "#ffffff";
2234
- card.style.borderRadius = "6px";
2235
- card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
2236
- card.style.padding = "48px 56px";
2237
- card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
2238
- card.style.color = "#1e293b";
2239
- card.style.lineHeight = "1.6";
2243
+ const sectPrs = Array.from(doc.getElementsByTagNameNS("*", "sectPr"));
2244
+ const lastSectPr = sectPrs[sectPrs.length - 1];
2245
+ let defaultW = 12240;
2246
+ let defaultH = 15840;
2247
+ let margins = { top: 1440, right: 1440, bottom: 1440, left: 1440 };
2248
+ if (lastSectPr) {
2249
+ const pgSz = lastSectPr.getElementsByTagNameNS("*", "pgSz")[0];
2250
+ if (pgSz) {
2251
+ defaultW = parseInt(pgSz.getAttribute("w:w") || pgSz.getAttribute("w") || "12240", 10);
2252
+ defaultH = parseInt(pgSz.getAttribute("w:h") || pgSz.getAttribute("h") || "15840", 10);
2253
+ }
2254
+ const pgMar = lastSectPr.getElementsByTagNameNS("*", "pgMar")[0];
2255
+ if (pgMar) {
2256
+ margins.top = parseInt(pgMar.getAttribute("w:top") || pgMar.getAttribute("top") || "1440", 10);
2257
+ margins.bottom = parseInt(pgMar.getAttribute("w:bottom") || pgMar.getAttribute("bottom") || "1440", 10);
2258
+ margins.left = parseInt(pgMar.getAttribute("w:left") || pgMar.getAttribute("left") || "1440", 10);
2259
+ margins.right = parseInt(pgMar.getAttribute("w:right") || pgMar.getAttribute("right") || "1440", 10);
2260
+ }
2261
+ }
2262
+ const createPageCard = () => {
2263
+ const card = document.createElement("div");
2264
+ card.className = "fp-docx-page-card";
2265
+ card.style.backgroundColor = "#ffffff";
2266
+ card.style.borderRadius = "4px";
2267
+ card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
2268
+ card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
2269
+ card.style.color = "#1e293b";
2270
+ card.style.lineHeight = "1.6";
2271
+ card.style.boxSizing = "border-box";
2272
+ card.style.overflow = "hidden";
2273
+ card.style.position = "relative";
2274
+ card.style.marginBottom = "24px";
2275
+ card.style.width = `${defaultW / 15}px`;
2276
+ card.style.height = `${defaultH / 15}px`;
2277
+ card.style.padding = `${margins.top / 15}px ${margins.right / 15}px ${margins.bottom / 15}px ${margins.left / 15}px`;
2278
+ return card;
2279
+ };
2280
+ let currentCard = createPageCard();
2281
+ let currentHtml = "";
2282
+ const pages = [{ card: currentCard, html: "" }];
2283
+ const flushHtml = () => {
2284
+ pages[pages.length - 1].html += currentHtml;
2285
+ currentHtml = "";
2286
+ };
2287
+ const newPage = () => {
2288
+ flushHtml();
2289
+ currentCard = createPageCard();
2290
+ pages.push({ card: currentCard, html: "" });
2291
+ };
2240
2292
  const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
2241
- let html = "";
2242
2293
  for (const child of Array.from(body.children)) {
2243
2294
  const tag = child.localName || child.nodeName.split(":").pop();
2244
2295
  if (tag === "p") {
2245
2296
  const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
2246
2297
  const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
2247
2298
  const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
2248
- const textContent = this.extractParagraphHtml(child, imageMap);
2249
- if (!textContent.trim()) {
2250
- html += '<div style="height: 10px;"></div>';
2251
- continue;
2252
- }
2253
- const lowerStyle = styleVal.toLowerCase();
2254
- if (lowerStyle.includes("title")) {
2255
- 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>`;
2256
- } else if (lowerStyle.includes("heading1") || styleVal === "1") {
2257
- html += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
2258
- } else if (lowerStyle.includes("heading2") || styleVal === "2") {
2259
- html += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
2260
- } else if (lowerStyle.includes("heading3") || styleVal === "3") {
2261
- html += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
2262
- } else if (numPr) {
2263
- 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>`;
2264
- } else {
2265
- html += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
2299
+ const chunks = this.extractParagraphChunks(child, imageMap);
2300
+ for (let i = 0; i < chunks.length; i++) {
2301
+ if (i > 0) {
2302
+ newPage();
2303
+ }
2304
+ const textContent = chunks[i];
2305
+ if (!textContent.trim() && !textContent.includes("<img")) {
2306
+ currentHtml += '<div style="height: 10px;"></div>';
2307
+ continue;
2308
+ }
2309
+ const lowerStyle = styleVal.toLowerCase();
2310
+ if (lowerStyle.includes("title")) {
2311
+ 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>`;
2312
+ } else if (lowerStyle.includes("heading1") || styleVal === "1") {
2313
+ currentHtml += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
2314
+ } else if (lowerStyle.includes("heading2") || styleVal === "2") {
2315
+ currentHtml += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
2316
+ } else if (lowerStyle.includes("heading3") || styleVal === "3") {
2317
+ currentHtml += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
2318
+ } else if (numPr) {
2319
+ 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>`;
2320
+ } else {
2321
+ currentHtml += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
2322
+ }
2266
2323
  }
2267
2324
  } else if (tag === "tbl") {
2268
- html += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
2325
+ currentHtml += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
2269
2326
  const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
2270
2327
  rows.forEach((tr, rIdx) => {
2271
- html += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
2328
+ currentHtml += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
2272
2329
  const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
2273
2330
  cells.forEach((tc) => {
2274
2331
  const cellText = this.extractParagraphHtml(tc, imageMap);
2275
- html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || "&nbsp;"}</td>`;
2332
+ currentHtml += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || "&nbsp;"}</td>`;
2276
2333
  });
2277
- html += "</tr>";
2334
+ currentHtml += "</tr>";
2278
2335
  });
2279
- html += "</table>";
2336
+ currentHtml += "</table>";
2280
2337
  }
2281
2338
  }
2282
- card.innerHTML = DOMPurify2__default.default.sanitize(html, {
2283
- ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
2284
- ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
2285
- });
2286
- wrapper.appendChild(card);
2339
+ flushHtml();
2340
+ for (const page of pages) {
2341
+ page.card.innerHTML = DOMPurify6__default.default.sanitize(page.html, {
2342
+ ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
2343
+ ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
2344
+ });
2345
+ wrapper.appendChild(page.card);
2346
+ }
2287
2347
  }
2288
2348
  extractParagraphHtml(pElement, imageMap = {}) {
2289
- let result = "";
2349
+ return this.extractParagraphChunks(pElement, imageMap).join("<br/>");
2350
+ }
2351
+ extractParagraphChunks(pElement, imageMap = {}) {
2352
+ const chunks = [""];
2353
+ let currentChunkIndex = 0;
2290
2354
  const drawings = Array.from(pElement.getElementsByTagNameNS("*", "drawing"));
2291
2355
  for (const drawing of drawings) {
2292
2356
  const blip = drawing.getElementsByTagNameNS("*", "blip")[0];
2293
2357
  const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
2294
2358
  if (rId && imageMap[rId]) {
2295
- result += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
2359
+ chunks[currentChunkIndex] += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
2296
2360
  }
2297
2361
  }
2298
2362
  const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
2299
- if (runs.length === 0 && !result) {
2300
- return DOMPurify2__default.default.sanitize(pElement.textContent || "");
2363
+ if (runs.length === 0 && !chunks[currentChunkIndex]) {
2364
+ chunks[currentChunkIndex] = DOMPurify6__default.default.sanitize(pElement.textContent || "");
2365
+ return chunks;
2301
2366
  }
2302
2367
  for (const r of runs) {
2303
2368
  const blip = r.getElementsByTagNameNS("*", "blip")[0] || r.getElementsByTagNameNS("*", "imagedata")[0];
2304
2369
  const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
2305
2370
  if (rId && imageMap[rId]) {
2306
- result += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
2371
+ chunks[currentChunkIndex] += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
2307
2372
  }
2308
- const brs = r.getElementsByTagNameNS("*", "br");
2309
- for (let i = 0; i < brs.length; i++) {
2310
- result += "<br/>";
2373
+ const brs = Array.from(r.getElementsByTagNameNS("*", "br"));
2374
+ for (const br of brs) {
2375
+ const type = br.getAttribute("w:type") || br.getAttribute("type");
2376
+ if (type === "page") {
2377
+ chunks.push("");
2378
+ currentChunkIndex++;
2379
+ } else {
2380
+ chunks[currentChunkIndex] += "<br/>";
2381
+ }
2311
2382
  }
2312
2383
  const tabs = r.getElementsByTagNameNS("*", "tab");
2313
2384
  if (tabs.length > 0) {
2314
- result += "&emsp;";
2385
+ chunks[currentChunkIndex] += "&emsp;";
2315
2386
  }
2316
2387
  const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
2317
2388
  const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
@@ -2325,7 +2396,7 @@ var DocxPlugin = class {
2325
2396
  const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
2326
2397
  let text = texts.map((t) => t.textContent || "").join("");
2327
2398
  if (!text) continue;
2328
- text = DOMPurify2__default.default.sanitize(text);
2399
+ text = DOMPurify6__default.default.sanitize(text);
2329
2400
  let styles = "";
2330
2401
  if (isBold) styles += "font-weight: bold; ";
2331
2402
  if (isItalic) styles += "font-style: italic; ";
@@ -2337,12 +2408,12 @@ var DocxPlugin = class {
2337
2408
  if (!isNaN(pt) && pt > 0) styles += `font-size: ${pt}pt; `;
2338
2409
  }
2339
2410
  if (styles) {
2340
- result += `<span style="${styles}">${text}</span>`;
2411
+ chunks[currentChunkIndex] += `<span style="${styles}">${text}</span>`;
2341
2412
  } else {
2342
- result += text;
2413
+ chunks[currentChunkIndex] += text;
2343
2414
  }
2344
2415
  }
2345
- return result;
2416
+ return chunks;
2346
2417
  }
2347
2418
  renderBinaryDocFallback(ctx, wrapper) {
2348
2419
  const card = document.createElement("div");
@@ -2359,14 +2430,14 @@ var DocxPlugin = class {
2359
2430
  const wordDocStream = cfbf.readStream("WordDocument");
2360
2431
  if (wordDocStream && wordDocStream.length >= 512) {
2361
2432
  const text2 = this.extractReadableStrings(wordDocStream);
2362
- card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify2__default.default.sanitize(text2)}</div>`;
2433
+ card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text2)}</div>`;
2363
2434
  wrapper.appendChild(card);
2364
2435
  return;
2365
2436
  }
2366
2437
  } catch {
2367
2438
  }
2368
2439
  const text = this.extractReadableStrings(new Uint8Array(ctx.buffer));
2369
- card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify2__default.default.sanitize(text)}</div>`;
2440
+ card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text)}</div>`;
2370
2441
  wrapper.appendChild(card);
2371
2442
  }
2372
2443
  extractReadableStrings(bytes) {
@@ -2965,41 +3036,94 @@ var CodePlugin = class {
2965
3036
  async render(ctx) {
2966
3037
  const decoder = new TextDecoder("utf-8");
2967
3038
  const fullText = decoder.decode(ctx.buffer);
2968
- const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
2969
- const rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
3039
+ const extRaw = ctx.metadata.extension?.toLowerCase();
3040
+ const mimeRaw = ctx.metadata.mimeType?.toLowerCase();
3041
+ const isTxt = extRaw === ".txt" || mimeRaw === "text/plain" && (!extRaw || !this.extensions.filter((e) => e !== ".txt").includes(extRaw));
3042
+ let rawPages = [];
3043
+ if (isTxt) {
3044
+ const explicitPages = fullText.split(/(?:\f|\x0C)/);
3045
+ for (const ep of explicitPages) {
3046
+ const lines = ep.split(/\r?\n/);
3047
+ let currentChunk = [];
3048
+ for (let i = 0; i < lines.length; i++) {
3049
+ currentChunk.push(lines[i]);
3050
+ if (currentChunk.length >= 46) {
3051
+ rawPages.push(currentChunk.join("\n"));
3052
+ currentChunk = [];
3053
+ }
3054
+ }
3055
+ if (currentChunk.length > 0 || lines.length === 0) {
3056
+ rawPages.push(currentChunk.join("\n"));
3057
+ }
3058
+ }
3059
+ if (rawPages.length === 0) rawPages = [""];
3060
+ } else {
3061
+ const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
3062
+ rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
3063
+ }
2970
3064
  const totalPages = Math.max(1, rawPages.length);
2971
3065
  let currentPage = 1;
2972
3066
  const container = document.createElement("div");
2973
3067
  container.style.width = "100%";
2974
3068
  container.style.height = "100%";
2975
3069
  container.style.overflow = "auto";
2976
- container.style.backgroundColor = "#1e1e1e";
2977
- container.style.color = "#d4d4d4";
2978
- container.style.padding = "16px";
2979
- container.style.boxSizing = "border-box";
2980
3070
  let fontSize = 13;
2981
3071
  let rotation = 0;
3072
+ let zoomLevel = 1;
2982
3073
  const pre = document.createElement("pre");
2983
- pre.style.margin = "0";
2984
- pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
2985
- pre.style.fontSize = `${fontSize}px`;
2986
- pre.style.lineHeight = "1.5";
2987
- pre.style.whiteSpace = "pre-wrap";
2988
- pre.style.wordBreak = "break-all";
2989
3074
  const code = document.createElement("code");
3075
+ if (isTxt) {
3076
+ container.style.backgroundColor = "#f1f5f9";
3077
+ container.style.padding = "32px";
3078
+ container.style.boxSizing = "border-box";
3079
+ container.style.display = "flex";
3080
+ container.style.flexDirection = "column";
3081
+ container.style.alignItems = "center";
3082
+ pre.style.margin = "0";
3083
+ pre.style.fontFamily = "Consolas, 'Courier New', monospace";
3084
+ pre.style.fontSize = "13px";
3085
+ pre.style.color = "#1e293b";
3086
+ pre.style.lineHeight = "1.5";
3087
+ pre.style.whiteSpace = "pre-wrap";
3088
+ pre.style.wordBreak = "break-word";
3089
+ pre.style.backgroundColor = "#ffffff";
3090
+ pre.style.width = "816px";
3091
+ pre.style.minHeight = "1056px";
3092
+ pre.style.padding = "72px 56px";
3093
+ pre.style.boxSizing = "border-box";
3094
+ pre.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)";
3095
+ pre.style.borderRadius = "4px";
3096
+ pre.style.transformOrigin = "top center";
3097
+ } else {
3098
+ container.style.backgroundColor = "#1e1e1e";
3099
+ container.style.color = "#d4d4d4";
3100
+ container.style.padding = "16px";
3101
+ container.style.boxSizing = "border-box";
3102
+ pre.style.margin = "0";
3103
+ pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
3104
+ pre.style.fontSize = `${fontSize}px`;
3105
+ pre.style.lineHeight = "1.5";
3106
+ pre.style.whiteSpace = "pre-wrap";
3107
+ pre.style.wordBreak = "break-all";
3108
+ pre.style.transformOrigin = "top left";
3109
+ }
2990
3110
  const ext = (ctx.metadata.extension || "").replace(".", "");
2991
3111
  const renderCodePage = (text) => {
2992
- try {
2993
- if (ext && hljs__default.default.getLanguage(ext)) {
2994
- code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
2995
- } else {
2996
- code.innerHTML = hljs__default.default.highlightAuto(text).value;
2997
- }
2998
- } catch {
3112
+ if (isTxt) {
2999
3113
  code.textContent = text;
3114
+ } else {
3115
+ try {
3116
+ if (ext && hljs__default.default.getLanguage(ext)) {
3117
+ code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
3118
+ } else {
3119
+ code.innerHTML = hljs__default.default.highlightAuto(text).value;
3120
+ }
3121
+ } catch {
3122
+ code.textContent = text;
3123
+ }
3000
3124
  }
3001
3125
  };
3002
- renderCodePage(rawPages[0] || fullText);
3126
+ renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
3003
3127
  pre.appendChild(code);
3004
3128
  container.appendChild(pre);
3005
3129
  let indicator = null;
@@ -3008,15 +3132,22 @@ var CodePlugin = class {
3008
3132
  indicator.className = "fp-code-page-indicator";
3009
3133
  indicator.style.position = "sticky";
3010
3134
  indicator.style.bottom = "16px";
3011
- indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
3012
- indicator.style.backdropFilter = "blur(8px)";
3013
- indicator.style.color = "#f8fafc";
3135
+ if (isTxt) {
3136
+ indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
3137
+ indicator.style.color = "#334155";
3138
+ indicator.style.border = "1px solid #e2e8f0";
3139
+ indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
3140
+ } else {
3141
+ indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
3142
+ indicator.style.color = "#f8fafc";
3143
+ indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
3144
+ indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
3145
+ indicator.style.backdropFilter = "blur(8px)";
3146
+ }
3014
3147
  indicator.style.fontSize = "12px";
3015
3148
  indicator.style.fontWeight = "600";
3016
3149
  indicator.style.padding = "5px 14px";
3017
3150
  indicator.style.borderRadius = "20px";
3018
- indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
3019
- indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
3020
3151
  indicator.style.zIndex = "10";
3021
3152
  indicator.style.userSelect = "none";
3022
3153
  indicator.style.pointerEvents = "none";
@@ -3027,7 +3158,7 @@ var CodePlugin = class {
3027
3158
  }
3028
3159
  const showPage = (pageNum) => {
3029
3160
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
3030
- renderCodePage(rawPages[currentPage - 1] || fullText);
3161
+ renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
3031
3162
  if (indicator) {
3032
3163
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
3033
3164
  }
@@ -3043,39 +3174,57 @@ var CodePlugin = class {
3043
3174
  ctx.container.innerHTML = "";
3044
3175
  };
3045
3176
  ctx.signal.addEventListener("abort", cleanup);
3177
+ const updateTransform = () => {
3178
+ if (isTxt) {
3179
+ pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
3180
+ } else {
3181
+ pre.style.transform = `rotate(${rotation}deg)`;
3182
+ pre.style.fontSize = `${fontSize}px`;
3183
+ }
3184
+ };
3046
3185
  return {
3047
3186
  destroy: cleanup,
3048
3187
  getPageCount: () => totalPages,
3049
3188
  getCurrentPage: () => currentPage,
3050
3189
  goToPage: (page) => showPage(page),
3051
3190
  zoomIn: () => {
3052
- fontSize = Math.min(32, fontSize + 2);
3053
- pre.style.fontSize = `${fontSize}px`;
3191
+ if (isTxt) {
3192
+ zoomLevel = Math.min(3, zoomLevel + 0.1);
3193
+ } else {
3194
+ fontSize = Math.min(32, fontSize + 2);
3195
+ }
3196
+ updateTransform();
3054
3197
  },
3055
3198
  zoomOut: () => {
3056
- fontSize = Math.max(8, fontSize - 2);
3057
- pre.style.fontSize = `${fontSize}px`;
3199
+ if (isTxt) {
3200
+ zoomLevel = Math.max(0.1, zoomLevel - 0.1);
3201
+ } else {
3202
+ fontSize = Math.max(8, fontSize - 2);
3203
+ }
3204
+ updateTransform();
3058
3205
  },
3059
- getZoom: () => fontSize / 13,
3206
+ getZoom: () => isTxt ? zoomLevel : fontSize / 13,
3060
3207
  setZoom: (level) => {
3061
- fontSize = Math.round(13 * level);
3062
- pre.style.fontSize = `${fontSize}px`;
3208
+ if (isTxt) {
3209
+ zoomLevel = level;
3210
+ } else {
3211
+ fontSize = Math.round(13 * level);
3212
+ }
3213
+ updateTransform();
3063
3214
  },
3064
3215
  fitToPage: () => {
3065
3216
  fontSize = 13;
3066
3217
  rotation = 0;
3067
- pre.style.fontSize = "13px";
3068
- pre.style.transform = "none";
3218
+ zoomLevel = 1;
3219
+ updateTransform();
3069
3220
  },
3070
3221
  rotateCW: () => {
3071
3222
  rotation = (rotation + 90) % 360;
3072
- pre.style.transform = `rotate(${rotation}deg)`;
3073
- pre.style.transformOrigin = "top left";
3223
+ updateTransform();
3074
3224
  },
3075
3225
  rotateCCW: () => {
3076
3226
  rotation = (rotation - 90 + 360) % 360;
3077
- pre.style.transform = `rotate(${rotation}deg)`;
3078
- pre.style.transformOrigin = "top left";
3227
+ updateTransform();
3079
3228
  },
3080
3229
  download: () => {
3081
3230
  const mimeType = ctx.metadata.mimeType || "text/plain";
@@ -3374,7 +3523,7 @@ var MarkdownPlugin = class {
3374
3523
  gfm: true,
3375
3524
  breaks: true
3376
3525
  });
3377
- const cleanHtml = DOMPurify2__default.default.sanitize(rawHtml, {
3526
+ const cleanHtml = DOMPurify6__default.default.sanitize(rawHtml, {
3378
3527
  USE_PROFILES: { html: true }
3379
3528
  });
3380
3529
  const wrapper = document.createElement("div");
@@ -4010,6 +4159,14 @@ var RtfPlugin = class {
4010
4159
  group: "actions",
4011
4160
  execute: () => instance.download?.()
4012
4161
  },
4162
+ {
4163
+ id: "copy",
4164
+ icon: "copy",
4165
+ label: "Copy Text",
4166
+ type: "button",
4167
+ group: "actions",
4168
+ execute: () => instance.copy?.()
4169
+ },
4013
4170
  {
4014
4171
  id: "print",
4015
4172
  icon: "print",
@@ -4071,14 +4228,31 @@ var RtfPlugin = class {
4071
4228
  } catch (err) {
4072
4229
  console.warn("[RtfPlugin] RTF render error, fallback text:", err);
4073
4230
  const text = new TextDecoder("latin1").decode(ctx.buffer);
4074
- const clean = text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "");
4075
- const pre = document.createElement("pre");
4076
- pre.style.whiteSpace = "pre-wrap";
4077
- pre.style.fontFamily = "serif";
4078
- pre.style.color = "#333";
4079
- pre.textContent = clean;
4080
- wrapper.appendChild(pre);
4081
- pageElements = [pre];
4231
+ const rawPages = text.split(/\\page\b/).map((segment) => {
4232
+ return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
4233
+ }).filter((p) => p.length > 0);
4234
+ const pages = rawPages.length > 0 ? rawPages : [text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim()];
4235
+ for (let i = 0; i < pages.length; i++) {
4236
+ const pageCard = document.createElement("div");
4237
+ pageCard.className = "fp-rtf-page-card";
4238
+ pageCard.style.backgroundColor = "#ffffff";
4239
+ pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
4240
+ pageCard.style.borderRadius = "4px";
4241
+ pageCard.style.padding = "72px 56px";
4242
+ pageCard.style.width = "816px";
4243
+ pageCard.style.minHeight = "1056px";
4244
+ pageCard.style.maxWidth = "100%";
4245
+ pageCard.style.boxSizing = "border-box";
4246
+ pageCard.style.fontFamily = "serif";
4247
+ pageCard.style.fontSize = "12pt";
4248
+ pageCard.style.lineHeight = "1.6";
4249
+ pageCard.style.color = "#1e293b";
4250
+ pageCard.style.whiteSpace = "pre-wrap";
4251
+ pageCard.style.display = i === 0 ? "block" : "none";
4252
+ pageCard.textContent = pages[i];
4253
+ wrapper.appendChild(pageCard);
4254
+ pageElements.push(pageCard);
4255
+ }
4082
4256
  }
4083
4257
  const totalPages = Math.max(1, pageElements.length);
4084
4258
  let currentPage = 1;
@@ -4166,6 +4340,10 @@ var RtfPlugin = class {
4166
4340
  a.click();
4167
4341
  URL.revokeObjectURL(url);
4168
4342
  },
4343
+ copy: () => {
4344
+ const text = wrapper.textContent || "";
4345
+ navigator.clipboard?.writeText(text);
4346
+ },
4169
4347
  print: () => {
4170
4348
  window.print();
4171
4349
  }
@@ -4240,7 +4418,7 @@ var HtmlPreviewPlugin = class {
4240
4418
  }
4241
4419
  async render(ctx) {
4242
4420
  const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
4243
- const sanitized = DOMPurify2__default.default.sanitize(rawHtml, {
4421
+ const sanitized = DOMPurify6__default.default.sanitize(rawHtml, {
4244
4422
  WHOLE_DOCUMENT: true,
4245
4423
  ADD_TAGS: ["style", "link"],
4246
4424
  ADD_ATTR: ["target", "rel"]
@@ -4506,14 +4684,97 @@ var OpenDocumentPlugin = class {
4506
4684
  wrapper.textContent = contentDoc.documentElement.textContent || "Formula content";
4507
4685
  }
4508
4686
  } else {
4509
- wrapper.style.maxWidth = "850px";
4510
- wrapper.style.padding = "48px";
4687
+ wrapper.style.maxWidth = "none";
4688
+ wrapper.style.padding = "0";
4511
4689
  wrapper.style.minHeight = "100%";
4690
+ wrapper.style.backgroundColor = "transparent";
4691
+ wrapper.style.boxShadow = "none";
4692
+ wrapper.style.position = "relative";
4693
+ const dims = this.getPageDimensions(stylesDoc, contentDoc);
4512
4694
  const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
4513
- wrapper.innerHTML = DOMPurify2__default.default.sanitize(bodyHtml, {
4514
- ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub"],
4695
+ const tempDiv = document.createElement("div");
4696
+ tempDiv.style.width = `${dims.width - dims.marginLeft - dims.marginRight}px`;
4697
+ tempDiv.style.position = "absolute";
4698
+ tempDiv.style.visibility = "hidden";
4699
+ tempDiv.innerHTML = DOMPurify6__default.default.sanitize(bodyHtml, {
4700
+ ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub", "hr"],
4515
4701
  ADD_ATTR: ["style", "colspan", "rowspan"]
4516
4702
  });
4703
+ document.body.appendChild(tempDiv);
4704
+ const contentHeight = dims.height - dims.marginTop - dims.marginBottom;
4705
+ const pageElements = [[]];
4706
+ let currentHeight = 0;
4707
+ let currentPageIdx = 0;
4708
+ Array.from(tempDiv.children).forEach((child) => {
4709
+ const el = child;
4710
+ const style = el.getAttribute("style") || "";
4711
+ const isBreakBefore = style.includes("page-break-before: always");
4712
+ const isBreakAfter = style.includes("page-break-after: always");
4713
+ const isSoftBreak = el.classList.contains("odf-page-break");
4714
+ if (isBreakBefore) {
4715
+ if (pageElements[currentPageIdx].length > 0) {
4716
+ currentPageIdx++;
4717
+ pageElements.push([]);
4718
+ currentHeight = 0;
4719
+ }
4720
+ }
4721
+ const h2 = el.offsetHeight || 0;
4722
+ if (currentHeight + h2 > contentHeight && pageElements[currentPageIdx].length > 0 && !isSoftBreak) {
4723
+ currentPageIdx++;
4724
+ pageElements.push([]);
4725
+ currentHeight = 0;
4726
+ }
4727
+ if (!isSoftBreak) {
4728
+ pageElements[currentPageIdx].push(el.cloneNode(true));
4729
+ currentHeight += h2;
4730
+ }
4731
+ if (isBreakAfter || isSoftBreak) {
4732
+ currentPageIdx++;
4733
+ pageElements.push([]);
4734
+ currentHeight = 0;
4735
+ }
4736
+ });
4737
+ document.body.removeChild(tempDiv);
4738
+ if (pageElements.length > 1 && pageElements[pageElements.length - 1].length === 0) {
4739
+ pageElements.pop();
4740
+ }
4741
+ totalPages = Math.max(1, pageElements.length);
4742
+ pageElements.forEach((elements, idx) => {
4743
+ const page = document.createElement("div");
4744
+ page.className = `fp-odt-page fp-odt-page-${idx + 1}`;
4745
+ page.style.width = `${dims.width}px`;
4746
+ page.style.minHeight = `${dims.height}px`;
4747
+ page.style.padding = `${dims.marginTop}px ${dims.marginRight}px ${dims.marginBottom}px ${dims.marginLeft}px`;
4748
+ page.style.margin = "0 auto";
4749
+ page.style.backgroundColor = "#ffffff";
4750
+ page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
4751
+ page.style.borderRadius = "4px";
4752
+ page.style.boxSizing = "border-box";
4753
+ page.style.display = idx === 0 ? "block" : "none";
4754
+ page.style.position = "absolute";
4755
+ page.style.top = "0";
4756
+ page.style.left = "50%";
4757
+ page.style.transform = "translateX(-50%)";
4758
+ elements.forEach((el) => page.appendChild(el));
4759
+ wrapper.appendChild(page);
4760
+ slides.push(page);
4761
+ });
4762
+ const pageIndicator = document.createElement("div");
4763
+ pageIndicator.className = "fp-odt-page-indicator";
4764
+ pageIndicator.style.position = "sticky";
4765
+ pageIndicator.style.bottom = "16px";
4766
+ pageIndicator.style.left = "50%";
4767
+ pageIndicator.style.transform = "translateX(-50%)";
4768
+ pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
4769
+ pageIndicator.style.color = "#fff";
4770
+ pageIndicator.style.padding = "6px 12px";
4771
+ pageIndicator.style.borderRadius = "16px";
4772
+ pageIndicator.style.fontSize = "12px";
4773
+ pageIndicator.style.zIndex = "100";
4774
+ pageIndicator.style.display = "inline-block";
4775
+ pageIndicator.style.width = "fit-content";
4776
+ pageIndicator.textContent = `Page 1 of ${totalPages}`;
4777
+ container.appendChild(pageIndicator);
4517
4778
  }
4518
4779
  const cleanup = () => {
4519
4780
  imageUrls.forEach((url) => URL.revokeObjectURL(url));
@@ -4522,11 +4783,15 @@ var OpenDocumentPlugin = class {
4522
4783
  };
4523
4784
  ctx.signal.addEventListener("abort", cleanup);
4524
4785
  const goToPage = (page) => {
4525
- if (!isPresentation || page < 1 || page > totalPages) return;
4786
+ if (page < 1 || page > totalPages) return;
4526
4787
  currentPage = page;
4527
4788
  slides.forEach((s, idx) => {
4528
4789
  s.style.display = idx === page - 1 ? "block" : "none";
4529
4790
  });
4791
+ const indicator = container.querySelector(".fp-odt-page-indicator");
4792
+ if (indicator) {
4793
+ indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4794
+ }
4530
4795
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4531
4796
  };
4532
4797
  return {
@@ -4595,6 +4860,43 @@ var OpenDocumentPlugin = class {
4595
4860
  }
4596
4861
  };
4597
4862
  }
4863
+ getPageDimensions(stylesDoc, contentDoc) {
4864
+ let width = 850;
4865
+ let height = 1123;
4866
+ let marginTop = 48;
4867
+ let marginBottom = 48;
4868
+ let marginLeft = 48;
4869
+ let marginRight = 48;
4870
+ const parseUnit = (val) => {
4871
+ if (!val) return null;
4872
+ if (val.endsWith("cm")) return parseFloat(val) * 37.8;
4873
+ if (val.endsWith("mm")) return parseFloat(val) * 3.78;
4874
+ if (val.endsWith("in")) return parseFloat(val) * 96;
4875
+ if (val.endsWith("pt")) return parseFloat(val) * 1.33;
4876
+ if (val.endsWith("px")) return parseFloat(val);
4877
+ return parseFloat(val);
4878
+ };
4879
+ const docs = [stylesDoc, contentDoc].filter(Boolean);
4880
+ for (const doc of docs) {
4881
+ const pageLayout = doc.querySelector("page-layout-properties, [page-width]");
4882
+ if (pageLayout) {
4883
+ const w = parseUnit(pageLayout.getAttribute("fo:page-width") || pageLayout.getAttribute("page-width"));
4884
+ const h2 = parseUnit(pageLayout.getAttribute("fo:page-height") || pageLayout.getAttribute("page-height"));
4885
+ const mt = parseUnit(pageLayout.getAttribute("fo:margin-top") || pageLayout.getAttribute("margin-top"));
4886
+ const mb = parseUnit(pageLayout.getAttribute("fo:margin-bottom") || pageLayout.getAttribute("margin-bottom"));
4887
+ const ml = parseUnit(pageLayout.getAttribute("fo:margin-left") || pageLayout.getAttribute("margin-left"));
4888
+ const mr = parseUnit(pageLayout.getAttribute("fo:margin-right") || pageLayout.getAttribute("margin-right"));
4889
+ if (w !== null) width = w;
4890
+ if (h2 !== null) height = h2;
4891
+ if (mt !== null) marginTop = mt;
4892
+ if (mb !== null) marginBottom = mb;
4893
+ if (ml !== null) marginLeft = ml;
4894
+ if (mr !== null) marginRight = mr;
4895
+ break;
4896
+ }
4897
+ }
4898
+ return { width, height, marginTop, marginBottom, marginLeft, marginRight };
4899
+ }
4598
4900
  extractStyles(stylesDoc, contentDoc) {
4599
4901
  const map = /* @__PURE__ */ new Map();
4600
4902
  const styleNodes = [];
@@ -4617,14 +4919,21 @@ var OpenDocumentPlugin = class {
4617
4919
  if (color) css += `color: ${color}; `;
4618
4920
  if (size) css += `font-size: ${size}; `;
4619
4921
  }
4620
- const paraProp = node.querySelector("paragraph-properties, [text-align]");
4922
+ let paraProp = node.querySelector("paragraph-properties, [text-align]");
4923
+ if (!paraProp) {
4924
+ paraProp = Array.from(node.children).find((c) => c.tagName.includes("paragraph-properties")) || null;
4925
+ }
4621
4926
  if (paraProp) {
4622
4927
  const align = paraProp.getAttribute("fo:text-align") || paraProp.getAttribute("text-align");
4623
4928
  const mt = paraProp.getAttribute("fo:margin-top") || paraProp.getAttribute("margin-top");
4624
4929
  const mb = paraProp.getAttribute("fo:margin-bottom") || paraProp.getAttribute("margin-bottom");
4930
+ const breakBefore = paraProp.getAttribute("fo:break-before") || paraProp.getAttribute("break-before");
4931
+ const breakAfter = paraProp.getAttribute("fo:break-after") || paraProp.getAttribute("break-after");
4625
4932
  if (align) css += `text-align: ${align}; `;
4626
4933
  if (mt) css += `margin-top: ${mt}; `;
4627
4934
  if (mb) css += `margin-bottom: ${mb}; `;
4935
+ if (breakBefore === "page") css += "page-break-before: always; ";
4936
+ if (breakAfter === "page") css += "page-break-after: always; ";
4628
4937
  }
4629
4938
  if (css) map.set(name, css);
4630
4939
  }
@@ -4709,6 +5018,8 @@ var OpenDocumentPlugin = class {
4709
5018
  result += "&emsp;";
4710
5019
  } else if (tag === "line-break") {
4711
5020
  result += "<br/>";
5021
+ } else if (tag === "soft-page-break") {
5022
+ result += '<hr class="odf-page-break" style="page-break-after: always; border: none; margin: 0; padding: 0; height: 0;" />';
4712
5023
  } else {
4713
5024
  result += el.textContent || "";
4714
5025
  }
@@ -4869,20 +5180,9 @@ var DocPlugin = class {
4869
5180
  container.style.overflow = "auto";
4870
5181
  container.style.padding = "32px 16px";
4871
5182
  container.style.backgroundColor = "#f1f5f9";
4872
- const wrapper = document.createElement("div");
4873
- wrapper.className = "fp-doc-wrapper";
4874
- wrapper.style.maxWidth = "850px";
4875
- wrapper.style.margin = "0 auto";
4876
- wrapper.style.backgroundColor = "#ffffff";
4877
- wrapper.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
4878
- wrapper.style.borderRadius = "4px";
4879
- wrapper.style.padding = "56px 48px";
4880
- wrapper.style.minHeight = "100%";
4881
- wrapper.style.transformOrigin = "top center";
4882
- wrapper.style.transition = "transform 0.2s ease";
4883
- wrapper.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
4884
- wrapper.style.color = "#1e293b";
4885
- container.appendChild(wrapper);
5183
+ container.style.display = "flex";
5184
+ container.style.justifyContent = "center";
5185
+ container.style.alignItems = "flex-start";
4886
5186
  ctx.container.appendChild(container);
4887
5187
  let scale = 1;
4888
5188
  let extractedRawText = "";
@@ -4909,21 +5209,27 @@ var DocPlugin = class {
4909
5209
  const rawPages = this.splitIntoPages(extractedRawText);
4910
5210
  const totalPages = Math.max(1, rawPages.length);
4911
5211
  let currentPage = 1;
4912
- wrapper.innerHTML = "";
4913
5212
  const pageCards = [];
4914
5213
  for (let i = 0; i < totalPages; i++) {
4915
5214
  const pageCard = document.createElement("div");
4916
5215
  pageCard.className = "fp-doc-page-card";
5216
+ pageCard.style.width = "816px";
5217
+ pageCard.style.height = "1056px";
4917
5218
  pageCard.style.backgroundColor = "#ffffff";
4918
5219
  pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
4919
5220
  pageCard.style.borderRadius = "4px";
4920
- pageCard.style.padding = "56px 48px";
4921
- pageCard.style.minHeight = "100%";
5221
+ pageCard.style.padding = "96px 72px";
5222
+ pageCard.style.boxSizing = "border-box";
5223
+ pageCard.style.overflow = "hidden";
4922
5224
  pageCard.style.display = i === 0 ? "block" : "none";
5225
+ pageCard.style.transformOrigin = "top center";
5226
+ pageCard.style.transition = "transform 0.2s ease";
5227
+ pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
5228
+ pageCard.style.color = "#1e293b";
4923
5229
  if (isFallback && i === 0) {
4924
5230
  pageCard.innerHTML = `
4925
5231
  <div style="border-bottom: 1px solid #e2e8f0; padding-bottom: 12px; margin-bottom: 24px;">
4926
- <h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify2__default.default.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
5232
+ <h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify6__default.default.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
4927
5233
  <span style="font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 4px;">Legacy Word 97-2003 Binary Preview</span>
4928
5234
  </div>
4929
5235
  ${this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document")}
@@ -4931,15 +5237,17 @@ var DocPlugin = class {
4931
5237
  } else {
4932
5238
  pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
4933
5239
  }
4934
- wrapper.appendChild(pageCard);
5240
+ container.appendChild(pageCard);
4935
5241
  pageCards.push(pageCard);
4936
5242
  }
4937
5243
  let indicator = null;
4938
5244
  if (totalPages > 1) {
4939
5245
  indicator = document.createElement("div");
4940
5246
  indicator.className = "fp-doc-page-indicator";
4941
- indicator.style.position = "sticky";
5247
+ indicator.style.position = "fixed";
4942
5248
  indicator.style.bottom = "16px";
5249
+ indicator.style.left = "50%";
5250
+ indicator.style.transform = "translateX(-50%)";
4943
5251
  indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
4944
5252
  indicator.style.backdropFilter = "blur(8px)";
4945
5253
  indicator.style.color = "#f8fafc";
@@ -4953,17 +5261,25 @@ var DocPlugin = class {
4953
5261
  indicator.style.userSelect = "none";
4954
5262
  indicator.style.pointerEvents = "none";
4955
5263
  indicator.style.textAlign = "center";
4956
- indicator.style.width = "fit-content";
4957
- indicator.style.margin = "16px auto 0";
4958
5264
  container.appendChild(indicator);
4959
5265
  }
5266
+ let rotation = 0;
5267
+ const applyTransform = () => {
5268
+ const activeCard = pageCards[currentPage - 1];
5269
+ if (activeCard) {
5270
+ activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
5271
+ }
5272
+ };
4960
5273
  const showPage = (pageNum) => {
4961
5274
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
4962
- if (totalPages > 1) {
4963
- pageCards.forEach((card, idx) => {
4964
- card.style.display = idx + 1 === currentPage ? "block" : "none";
4965
- });
4966
- }
5275
+ pageCards.forEach((card, idx) => {
5276
+ if (idx + 1 === currentPage) {
5277
+ card.style.display = "block";
5278
+ card.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
5279
+ } else {
5280
+ card.style.display = "none";
5281
+ }
5282
+ });
4967
5283
  if (indicator) {
4968
5284
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4969
5285
  }
@@ -4972,19 +5288,13 @@ var DocPlugin = class {
4972
5288
  if (totalPages > 1) {
4973
5289
  showPage(1);
4974
5290
  }
4975
- let rotation = 0;
4976
5291
  const calculateFitScale = () => {
4977
- const activeCard = pageCards[currentPage - 1] || wrapper;
4978
- const elW = activeCard.offsetWidth || 850;
4979
- const elH = activeCard.offsetHeight || 1e3;
5292
+ const elW = 816;
5293
+ const elH = 1056;
4980
5294
  const availW = Math.max(200, ctx.container.clientWidth - 48);
4981
5295
  const availH = Math.max(200, ctx.container.clientHeight - 80);
4982
5296
  return Math.min(1.1, Math.min(availW / elW, availH / elH));
4983
5297
  };
4984
- const applyTransform = () => {
4985
- wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4986
- wrapper.style.transformOrigin = "top center";
4987
- };
4988
5298
  setTimeout(() => {
4989
5299
  scale = calculateFitScale();
4990
5300
  applyTransform();
@@ -5142,8 +5452,28 @@ var DocPlugin = class {
5142
5452
  }
5143
5453
  splitIntoPages(text) {
5144
5454
  if (!text) return [""];
5145
- 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);
5146
- return parts.length > 0 ? parts : [text];
5455
+ 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);
5456
+ if (explicitParts.length === 0) explicitParts.push(text);
5457
+ const maxLinesPerPage = 48;
5458
+ const finalPages = [];
5459
+ for (const part of explicitParts) {
5460
+ const lines = part.split(/\r?\n/);
5461
+ let currentLines = [];
5462
+ let count = 0;
5463
+ for (const line of lines) {
5464
+ currentLines.push(line);
5465
+ count++;
5466
+ if (count >= maxLinesPerPage) {
5467
+ finalPages.push(currentLines.join("\n"));
5468
+ currentLines = [];
5469
+ count = 0;
5470
+ }
5471
+ }
5472
+ if (currentLines.length > 0) {
5473
+ finalPages.push(currentLines.join("\n"));
5474
+ }
5475
+ }
5476
+ return finalPages.length > 0 ? finalPages : [text];
5147
5477
  }
5148
5478
  /**
5149
5479
  * Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
@@ -5152,17 +5482,65 @@ var DocPlugin = class {
5152
5482
  const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
5153
5483
  let html = "";
5154
5484
  let inList = false;
5155
- for (const rawLine of lines) {
5156
- const line = rawLine.trim();
5485
+ let tableLines = [];
5486
+ const flushTable = () => {
5487
+ if (tableLines.length > 0) {
5488
+ html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
5489
+ for (const tLine of tableLines) {
5490
+ html += "<tr>";
5491
+ const cols = tLine.split(" ");
5492
+ for (const col of cols) {
5493
+ html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
5494
+ }
5495
+ html += "</tr>";
5496
+ }
5497
+ html += "</table>";
5498
+ tableLines = [];
5499
+ }
5500
+ };
5501
+ let i = 0;
5502
+ while (i < lines.length) {
5503
+ let line = lines[i];
5504
+ let tabCount = (line.match(/\t/g) || []).length;
5505
+ if (tabCount > 0) {
5506
+ let consecutiveTableLines = 1;
5507
+ let j = i + 1;
5508
+ while (j < lines.length) {
5509
+ const nextTabCount = (lines[j].match(/\t/g) || []).length;
5510
+ if (nextTabCount === tabCount) {
5511
+ consecutiveTableLines++;
5512
+ j++;
5513
+ } else {
5514
+ break;
5515
+ }
5516
+ }
5517
+ if (consecutiveTableLines >= 3) {
5518
+ if (inList) {
5519
+ html += "</ul>";
5520
+ inList = false;
5521
+ }
5522
+ tableLines = lines.slice(i, j);
5523
+ flushTable();
5524
+ i = j;
5525
+ continue;
5526
+ }
5527
+ }
5528
+ line = line.trim();
5157
5529
  if (!line) {
5158
5530
  if (inList) {
5159
5531
  html += "</ul>";
5160
5532
  inList = false;
5161
5533
  }
5534
+ html += '<div style="height: 1.15em;"></div>';
5535
+ i++;
5536
+ continue;
5537
+ }
5538
+ if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line)) {
5539
+ i++;
5162
5540
  continue;
5163
5541
  }
5164
- if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line)) continue;
5165
- if (line.includes("Normal.dot") || line.includes("Microsoft Word") || line.includes("Times New Roman") && line.length < 30) {
5542
+ if ((line.includes("Normal.dot") || line.includes("Microsoft Word") || line.includes("Times New Roman")) && line.length < 30) {
5543
+ i++;
5166
5544
  continue;
5167
5545
  }
5168
5546
  if (line.length < 60 && !line.endsWith(".") && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#"))) {
@@ -5170,24 +5548,26 @@ var DocPlugin = class {
5170
5548
  html += "</ul>";
5171
5549
  inList = false;
5172
5550
  }
5173
- 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>`;
5551
+ 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>`;
5174
5552
  } else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
5175
5553
  if (!inList) {
5176
5554
  html += '<ul style="margin: 8px 0; padding-left: 24px;">';
5177
5555
  inList = true;
5178
5556
  }
5179
5557
  const bulletText = line.replace(/^[•\-\*]\s*/, "");
5180
- html += `<li style="margin: 4px 0; line-height: 1.6;">${DOMPurify2__default.default.sanitize(bulletText)}</li>`;
5558
+ html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6__default.default.sanitize(bulletText)}</li>`;
5181
5559
  } else {
5182
5560
  if (inList) {
5183
5561
  html += "</ul>";
5184
5562
  inList = false;
5185
5563
  }
5186
- html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${DOMPurify2__default.default.sanitize(line)}</p>`;
5564
+ html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6__default.default.sanitize(line)}</p>`;
5187
5565
  }
5566
+ i++;
5188
5567
  }
5189
5568
  if (inList) html += "</ul>";
5190
- return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify2__default.default.sanitize(filename)})</p>`;
5569
+ flushTable();
5570
+ return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6__default.default.sanitize(filename)})</p>`;
5191
5571
  }
5192
5572
  };
5193
5573
  function docPlugin() {
@@ -5365,7 +5745,7 @@ var PptPlugin = class {
5365
5745
  if (s.pictureUrl) {
5366
5746
  contentHtml = `
5367
5747
  <div style="flex: 1; display: flex; justify-content: center; align-items: center; padding: 12px; overflow: hidden;">
5368
- <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;" />
5748
+ <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;" />
5369
5749
  </div>
5370
5750
  `;
5371
5751
  } else if (s.tableColumns.length > 0) {
@@ -5375,7 +5755,7 @@ var PptPlugin = class {
5375
5755
  <table style="width: 100%; border-collapse: collapse; border: 1px solid #cbd5e1; border-radius: 6px; overflow: hidden; background: #ffffff;">
5376
5756
  <thead>
5377
5757
  <tr style="background: #e2e8f0; color: #1e293b; font-weight: 600; font-size: 14px;">
5378
- ${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${DOMPurify2__default.default.sanitize(c)}</th>`).join("")}
5758
+ ${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${DOMPurify6__default.default.sanitize(c)}</th>`).join("")}
5379
5759
  </tr>
5380
5760
  </thead>
5381
5761
  <tbody>
@@ -5391,7 +5771,7 @@ var PptPlugin = class {
5391
5771
  } else {
5392
5772
  const pTags = s.paragraphs.map((p) => {
5393
5773
  const lines = p.split(/[\r\n]+/).map((l) => l.trim()).filter(Boolean);
5394
- 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("");
5774
+ 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("");
5395
5775
  }).join("");
5396
5776
  contentHtml = `
5397
5777
  <div style="flex: 1; overflow: auto; padding: 4px 8px; display: flex; flex-direction: column; justify-content: flex-start;">
@@ -5404,11 +5784,11 @@ var PptPlugin = class {
5404
5784
  <!-- Header Banner matching PowerPoint design -->
5405
5785
  <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;">
5406
5786
  <h1 style="margin: 0; font-size: 26px; font-weight: 700; color: #1e293b; letter-spacing: -0.3px;">
5407
- ${DOMPurify2__default.default.sanitize(s.title)}
5787
+ ${DOMPurify6__default.default.sanitize(s.title)}
5408
5788
  </h1>
5409
5789
  ${s.subtitle ? `
5410
5790
  <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);">
5411
- ${DOMPurify2__default.default.sanitize(s.subtitle)}
5791
+ ${DOMPurify6__default.default.sanitize(s.subtitle)}
5412
5792
  </span>
5413
5793
  ` : `
5414
5794
  <span style="font-size: 12px; color: #365314; font-weight: 600;">