@files-preview-app/preview-file 1.2.7 → 1.2.9

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/react.cjs CHANGED
@@ -466,7 +466,8 @@ function createElement(tag, attrs, ...children) {
466
466
  }
467
467
  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>`;
468
468
  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>`;
469
- 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>`;
469
+ 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>`;
470
+ 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>`;
470
471
  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>`;
471
472
  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>`;
472
473
  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>`;
@@ -486,6 +487,7 @@ var ICON_MAP = {
486
487
  "zoom-in": ICON_ZOOM_IN,
487
488
  "zoom-out": ICON_ZOOM_OUT,
488
489
  "fit-page": ICON_FIT_PAGE,
490
+ "fit-width": ICON_FIT_WIDTH,
489
491
  "fit-slide": ICON_FIT_PAGE,
490
492
  "rotate-cw": ICON_ROTATE_CW,
491
493
  "rotate-ccw": ICON_ROTATE_CCW,
@@ -1432,6 +1434,7 @@ var PdfPlugin = class {
1432
1434
  let currentPage = 1;
1433
1435
  let zoomScale = 1;
1434
1436
  let rotation = 0;
1437
+ let fitMode = "width";
1435
1438
  let currentRenderTask = null;
1436
1439
  const renderPage = async (pageNum) => {
1437
1440
  if (currentRenderTask) {
@@ -1451,11 +1454,16 @@ var PdfPlugin = class {
1451
1454
  const containerWidth = container.clientWidth || 900;
1452
1455
  const containerHeight = container.clientHeight || 700;
1453
1456
  const unscaledVp = page.getViewport({ scale: 1, rotation });
1454
- const availWidth = Math.max(100, containerWidth - 48);
1455
- const availHeight = Math.max(100, containerHeight - 88);
1457
+ const availWidth = Math.max(280, containerWidth - 48);
1458
+ const availHeight = Math.max(280, containerHeight - 88);
1456
1459
  const scaleW = availWidth / unscaledVp.width;
1457
1460
  const scaleH = availHeight / unscaledVp.height;
1458
- const fitScale = Math.min(scaleW, scaleH);
1461
+ let fitScale;
1462
+ if (fitMode === "page") {
1463
+ fitScale = Math.max(0.5, Math.min(scaleW, scaleH));
1464
+ } else {
1465
+ fitScale = Math.max(0.65, Math.min(1.15, scaleW));
1466
+ }
1459
1467
  const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
1460
1468
  const pixelRatio = window.devicePixelRatio || 1;
1461
1469
  const viewport = page.getViewport({ scale: effectiveScale, rotation });
@@ -1524,6 +1532,7 @@ var PdfPlugin = class {
1524
1532
  renderPage(currentPage);
1525
1533
  },
1526
1534
  fitToPage: () => {
1535
+ fitMode = fitMode === "width" ? "page" : "width";
1527
1536
  zoomScale = 1;
1528
1537
  rotation = 0;
1529
1538
  renderPage(currentPage);
@@ -1540,6 +1549,7 @@ var PdfPlugin = class {
1540
1549
  getPageCount: () => totalPages,
1541
1550
  getCurrentPage: () => currentPage,
1542
1551
  goToPage: (page) => {
1552
+ container.scrollTop = 0;
1543
1553
  renderPage(page);
1544
1554
  },
1545
1555
  download: () => {
@@ -2044,7 +2054,14 @@ var DocxPlugin = class {
2044
2054
  ignoreFonts: true,
2045
2055
  // Avoid crashes on embedded obfuscated fonts
2046
2056
  breakPages: true,
2047
- experimental: true
2057
+ experimental: true,
2058
+ ignoreLastRenderedPageBreak: false,
2059
+ // Honor Word's exact page breaks!
2060
+ renderHeaders: true,
2061
+ renderFooters: true,
2062
+ renderFootnotes: true,
2063
+ renderEndnotes: true,
2064
+ useBase64URL: true
2048
2065
  });
2049
2066
  if (!ctx.container.contains(wrapper)) {
2050
2067
  ctx.container.appendChild(wrapper);
@@ -2065,11 +2082,14 @@ var DocxPlugin = class {
2065
2082
  renderedSuccessfully = true;
2066
2083
  } catch (fallbackErr) {
2067
2084
  console.error("[DocxPlugin] Native fallback failed:", fallbackErr);
2085
+ const isCorrupt = fallbackErr?.message?.includes("invalid zip") || fallbackErr?.message?.includes("corrupted");
2068
2086
  wrapper.innerHTML = `
2069
- <div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
2070
- <div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
2071
- <h3 style="margin: 0 0 8px; color: #1e293b;">${ctx.metadata.name || "Word Document"}</h3>
2072
- <p style="color: #64748b; margin: 0;">Could not parse document content</p>
2087
+ <div style="text-align:center; padding: 48px 32px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06); max-width: 600px; margin: 40px auto;">
2088
+ <div style="font-size:48px; margin-bottom: 16px;">${isCorrupt ? "\u26A0\uFE0F" : "\u{1F4C4}"}</div>
2089
+ <h3 style="margin: 0 0 8px; color: #1e293b; font-size: 18px;">${ctx.metadata.name || "Word Document"}</h3>
2090
+ <p style="color: #64748b; margin: 0 0 16px; font-size: 14px; line-height: 1.5;">
2091
+ ${isCorrupt ? "This document appears to be corrupted or contains invalid archive data and cannot be opened (matches Microsoft Word on Windows)." : "Could not render document content. The file structure may be damaged."}
2092
+ </p>
2073
2093
  </div>
2074
2094
  `;
2075
2095
  if (!ctx.container.contains(wrapper)) {
@@ -2077,8 +2097,67 @@ var DocxPlugin = class {
2077
2097
  }
2078
2098
  }
2079
2099
  }
2080
- const sections = wrapper.querySelectorAll("section.docx");
2081
- const cards = wrapper.querySelectorAll(".fp-docx-page-card");
2100
+ let sections = Array.from(wrapper.querySelectorAll("section.docx"));
2101
+ const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
2102
+ if (sections.length === 1 && cards.length === 0) {
2103
+ const singleSec = sections[0];
2104
+ const contentContainer = singleSec.querySelector("article") || singleSec;
2105
+ const children = Array.from(contentContainer.children);
2106
+ const pageH = singleSec.offsetHeight > 1300 ? 1122 : Math.max(1056, singleSec.offsetHeight);
2107
+ const secH = singleSec.offsetHeight || singleSec.scrollHeight;
2108
+ if (secH > pageH * 1.25 && children.length > 1) {
2109
+ const childHeights = children.map((c) => {
2110
+ const rectH = c.getBoundingClientRect().height;
2111
+ const offH = c.offsetHeight;
2112
+ const textLen = c.textContent?.trim().length || 0;
2113
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
2114
+ return Math.max(rectH, offH, estH);
2115
+ });
2116
+ const parent = singleSec.parentElement || wrapper;
2117
+ const newSections = [singleSec];
2118
+ const headerEl = singleSec.querySelector("header");
2119
+ const footerEl = singleSec.querySelector("footer");
2120
+ contentContainer.innerHTML = "";
2121
+ singleSec.style.minHeight = `${pageH}px`;
2122
+ singleSec.style.boxSizing = "border-box";
2123
+ let curContent = contentContainer;
2124
+ let curH = 0;
2125
+ const maxH = pageH - 140;
2126
+ for (let i = 0; i < children.length; i++) {
2127
+ const child = children[i];
2128
+ const chH = childHeights[i];
2129
+ curContent.appendChild(child);
2130
+ curH += chH;
2131
+ if (curH >= maxH && i < children.length - 1) {
2132
+ const nextSec = document.createElement("section");
2133
+ nextSec.className = singleSec.className;
2134
+ nextSec.style.cssText = singleSec.style.cssText;
2135
+ nextSec.style.minHeight = `${pageH}px`;
2136
+ nextSec.style.boxSizing = "border-box";
2137
+ nextSec.style.backgroundColor = "#ffffff";
2138
+ nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
2139
+ nextSec.style.borderRadius = "4px";
2140
+ nextSec.style.marginBottom = "24px";
2141
+ if (headerEl) {
2142
+ nextSec.appendChild(headerEl.cloneNode(true));
2143
+ }
2144
+ const nextArticle = document.createElement("article");
2145
+ if (contentContainer.tagName.toLowerCase() === "article") {
2146
+ nextArticle.style.cssText = contentContainer.style.cssText;
2147
+ }
2148
+ nextSec.appendChild(nextArticle);
2149
+ if (footerEl) {
2150
+ nextSec.appendChild(footerEl.cloneNode(true));
2151
+ }
2152
+ parent.appendChild(nextSec);
2153
+ newSections.push(nextSec);
2154
+ curContent = nextArticle;
2155
+ curH = 0;
2156
+ }
2157
+ }
2158
+ sections = newSections;
2159
+ }
2160
+ }
2082
2161
  const pageElements = sections.length > 0 ? sections : cards;
2083
2162
  const totalPages = Math.max(1, pageElements.length);
2084
2163
  let currentPage = 1;
@@ -2115,6 +2194,7 @@ var DocxPlugin = class {
2115
2194
  if (indicator) {
2116
2195
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
2117
2196
  }
2197
+ ctx.container.scrollTop = 0;
2118
2198
  ctx.emit("page-change", { page: currentPage, total: totalPages });
2119
2199
  };
2120
2200
  if (totalPages > 1) {
@@ -2122,22 +2202,27 @@ var DocxPlugin = class {
2122
2202
  }
2123
2203
  scale = 1;
2124
2204
  let rotation = 0;
2125
- const calculateFitScale = () => {
2205
+ let fitMode = "width";
2206
+ const calculateFitScale = (mode = fitMode) => {
2126
2207
  const activeEl = pageElements[currentPage - 1] || wrapper.firstElementChild || wrapper;
2127
2208
  const elW = activeEl.offsetWidth || 816;
2128
- const elH = activeEl.offsetHeight || 1056;
2129
- const availW = Math.max(200, ctx.container.clientWidth - 48);
2130
- const availH = Math.max(200, ctx.container.clientHeight - 80);
2209
+ const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
2210
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
2211
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
2131
2212
  const sW = availW / elW;
2132
- const sH = availH / elH;
2133
- return Math.min(1.1, Math.min(sW, sH));
2213
+ const sH = availH / singlePageH;
2214
+ if (mode === "page") {
2215
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
2216
+ }
2217
+ return Math.max(0.65, Math.min(1.05, sW));
2134
2218
  };
2135
2219
  const applyTransform = () => {
2136
2220
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
2137
2221
  wrapper.style.transformOrigin = "top center";
2138
2222
  };
2139
2223
  setTimeout(() => {
2140
- scale = calculateFitScale();
2224
+ fitMode = "width";
2225
+ scale = calculateFitScale("width");
2141
2226
  applyTransform();
2142
2227
  }, 60);
2143
2228
  const cleanup = () => {
@@ -2171,7 +2256,8 @@ var DocxPlugin = class {
2171
2256
  applyTransform();
2172
2257
  },
2173
2258
  fitToPage: () => {
2174
- scale = calculateFitScale();
2259
+ fitMode = fitMode === "width" ? "page" : "width";
2260
+ scale = calculateFitScale(fitMode);
2175
2261
  rotation = 0;
2176
2262
  applyTransform();
2177
2263
  },
@@ -2615,11 +2701,9 @@ var ExcelPlugin = class {
2615
2701
  const calculateFitScale = () => {
2616
2702
  const table = contentArea.querySelector("table");
2617
2703
  if (!table) return 1;
2618
- const availW = Math.max(200, container.clientWidth - 48);
2619
- const availH = Math.max(200, container.clientHeight - 80);
2704
+ const availW = Math.max(280, container.clientWidth - 48);
2620
2705
  const tW = table.offsetWidth || 800;
2621
- const tH = table.offsetHeight || 600;
2622
- return Math.min(1, Math.min(availW / tW, availH / tH));
2706
+ return Math.max(0.65, Math.min(1, availW / tW));
2623
2707
  };
2624
2708
  try {
2625
2709
  wb = XLSX__namespace.read(new Uint8Array(ctx.buffer), { type: "array", cellDates: true });
@@ -3043,17 +3127,39 @@ var CodePlugin = class {
3043
3127
  let rawPages = [];
3044
3128
  if (isTxt) {
3045
3129
  const explicitPages = fullText.split(/(?:\f|\x0C)/);
3130
+ const charsPerLine = 85;
3131
+ const maxVisualLines = 45;
3132
+ const charsPerPage = charsPerLine * maxVisualLines;
3046
3133
  for (const ep of explicitPages) {
3047
3134
  const lines = ep.split(/\r?\n/);
3048
3135
  let currentChunk = [];
3136
+ let currentLines = 0;
3049
3137
  for (let i = 0; i < lines.length; i++) {
3050
- currentChunk.push(lines[i]);
3051
- if (currentChunk.length >= 46) {
3138
+ const line = lines[i];
3139
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
3140
+ if (currentLines + vLines > maxVisualLines && currentChunk.length > 0) {
3052
3141
  rawPages.push(currentChunk.join("\n"));
3053
3142
  currentChunk = [];
3143
+ currentLines = 0;
3144
+ }
3145
+ if (vLines > maxVisualLines) {
3146
+ let remaining = line;
3147
+ while (remaining.length > charsPerPage) {
3148
+ let splitIdx = remaining.lastIndexOf(" ", charsPerPage);
3149
+ if (splitIdx < charsPerPage * 0.75) splitIdx = charsPerPage;
3150
+ rawPages.push(remaining.slice(0, splitIdx));
3151
+ remaining = remaining.slice(splitIdx).trimStart();
3152
+ }
3153
+ if (remaining.length > 0) {
3154
+ currentChunk.push(remaining);
3155
+ currentLines = Math.ceil(remaining.length / charsPerLine);
3156
+ }
3157
+ } else {
3158
+ currentChunk.push(line);
3159
+ currentLines += vLines;
3054
3160
  }
3055
3161
  }
3056
- if (currentChunk.length > 0 || lines.length === 0) {
3162
+ if (currentChunk.length > 0) {
3057
3163
  rawPages.push(currentChunk.join("\n"));
3058
3164
  }
3059
3165
  }
@@ -3163,6 +3269,7 @@ var CodePlugin = class {
3163
3269
  if (indicator) {
3164
3270
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
3165
3271
  }
3272
+ container.scrollTop = 0;
3166
3273
  ctx.emit("page-change", { page: currentPage, total: totalPages });
3167
3274
  };
3168
3275
  if (totalPages > 1) {
@@ -3216,7 +3323,7 @@ var CodePlugin = class {
3216
3323
  fitToPage: () => {
3217
3324
  fontSize = 13;
3218
3325
  rotation = 0;
3219
- zoomLevel = 1;
3326
+ zoomLevel = isTxt ? Math.max(0.65, Math.min(1.05, (container.clientWidth - 48) / 816)) : 1;
3220
3327
  updateTransform();
3221
3328
  },
3222
3329
  rotateCW: () => {
@@ -4198,20 +4305,27 @@ var RtfPlugin = class {
4198
4305
  let scale = 1;
4199
4306
  let rotation = 0;
4200
4307
  let pageElements = [];
4201
- const calculateFitScale = () => {
4308
+ let fitMode = "width";
4309
+ const calculateFitScale = (mode = fitMode) => {
4202
4310
  const activeEl = pageElements[currentPage - 1] || wrapper;
4203
4311
  const elW = activeEl.offsetWidth || 850;
4204
- const elH = activeEl.offsetHeight || 1e3;
4205
- const availW = Math.max(200, ctx.container.clientWidth - 48);
4206
- const availH = Math.max(200, ctx.container.clientHeight - 80);
4207
- return Math.min(1.1, Math.min(availW / elW, availH / elH));
4312
+ const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
4313
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
4314
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
4315
+ const sW = availW / elW;
4316
+ const sH = availH / singlePageH;
4317
+ if (mode === "page") {
4318
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
4319
+ }
4320
+ return Math.max(0.65, Math.min(1.05, sW));
4208
4321
  };
4209
4322
  const applyTransform = () => {
4210
4323
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4211
4324
  wrapper.style.transformOrigin = "top center";
4212
4325
  };
4213
4326
  setTimeout(() => {
4214
- scale = calculateFitScale();
4327
+ fitMode = "width";
4328
+ scale = calculateFitScale("width");
4215
4329
  applyTransform();
4216
4330
  }, 60);
4217
4331
  try {
@@ -4220,11 +4334,60 @@ var RtfPlugin = class {
4220
4334
  }
4221
4335
  const doc = new RTFJS__namespace.Document(ctx.buffer, {});
4222
4336
  const htmlElements = await doc.render();
4223
- pageElements = htmlElements;
4224
- for (let i = 0; i < htmlElements.length; i++) {
4225
- const el = htmlElements[i];
4226
- el.style.display = i === 0 ? "block" : "none";
4227
- wrapper.appendChild(el);
4337
+ if (htmlElements.length === 1) {
4338
+ const singleEl = htmlElements[0];
4339
+ wrapper.appendChild(singleEl);
4340
+ const children = Array.from(singleEl.children);
4341
+ const secH = singleEl.offsetHeight || singleEl.scrollHeight;
4342
+ if (secH > 1300 && children.length > 1) {
4343
+ const childHeights = children.map((c) => {
4344
+ const rectH = c.getBoundingClientRect().height;
4345
+ const offH = c.offsetHeight;
4346
+ const textLen = c.textContent?.trim().length || 0;
4347
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
4348
+ return Math.max(rectH, offH, estH);
4349
+ });
4350
+ wrapper.innerHTML = "";
4351
+ const createRtfCard = () => {
4352
+ const card = document.createElement("div");
4353
+ card.className = "fp-rtf-page-card";
4354
+ card.style.backgroundColor = "#ffffff";
4355
+ card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
4356
+ card.style.borderRadius = "4px";
4357
+ card.style.padding = "72px 56px";
4358
+ card.style.width = "816px";
4359
+ card.style.minHeight = "1056px";
4360
+ card.style.boxSizing = "border-box";
4361
+ card.style.marginBottom = "24px";
4362
+ return card;
4363
+ };
4364
+ let curCard = createRtfCard();
4365
+ wrapper.appendChild(curCard);
4366
+ pageElements = [curCard];
4367
+ let curH = 0;
4368
+ const maxH = 920;
4369
+ for (let i = 0; i < children.length; i++) {
4370
+ const child = children[i];
4371
+ const chH = childHeights[i];
4372
+ curCard.appendChild(child);
4373
+ curH += chH;
4374
+ if (curH >= maxH && i < children.length - 1) {
4375
+ curCard = createRtfCard();
4376
+ wrapper.appendChild(curCard);
4377
+ pageElements.push(curCard);
4378
+ curH = 0;
4379
+ }
4380
+ }
4381
+ } else {
4382
+ pageElements = [singleEl];
4383
+ }
4384
+ } else {
4385
+ pageElements = htmlElements;
4386
+ for (let i = 0; i < htmlElements.length; i++) {
4387
+ const el = htmlElements[i];
4388
+ el.style.display = i === 0 ? "block" : "none";
4389
+ wrapper.appendChild(el);
4390
+ }
4228
4391
  }
4229
4392
  } catch (err) {
4230
4393
  console.warn("[RtfPlugin] RTF render error, fallback text:", err);
@@ -4290,6 +4453,7 @@ var RtfPlugin = class {
4290
4453
  if (indicator) {
4291
4454
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4292
4455
  }
4456
+ ctx.container.scrollTop = 0;
4293
4457
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4294
4458
  };
4295
4459
  if (totalPages > 1) {
@@ -4320,7 +4484,8 @@ var RtfPlugin = class {
4320
4484
  applyTransform();
4321
4485
  },
4322
4486
  fitToPage: () => {
4323
- scale = calculateFitScale();
4487
+ fitMode = fitMode === "width" ? "page" : "width";
4488
+ scale = calculateFitScale(fitMode);
4324
4489
  rotation = 0;
4325
4490
  applyTransform();
4326
4491
  },
@@ -4639,19 +4804,29 @@ var OpenDocumentPlugin = class {
4639
4804
  ctx.container.appendChild(container);
4640
4805
  let scale = 1;
4641
4806
  let rotation = 0;
4642
- const calculateFitScale = () => {
4807
+ let fitMode = "width";
4808
+ const calculateFitScale = (mode = fitMode) => {
4643
4809
  const elW = wrapper.offsetWidth || 850;
4644
- const elH = wrapper.offsetHeight || (isPresentation ? 540 : 1e3);
4645
- const availW = Math.max(200, ctx.container.clientWidth - 48);
4646
- const availH = Math.max(200, ctx.container.clientHeight - 80);
4647
- return Math.min(1, Math.min(availW / elW, availH / elH));
4810
+ const singlePageH = Math.min(wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
4811
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
4812
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
4813
+ const sW = availW / elW;
4814
+ const sH = availH / (isPresentation ? 540 : singlePageH);
4815
+ if (isPresentation) {
4816
+ return Math.min(1, Math.min(sW, sH));
4817
+ }
4818
+ if (mode === "page") {
4819
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
4820
+ }
4821
+ return Math.max(0.65, Math.min(1.05, sW));
4648
4822
  };
4649
4823
  const applyTransform = () => {
4650
4824
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4651
4825
  wrapper.style.transformOrigin = "top center";
4652
4826
  };
4653
4827
  setTimeout(() => {
4654
- scale = calculateFitScale();
4828
+ fitMode = "width";
4829
+ scale = calculateFitScale("width");
4655
4830
  applyTransform();
4656
4831
  }, 60);
4657
4832
  let currentPage = 1;
@@ -4750,12 +4925,9 @@ var OpenDocumentPlugin = class {
4750
4925
  page.style.backgroundColor = "#ffffff";
4751
4926
  page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
4752
4927
  page.style.borderRadius = "4px";
4753
- page.style.boxSizing = "border-box";
4754
4928
  page.style.display = idx === 0 ? "block" : "none";
4755
- page.style.position = "absolute";
4756
- page.style.top = "0";
4757
- page.style.left = "50%";
4758
- page.style.transform = "translateX(-50%)";
4929
+ page.style.margin = "0 auto 24px";
4930
+ page.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
4759
4931
  elements.forEach((el) => page.appendChild(el));
4760
4932
  wrapper.appendChild(page);
4761
4933
  slides.push(page);
@@ -4793,6 +4965,7 @@ var OpenDocumentPlugin = class {
4793
4965
  if (indicator) {
4794
4966
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4795
4967
  }
4968
+ container.scrollTop = 0;
4796
4969
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4797
4970
  };
4798
4971
  return {
@@ -4812,7 +4985,8 @@ var OpenDocumentPlugin = class {
4812
4985
  applyTransform();
4813
4986
  },
4814
4987
  fitToPage: () => {
4815
- scale = calculateFitScale();
4988
+ fitMode = fitMode === "width" ? "page" : "width";
4989
+ scale = calculateFitScale(fitMode);
4816
4990
  rotation = 0;
4817
4991
  applyTransform();
4818
4992
  },
@@ -5284,20 +5458,28 @@ var DocPlugin = class {
5284
5458
  if (indicator) {
5285
5459
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
5286
5460
  }
5461
+ container.scrollTop = 0;
5287
5462
  ctx.emit("page-change", { page: currentPage, total: totalPages });
5288
5463
  };
5289
5464
  if (totalPages > 1) {
5290
5465
  showPage(1);
5291
5466
  }
5292
- const calculateFitScale = () => {
5467
+ let fitMode = "width";
5468
+ const calculateFitScale = (mode = fitMode) => {
5293
5469
  const elW = 816;
5294
5470
  const elH = 1056;
5295
- const availW = Math.max(200, ctx.container.clientWidth - 48);
5296
- const availH = Math.max(200, ctx.container.clientHeight - 80);
5297
- return Math.min(1.1, Math.min(availW / elW, availH / elH));
5471
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
5472
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
5473
+ const sW = availW / elW;
5474
+ const sH = availH / elH;
5475
+ if (mode === "page") {
5476
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
5477
+ }
5478
+ return Math.max(0.65, Math.min(1.05, sW));
5298
5479
  };
5299
5480
  setTimeout(() => {
5300
- scale = calculateFitScale();
5481
+ fitMode = "width";
5482
+ scale = calculateFitScale("width");
5301
5483
  applyTransform();
5302
5484
  }, 60);
5303
5485
  const cleanup = () => {
@@ -5325,7 +5507,8 @@ var DocPlugin = class {
5325
5507
  applyTransform();
5326
5508
  },
5327
5509
  fitToPage: () => {
5328
- scale = calculateFitScale();
5510
+ fitMode = fitMode === "width" ? "page" : "width";
5511
+ scale = calculateFitScale(fitMode);
5329
5512
  rotation = 0;
5330
5513
  applyTransform();
5331
5514
  },
@@ -5453,45 +5636,50 @@ var DocPlugin = class {
5453
5636
  }
5454
5637
  splitIntoPages(text) {
5455
5638
  if (!text) return [""];
5456
- 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);
5457
- if (explicitParts.length === 0) explicitParts.push(text);
5458
- const maxLinesPerPage = 48;
5639
+ const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ");
5640
+ const explicitParts = normalized.split(/[\x0C\f]|\n\s*[-=_]{3,}\s*(?:PAGE|Page|page break)[\s\d\w-]*[-=_]{3,}\s*\n/i).map((p) => p.trim()).filter((p) => p.length > 0);
5641
+ if (explicitParts.length === 0) explicitParts.push(normalized);
5642
+ const maxLinesPerPage = 32;
5643
+ const charsPerLine = 80;
5459
5644
  const finalPages = [];
5460
5645
  for (const part of explicitParts) {
5461
- const lines = part.split(/\r?\n/);
5646
+ const lines = part.split("\n");
5462
5647
  let currentLines = [];
5463
5648
  let count = 0;
5464
5649
  for (const line of lines) {
5465
- currentLines.push(line);
5466
- count++;
5467
- if (count >= maxLinesPerPage) {
5650
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
5651
+ if (count + vLines > maxLinesPerPage && currentLines.length > 0) {
5468
5652
  finalPages.push(currentLines.join("\n"));
5469
5653
  currentLines = [];
5470
5654
  count = 0;
5471
5655
  }
5656
+ currentLines.push(line);
5657
+ count += vLines;
5472
5658
  }
5473
5659
  if (currentLines.length > 0) {
5474
5660
  finalPages.push(currentLines.join("\n"));
5475
5661
  }
5476
5662
  }
5477
- return finalPages.length > 0 ? finalPages : [text];
5663
+ return finalPages.length > 0 ? finalPages : [normalized];
5478
5664
  }
5479
5665
  /**
5480
5666
  * Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
5481
5667
  */
5482
5668
  formatDocToHtml(text, filename) {
5483
- const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
5669
+ const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ").split("\n");
5484
5670
  let html = "";
5485
5671
  let inList = false;
5486
5672
  let tableLines = [];
5487
5673
  const flushTable = () => {
5488
5674
  if (tableLines.length > 0) {
5489
- html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
5490
- for (const tLine of tableLines) {
5491
- html += "<tr>";
5492
- const cols = tLine.split(" ");
5675
+ html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 13px; font-family: Calibri, sans-serif;">';
5676
+ for (let rIdx = 0; rIdx < tableLines.length; rIdx++) {
5677
+ const tLine = tableLines[rIdx];
5678
+ const isHeader = rIdx === 0;
5679
+ html += `<tr style="${isHeader ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
5680
+ const cols = tLine.split(" ").filter((c) => c.trim().length > 0);
5493
5681
  for (const col of cols) {
5494
- html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
5682
+ html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
5495
5683
  }
5496
5684
  html += "</tr>";
5497
5685
  }
@@ -5504,27 +5692,18 @@ var DocPlugin = class {
5504
5692
  let line = lines[i];
5505
5693
  let tabCount = (line.match(/\t/g) || []).length;
5506
5694
  if (tabCount > 0) {
5507
- let consecutiveTableLines = 1;
5508
- let j = i + 1;
5509
- while (j < lines.length) {
5510
- const nextTabCount = (lines[j].match(/\t/g) || []).length;
5511
- if (nextTabCount === tabCount) {
5512
- consecutiveTableLines++;
5513
- j++;
5514
- } else {
5515
- break;
5516
- }
5695
+ let j = i;
5696
+ while (j < lines.length && (lines[j].match(/\t/g) || []).length > 0) {
5697
+ j++;
5517
5698
  }
5518
- if (consecutiveTableLines >= 3) {
5519
- if (inList) {
5520
- html += "</ul>";
5521
- inList = false;
5522
- }
5523
- tableLines = lines.slice(i, j);
5524
- flushTable();
5525
- i = j;
5526
- continue;
5699
+ if (inList) {
5700
+ html += "</ul>";
5701
+ inList = false;
5527
5702
  }
5703
+ tableLines = lines.slice(i, j);
5704
+ flushTable();
5705
+ i = j;
5706
+ continue;
5528
5707
  }
5529
5708
  line = line.trim();
5530
5709
  if (!line) {