@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/index.cjs CHANGED
@@ -506,7 +506,8 @@ function createElement(tag, attrs, ...children) {
506
506
  }
507
507
  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>`;
508
508
  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>`;
509
- 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>`;
509
+ 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>`;
510
+ 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>`;
510
511
  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>`;
511
512
  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>`;
512
513
  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>`;
@@ -526,6 +527,7 @@ var ICON_MAP = {
526
527
  "zoom-in": ICON_ZOOM_IN,
527
528
  "zoom-out": ICON_ZOOM_OUT,
528
529
  "fit-page": ICON_FIT_PAGE,
530
+ "fit-width": ICON_FIT_WIDTH,
529
531
  "fit-slide": ICON_FIT_PAGE,
530
532
  "rotate-cw": ICON_ROTATE_CW,
531
533
  "rotate-ccw": ICON_ROTATE_CCW,
@@ -1472,6 +1474,7 @@ var PdfPlugin = class {
1472
1474
  let currentPage = 1;
1473
1475
  let zoomScale = 1;
1474
1476
  let rotation = 0;
1477
+ let fitMode = "width";
1475
1478
  let currentRenderTask = null;
1476
1479
  const renderPage = async (pageNum) => {
1477
1480
  if (currentRenderTask) {
@@ -1491,11 +1494,16 @@ var PdfPlugin = class {
1491
1494
  const containerWidth = container.clientWidth || 900;
1492
1495
  const containerHeight = container.clientHeight || 700;
1493
1496
  const unscaledVp = page.getViewport({ scale: 1, rotation });
1494
- const availWidth = Math.max(100, containerWidth - 48);
1495
- const availHeight = Math.max(100, containerHeight - 88);
1497
+ const availWidth = Math.max(280, containerWidth - 48);
1498
+ const availHeight = Math.max(280, containerHeight - 88);
1496
1499
  const scaleW = availWidth / unscaledVp.width;
1497
1500
  const scaleH = availHeight / unscaledVp.height;
1498
- const fitScale = Math.min(scaleW, scaleH);
1501
+ let fitScale;
1502
+ if (fitMode === "page") {
1503
+ fitScale = Math.max(0.5, Math.min(scaleW, scaleH));
1504
+ } else {
1505
+ fitScale = Math.max(0.65, Math.min(1.15, scaleW));
1506
+ }
1499
1507
  const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
1500
1508
  const pixelRatio = window.devicePixelRatio || 1;
1501
1509
  const viewport = page.getViewport({ scale: effectiveScale, rotation });
@@ -1564,6 +1572,7 @@ var PdfPlugin = class {
1564
1572
  renderPage(currentPage);
1565
1573
  },
1566
1574
  fitToPage: () => {
1575
+ fitMode = fitMode === "width" ? "page" : "width";
1567
1576
  zoomScale = 1;
1568
1577
  rotation = 0;
1569
1578
  renderPage(currentPage);
@@ -1580,6 +1589,7 @@ var PdfPlugin = class {
1580
1589
  getPageCount: () => totalPages,
1581
1590
  getCurrentPage: () => currentPage,
1582
1591
  goToPage: (page) => {
1592
+ container.scrollTop = 0;
1583
1593
  renderPage(page);
1584
1594
  },
1585
1595
  download: () => {
@@ -2084,7 +2094,14 @@ var DocxPlugin = class {
2084
2094
  ignoreFonts: true,
2085
2095
  // Avoid crashes on embedded obfuscated fonts
2086
2096
  breakPages: true,
2087
- experimental: true
2097
+ experimental: true,
2098
+ ignoreLastRenderedPageBreak: false,
2099
+ // Honor Word's exact page breaks!
2100
+ renderHeaders: true,
2101
+ renderFooters: true,
2102
+ renderFootnotes: true,
2103
+ renderEndnotes: true,
2104
+ useBase64URL: true
2088
2105
  });
2089
2106
  if (!ctx.container.contains(wrapper)) {
2090
2107
  ctx.container.appendChild(wrapper);
@@ -2105,11 +2122,14 @@ var DocxPlugin = class {
2105
2122
  renderedSuccessfully = true;
2106
2123
  } catch (fallbackErr) {
2107
2124
  console.error("[DocxPlugin] Native fallback failed:", fallbackErr);
2125
+ const isCorrupt = fallbackErr?.message?.includes("invalid zip") || fallbackErr?.message?.includes("corrupted");
2108
2126
  wrapper.innerHTML = `
2109
- <div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
2110
- <div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
2111
- <h3 style="margin: 0 0 8px; color: #1e293b;">${ctx.metadata.name || "Word Document"}</h3>
2112
- <p style="color: #64748b; margin: 0;">Could not parse document content</p>
2127
+ <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;">
2128
+ <div style="font-size:48px; margin-bottom: 16px;">${isCorrupt ? "\u26A0\uFE0F" : "\u{1F4C4}"}</div>
2129
+ <h3 style="margin: 0 0 8px; color: #1e293b; font-size: 18px;">${ctx.metadata.name || "Word Document"}</h3>
2130
+ <p style="color: #64748b; margin: 0 0 16px; font-size: 14px; line-height: 1.5;">
2131
+ ${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."}
2132
+ </p>
2113
2133
  </div>
2114
2134
  `;
2115
2135
  if (!ctx.container.contains(wrapper)) {
@@ -2117,8 +2137,67 @@ var DocxPlugin = class {
2117
2137
  }
2118
2138
  }
2119
2139
  }
2120
- const sections = wrapper.querySelectorAll("section.docx");
2121
- const cards = wrapper.querySelectorAll(".fp-docx-page-card");
2140
+ let sections = Array.from(wrapper.querySelectorAll("section.docx"));
2141
+ const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
2142
+ if (sections.length === 1 && cards.length === 0) {
2143
+ const singleSec = sections[0];
2144
+ const contentContainer = singleSec.querySelector("article") || singleSec;
2145
+ const children = Array.from(contentContainer.children);
2146
+ const pageH = singleSec.offsetHeight > 1300 ? 1122 : Math.max(1056, singleSec.offsetHeight);
2147
+ const secH = singleSec.offsetHeight || singleSec.scrollHeight;
2148
+ if (secH > pageH * 1.25 && children.length > 1) {
2149
+ const childHeights = children.map((c) => {
2150
+ const rectH = c.getBoundingClientRect().height;
2151
+ const offH = c.offsetHeight;
2152
+ const textLen = c.textContent?.trim().length || 0;
2153
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
2154
+ return Math.max(rectH, offH, estH);
2155
+ });
2156
+ const parent = singleSec.parentElement || wrapper;
2157
+ const newSections = [singleSec];
2158
+ const headerEl = singleSec.querySelector("header");
2159
+ const footerEl = singleSec.querySelector("footer");
2160
+ contentContainer.innerHTML = "";
2161
+ singleSec.style.minHeight = `${pageH}px`;
2162
+ singleSec.style.boxSizing = "border-box";
2163
+ let curContent = contentContainer;
2164
+ let curH = 0;
2165
+ const maxH = pageH - 140;
2166
+ for (let i = 0; i < children.length; i++) {
2167
+ const child = children[i];
2168
+ const chH = childHeights[i];
2169
+ curContent.appendChild(child);
2170
+ curH += chH;
2171
+ if (curH >= maxH && i < children.length - 1) {
2172
+ const nextSec = document.createElement("section");
2173
+ nextSec.className = singleSec.className;
2174
+ nextSec.style.cssText = singleSec.style.cssText;
2175
+ nextSec.style.minHeight = `${pageH}px`;
2176
+ nextSec.style.boxSizing = "border-box";
2177
+ nextSec.style.backgroundColor = "#ffffff";
2178
+ nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
2179
+ nextSec.style.borderRadius = "4px";
2180
+ nextSec.style.marginBottom = "24px";
2181
+ if (headerEl) {
2182
+ nextSec.appendChild(headerEl.cloneNode(true));
2183
+ }
2184
+ const nextArticle = document.createElement("article");
2185
+ if (contentContainer.tagName.toLowerCase() === "article") {
2186
+ nextArticle.style.cssText = contentContainer.style.cssText;
2187
+ }
2188
+ nextSec.appendChild(nextArticle);
2189
+ if (footerEl) {
2190
+ nextSec.appendChild(footerEl.cloneNode(true));
2191
+ }
2192
+ parent.appendChild(nextSec);
2193
+ newSections.push(nextSec);
2194
+ curContent = nextArticle;
2195
+ curH = 0;
2196
+ }
2197
+ }
2198
+ sections = newSections;
2199
+ }
2200
+ }
2122
2201
  const pageElements = sections.length > 0 ? sections : cards;
2123
2202
  const totalPages = Math.max(1, pageElements.length);
2124
2203
  let currentPage = 1;
@@ -2155,6 +2234,7 @@ var DocxPlugin = class {
2155
2234
  if (indicator) {
2156
2235
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
2157
2236
  }
2237
+ ctx.container.scrollTop = 0;
2158
2238
  ctx.emit("page-change", { page: currentPage, total: totalPages });
2159
2239
  };
2160
2240
  if (totalPages > 1) {
@@ -2162,22 +2242,27 @@ var DocxPlugin = class {
2162
2242
  }
2163
2243
  scale = 1;
2164
2244
  let rotation = 0;
2165
- const calculateFitScale = () => {
2245
+ let fitMode = "width";
2246
+ const calculateFitScale = (mode = fitMode) => {
2166
2247
  const activeEl = pageElements[currentPage - 1] || wrapper.firstElementChild || wrapper;
2167
2248
  const elW = activeEl.offsetWidth || 816;
2168
- const elH = activeEl.offsetHeight || 1056;
2169
- const availW = Math.max(200, ctx.container.clientWidth - 48);
2170
- const availH = Math.max(200, ctx.container.clientHeight - 80);
2249
+ const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
2250
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
2251
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
2171
2252
  const sW = availW / elW;
2172
- const sH = availH / elH;
2173
- return Math.min(1.1, Math.min(sW, sH));
2253
+ const sH = availH / singlePageH;
2254
+ if (mode === "page") {
2255
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
2256
+ }
2257
+ return Math.max(0.65, Math.min(1.05, sW));
2174
2258
  };
2175
2259
  const applyTransform = () => {
2176
2260
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
2177
2261
  wrapper.style.transformOrigin = "top center";
2178
2262
  };
2179
2263
  setTimeout(() => {
2180
- scale = calculateFitScale();
2264
+ fitMode = "width";
2265
+ scale = calculateFitScale("width");
2181
2266
  applyTransform();
2182
2267
  }, 60);
2183
2268
  const cleanup = () => {
@@ -2211,7 +2296,8 @@ var DocxPlugin = class {
2211
2296
  applyTransform();
2212
2297
  },
2213
2298
  fitToPage: () => {
2214
- scale = calculateFitScale();
2299
+ fitMode = fitMode === "width" ? "page" : "width";
2300
+ scale = calculateFitScale(fitMode);
2215
2301
  rotation = 0;
2216
2302
  applyTransform();
2217
2303
  },
@@ -2655,11 +2741,9 @@ var ExcelPlugin = class {
2655
2741
  const calculateFitScale = () => {
2656
2742
  const table = contentArea.querySelector("table");
2657
2743
  if (!table) return 1;
2658
- const availW = Math.max(200, container.clientWidth - 48);
2659
- const availH = Math.max(200, container.clientHeight - 80);
2744
+ const availW = Math.max(280, container.clientWidth - 48);
2660
2745
  const tW = table.offsetWidth || 800;
2661
- const tH = table.offsetHeight || 600;
2662
- return Math.min(1, Math.min(availW / tW, availH / tH));
2746
+ return Math.max(0.65, Math.min(1, availW / tW));
2663
2747
  };
2664
2748
  try {
2665
2749
  wb = XLSX__namespace.read(new Uint8Array(ctx.buffer), { type: "array", cellDates: true });
@@ -3083,17 +3167,39 @@ var CodePlugin = class {
3083
3167
  let rawPages = [];
3084
3168
  if (isTxt) {
3085
3169
  const explicitPages = fullText.split(/(?:\f|\x0C)/);
3170
+ const charsPerLine = 85;
3171
+ const maxVisualLines = 45;
3172
+ const charsPerPage = charsPerLine * maxVisualLines;
3086
3173
  for (const ep of explicitPages) {
3087
3174
  const lines = ep.split(/\r?\n/);
3088
3175
  let currentChunk = [];
3176
+ let currentLines = 0;
3089
3177
  for (let i = 0; i < lines.length; i++) {
3090
- currentChunk.push(lines[i]);
3091
- if (currentChunk.length >= 46) {
3178
+ const line = lines[i];
3179
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
3180
+ if (currentLines + vLines > maxVisualLines && currentChunk.length > 0) {
3092
3181
  rawPages.push(currentChunk.join("\n"));
3093
3182
  currentChunk = [];
3183
+ currentLines = 0;
3184
+ }
3185
+ if (vLines > maxVisualLines) {
3186
+ let remaining = line;
3187
+ while (remaining.length > charsPerPage) {
3188
+ let splitIdx = remaining.lastIndexOf(" ", charsPerPage);
3189
+ if (splitIdx < charsPerPage * 0.75) splitIdx = charsPerPage;
3190
+ rawPages.push(remaining.slice(0, splitIdx));
3191
+ remaining = remaining.slice(splitIdx).trimStart();
3192
+ }
3193
+ if (remaining.length > 0) {
3194
+ currentChunk.push(remaining);
3195
+ currentLines = Math.ceil(remaining.length / charsPerLine);
3196
+ }
3197
+ } else {
3198
+ currentChunk.push(line);
3199
+ currentLines += vLines;
3094
3200
  }
3095
3201
  }
3096
- if (currentChunk.length > 0 || lines.length === 0) {
3202
+ if (currentChunk.length > 0) {
3097
3203
  rawPages.push(currentChunk.join("\n"));
3098
3204
  }
3099
3205
  }
@@ -3203,6 +3309,7 @@ var CodePlugin = class {
3203
3309
  if (indicator) {
3204
3310
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
3205
3311
  }
3312
+ container.scrollTop = 0;
3206
3313
  ctx.emit("page-change", { page: currentPage, total: totalPages });
3207
3314
  };
3208
3315
  if (totalPages > 1) {
@@ -3256,7 +3363,7 @@ var CodePlugin = class {
3256
3363
  fitToPage: () => {
3257
3364
  fontSize = 13;
3258
3365
  rotation = 0;
3259
- zoomLevel = 1;
3366
+ zoomLevel = isTxt ? Math.max(0.65, Math.min(1.05, (container.clientWidth - 48) / 816)) : 1;
3260
3367
  updateTransform();
3261
3368
  },
3262
3369
  rotateCW: () => {
@@ -4238,20 +4345,27 @@ var RtfPlugin = class {
4238
4345
  let scale = 1;
4239
4346
  let rotation = 0;
4240
4347
  let pageElements = [];
4241
- const calculateFitScale = () => {
4348
+ let fitMode = "width";
4349
+ const calculateFitScale = (mode = fitMode) => {
4242
4350
  const activeEl = pageElements[currentPage - 1] || wrapper;
4243
4351
  const elW = activeEl.offsetWidth || 850;
4244
- const elH = activeEl.offsetHeight || 1e3;
4245
- const availW = Math.max(200, ctx.container.clientWidth - 48);
4246
- const availH = Math.max(200, ctx.container.clientHeight - 80);
4247
- return Math.min(1.1, Math.min(availW / elW, availH / elH));
4352
+ const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
4353
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
4354
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
4355
+ const sW = availW / elW;
4356
+ const sH = availH / singlePageH;
4357
+ if (mode === "page") {
4358
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
4359
+ }
4360
+ return Math.max(0.65, Math.min(1.05, sW));
4248
4361
  };
4249
4362
  const applyTransform = () => {
4250
4363
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4251
4364
  wrapper.style.transformOrigin = "top center";
4252
4365
  };
4253
4366
  setTimeout(() => {
4254
- scale = calculateFitScale();
4367
+ fitMode = "width";
4368
+ scale = calculateFitScale("width");
4255
4369
  applyTransform();
4256
4370
  }, 60);
4257
4371
  try {
@@ -4260,11 +4374,60 @@ var RtfPlugin = class {
4260
4374
  }
4261
4375
  const doc = new RTFJS__namespace.Document(ctx.buffer, {});
4262
4376
  const htmlElements = await doc.render();
4263
- pageElements = htmlElements;
4264
- for (let i = 0; i < htmlElements.length; i++) {
4265
- const el = htmlElements[i];
4266
- el.style.display = i === 0 ? "block" : "none";
4267
- wrapper.appendChild(el);
4377
+ if (htmlElements.length === 1) {
4378
+ const singleEl = htmlElements[0];
4379
+ wrapper.appendChild(singleEl);
4380
+ const children = Array.from(singleEl.children);
4381
+ const secH = singleEl.offsetHeight || singleEl.scrollHeight;
4382
+ if (secH > 1300 && children.length > 1) {
4383
+ const childHeights = children.map((c) => {
4384
+ const rectH = c.getBoundingClientRect().height;
4385
+ const offH = c.offsetHeight;
4386
+ const textLen = c.textContent?.trim().length || 0;
4387
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
4388
+ return Math.max(rectH, offH, estH);
4389
+ });
4390
+ wrapper.innerHTML = "";
4391
+ const createRtfCard = () => {
4392
+ const card = document.createElement("div");
4393
+ card.className = "fp-rtf-page-card";
4394
+ card.style.backgroundColor = "#ffffff";
4395
+ card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
4396
+ card.style.borderRadius = "4px";
4397
+ card.style.padding = "72px 56px";
4398
+ card.style.width = "816px";
4399
+ card.style.minHeight = "1056px";
4400
+ card.style.boxSizing = "border-box";
4401
+ card.style.marginBottom = "24px";
4402
+ return card;
4403
+ };
4404
+ let curCard = createRtfCard();
4405
+ wrapper.appendChild(curCard);
4406
+ pageElements = [curCard];
4407
+ let curH = 0;
4408
+ const maxH = 920;
4409
+ for (let i = 0; i < children.length; i++) {
4410
+ const child = children[i];
4411
+ const chH = childHeights[i];
4412
+ curCard.appendChild(child);
4413
+ curH += chH;
4414
+ if (curH >= maxH && i < children.length - 1) {
4415
+ curCard = createRtfCard();
4416
+ wrapper.appendChild(curCard);
4417
+ pageElements.push(curCard);
4418
+ curH = 0;
4419
+ }
4420
+ }
4421
+ } else {
4422
+ pageElements = [singleEl];
4423
+ }
4424
+ } else {
4425
+ pageElements = htmlElements;
4426
+ for (let i = 0; i < htmlElements.length; i++) {
4427
+ const el = htmlElements[i];
4428
+ el.style.display = i === 0 ? "block" : "none";
4429
+ wrapper.appendChild(el);
4430
+ }
4268
4431
  }
4269
4432
  } catch (err) {
4270
4433
  console.warn("[RtfPlugin] RTF render error, fallback text:", err);
@@ -4330,6 +4493,7 @@ var RtfPlugin = class {
4330
4493
  if (indicator) {
4331
4494
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4332
4495
  }
4496
+ ctx.container.scrollTop = 0;
4333
4497
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4334
4498
  };
4335
4499
  if (totalPages > 1) {
@@ -4360,7 +4524,8 @@ var RtfPlugin = class {
4360
4524
  applyTransform();
4361
4525
  },
4362
4526
  fitToPage: () => {
4363
- scale = calculateFitScale();
4527
+ fitMode = fitMode === "width" ? "page" : "width";
4528
+ scale = calculateFitScale(fitMode);
4364
4529
  rotation = 0;
4365
4530
  applyTransform();
4366
4531
  },
@@ -4679,19 +4844,29 @@ var OpenDocumentPlugin = class {
4679
4844
  ctx.container.appendChild(container);
4680
4845
  let scale = 1;
4681
4846
  let rotation = 0;
4682
- const calculateFitScale = () => {
4847
+ let fitMode = "width";
4848
+ const calculateFitScale = (mode = fitMode) => {
4683
4849
  const elW = wrapper.offsetWidth || 850;
4684
- const elH = wrapper.offsetHeight || (isPresentation ? 540 : 1e3);
4685
- const availW = Math.max(200, ctx.container.clientWidth - 48);
4686
- const availH = Math.max(200, ctx.container.clientHeight - 80);
4687
- return Math.min(1, Math.min(availW / elW, availH / elH));
4850
+ const singlePageH = Math.min(wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
4851
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
4852
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
4853
+ const sW = availW / elW;
4854
+ const sH = availH / (isPresentation ? 540 : singlePageH);
4855
+ if (isPresentation) {
4856
+ return Math.min(1, Math.min(sW, sH));
4857
+ }
4858
+ if (mode === "page") {
4859
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
4860
+ }
4861
+ return Math.max(0.65, Math.min(1.05, sW));
4688
4862
  };
4689
4863
  const applyTransform = () => {
4690
4864
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4691
4865
  wrapper.style.transformOrigin = "top center";
4692
4866
  };
4693
4867
  setTimeout(() => {
4694
- scale = calculateFitScale();
4868
+ fitMode = "width";
4869
+ scale = calculateFitScale("width");
4695
4870
  applyTransform();
4696
4871
  }, 60);
4697
4872
  let currentPage = 1;
@@ -4790,12 +4965,9 @@ var OpenDocumentPlugin = class {
4790
4965
  page.style.backgroundColor = "#ffffff";
4791
4966
  page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
4792
4967
  page.style.borderRadius = "4px";
4793
- page.style.boxSizing = "border-box";
4794
4968
  page.style.display = idx === 0 ? "block" : "none";
4795
- page.style.position = "absolute";
4796
- page.style.top = "0";
4797
- page.style.left = "50%";
4798
- page.style.transform = "translateX(-50%)";
4969
+ page.style.margin = "0 auto 24px";
4970
+ page.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
4799
4971
  elements.forEach((el) => page.appendChild(el));
4800
4972
  wrapper.appendChild(page);
4801
4973
  slides.push(page);
@@ -4833,6 +5005,7 @@ var OpenDocumentPlugin = class {
4833
5005
  if (indicator) {
4834
5006
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4835
5007
  }
5008
+ container.scrollTop = 0;
4836
5009
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4837
5010
  };
4838
5011
  return {
@@ -4852,7 +5025,8 @@ var OpenDocumentPlugin = class {
4852
5025
  applyTransform();
4853
5026
  },
4854
5027
  fitToPage: () => {
4855
- scale = calculateFitScale();
5028
+ fitMode = fitMode === "width" ? "page" : "width";
5029
+ scale = calculateFitScale(fitMode);
4856
5030
  rotation = 0;
4857
5031
  applyTransform();
4858
5032
  },
@@ -5324,20 +5498,28 @@ var DocPlugin = class {
5324
5498
  if (indicator) {
5325
5499
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
5326
5500
  }
5501
+ container.scrollTop = 0;
5327
5502
  ctx.emit("page-change", { page: currentPage, total: totalPages });
5328
5503
  };
5329
5504
  if (totalPages > 1) {
5330
5505
  showPage(1);
5331
5506
  }
5332
- const calculateFitScale = () => {
5507
+ let fitMode = "width";
5508
+ const calculateFitScale = (mode = fitMode) => {
5333
5509
  const elW = 816;
5334
5510
  const elH = 1056;
5335
- const availW = Math.max(200, ctx.container.clientWidth - 48);
5336
- const availH = Math.max(200, ctx.container.clientHeight - 80);
5337
- return Math.min(1.1, Math.min(availW / elW, availH / elH));
5511
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
5512
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
5513
+ const sW = availW / elW;
5514
+ const sH = availH / elH;
5515
+ if (mode === "page") {
5516
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
5517
+ }
5518
+ return Math.max(0.65, Math.min(1.05, sW));
5338
5519
  };
5339
5520
  setTimeout(() => {
5340
- scale = calculateFitScale();
5521
+ fitMode = "width";
5522
+ scale = calculateFitScale("width");
5341
5523
  applyTransform();
5342
5524
  }, 60);
5343
5525
  const cleanup = () => {
@@ -5365,7 +5547,8 @@ var DocPlugin = class {
5365
5547
  applyTransform();
5366
5548
  },
5367
5549
  fitToPage: () => {
5368
- scale = calculateFitScale();
5550
+ fitMode = fitMode === "width" ? "page" : "width";
5551
+ scale = calculateFitScale(fitMode);
5369
5552
  rotation = 0;
5370
5553
  applyTransform();
5371
5554
  },
@@ -5493,45 +5676,50 @@ var DocPlugin = class {
5493
5676
  }
5494
5677
  splitIntoPages(text) {
5495
5678
  if (!text) return [""];
5496
- 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);
5497
- if (explicitParts.length === 0) explicitParts.push(text);
5498
- const maxLinesPerPage = 48;
5679
+ const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ");
5680
+ 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);
5681
+ if (explicitParts.length === 0) explicitParts.push(normalized);
5682
+ const maxLinesPerPage = 32;
5683
+ const charsPerLine = 80;
5499
5684
  const finalPages = [];
5500
5685
  for (const part of explicitParts) {
5501
- const lines = part.split(/\r?\n/);
5686
+ const lines = part.split("\n");
5502
5687
  let currentLines = [];
5503
5688
  let count = 0;
5504
5689
  for (const line of lines) {
5505
- currentLines.push(line);
5506
- count++;
5507
- if (count >= maxLinesPerPage) {
5690
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
5691
+ if (count + vLines > maxLinesPerPage && currentLines.length > 0) {
5508
5692
  finalPages.push(currentLines.join("\n"));
5509
5693
  currentLines = [];
5510
5694
  count = 0;
5511
5695
  }
5696
+ currentLines.push(line);
5697
+ count += vLines;
5512
5698
  }
5513
5699
  if (currentLines.length > 0) {
5514
5700
  finalPages.push(currentLines.join("\n"));
5515
5701
  }
5516
5702
  }
5517
- return finalPages.length > 0 ? finalPages : [text];
5703
+ return finalPages.length > 0 ? finalPages : [normalized];
5518
5704
  }
5519
5705
  /**
5520
5706
  * Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
5521
5707
  */
5522
5708
  formatDocToHtml(text, filename) {
5523
- const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
5709
+ 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");
5524
5710
  let html = "";
5525
5711
  let inList = false;
5526
5712
  let tableLines = [];
5527
5713
  const flushTable = () => {
5528
5714
  if (tableLines.length > 0) {
5529
- html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
5530
- for (const tLine of tableLines) {
5531
- html += "<tr>";
5532
- const cols = tLine.split(" ");
5715
+ html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 13px; font-family: Calibri, sans-serif;">';
5716
+ for (let rIdx = 0; rIdx < tableLines.length; rIdx++) {
5717
+ const tLine = tableLines[rIdx];
5718
+ const isHeader = rIdx === 0;
5719
+ html += `<tr style="${isHeader ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
5720
+ const cols = tLine.split(" ").filter((c) => c.trim().length > 0);
5533
5721
  for (const col of cols) {
5534
- html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
5722
+ html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
5535
5723
  }
5536
5724
  html += "</tr>";
5537
5725
  }
@@ -5544,27 +5732,18 @@ var DocPlugin = class {
5544
5732
  let line = lines[i];
5545
5733
  let tabCount = (line.match(/\t/g) || []).length;
5546
5734
  if (tabCount > 0) {
5547
- let consecutiveTableLines = 1;
5548
- let j = i + 1;
5549
- while (j < lines.length) {
5550
- const nextTabCount = (lines[j].match(/\t/g) || []).length;
5551
- if (nextTabCount === tabCount) {
5552
- consecutiveTableLines++;
5553
- j++;
5554
- } else {
5555
- break;
5556
- }
5735
+ let j = i;
5736
+ while (j < lines.length && (lines[j].match(/\t/g) || []).length > 0) {
5737
+ j++;
5557
5738
  }
5558
- if (consecutiveTableLines >= 3) {
5559
- if (inList) {
5560
- html += "</ul>";
5561
- inList = false;
5562
- }
5563
- tableLines = lines.slice(i, j);
5564
- flushTable();
5565
- i = j;
5566
- continue;
5739
+ if (inList) {
5740
+ html += "</ul>";
5741
+ inList = false;
5567
5742
  }
5743
+ tableLines = lines.slice(i, j);
5744
+ flushTable();
5745
+ i = j;
5746
+ continue;
5568
5747
  }
5569
5748
  line = line.trim();
5570
5749
  if (!line) {