@files-preview-app/preview-file 1.2.6 → 1.2.8

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
  }
@@ -465,7 +465,8 @@ function createElement(tag, attrs, ...children) {
465
465
  }
466
466
  var ICON_ZOOM_IN = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><line x1="11" y1="8" x2="11" y2="14"></line><line x1="8" y1="11" x2="14" y2="11"></line></svg>`;
467
467
  var ICON_ZOOM_OUT = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><line x1="8" y1="11" x2="14" y2="11"></line></svg>`;
468
- var ICON_FIT_PAGE = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" y1="3" x2="14" y2="10"></line><line x1="3" y1="21" x2="10" y2="14"></line></svg>`;
468
+ var ICON_FIT_PAGE = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"></rect><line x1="8" y1="12" x2="16" y2="12"></line><polyline points="11 9 8 12 11 15"></polyline><polyline points="13 9 16 12 13 15"></polyline></svg>`;
469
+ var ICON_FIT_WIDTH = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="2" y1="12" x2="22" y2="12"></line><polyline points="5 9 2 12 5 15"></polyline><polyline points="19 9 22 12 19 15"></polyline><line x1="2" y1="5" x2="2" y2="19"></line><line x1="22" y1="5" x2="22" y2="19"></line></svg>`;
469
470
  var ICON_ROTATE_CW = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"></polyline><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path></svg>`;
470
471
  var ICON_ROTATE_CCW = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"></polyline><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path></svg>`;
471
472
  var ICON_DOWNLOAD = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>`;
@@ -485,6 +486,7 @@ var ICON_MAP = {
485
486
  "zoom-in": ICON_ZOOM_IN,
486
487
  "zoom-out": ICON_ZOOM_OUT,
487
488
  "fit-page": ICON_FIT_PAGE,
489
+ "fit-width": ICON_FIT_WIDTH,
488
490
  "fit-slide": ICON_FIT_PAGE,
489
491
  "rotate-cw": ICON_ROTATE_CW,
490
492
  "rotate-ccw": ICON_ROTATE_CCW,
@@ -1431,6 +1433,7 @@ var PdfPlugin = class {
1431
1433
  let currentPage = 1;
1432
1434
  let zoomScale = 1;
1433
1435
  let rotation = 0;
1436
+ let fitMode = "width";
1434
1437
  let currentRenderTask = null;
1435
1438
  const renderPage = async (pageNum) => {
1436
1439
  if (currentRenderTask) {
@@ -1450,11 +1453,16 @@ var PdfPlugin = class {
1450
1453
  const containerWidth = container.clientWidth || 900;
1451
1454
  const containerHeight = container.clientHeight || 700;
1452
1455
  const unscaledVp = page.getViewport({ scale: 1, rotation });
1453
- const availWidth = Math.max(100, containerWidth - 48);
1454
- const availHeight = Math.max(100, containerHeight - 88);
1456
+ const availWidth = Math.max(280, containerWidth - 48);
1457
+ const availHeight = Math.max(280, containerHeight - 88);
1455
1458
  const scaleW = availWidth / unscaledVp.width;
1456
1459
  const scaleH = availHeight / unscaledVp.height;
1457
- const fitScale = Math.min(scaleW, scaleH);
1460
+ let fitScale;
1461
+ if (fitMode === "page") {
1462
+ fitScale = Math.max(0.5, Math.min(scaleW, scaleH));
1463
+ } else {
1464
+ fitScale = Math.max(0.65, Math.min(1.15, scaleW));
1465
+ }
1458
1466
  const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
1459
1467
  const pixelRatio = window.devicePixelRatio || 1;
1460
1468
  const viewport = page.getViewport({ scale: effectiveScale, rotation });
@@ -1480,7 +1488,19 @@ var PdfPlugin = class {
1480
1488
  }
1481
1489
  };
1482
1490
  await renderPage(1);
1491
+ let resizeTimer = null;
1492
+ const resizeObserver = new ResizeObserver(() => {
1493
+ if (resizeTimer) clearTimeout(resizeTimer);
1494
+ resizeTimer = setTimeout(() => {
1495
+ if (Math.abs(zoomScale - 1) < 0.05) {
1496
+ renderPage(currentPage);
1497
+ }
1498
+ }, 150);
1499
+ });
1500
+ resizeObserver.observe(container);
1483
1501
  const cleanup = () => {
1502
+ resizeObserver.disconnect();
1503
+ if (resizeTimer) clearTimeout(resizeTimer);
1484
1504
  if (currentRenderTask) {
1485
1505
  try {
1486
1506
  currentRenderTask.cancel();
@@ -1511,6 +1531,7 @@ var PdfPlugin = class {
1511
1531
  renderPage(currentPage);
1512
1532
  },
1513
1533
  fitToPage: () => {
1534
+ fitMode = fitMode === "width" ? "page" : "width";
1514
1535
  zoomScale = 1;
1515
1536
  rotation = 0;
1516
1537
  renderPage(currentPage);
@@ -2064,8 +2085,53 @@ var DocxPlugin = class {
2064
2085
  }
2065
2086
  }
2066
2087
  }
2067
- const sections = wrapper.querySelectorAll("section.docx");
2068
- const cards = wrapper.querySelectorAll(".fp-docx-page-card");
2088
+ let sections = Array.from(wrapper.querySelectorAll("section.docx"));
2089
+ const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
2090
+ if (sections.length === 1 && cards.length === 0) {
2091
+ const singleSec = sections[0];
2092
+ const pageH = 1056;
2093
+ const secH = singleSec.offsetHeight || singleSec.scrollHeight;
2094
+ if (secH > pageH * 1.25) {
2095
+ const children = Array.from(singleSec.children);
2096
+ if (children.length > 1) {
2097
+ const parent = singleSec.parentElement || wrapper;
2098
+ const newSections = [singleSec];
2099
+ singleSec.innerHTML = "";
2100
+ singleSec.style.minHeight = `${pageH}px`;
2101
+ singleSec.style.maxHeight = `${pageH}px`;
2102
+ singleSec.style.overflow = "hidden";
2103
+ singleSec.style.boxSizing = "border-box";
2104
+ let curSec = singleSec;
2105
+ let curH = 0;
2106
+ const maxH = pageH - 96;
2107
+ for (let i = 0; i < children.length; i++) {
2108
+ const child = children[i];
2109
+ curSec.appendChild(child);
2110
+ const chH = child.offsetHeight || 28;
2111
+ curH += chH;
2112
+ if (curH >= maxH && i < children.length - 1) {
2113
+ const nextSec = document.createElement("section");
2114
+ nextSec.className = singleSec.className;
2115
+ nextSec.style.cssText = singleSec.style.cssText;
2116
+ nextSec.style.width = singleSec.style.width || "816px";
2117
+ nextSec.style.minHeight = `${pageH}px`;
2118
+ nextSec.style.maxHeight = `${pageH}px`;
2119
+ nextSec.style.overflow = "hidden";
2120
+ nextSec.style.boxSizing = "border-box";
2121
+ nextSec.style.backgroundColor = "#ffffff";
2122
+ nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
2123
+ nextSec.style.borderRadius = "4px";
2124
+ nextSec.style.marginBottom = "24px";
2125
+ parent.appendChild(nextSec);
2126
+ newSections.push(nextSec);
2127
+ curSec = nextSec;
2128
+ curH = 0;
2129
+ }
2130
+ }
2131
+ sections = newSections;
2132
+ }
2133
+ }
2134
+ }
2069
2135
  const pageElements = sections.length > 0 ? sections : cards;
2070
2136
  const totalPages = Math.max(1, pageElements.length);
2071
2137
  let currentPage = 1;
@@ -2109,22 +2175,27 @@ var DocxPlugin = class {
2109
2175
  }
2110
2176
  scale = 1;
2111
2177
  let rotation = 0;
2112
- const calculateFitScale = () => {
2178
+ let fitMode = "width";
2179
+ const calculateFitScale = (mode = fitMode) => {
2113
2180
  const activeEl = pageElements[currentPage - 1] || wrapper.firstElementChild || wrapper;
2114
2181
  const elW = activeEl.offsetWidth || 816;
2115
- const elH = activeEl.offsetHeight || 1056;
2116
- const availW = Math.max(200, ctx.container.clientWidth - 48);
2117
- const availH = Math.max(200, ctx.container.clientHeight - 80);
2182
+ const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
2183
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
2184
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
2118
2185
  const sW = availW / elW;
2119
- const sH = availH / elH;
2120
- return Math.min(1.1, Math.min(sW, sH));
2186
+ const sH = availH / singlePageH;
2187
+ if (mode === "page") {
2188
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
2189
+ }
2190
+ return Math.max(0.65, Math.min(1.05, sW));
2121
2191
  };
2122
2192
  const applyTransform = () => {
2123
2193
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
2124
2194
  wrapper.style.transformOrigin = "top center";
2125
2195
  };
2126
2196
  setTimeout(() => {
2127
- scale = calculateFitScale();
2197
+ fitMode = "width";
2198
+ scale = calculateFitScale("width");
2128
2199
  applyTransform();
2129
2200
  }, 60);
2130
2201
  const cleanup = () => {
@@ -2158,7 +2229,8 @@ var DocxPlugin = class {
2158
2229
  applyTransform();
2159
2230
  },
2160
2231
  fitToPage: () => {
2161
- scale = calculateFitScale();
2232
+ fitMode = fitMode === "width" ? "page" : "width";
2233
+ scale = calculateFitScale(fitMode);
2162
2234
  rotation = 0;
2163
2235
  applyTransform();
2164
2236
  },
@@ -2228,90 +2300,149 @@ var DocxPlugin = class {
2228
2300
  console.warn("[DocxPlugin] Error parsing relationships:", relsErr);
2229
2301
  }
2230
2302
  }
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";
2303
+ const sectPrs = Array.from(doc.getElementsByTagNameNS("*", "sectPr"));
2304
+ const lastSectPr = sectPrs[sectPrs.length - 1];
2305
+ let defaultW = 12240;
2306
+ let defaultH = 15840;
2307
+ let margins = { top: 1440, right: 1440, bottom: 1440, left: 1440 };
2308
+ if (lastSectPr) {
2309
+ const pgSz = lastSectPr.getElementsByTagNameNS("*", "pgSz")[0];
2310
+ if (pgSz) {
2311
+ defaultW = parseInt(pgSz.getAttribute("w:w") || pgSz.getAttribute("w") || "12240", 10);
2312
+ defaultH = parseInt(pgSz.getAttribute("w:h") || pgSz.getAttribute("h") || "15840", 10);
2313
+ }
2314
+ const pgMar = lastSectPr.getElementsByTagNameNS("*", "pgMar")[0];
2315
+ if (pgMar) {
2316
+ margins.top = parseInt(pgMar.getAttribute("w:top") || pgMar.getAttribute("top") || "1440", 10);
2317
+ margins.bottom = parseInt(pgMar.getAttribute("w:bottom") || pgMar.getAttribute("bottom") || "1440", 10);
2318
+ margins.left = parseInt(pgMar.getAttribute("w:left") || pgMar.getAttribute("left") || "1440", 10);
2319
+ margins.right = parseInt(pgMar.getAttribute("w:right") || pgMar.getAttribute("right") || "1440", 10);
2320
+ }
2321
+ }
2322
+ const createPageCard = () => {
2323
+ const card = document.createElement("div");
2324
+ card.className = "fp-docx-page-card";
2325
+ card.style.backgroundColor = "#ffffff";
2326
+ card.style.borderRadius = "4px";
2327
+ card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
2328
+ card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
2329
+ card.style.color = "#1e293b";
2330
+ card.style.lineHeight = "1.6";
2331
+ card.style.boxSizing = "border-box";
2332
+ card.style.overflow = "hidden";
2333
+ card.style.position = "relative";
2334
+ card.style.marginBottom = "24px";
2335
+ card.style.width = `${defaultW / 15}px`;
2336
+ card.style.height = `${defaultH / 15}px`;
2337
+ card.style.padding = `${margins.top / 15}px ${margins.right / 15}px ${margins.bottom / 15}px ${margins.left / 15}px`;
2338
+ return card;
2339
+ };
2340
+ let currentCard = createPageCard();
2341
+ let currentHtml = "";
2342
+ const pages = [{ card: currentCard, html: "" }];
2343
+ const flushHtml = () => {
2344
+ pages[pages.length - 1].html += currentHtml;
2345
+ currentHtml = "";
2346
+ };
2347
+ const newPage = () => {
2348
+ flushHtml();
2349
+ currentCard = createPageCard();
2350
+ pages.push({ card: currentCard, html: "" });
2351
+ };
2240
2352
  const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
2241
- let html = "";
2242
2353
  for (const child of Array.from(body.children)) {
2243
2354
  const tag = child.localName || child.nodeName.split(":").pop();
2244
2355
  if (tag === "p") {
2245
2356
  const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
2246
2357
  const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
2247
2358
  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>`;
2359
+ const chunks = this.extractParagraphChunks(child, imageMap);
2360
+ for (let i = 0; i < chunks.length; i++) {
2361
+ if (i > 0) {
2362
+ newPage();
2363
+ }
2364
+ const textContent = chunks[i];
2365
+ if (!textContent.trim() && !textContent.includes("<img")) {
2366
+ currentHtml += '<div style="height: 10px;"></div>';
2367
+ continue;
2368
+ }
2369
+ const lowerStyle = styleVal.toLowerCase();
2370
+ if (lowerStyle.includes("title")) {
2371
+ 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>`;
2372
+ } else if (lowerStyle.includes("heading1") || styleVal === "1") {
2373
+ currentHtml += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
2374
+ } else if (lowerStyle.includes("heading2") || styleVal === "2") {
2375
+ currentHtml += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
2376
+ } else if (lowerStyle.includes("heading3") || styleVal === "3") {
2377
+ currentHtml += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
2378
+ } else if (numPr) {
2379
+ 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>`;
2380
+ } else {
2381
+ currentHtml += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
2382
+ }
2266
2383
  }
2267
2384
  } else if (tag === "tbl") {
2268
- html += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
2385
+ currentHtml += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
2269
2386
  const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
2270
2387
  rows.forEach((tr, rIdx) => {
2271
- html += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
2388
+ currentHtml += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
2272
2389
  const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
2273
2390
  cells.forEach((tc) => {
2274
2391
  const cellText = this.extractParagraphHtml(tc, imageMap);
2275
- html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || "&nbsp;"}</td>`;
2392
+ currentHtml += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || "&nbsp;"}</td>`;
2276
2393
  });
2277
- html += "</tr>";
2394
+ currentHtml += "</tr>";
2278
2395
  });
2279
- html += "</table>";
2396
+ currentHtml += "</table>";
2280
2397
  }
2281
2398
  }
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);
2399
+ flushHtml();
2400
+ for (const page of pages) {
2401
+ page.card.innerHTML = DOMPurify6__default.default.sanitize(page.html, {
2402
+ ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
2403
+ ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
2404
+ });
2405
+ wrapper.appendChild(page.card);
2406
+ }
2287
2407
  }
2288
2408
  extractParagraphHtml(pElement, imageMap = {}) {
2289
- let result = "";
2409
+ return this.extractParagraphChunks(pElement, imageMap).join("<br/>");
2410
+ }
2411
+ extractParagraphChunks(pElement, imageMap = {}) {
2412
+ const chunks = [""];
2413
+ let currentChunkIndex = 0;
2290
2414
  const drawings = Array.from(pElement.getElementsByTagNameNS("*", "drawing"));
2291
2415
  for (const drawing of drawings) {
2292
2416
  const blip = drawing.getElementsByTagNameNS("*", "blip")[0];
2293
2417
  const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
2294
2418
  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>`;
2419
+ 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
2420
  }
2297
2421
  }
2298
2422
  const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
2299
- if (runs.length === 0 && !result) {
2300
- return DOMPurify2__default.default.sanitize(pElement.textContent || "");
2423
+ if (runs.length === 0 && !chunks[currentChunkIndex]) {
2424
+ chunks[currentChunkIndex] = DOMPurify6__default.default.sanitize(pElement.textContent || "");
2425
+ return chunks;
2301
2426
  }
2302
2427
  for (const r of runs) {
2303
2428
  const blip = r.getElementsByTagNameNS("*", "blip")[0] || r.getElementsByTagNameNS("*", "imagedata")[0];
2304
2429
  const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
2305
2430
  if (rId && imageMap[rId]) {
2306
- result += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
2431
+ chunks[currentChunkIndex] += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
2307
2432
  }
2308
- const brs = r.getElementsByTagNameNS("*", "br");
2309
- for (let i = 0; i < brs.length; i++) {
2310
- result += "<br/>";
2433
+ const brs = Array.from(r.getElementsByTagNameNS("*", "br"));
2434
+ for (const br of brs) {
2435
+ const type = br.getAttribute("w:type") || br.getAttribute("type");
2436
+ if (type === "page") {
2437
+ chunks.push("");
2438
+ currentChunkIndex++;
2439
+ } else {
2440
+ chunks[currentChunkIndex] += "<br/>";
2441
+ }
2311
2442
  }
2312
2443
  const tabs = r.getElementsByTagNameNS("*", "tab");
2313
2444
  if (tabs.length > 0) {
2314
- result += "&emsp;";
2445
+ chunks[currentChunkIndex] += "&emsp;";
2315
2446
  }
2316
2447
  const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
2317
2448
  const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
@@ -2325,7 +2456,7 @@ var DocxPlugin = class {
2325
2456
  const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
2326
2457
  let text = texts.map((t) => t.textContent || "").join("");
2327
2458
  if (!text) continue;
2328
- text = DOMPurify2__default.default.sanitize(text);
2459
+ text = DOMPurify6__default.default.sanitize(text);
2329
2460
  let styles = "";
2330
2461
  if (isBold) styles += "font-weight: bold; ";
2331
2462
  if (isItalic) styles += "font-style: italic; ";
@@ -2337,12 +2468,12 @@ var DocxPlugin = class {
2337
2468
  if (!isNaN(pt) && pt > 0) styles += `font-size: ${pt}pt; `;
2338
2469
  }
2339
2470
  if (styles) {
2340
- result += `<span style="${styles}">${text}</span>`;
2471
+ chunks[currentChunkIndex] += `<span style="${styles}">${text}</span>`;
2341
2472
  } else {
2342
- result += text;
2473
+ chunks[currentChunkIndex] += text;
2343
2474
  }
2344
2475
  }
2345
- return result;
2476
+ return chunks;
2346
2477
  }
2347
2478
  renderBinaryDocFallback(ctx, wrapper) {
2348
2479
  const card = document.createElement("div");
@@ -2359,14 +2490,14 @@ var DocxPlugin = class {
2359
2490
  const wordDocStream = cfbf.readStream("WordDocument");
2360
2491
  if (wordDocStream && wordDocStream.length >= 512) {
2361
2492
  const text2 = this.extractReadableStrings(wordDocStream);
2362
- card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify2__default.default.sanitize(text2)}</div>`;
2493
+ card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text2)}</div>`;
2363
2494
  wrapper.appendChild(card);
2364
2495
  return;
2365
2496
  }
2366
2497
  } catch {
2367
2498
  }
2368
2499
  const text = this.extractReadableStrings(new Uint8Array(ctx.buffer));
2369
- card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify2__default.default.sanitize(text)}</div>`;
2500
+ card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify6__default.default.sanitize(text)}</div>`;
2370
2501
  wrapper.appendChild(card);
2371
2502
  }
2372
2503
  extractReadableStrings(bytes) {
@@ -2543,11 +2674,9 @@ var ExcelPlugin = class {
2543
2674
  const calculateFitScale = () => {
2544
2675
  const table = contentArea.querySelector("table");
2545
2676
  if (!table) return 1;
2546
- const availW = Math.max(200, container.clientWidth - 48);
2547
- const availH = Math.max(200, container.clientHeight - 80);
2677
+ const availW = Math.max(280, container.clientWidth - 48);
2548
2678
  const tW = table.offsetWidth || 800;
2549
- const tH = table.offsetHeight || 600;
2550
- return Math.min(1, Math.min(availW / tW, availH / tH));
2679
+ return Math.max(0.65, Math.min(1, availW / tW));
2551
2680
  };
2552
2681
  try {
2553
2682
  wb = XLSX__namespace.read(new Uint8Array(ctx.buffer), { type: "array", cellDates: true });
@@ -2965,41 +3094,94 @@ var CodePlugin = class {
2965
3094
  async render(ctx) {
2966
3095
  const decoder = new TextDecoder("utf-8");
2967
3096
  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);
3097
+ const extRaw = ctx.metadata.extension?.toLowerCase();
3098
+ const mimeRaw = ctx.metadata.mimeType?.toLowerCase();
3099
+ const isTxt = extRaw === ".txt" || mimeRaw === "text/plain" && (!extRaw || !this.extensions.filter((e) => e !== ".txt").includes(extRaw));
3100
+ let rawPages = [];
3101
+ if (isTxt) {
3102
+ const explicitPages = fullText.split(/(?:\f|\x0C)/);
3103
+ for (const ep of explicitPages) {
3104
+ const lines = ep.split(/\r?\n/);
3105
+ let currentChunk = [];
3106
+ for (let i = 0; i < lines.length; i++) {
3107
+ currentChunk.push(lines[i]);
3108
+ if (currentChunk.length >= 46) {
3109
+ rawPages.push(currentChunk.join("\n"));
3110
+ currentChunk = [];
3111
+ }
3112
+ }
3113
+ if (currentChunk.length > 0 || lines.length === 0) {
3114
+ rawPages.push(currentChunk.join("\n"));
3115
+ }
3116
+ }
3117
+ if (rawPages.length === 0) rawPages = [""];
3118
+ } else {
3119
+ const pageSplitRegex = /(?:\f|\x0C|(?:\r?\n|^)\s*[-=_]{3,}\s*(?:PAGE|Page|page break|Page Break)[\s\d\w-]*[-=_]{3,}\s*(?:\r?\n|$))/i;
3120
+ rawPages = fullText.split(pageSplitRegex).map((p) => p.trim()).filter((p) => p.length > 0);
3121
+ }
2970
3122
  const totalPages = Math.max(1, rawPages.length);
2971
3123
  let currentPage = 1;
2972
3124
  const container = document.createElement("div");
2973
3125
  container.style.width = "100%";
2974
3126
  container.style.height = "100%";
2975
3127
  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
3128
  let fontSize = 13;
2981
3129
  let rotation = 0;
3130
+ let zoomLevel = 1;
2982
3131
  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
3132
  const code = document.createElement("code");
3133
+ if (isTxt) {
3134
+ container.style.backgroundColor = "#f1f5f9";
3135
+ container.style.padding = "32px";
3136
+ container.style.boxSizing = "border-box";
3137
+ container.style.display = "flex";
3138
+ container.style.flexDirection = "column";
3139
+ container.style.alignItems = "center";
3140
+ pre.style.margin = "0";
3141
+ pre.style.fontFamily = "Consolas, 'Courier New', monospace";
3142
+ pre.style.fontSize = "13px";
3143
+ pre.style.color = "#1e293b";
3144
+ pre.style.lineHeight = "1.5";
3145
+ pre.style.whiteSpace = "pre-wrap";
3146
+ pre.style.wordBreak = "break-word";
3147
+ pre.style.backgroundColor = "#ffffff";
3148
+ pre.style.width = "816px";
3149
+ pre.style.minHeight = "1056px";
3150
+ pre.style.padding = "72px 56px";
3151
+ pre.style.boxSizing = "border-box";
3152
+ pre.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)";
3153
+ pre.style.borderRadius = "4px";
3154
+ pre.style.transformOrigin = "top center";
3155
+ } else {
3156
+ container.style.backgroundColor = "#1e1e1e";
3157
+ container.style.color = "#d4d4d4";
3158
+ container.style.padding = "16px";
3159
+ container.style.boxSizing = "border-box";
3160
+ pre.style.margin = "0";
3161
+ pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
3162
+ pre.style.fontSize = `${fontSize}px`;
3163
+ pre.style.lineHeight = "1.5";
3164
+ pre.style.whiteSpace = "pre-wrap";
3165
+ pre.style.wordBreak = "break-all";
3166
+ pre.style.transformOrigin = "top left";
3167
+ }
2990
3168
  const ext = (ctx.metadata.extension || "").replace(".", "");
2991
3169
  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 {
3170
+ if (isTxt) {
2999
3171
  code.textContent = text;
3172
+ } else {
3173
+ try {
3174
+ if (ext && hljs__default.default.getLanguage(ext)) {
3175
+ code.innerHTML = hljs__default.default.highlight(text, { language: ext }).value;
3176
+ } else {
3177
+ code.innerHTML = hljs__default.default.highlightAuto(text).value;
3178
+ }
3179
+ } catch {
3180
+ code.textContent = text;
3181
+ }
3000
3182
  }
3001
3183
  };
3002
- renderCodePage(rawPages[0] || fullText);
3184
+ renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
3003
3185
  pre.appendChild(code);
3004
3186
  container.appendChild(pre);
3005
3187
  let indicator = null;
@@ -3008,15 +3190,22 @@ var CodePlugin = class {
3008
3190
  indicator.className = "fp-code-page-indicator";
3009
3191
  indicator.style.position = "sticky";
3010
3192
  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";
3193
+ if (isTxt) {
3194
+ indicator.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
3195
+ indicator.style.color = "#334155";
3196
+ indicator.style.border = "1px solid #e2e8f0";
3197
+ indicator.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
3198
+ } else {
3199
+ indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
3200
+ indicator.style.color = "#f8fafc";
3201
+ indicator.style.border = "1px solid rgba(255, 255, 255, 0.15)";
3202
+ indicator.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.3)";
3203
+ indicator.style.backdropFilter = "blur(8px)";
3204
+ }
3014
3205
  indicator.style.fontSize = "12px";
3015
3206
  indicator.style.fontWeight = "600";
3016
3207
  indicator.style.padding = "5px 14px";
3017
3208
  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
3209
  indicator.style.zIndex = "10";
3021
3210
  indicator.style.userSelect = "none";
3022
3211
  indicator.style.pointerEvents = "none";
@@ -3027,7 +3216,7 @@ var CodePlugin = class {
3027
3216
  }
3028
3217
  const showPage = (pageNum) => {
3029
3218
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
3030
- renderCodePage(rawPages[currentPage - 1] || fullText);
3219
+ renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
3031
3220
  if (indicator) {
3032
3221
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
3033
3222
  }
@@ -3043,39 +3232,57 @@ var CodePlugin = class {
3043
3232
  ctx.container.innerHTML = "";
3044
3233
  };
3045
3234
  ctx.signal.addEventListener("abort", cleanup);
3235
+ const updateTransform = () => {
3236
+ if (isTxt) {
3237
+ pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
3238
+ } else {
3239
+ pre.style.transform = `rotate(${rotation}deg)`;
3240
+ pre.style.fontSize = `${fontSize}px`;
3241
+ }
3242
+ };
3046
3243
  return {
3047
3244
  destroy: cleanup,
3048
3245
  getPageCount: () => totalPages,
3049
3246
  getCurrentPage: () => currentPage,
3050
3247
  goToPage: (page) => showPage(page),
3051
3248
  zoomIn: () => {
3052
- fontSize = Math.min(32, fontSize + 2);
3053
- pre.style.fontSize = `${fontSize}px`;
3249
+ if (isTxt) {
3250
+ zoomLevel = Math.min(3, zoomLevel + 0.1);
3251
+ } else {
3252
+ fontSize = Math.min(32, fontSize + 2);
3253
+ }
3254
+ updateTransform();
3054
3255
  },
3055
3256
  zoomOut: () => {
3056
- fontSize = Math.max(8, fontSize - 2);
3057
- pre.style.fontSize = `${fontSize}px`;
3257
+ if (isTxt) {
3258
+ zoomLevel = Math.max(0.1, zoomLevel - 0.1);
3259
+ } else {
3260
+ fontSize = Math.max(8, fontSize - 2);
3261
+ }
3262
+ updateTransform();
3058
3263
  },
3059
- getZoom: () => fontSize / 13,
3264
+ getZoom: () => isTxt ? zoomLevel : fontSize / 13,
3060
3265
  setZoom: (level) => {
3061
- fontSize = Math.round(13 * level);
3062
- pre.style.fontSize = `${fontSize}px`;
3266
+ if (isTxt) {
3267
+ zoomLevel = level;
3268
+ } else {
3269
+ fontSize = Math.round(13 * level);
3270
+ }
3271
+ updateTransform();
3063
3272
  },
3064
3273
  fitToPage: () => {
3065
3274
  fontSize = 13;
3066
3275
  rotation = 0;
3067
- pre.style.fontSize = "13px";
3068
- pre.style.transform = "none";
3276
+ zoomLevel = isTxt ? Math.max(0.65, Math.min(1.05, (container.clientWidth - 48) / 816)) : 1;
3277
+ updateTransform();
3069
3278
  },
3070
3279
  rotateCW: () => {
3071
3280
  rotation = (rotation + 90) % 360;
3072
- pre.style.transform = `rotate(${rotation}deg)`;
3073
- pre.style.transformOrigin = "top left";
3281
+ updateTransform();
3074
3282
  },
3075
3283
  rotateCCW: () => {
3076
3284
  rotation = (rotation - 90 + 360) % 360;
3077
- pre.style.transform = `rotate(${rotation}deg)`;
3078
- pre.style.transformOrigin = "top left";
3285
+ updateTransform();
3079
3286
  },
3080
3287
  download: () => {
3081
3288
  const mimeType = ctx.metadata.mimeType || "text/plain";
@@ -3374,7 +3581,7 @@ var MarkdownPlugin = class {
3374
3581
  gfm: true,
3375
3582
  breaks: true
3376
3583
  });
3377
- const cleanHtml = DOMPurify2__default.default.sanitize(rawHtml, {
3584
+ const cleanHtml = DOMPurify6__default.default.sanitize(rawHtml, {
3378
3585
  USE_PROFILES: { html: true }
3379
3586
  });
3380
3587
  const wrapper = document.createElement("div");
@@ -4010,6 +4217,14 @@ var RtfPlugin = class {
4010
4217
  group: "actions",
4011
4218
  execute: () => instance.download?.()
4012
4219
  },
4220
+ {
4221
+ id: "copy",
4222
+ icon: "copy",
4223
+ label: "Copy Text",
4224
+ type: "button",
4225
+ group: "actions",
4226
+ execute: () => instance.copy?.()
4227
+ },
4013
4228
  {
4014
4229
  id: "print",
4015
4230
  icon: "print",
@@ -4040,20 +4255,27 @@ var RtfPlugin = class {
4040
4255
  let scale = 1;
4041
4256
  let rotation = 0;
4042
4257
  let pageElements = [];
4043
- const calculateFitScale = () => {
4258
+ let fitMode = "width";
4259
+ const calculateFitScale = (mode = fitMode) => {
4044
4260
  const activeEl = pageElements[currentPage - 1] || wrapper;
4045
4261
  const elW = activeEl.offsetWidth || 850;
4046
- const elH = activeEl.offsetHeight || 1e3;
4047
- const availW = Math.max(200, ctx.container.clientWidth - 48);
4048
- const availH = Math.max(200, ctx.container.clientHeight - 80);
4049
- return Math.min(1.1, Math.min(availW / elW, availH / elH));
4262
+ const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
4263
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
4264
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
4265
+ const sW = availW / elW;
4266
+ const sH = availH / singlePageH;
4267
+ if (mode === "page") {
4268
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
4269
+ }
4270
+ return Math.max(0.65, Math.min(1.05, sW));
4050
4271
  };
4051
4272
  const applyTransform = () => {
4052
4273
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4053
4274
  wrapper.style.transformOrigin = "top center";
4054
4275
  };
4055
4276
  setTimeout(() => {
4056
- scale = calculateFitScale();
4277
+ fitMode = "width";
4278
+ scale = calculateFitScale("width");
4057
4279
  applyTransform();
4058
4280
  }, 60);
4059
4281
  try {
@@ -4071,14 +4293,31 @@ var RtfPlugin = class {
4071
4293
  } catch (err) {
4072
4294
  console.warn("[RtfPlugin] RTF render error, fallback text:", err);
4073
4295
  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];
4296
+ const rawPages = text.split(/\\page\b/).map((segment) => {
4297
+ return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
4298
+ }).filter((p) => p.length > 0);
4299
+ const pages = rawPages.length > 0 ? rawPages : [text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim()];
4300
+ for (let i = 0; i < pages.length; i++) {
4301
+ const pageCard = document.createElement("div");
4302
+ pageCard.className = "fp-rtf-page-card";
4303
+ pageCard.style.backgroundColor = "#ffffff";
4304
+ pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
4305
+ pageCard.style.borderRadius = "4px";
4306
+ pageCard.style.padding = "72px 56px";
4307
+ pageCard.style.width = "816px";
4308
+ pageCard.style.minHeight = "1056px";
4309
+ pageCard.style.maxWidth = "100%";
4310
+ pageCard.style.boxSizing = "border-box";
4311
+ pageCard.style.fontFamily = "serif";
4312
+ pageCard.style.fontSize = "12pt";
4313
+ pageCard.style.lineHeight = "1.6";
4314
+ pageCard.style.color = "#1e293b";
4315
+ pageCard.style.whiteSpace = "pre-wrap";
4316
+ pageCard.style.display = i === 0 ? "block" : "none";
4317
+ pageCard.textContent = pages[i];
4318
+ wrapper.appendChild(pageCard);
4319
+ pageElements.push(pageCard);
4320
+ }
4082
4321
  }
4083
4322
  const totalPages = Math.max(1, pageElements.length);
4084
4323
  let currentPage = 1;
@@ -4145,7 +4384,8 @@ var RtfPlugin = class {
4145
4384
  applyTransform();
4146
4385
  },
4147
4386
  fitToPage: () => {
4148
- scale = calculateFitScale();
4387
+ fitMode = fitMode === "width" ? "page" : "width";
4388
+ scale = calculateFitScale(fitMode);
4149
4389
  rotation = 0;
4150
4390
  applyTransform();
4151
4391
  },
@@ -4166,6 +4406,10 @@ var RtfPlugin = class {
4166
4406
  a.click();
4167
4407
  URL.revokeObjectURL(url);
4168
4408
  },
4409
+ copy: () => {
4410
+ const text = wrapper.textContent || "";
4411
+ navigator.clipboard?.writeText(text);
4412
+ },
4169
4413
  print: () => {
4170
4414
  window.print();
4171
4415
  }
@@ -4240,7 +4484,7 @@ var HtmlPreviewPlugin = class {
4240
4484
  }
4241
4485
  async render(ctx) {
4242
4486
  const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
4243
- const sanitized = DOMPurify2__default.default.sanitize(rawHtml, {
4487
+ const sanitized = DOMPurify6__default.default.sanitize(rawHtml, {
4244
4488
  WHOLE_DOCUMENT: true,
4245
4489
  ADD_TAGS: ["style", "link"],
4246
4490
  ADD_ATTR: ["target", "rel"]
@@ -4460,19 +4704,29 @@ var OpenDocumentPlugin = class {
4460
4704
  ctx.container.appendChild(container);
4461
4705
  let scale = 1;
4462
4706
  let rotation = 0;
4463
- const calculateFitScale = () => {
4707
+ let fitMode = "width";
4708
+ const calculateFitScale = (mode = fitMode) => {
4464
4709
  const elW = wrapper.offsetWidth || 850;
4465
- const elH = wrapper.offsetHeight || (isPresentation ? 540 : 1e3);
4466
- const availW = Math.max(200, ctx.container.clientWidth - 48);
4467
- const availH = Math.max(200, ctx.container.clientHeight - 80);
4468
- return Math.min(1, Math.min(availW / elW, availH / elH));
4710
+ const singlePageH = Math.min(wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
4711
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
4712
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
4713
+ const sW = availW / elW;
4714
+ const sH = availH / (isPresentation ? 540 : singlePageH);
4715
+ if (isPresentation) {
4716
+ return Math.min(1, Math.min(sW, sH));
4717
+ }
4718
+ if (mode === "page") {
4719
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
4720
+ }
4721
+ return Math.max(0.65, Math.min(1.05, sW));
4469
4722
  };
4470
4723
  const applyTransform = () => {
4471
4724
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4472
4725
  wrapper.style.transformOrigin = "top center";
4473
4726
  };
4474
4727
  setTimeout(() => {
4475
- scale = calculateFitScale();
4728
+ fitMode = "width";
4729
+ scale = calculateFitScale("width");
4476
4730
  applyTransform();
4477
4731
  }, 60);
4478
4732
  let currentPage = 1;
@@ -4506,14 +4760,97 @@ var OpenDocumentPlugin = class {
4506
4760
  wrapper.textContent = contentDoc.documentElement.textContent || "Formula content";
4507
4761
  }
4508
4762
  } else {
4509
- wrapper.style.maxWidth = "850px";
4510
- wrapper.style.padding = "48px";
4763
+ wrapper.style.maxWidth = "none";
4764
+ wrapper.style.padding = "0";
4511
4765
  wrapper.style.minHeight = "100%";
4766
+ wrapper.style.backgroundColor = "transparent";
4767
+ wrapper.style.boxShadow = "none";
4768
+ wrapper.style.position = "relative";
4769
+ const dims = this.getPageDimensions(stylesDoc, contentDoc);
4512
4770
  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"],
4771
+ const tempDiv = document.createElement("div");
4772
+ tempDiv.style.width = `${dims.width - dims.marginLeft - dims.marginRight}px`;
4773
+ tempDiv.style.position = "absolute";
4774
+ tempDiv.style.visibility = "hidden";
4775
+ tempDiv.innerHTML = DOMPurify6__default.default.sanitize(bodyHtml, {
4776
+ ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub", "hr"],
4515
4777
  ADD_ATTR: ["style", "colspan", "rowspan"]
4516
4778
  });
4779
+ document.body.appendChild(tempDiv);
4780
+ const contentHeight = dims.height - dims.marginTop - dims.marginBottom;
4781
+ const pageElements = [[]];
4782
+ let currentHeight = 0;
4783
+ let currentPageIdx = 0;
4784
+ Array.from(tempDiv.children).forEach((child) => {
4785
+ const el = child;
4786
+ const style = el.getAttribute("style") || "";
4787
+ const isBreakBefore = style.includes("page-break-before: always");
4788
+ const isBreakAfter = style.includes("page-break-after: always");
4789
+ const isSoftBreak = el.classList.contains("odf-page-break");
4790
+ if (isBreakBefore) {
4791
+ if (pageElements[currentPageIdx].length > 0) {
4792
+ currentPageIdx++;
4793
+ pageElements.push([]);
4794
+ currentHeight = 0;
4795
+ }
4796
+ }
4797
+ const h2 = el.offsetHeight || 0;
4798
+ if (currentHeight + h2 > contentHeight && pageElements[currentPageIdx].length > 0 && !isSoftBreak) {
4799
+ currentPageIdx++;
4800
+ pageElements.push([]);
4801
+ currentHeight = 0;
4802
+ }
4803
+ if (!isSoftBreak) {
4804
+ pageElements[currentPageIdx].push(el.cloneNode(true));
4805
+ currentHeight += h2;
4806
+ }
4807
+ if (isBreakAfter || isSoftBreak) {
4808
+ currentPageIdx++;
4809
+ pageElements.push([]);
4810
+ currentHeight = 0;
4811
+ }
4812
+ });
4813
+ document.body.removeChild(tempDiv);
4814
+ if (pageElements.length > 1 && pageElements[pageElements.length - 1].length === 0) {
4815
+ pageElements.pop();
4816
+ }
4817
+ totalPages = Math.max(1, pageElements.length);
4818
+ pageElements.forEach((elements, idx) => {
4819
+ const page = document.createElement("div");
4820
+ page.className = `fp-odt-page fp-odt-page-${idx + 1}`;
4821
+ page.style.width = `${dims.width}px`;
4822
+ page.style.minHeight = `${dims.height}px`;
4823
+ page.style.padding = `${dims.marginTop}px ${dims.marginRight}px ${dims.marginBottom}px ${dims.marginLeft}px`;
4824
+ page.style.margin = "0 auto";
4825
+ page.style.backgroundColor = "#ffffff";
4826
+ page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
4827
+ page.style.borderRadius = "4px";
4828
+ page.style.boxSizing = "border-box";
4829
+ page.style.display = idx === 0 ? "block" : "none";
4830
+ page.style.position = "absolute";
4831
+ page.style.top = "0";
4832
+ page.style.left = "50%";
4833
+ page.style.transform = "translateX(-50%)";
4834
+ elements.forEach((el) => page.appendChild(el));
4835
+ wrapper.appendChild(page);
4836
+ slides.push(page);
4837
+ });
4838
+ const pageIndicator = document.createElement("div");
4839
+ pageIndicator.className = "fp-odt-page-indicator";
4840
+ pageIndicator.style.position = "sticky";
4841
+ pageIndicator.style.bottom = "16px";
4842
+ pageIndicator.style.left = "50%";
4843
+ pageIndicator.style.transform = "translateX(-50%)";
4844
+ pageIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
4845
+ pageIndicator.style.color = "#fff";
4846
+ pageIndicator.style.padding = "6px 12px";
4847
+ pageIndicator.style.borderRadius = "16px";
4848
+ pageIndicator.style.fontSize = "12px";
4849
+ pageIndicator.style.zIndex = "100";
4850
+ pageIndicator.style.display = "inline-block";
4851
+ pageIndicator.style.width = "fit-content";
4852
+ pageIndicator.textContent = `Page 1 of ${totalPages}`;
4853
+ container.appendChild(pageIndicator);
4517
4854
  }
4518
4855
  const cleanup = () => {
4519
4856
  imageUrls.forEach((url) => URL.revokeObjectURL(url));
@@ -4522,11 +4859,15 @@ var OpenDocumentPlugin = class {
4522
4859
  };
4523
4860
  ctx.signal.addEventListener("abort", cleanup);
4524
4861
  const goToPage = (page) => {
4525
- if (!isPresentation || page < 1 || page > totalPages) return;
4862
+ if (page < 1 || page > totalPages) return;
4526
4863
  currentPage = page;
4527
4864
  slides.forEach((s, idx) => {
4528
4865
  s.style.display = idx === page - 1 ? "block" : "none";
4529
4866
  });
4867
+ const indicator = container.querySelector(".fp-odt-page-indicator");
4868
+ if (indicator) {
4869
+ indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4870
+ }
4530
4871
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4531
4872
  };
4532
4873
  return {
@@ -4546,7 +4887,8 @@ var OpenDocumentPlugin = class {
4546
4887
  applyTransform();
4547
4888
  },
4548
4889
  fitToPage: () => {
4549
- scale = calculateFitScale();
4890
+ fitMode = fitMode === "width" ? "page" : "width";
4891
+ scale = calculateFitScale(fitMode);
4550
4892
  rotation = 0;
4551
4893
  applyTransform();
4552
4894
  },
@@ -4595,6 +4937,43 @@ var OpenDocumentPlugin = class {
4595
4937
  }
4596
4938
  };
4597
4939
  }
4940
+ getPageDimensions(stylesDoc, contentDoc) {
4941
+ let width = 850;
4942
+ let height = 1123;
4943
+ let marginTop = 48;
4944
+ let marginBottom = 48;
4945
+ let marginLeft = 48;
4946
+ let marginRight = 48;
4947
+ const parseUnit = (val) => {
4948
+ if (!val) return null;
4949
+ if (val.endsWith("cm")) return parseFloat(val) * 37.8;
4950
+ if (val.endsWith("mm")) return parseFloat(val) * 3.78;
4951
+ if (val.endsWith("in")) return parseFloat(val) * 96;
4952
+ if (val.endsWith("pt")) return parseFloat(val) * 1.33;
4953
+ if (val.endsWith("px")) return parseFloat(val);
4954
+ return parseFloat(val);
4955
+ };
4956
+ const docs = [stylesDoc, contentDoc].filter(Boolean);
4957
+ for (const doc of docs) {
4958
+ const pageLayout = doc.querySelector("page-layout-properties, [page-width]");
4959
+ if (pageLayout) {
4960
+ const w = parseUnit(pageLayout.getAttribute("fo:page-width") || pageLayout.getAttribute("page-width"));
4961
+ const h2 = parseUnit(pageLayout.getAttribute("fo:page-height") || pageLayout.getAttribute("page-height"));
4962
+ const mt = parseUnit(pageLayout.getAttribute("fo:margin-top") || pageLayout.getAttribute("margin-top"));
4963
+ const mb = parseUnit(pageLayout.getAttribute("fo:margin-bottom") || pageLayout.getAttribute("margin-bottom"));
4964
+ const ml = parseUnit(pageLayout.getAttribute("fo:margin-left") || pageLayout.getAttribute("margin-left"));
4965
+ const mr = parseUnit(pageLayout.getAttribute("fo:margin-right") || pageLayout.getAttribute("margin-right"));
4966
+ if (w !== null) width = w;
4967
+ if (h2 !== null) height = h2;
4968
+ if (mt !== null) marginTop = mt;
4969
+ if (mb !== null) marginBottom = mb;
4970
+ if (ml !== null) marginLeft = ml;
4971
+ if (mr !== null) marginRight = mr;
4972
+ break;
4973
+ }
4974
+ }
4975
+ return { width, height, marginTop, marginBottom, marginLeft, marginRight };
4976
+ }
4598
4977
  extractStyles(stylesDoc, contentDoc) {
4599
4978
  const map = /* @__PURE__ */ new Map();
4600
4979
  const styleNodes = [];
@@ -4617,14 +4996,21 @@ var OpenDocumentPlugin = class {
4617
4996
  if (color) css += `color: ${color}; `;
4618
4997
  if (size) css += `font-size: ${size}; `;
4619
4998
  }
4620
- const paraProp = node.querySelector("paragraph-properties, [text-align]");
4999
+ let paraProp = node.querySelector("paragraph-properties, [text-align]");
5000
+ if (!paraProp) {
5001
+ paraProp = Array.from(node.children).find((c) => c.tagName.includes("paragraph-properties")) || null;
5002
+ }
4621
5003
  if (paraProp) {
4622
5004
  const align = paraProp.getAttribute("fo:text-align") || paraProp.getAttribute("text-align");
4623
5005
  const mt = paraProp.getAttribute("fo:margin-top") || paraProp.getAttribute("margin-top");
4624
5006
  const mb = paraProp.getAttribute("fo:margin-bottom") || paraProp.getAttribute("margin-bottom");
5007
+ const breakBefore = paraProp.getAttribute("fo:break-before") || paraProp.getAttribute("break-before");
5008
+ const breakAfter = paraProp.getAttribute("fo:break-after") || paraProp.getAttribute("break-after");
4625
5009
  if (align) css += `text-align: ${align}; `;
4626
5010
  if (mt) css += `margin-top: ${mt}; `;
4627
5011
  if (mb) css += `margin-bottom: ${mb}; `;
5012
+ if (breakBefore === "page") css += "page-break-before: always; ";
5013
+ if (breakAfter === "page") css += "page-break-after: always; ";
4628
5014
  }
4629
5015
  if (css) map.set(name, css);
4630
5016
  }
@@ -4709,6 +5095,8 @@ var OpenDocumentPlugin = class {
4709
5095
  result += "&emsp;";
4710
5096
  } else if (tag === "line-break") {
4711
5097
  result += "<br/>";
5098
+ } else if (tag === "soft-page-break") {
5099
+ result += '<hr class="odf-page-break" style="page-break-after: always; border: none; margin: 0; padding: 0; height: 0;" />';
4712
5100
  } else {
4713
5101
  result += el.textContent || "";
4714
5102
  }
@@ -4869,20 +5257,9 @@ var DocPlugin = class {
4869
5257
  container.style.overflow = "auto";
4870
5258
  container.style.padding = "32px 16px";
4871
5259
  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);
5260
+ container.style.display = "flex";
5261
+ container.style.justifyContent = "center";
5262
+ container.style.alignItems = "flex-start";
4886
5263
  ctx.container.appendChild(container);
4887
5264
  let scale = 1;
4888
5265
  let extractedRawText = "";
@@ -4909,21 +5286,27 @@ var DocPlugin = class {
4909
5286
  const rawPages = this.splitIntoPages(extractedRawText);
4910
5287
  const totalPages = Math.max(1, rawPages.length);
4911
5288
  let currentPage = 1;
4912
- wrapper.innerHTML = "";
4913
5289
  const pageCards = [];
4914
5290
  for (let i = 0; i < totalPages; i++) {
4915
5291
  const pageCard = document.createElement("div");
4916
5292
  pageCard.className = "fp-doc-page-card";
5293
+ pageCard.style.width = "816px";
5294
+ pageCard.style.height = "1056px";
4917
5295
  pageCard.style.backgroundColor = "#ffffff";
4918
5296
  pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
4919
5297
  pageCard.style.borderRadius = "4px";
4920
- pageCard.style.padding = "56px 48px";
4921
- pageCard.style.minHeight = "100%";
5298
+ pageCard.style.padding = "96px 72px";
5299
+ pageCard.style.boxSizing = "border-box";
5300
+ pageCard.style.overflow = "hidden";
4922
5301
  pageCard.style.display = i === 0 ? "block" : "none";
5302
+ pageCard.style.transformOrigin = "top center";
5303
+ pageCard.style.transition = "transform 0.2s ease";
5304
+ pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
5305
+ pageCard.style.color = "#1e293b";
4923
5306
  if (isFallback && i === 0) {
4924
5307
  pageCard.innerHTML = `
4925
5308
  <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>
5309
+ <h2 style="margin: 0 0 6px; font-size: 20px; color: #334155;">${DOMPurify6__default.default.sanitize(ctx.metadata.name || "Word Document (.doc)")}</h2>
4927
5310
  <span style="font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 4px;">Legacy Word 97-2003 Binary Preview</span>
4928
5311
  </div>
4929
5312
  ${this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document")}
@@ -4931,15 +5314,17 @@ var DocPlugin = class {
4931
5314
  } else {
4932
5315
  pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
4933
5316
  }
4934
- wrapper.appendChild(pageCard);
5317
+ container.appendChild(pageCard);
4935
5318
  pageCards.push(pageCard);
4936
5319
  }
4937
5320
  let indicator = null;
4938
5321
  if (totalPages > 1) {
4939
5322
  indicator = document.createElement("div");
4940
5323
  indicator.className = "fp-doc-page-indicator";
4941
- indicator.style.position = "sticky";
5324
+ indicator.style.position = "fixed";
4942
5325
  indicator.style.bottom = "16px";
5326
+ indicator.style.left = "50%";
5327
+ indicator.style.transform = "translateX(-50%)";
4943
5328
  indicator.style.backgroundColor = "rgba(15, 23, 42, 0.85)";
4944
5329
  indicator.style.backdropFilter = "blur(8px)";
4945
5330
  indicator.style.color = "#f8fafc";
@@ -4953,17 +5338,25 @@ var DocPlugin = class {
4953
5338
  indicator.style.userSelect = "none";
4954
5339
  indicator.style.pointerEvents = "none";
4955
5340
  indicator.style.textAlign = "center";
4956
- indicator.style.width = "fit-content";
4957
- indicator.style.margin = "16px auto 0";
4958
5341
  container.appendChild(indicator);
4959
5342
  }
5343
+ let rotation = 0;
5344
+ const applyTransform = () => {
5345
+ const activeCard = pageCards[currentPage - 1];
5346
+ if (activeCard) {
5347
+ activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
5348
+ }
5349
+ };
4960
5350
  const showPage = (pageNum) => {
4961
5351
  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
- }
5352
+ pageCards.forEach((card, idx) => {
5353
+ if (idx + 1 === currentPage) {
5354
+ card.style.display = "block";
5355
+ card.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
5356
+ } else {
5357
+ card.style.display = "none";
5358
+ }
5359
+ });
4967
5360
  if (indicator) {
4968
5361
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4969
5362
  }
@@ -4972,21 +5365,22 @@ var DocPlugin = class {
4972
5365
  if (totalPages > 1) {
4973
5366
  showPage(1);
4974
5367
  }
4975
- let rotation = 0;
4976
- const calculateFitScale = () => {
4977
- const activeCard = pageCards[currentPage - 1] || wrapper;
4978
- const elW = activeCard.offsetWidth || 850;
4979
- const elH = activeCard.offsetHeight || 1e3;
4980
- const availW = Math.max(200, ctx.container.clientWidth - 48);
4981
- const availH = Math.max(200, ctx.container.clientHeight - 80);
4982
- return Math.min(1.1, Math.min(availW / elW, availH / elH));
4983
- };
4984
- const applyTransform = () => {
4985
- wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4986
- wrapper.style.transformOrigin = "top center";
5368
+ let fitMode = "width";
5369
+ const calculateFitScale = (mode = fitMode) => {
5370
+ const elW = 816;
5371
+ const elH = 1056;
5372
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
5373
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
5374
+ const sW = availW / elW;
5375
+ const sH = availH / elH;
5376
+ if (mode === "page") {
5377
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
5378
+ }
5379
+ return Math.max(0.65, Math.min(1.05, sW));
4987
5380
  };
4988
5381
  setTimeout(() => {
4989
- scale = calculateFitScale();
5382
+ fitMode = "width";
5383
+ scale = calculateFitScale("width");
4990
5384
  applyTransform();
4991
5385
  }, 60);
4992
5386
  const cleanup = () => {
@@ -5014,7 +5408,8 @@ var DocPlugin = class {
5014
5408
  applyTransform();
5015
5409
  },
5016
5410
  fitToPage: () => {
5017
- scale = calculateFitScale();
5411
+ fitMode = fitMode === "width" ? "page" : "width";
5412
+ scale = calculateFitScale(fitMode);
5018
5413
  rotation = 0;
5019
5414
  applyTransform();
5020
5415
  },
@@ -5142,8 +5537,28 @@ var DocPlugin = class {
5142
5537
  }
5143
5538
  splitIntoPages(text) {
5144
5539
  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];
5540
+ 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);
5541
+ if (explicitParts.length === 0) explicitParts.push(text);
5542
+ const maxLinesPerPage = 48;
5543
+ const finalPages = [];
5544
+ for (const part of explicitParts) {
5545
+ const lines = part.split(/\r?\n/);
5546
+ let currentLines = [];
5547
+ let count = 0;
5548
+ for (const line of lines) {
5549
+ currentLines.push(line);
5550
+ count++;
5551
+ if (count >= maxLinesPerPage) {
5552
+ finalPages.push(currentLines.join("\n"));
5553
+ currentLines = [];
5554
+ count = 0;
5555
+ }
5556
+ }
5557
+ if (currentLines.length > 0) {
5558
+ finalPages.push(currentLines.join("\n"));
5559
+ }
5560
+ }
5561
+ return finalPages.length > 0 ? finalPages : [text];
5147
5562
  }
5148
5563
  /**
5149
5564
  * Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
@@ -5152,17 +5567,65 @@ var DocPlugin = class {
5152
5567
  const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
5153
5568
  let html = "";
5154
5569
  let inList = false;
5155
- for (const rawLine of lines) {
5156
- const line = rawLine.trim();
5570
+ let tableLines = [];
5571
+ const flushTable = () => {
5572
+ if (tableLines.length > 0) {
5573
+ html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
5574
+ for (const tLine of tableLines) {
5575
+ html += "<tr>";
5576
+ const cols = tLine.split(" ");
5577
+ for (const col of cols) {
5578
+ html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
5579
+ }
5580
+ html += "</tr>";
5581
+ }
5582
+ html += "</table>";
5583
+ tableLines = [];
5584
+ }
5585
+ };
5586
+ let i = 0;
5587
+ while (i < lines.length) {
5588
+ let line = lines[i];
5589
+ let tabCount = (line.match(/\t/g) || []).length;
5590
+ if (tabCount > 0) {
5591
+ let consecutiveTableLines = 1;
5592
+ let j = i + 1;
5593
+ while (j < lines.length) {
5594
+ const nextTabCount = (lines[j].match(/\t/g) || []).length;
5595
+ if (nextTabCount === tabCount) {
5596
+ consecutiveTableLines++;
5597
+ j++;
5598
+ } else {
5599
+ break;
5600
+ }
5601
+ }
5602
+ if (consecutiveTableLines >= 3) {
5603
+ if (inList) {
5604
+ html += "</ul>";
5605
+ inList = false;
5606
+ }
5607
+ tableLines = lines.slice(i, j);
5608
+ flushTable();
5609
+ i = j;
5610
+ continue;
5611
+ }
5612
+ }
5613
+ line = line.trim();
5157
5614
  if (!line) {
5158
5615
  if (inList) {
5159
5616
  html += "</ul>";
5160
5617
  inList = false;
5161
5618
  }
5619
+ html += '<div style="height: 1.15em;"></div>';
5620
+ i++;
5621
+ continue;
5622
+ }
5623
+ if (/^[\x00-\x1F\x7F-\x9F]+$/.test(line)) {
5624
+ i++;
5162
5625
  continue;
5163
5626
  }
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) {
5627
+ if ((line.includes("Normal.dot") || line.includes("Microsoft Word") || line.includes("Times New Roman")) && line.length < 30) {
5628
+ i++;
5166
5629
  continue;
5167
5630
  }
5168
5631
  if (line.length < 60 && !line.endsWith(".") && (/^[A-Z0-9\s:_-]+$/.test(line) || line.startsWith("#"))) {
@@ -5170,24 +5633,26 @@ var DocPlugin = class {
5170
5633
  html += "</ul>";
5171
5634
  inList = false;
5172
5635
  }
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>`;
5636
+ 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
5637
  } else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
5175
5638
  if (!inList) {
5176
5639
  html += '<ul style="margin: 8px 0; padding-left: 24px;">';
5177
5640
  inList = true;
5178
5641
  }
5179
5642
  const bulletText = line.replace(/^[•\-\*]\s*/, "");
5180
- html += `<li style="margin: 4px 0; line-height: 1.6;">${DOMPurify2__default.default.sanitize(bulletText)}</li>`;
5643
+ html += `<li style="margin: 4px 0; line-height: 1.15; font-size: 12pt;">${DOMPurify6__default.default.sanitize(bulletText)}</li>`;
5181
5644
  } else {
5182
5645
  if (inList) {
5183
5646
  html += "</ul>";
5184
5647
  inList = false;
5185
5648
  }
5186
- html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${DOMPurify2__default.default.sanitize(line)}</p>`;
5649
+ html += `<p style="line-height: 1.15; margin: 0; font-size: 12pt; text-align: justify;">${DOMPurify6__default.default.sanitize(line)}</p>`;
5187
5650
  }
5651
+ i++;
5188
5652
  }
5189
5653
  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>`;
5654
+ flushTable();
5655
+ return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6__default.default.sanitize(filename)})</p>`;
5191
5656
  }
5192
5657
  };
5193
5658
  function docPlugin() {
@@ -5365,7 +5830,7 @@ var PptPlugin = class {
5365
5830
  if (s.pictureUrl) {
5366
5831
  contentHtml = `
5367
5832
  <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;" />
5833
+ <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
5834
  </div>
5370
5835
  `;
5371
5836
  } else if (s.tableColumns.length > 0) {
@@ -5375,7 +5840,7 @@ var PptPlugin = class {
5375
5840
  <table style="width: 100%; border-collapse: collapse; border: 1px solid #cbd5e1; border-radius: 6px; overflow: hidden; background: #ffffff;">
5376
5841
  <thead>
5377
5842
  <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("")}
5843
+ ${cols.map((c) => `<th style="padding: 12px 16px; border: 1px solid #cbd5e1; text-align: left;">${DOMPurify6__default.default.sanitize(c)}</th>`).join("")}
5379
5844
  </tr>
5380
5845
  </thead>
5381
5846
  <tbody>
@@ -5391,7 +5856,7 @@ var PptPlugin = class {
5391
5856
  } else {
5392
5857
  const pTags = s.paragraphs.map((p) => {
5393
5858
  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("");
5859
+ 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
5860
  }).join("");
5396
5861
  contentHtml = `
5397
5862
  <div style="flex: 1; overflow: auto; padding: 4px 8px; display: flex; flex-direction: column; justify-content: flex-start;">
@@ -5404,11 +5869,11 @@ var PptPlugin = class {
5404
5869
  <!-- Header Banner matching PowerPoint design -->
5405
5870
  <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
5871
  <h1 style="margin: 0; font-size: 26px; font-weight: 700; color: #1e293b; letter-spacing: -0.3px;">
5407
- ${DOMPurify2__default.default.sanitize(s.title)}
5872
+ ${DOMPurify6__default.default.sanitize(s.title)}
5408
5873
  </h1>
5409
5874
  ${s.subtitle ? `
5410
5875
  <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)}
5876
+ ${DOMPurify6__default.default.sanitize(s.subtitle)}
5412
5877
  </span>
5413
5878
  ` : `
5414
5879
  <span style="font-size: 12px; color: #365314; font-weight: 600;">