@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/angular.cjs CHANGED
@@ -513,7 +513,8 @@ function createElement(tag, attrs, ...children) {
513
513
  }
514
514
  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>`;
515
515
  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>`;
516
- 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>`;
516
+ 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>`;
517
+ 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>`;
517
518
  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>`;
518
519
  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>`;
519
520
  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>`;
@@ -533,6 +534,7 @@ var ICON_MAP = {
533
534
  "zoom-in": ICON_ZOOM_IN,
534
535
  "zoom-out": ICON_ZOOM_OUT,
535
536
  "fit-page": ICON_FIT_PAGE,
537
+ "fit-width": ICON_FIT_WIDTH,
536
538
  "fit-slide": ICON_FIT_PAGE,
537
539
  "rotate-cw": ICON_ROTATE_CW,
538
540
  "rotate-ccw": ICON_ROTATE_CCW,
@@ -1479,6 +1481,7 @@ var PdfPlugin = class {
1479
1481
  let currentPage = 1;
1480
1482
  let zoomScale = 1;
1481
1483
  let rotation = 0;
1484
+ let fitMode = "width";
1482
1485
  let currentRenderTask = null;
1483
1486
  const renderPage = async (pageNum) => {
1484
1487
  if (currentRenderTask) {
@@ -1498,11 +1501,16 @@ var PdfPlugin = class {
1498
1501
  const containerWidth = container.clientWidth || 900;
1499
1502
  const containerHeight = container.clientHeight || 700;
1500
1503
  const unscaledVp = page.getViewport({ scale: 1, rotation });
1501
- const availWidth = Math.max(100, containerWidth - 48);
1502
- const availHeight = Math.max(100, containerHeight - 88);
1504
+ const availWidth = Math.max(280, containerWidth - 48);
1505
+ const availHeight = Math.max(280, containerHeight - 88);
1503
1506
  const scaleW = availWidth / unscaledVp.width;
1504
1507
  const scaleH = availHeight / unscaledVp.height;
1505
- const fitScale = Math.min(scaleW, scaleH);
1508
+ let fitScale;
1509
+ if (fitMode === "page") {
1510
+ fitScale = Math.max(0.5, Math.min(scaleW, scaleH));
1511
+ } else {
1512
+ fitScale = Math.max(0.65, Math.min(1.15, scaleW));
1513
+ }
1506
1514
  const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
1507
1515
  const pixelRatio = window.devicePixelRatio || 1;
1508
1516
  const viewport = page.getViewport({ scale: effectiveScale, rotation });
@@ -1571,6 +1579,7 @@ var PdfPlugin = class {
1571
1579
  renderPage(currentPage);
1572
1580
  },
1573
1581
  fitToPage: () => {
1582
+ fitMode = fitMode === "width" ? "page" : "width";
1574
1583
  zoomScale = 1;
1575
1584
  rotation = 0;
1576
1585
  renderPage(currentPage);
@@ -1587,6 +1596,7 @@ var PdfPlugin = class {
1587
1596
  getPageCount: () => totalPages,
1588
1597
  getCurrentPage: () => currentPage,
1589
1598
  goToPage: (page) => {
1599
+ container.scrollTop = 0;
1590
1600
  renderPage(page);
1591
1601
  },
1592
1602
  download: () => {
@@ -2091,7 +2101,14 @@ var DocxPlugin = class {
2091
2101
  ignoreFonts: true,
2092
2102
  // Avoid crashes on embedded obfuscated fonts
2093
2103
  breakPages: true,
2094
- experimental: true
2104
+ experimental: true,
2105
+ ignoreLastRenderedPageBreak: false,
2106
+ // Honor Word's exact page breaks!
2107
+ renderHeaders: true,
2108
+ renderFooters: true,
2109
+ renderFootnotes: true,
2110
+ renderEndnotes: true,
2111
+ useBase64URL: true
2095
2112
  });
2096
2113
  if (!ctx.container.contains(wrapper)) {
2097
2114
  ctx.container.appendChild(wrapper);
@@ -2112,11 +2129,14 @@ var DocxPlugin = class {
2112
2129
  renderedSuccessfully = true;
2113
2130
  } catch (fallbackErr) {
2114
2131
  console.error("[DocxPlugin] Native fallback failed:", fallbackErr);
2132
+ const isCorrupt = fallbackErr?.message?.includes("invalid zip") || fallbackErr?.message?.includes("corrupted");
2115
2133
  wrapper.innerHTML = `
2116
- <div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
2117
- <div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
2118
- <h3 style="margin: 0 0 8px; color: #1e293b;">${ctx.metadata.name || "Word Document"}</h3>
2119
- <p style="color: #64748b; margin: 0;">Could not parse document content</p>
2134
+ <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;">
2135
+ <div style="font-size:48px; margin-bottom: 16px;">${isCorrupt ? "\u26A0\uFE0F" : "\u{1F4C4}"}</div>
2136
+ <h3 style="margin: 0 0 8px; color: #1e293b; font-size: 18px;">${ctx.metadata.name || "Word Document"}</h3>
2137
+ <p style="color: #64748b; margin: 0 0 16px; font-size: 14px; line-height: 1.5;">
2138
+ ${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."}
2139
+ </p>
2120
2140
  </div>
2121
2141
  `;
2122
2142
  if (!ctx.container.contains(wrapper)) {
@@ -2124,8 +2144,67 @@ var DocxPlugin = class {
2124
2144
  }
2125
2145
  }
2126
2146
  }
2127
- const sections = wrapper.querySelectorAll("section.docx");
2128
- const cards = wrapper.querySelectorAll(".fp-docx-page-card");
2147
+ let sections = Array.from(wrapper.querySelectorAll("section.docx"));
2148
+ const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
2149
+ if (sections.length === 1 && cards.length === 0) {
2150
+ const singleSec = sections[0];
2151
+ const contentContainer = singleSec.querySelector("article") || singleSec;
2152
+ const children = Array.from(contentContainer.children);
2153
+ const pageH = singleSec.offsetHeight > 1300 ? 1122 : Math.max(1056, singleSec.offsetHeight);
2154
+ const secH = singleSec.offsetHeight || singleSec.scrollHeight;
2155
+ if (secH > pageH * 1.25 && children.length > 1) {
2156
+ const childHeights = children.map((c) => {
2157
+ const rectH = c.getBoundingClientRect().height;
2158
+ const offH = c.offsetHeight;
2159
+ const textLen = c.textContent?.trim().length || 0;
2160
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
2161
+ return Math.max(rectH, offH, estH);
2162
+ });
2163
+ const parent = singleSec.parentElement || wrapper;
2164
+ const newSections = [singleSec];
2165
+ const headerEl = singleSec.querySelector("header");
2166
+ const footerEl = singleSec.querySelector("footer");
2167
+ contentContainer.innerHTML = "";
2168
+ singleSec.style.minHeight = `${pageH}px`;
2169
+ singleSec.style.boxSizing = "border-box";
2170
+ let curContent = contentContainer;
2171
+ let curH = 0;
2172
+ const maxH = pageH - 140;
2173
+ for (let i = 0; i < children.length; i++) {
2174
+ const child = children[i];
2175
+ const chH = childHeights[i];
2176
+ curContent.appendChild(child);
2177
+ curH += chH;
2178
+ if (curH >= maxH && i < children.length - 1) {
2179
+ const nextSec = document.createElement("section");
2180
+ nextSec.className = singleSec.className;
2181
+ nextSec.style.cssText = singleSec.style.cssText;
2182
+ nextSec.style.minHeight = `${pageH}px`;
2183
+ nextSec.style.boxSizing = "border-box";
2184
+ nextSec.style.backgroundColor = "#ffffff";
2185
+ nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
2186
+ nextSec.style.borderRadius = "4px";
2187
+ nextSec.style.marginBottom = "24px";
2188
+ if (headerEl) {
2189
+ nextSec.appendChild(headerEl.cloneNode(true));
2190
+ }
2191
+ const nextArticle = document.createElement("article");
2192
+ if (contentContainer.tagName.toLowerCase() === "article") {
2193
+ nextArticle.style.cssText = contentContainer.style.cssText;
2194
+ }
2195
+ nextSec.appendChild(nextArticle);
2196
+ if (footerEl) {
2197
+ nextSec.appendChild(footerEl.cloneNode(true));
2198
+ }
2199
+ parent.appendChild(nextSec);
2200
+ newSections.push(nextSec);
2201
+ curContent = nextArticle;
2202
+ curH = 0;
2203
+ }
2204
+ }
2205
+ sections = newSections;
2206
+ }
2207
+ }
2129
2208
  const pageElements = sections.length > 0 ? sections : cards;
2130
2209
  const totalPages = Math.max(1, pageElements.length);
2131
2210
  let currentPage = 1;
@@ -2162,6 +2241,7 @@ var DocxPlugin = class {
2162
2241
  if (indicator) {
2163
2242
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
2164
2243
  }
2244
+ ctx.container.scrollTop = 0;
2165
2245
  ctx.emit("page-change", { page: currentPage, total: totalPages });
2166
2246
  };
2167
2247
  if (totalPages > 1) {
@@ -2169,22 +2249,27 @@ var DocxPlugin = class {
2169
2249
  }
2170
2250
  scale = 1;
2171
2251
  let rotation = 0;
2172
- const calculateFitScale = () => {
2252
+ let fitMode = "width";
2253
+ const calculateFitScale = (mode = fitMode) => {
2173
2254
  const activeEl = pageElements[currentPage - 1] || wrapper.firstElementChild || wrapper;
2174
2255
  const elW = activeEl.offsetWidth || 816;
2175
- const elH = activeEl.offsetHeight || 1056;
2176
- const availW = Math.max(200, ctx.container.clientWidth - 48);
2177
- const availH = Math.max(200, ctx.container.clientHeight - 80);
2256
+ const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
2257
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
2258
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
2178
2259
  const sW = availW / elW;
2179
- const sH = availH / elH;
2180
- return Math.min(1.1, Math.min(sW, sH));
2260
+ const sH = availH / singlePageH;
2261
+ if (mode === "page") {
2262
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
2263
+ }
2264
+ return Math.max(0.65, Math.min(1.05, sW));
2181
2265
  };
2182
2266
  const applyTransform = () => {
2183
2267
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
2184
2268
  wrapper.style.transformOrigin = "top center";
2185
2269
  };
2186
2270
  setTimeout(() => {
2187
- scale = calculateFitScale();
2271
+ fitMode = "width";
2272
+ scale = calculateFitScale("width");
2188
2273
  applyTransform();
2189
2274
  }, 60);
2190
2275
  const cleanup = () => {
@@ -2218,7 +2303,8 @@ var DocxPlugin = class {
2218
2303
  applyTransform();
2219
2304
  },
2220
2305
  fitToPage: () => {
2221
- scale = calculateFitScale();
2306
+ fitMode = fitMode === "width" ? "page" : "width";
2307
+ scale = calculateFitScale(fitMode);
2222
2308
  rotation = 0;
2223
2309
  applyTransform();
2224
2310
  },
@@ -2662,11 +2748,9 @@ var ExcelPlugin = class {
2662
2748
  const calculateFitScale = () => {
2663
2749
  const table = contentArea.querySelector("table");
2664
2750
  if (!table) return 1;
2665
- const availW = Math.max(200, container.clientWidth - 48);
2666
- const availH = Math.max(200, container.clientHeight - 80);
2751
+ const availW = Math.max(280, container.clientWidth - 48);
2667
2752
  const tW = table.offsetWidth || 800;
2668
- const tH = table.offsetHeight || 600;
2669
- return Math.min(1, Math.min(availW / tW, availH / tH));
2753
+ return Math.max(0.65, Math.min(1, availW / tW));
2670
2754
  };
2671
2755
  try {
2672
2756
  wb = XLSX__namespace.read(new Uint8Array(ctx.buffer), { type: "array", cellDates: true });
@@ -3090,17 +3174,39 @@ var CodePlugin = class {
3090
3174
  let rawPages = [];
3091
3175
  if (isTxt) {
3092
3176
  const explicitPages = fullText.split(/(?:\f|\x0C)/);
3177
+ const charsPerLine = 85;
3178
+ const maxVisualLines = 45;
3179
+ const charsPerPage = charsPerLine * maxVisualLines;
3093
3180
  for (const ep of explicitPages) {
3094
3181
  const lines = ep.split(/\r?\n/);
3095
3182
  let currentChunk = [];
3183
+ let currentLines = 0;
3096
3184
  for (let i = 0; i < lines.length; i++) {
3097
- currentChunk.push(lines[i]);
3098
- if (currentChunk.length >= 46) {
3185
+ const line = lines[i];
3186
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
3187
+ if (currentLines + vLines > maxVisualLines && currentChunk.length > 0) {
3099
3188
  rawPages.push(currentChunk.join("\n"));
3100
3189
  currentChunk = [];
3190
+ currentLines = 0;
3191
+ }
3192
+ if (vLines > maxVisualLines) {
3193
+ let remaining = line;
3194
+ while (remaining.length > charsPerPage) {
3195
+ let splitIdx = remaining.lastIndexOf(" ", charsPerPage);
3196
+ if (splitIdx < charsPerPage * 0.75) splitIdx = charsPerPage;
3197
+ rawPages.push(remaining.slice(0, splitIdx));
3198
+ remaining = remaining.slice(splitIdx).trimStart();
3199
+ }
3200
+ if (remaining.length > 0) {
3201
+ currentChunk.push(remaining);
3202
+ currentLines = Math.ceil(remaining.length / charsPerLine);
3203
+ }
3204
+ } else {
3205
+ currentChunk.push(line);
3206
+ currentLines += vLines;
3101
3207
  }
3102
3208
  }
3103
- if (currentChunk.length > 0 || lines.length === 0) {
3209
+ if (currentChunk.length > 0) {
3104
3210
  rawPages.push(currentChunk.join("\n"));
3105
3211
  }
3106
3212
  }
@@ -3210,6 +3316,7 @@ var CodePlugin = class {
3210
3316
  if (indicator) {
3211
3317
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
3212
3318
  }
3319
+ container.scrollTop = 0;
3213
3320
  ctx.emit("page-change", { page: currentPage, total: totalPages });
3214
3321
  };
3215
3322
  if (totalPages > 1) {
@@ -3263,7 +3370,7 @@ var CodePlugin = class {
3263
3370
  fitToPage: () => {
3264
3371
  fontSize = 13;
3265
3372
  rotation = 0;
3266
- zoomLevel = 1;
3373
+ zoomLevel = isTxt ? Math.max(0.65, Math.min(1.05, (container.clientWidth - 48) / 816)) : 1;
3267
3374
  updateTransform();
3268
3375
  },
3269
3376
  rotateCW: () => {
@@ -4245,20 +4352,27 @@ var RtfPlugin = class {
4245
4352
  let scale = 1;
4246
4353
  let rotation = 0;
4247
4354
  let pageElements = [];
4248
- const calculateFitScale = () => {
4355
+ let fitMode = "width";
4356
+ const calculateFitScale = (mode = fitMode) => {
4249
4357
  const activeEl = pageElements[currentPage - 1] || wrapper;
4250
4358
  const elW = activeEl.offsetWidth || 850;
4251
- const elH = activeEl.offsetHeight || 1e3;
4252
- const availW = Math.max(200, ctx.container.clientWidth - 48);
4253
- const availH = Math.max(200, ctx.container.clientHeight - 80);
4254
- return Math.min(1.1, Math.min(availW / elW, availH / elH));
4359
+ const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
4360
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
4361
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
4362
+ const sW = availW / elW;
4363
+ const sH = availH / singlePageH;
4364
+ if (mode === "page") {
4365
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
4366
+ }
4367
+ return Math.max(0.65, Math.min(1.05, sW));
4255
4368
  };
4256
4369
  const applyTransform = () => {
4257
4370
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4258
4371
  wrapper.style.transformOrigin = "top center";
4259
4372
  };
4260
4373
  setTimeout(() => {
4261
- scale = calculateFitScale();
4374
+ fitMode = "width";
4375
+ scale = calculateFitScale("width");
4262
4376
  applyTransform();
4263
4377
  }, 60);
4264
4378
  try {
@@ -4267,11 +4381,60 @@ var RtfPlugin = class {
4267
4381
  }
4268
4382
  const doc = new RTFJS__namespace.Document(ctx.buffer, {});
4269
4383
  const htmlElements = await doc.render();
4270
- pageElements = htmlElements;
4271
- for (let i = 0; i < htmlElements.length; i++) {
4272
- const el = htmlElements[i];
4273
- el.style.display = i === 0 ? "block" : "none";
4274
- wrapper.appendChild(el);
4384
+ if (htmlElements.length === 1) {
4385
+ const singleEl = htmlElements[0];
4386
+ wrapper.appendChild(singleEl);
4387
+ const children = Array.from(singleEl.children);
4388
+ const secH = singleEl.offsetHeight || singleEl.scrollHeight;
4389
+ if (secH > 1300 && children.length > 1) {
4390
+ const childHeights = children.map((c) => {
4391
+ const rectH = c.getBoundingClientRect().height;
4392
+ const offH = c.offsetHeight;
4393
+ const textLen = c.textContent?.trim().length || 0;
4394
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
4395
+ return Math.max(rectH, offH, estH);
4396
+ });
4397
+ wrapper.innerHTML = "";
4398
+ const createRtfCard = () => {
4399
+ const card = document.createElement("div");
4400
+ card.className = "fp-rtf-page-card";
4401
+ card.style.backgroundColor = "#ffffff";
4402
+ card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
4403
+ card.style.borderRadius = "4px";
4404
+ card.style.padding = "72px 56px";
4405
+ card.style.width = "816px";
4406
+ card.style.minHeight = "1056px";
4407
+ card.style.boxSizing = "border-box";
4408
+ card.style.marginBottom = "24px";
4409
+ return card;
4410
+ };
4411
+ let curCard = createRtfCard();
4412
+ wrapper.appendChild(curCard);
4413
+ pageElements = [curCard];
4414
+ let curH = 0;
4415
+ const maxH = 920;
4416
+ for (let i = 0; i < children.length; i++) {
4417
+ const child = children[i];
4418
+ const chH = childHeights[i];
4419
+ curCard.appendChild(child);
4420
+ curH += chH;
4421
+ if (curH >= maxH && i < children.length - 1) {
4422
+ curCard = createRtfCard();
4423
+ wrapper.appendChild(curCard);
4424
+ pageElements.push(curCard);
4425
+ curH = 0;
4426
+ }
4427
+ }
4428
+ } else {
4429
+ pageElements = [singleEl];
4430
+ }
4431
+ } else {
4432
+ pageElements = htmlElements;
4433
+ for (let i = 0; i < htmlElements.length; i++) {
4434
+ const el = htmlElements[i];
4435
+ el.style.display = i === 0 ? "block" : "none";
4436
+ wrapper.appendChild(el);
4437
+ }
4275
4438
  }
4276
4439
  } catch (err) {
4277
4440
  console.warn("[RtfPlugin] RTF render error, fallback text:", err);
@@ -4337,6 +4500,7 @@ var RtfPlugin = class {
4337
4500
  if (indicator) {
4338
4501
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4339
4502
  }
4503
+ ctx.container.scrollTop = 0;
4340
4504
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4341
4505
  };
4342
4506
  if (totalPages > 1) {
@@ -4367,7 +4531,8 @@ var RtfPlugin = class {
4367
4531
  applyTransform();
4368
4532
  },
4369
4533
  fitToPage: () => {
4370
- scale = calculateFitScale();
4534
+ fitMode = fitMode === "width" ? "page" : "width";
4535
+ scale = calculateFitScale(fitMode);
4371
4536
  rotation = 0;
4372
4537
  applyTransform();
4373
4538
  },
@@ -4686,19 +4851,29 @@ var OpenDocumentPlugin = class {
4686
4851
  ctx.container.appendChild(container);
4687
4852
  let scale = 1;
4688
4853
  let rotation = 0;
4689
- const calculateFitScale = () => {
4854
+ let fitMode = "width";
4855
+ const calculateFitScale = (mode = fitMode) => {
4690
4856
  const elW = wrapper.offsetWidth || 850;
4691
- const elH = wrapper.offsetHeight || (isPresentation ? 540 : 1e3);
4692
- const availW = Math.max(200, ctx.container.clientWidth - 48);
4693
- const availH = Math.max(200, ctx.container.clientHeight - 80);
4694
- return Math.min(1, Math.min(availW / elW, availH / elH));
4857
+ const singlePageH = Math.min(wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
4858
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
4859
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
4860
+ const sW = availW / elW;
4861
+ const sH = availH / (isPresentation ? 540 : singlePageH);
4862
+ if (isPresentation) {
4863
+ return Math.min(1, Math.min(sW, sH));
4864
+ }
4865
+ if (mode === "page") {
4866
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
4867
+ }
4868
+ return Math.max(0.65, Math.min(1.05, sW));
4695
4869
  };
4696
4870
  const applyTransform = () => {
4697
4871
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4698
4872
  wrapper.style.transformOrigin = "top center";
4699
4873
  };
4700
4874
  setTimeout(() => {
4701
- scale = calculateFitScale();
4875
+ fitMode = "width";
4876
+ scale = calculateFitScale("width");
4702
4877
  applyTransform();
4703
4878
  }, 60);
4704
4879
  let currentPage = 1;
@@ -4797,12 +4972,9 @@ var OpenDocumentPlugin = class {
4797
4972
  page.style.backgroundColor = "#ffffff";
4798
4973
  page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
4799
4974
  page.style.borderRadius = "4px";
4800
- page.style.boxSizing = "border-box";
4801
4975
  page.style.display = idx === 0 ? "block" : "none";
4802
- page.style.position = "absolute";
4803
- page.style.top = "0";
4804
- page.style.left = "50%";
4805
- page.style.transform = "translateX(-50%)";
4976
+ page.style.margin = "0 auto 24px";
4977
+ page.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
4806
4978
  elements.forEach((el) => page.appendChild(el));
4807
4979
  wrapper.appendChild(page);
4808
4980
  slides.push(page);
@@ -4840,6 +5012,7 @@ var OpenDocumentPlugin = class {
4840
5012
  if (indicator) {
4841
5013
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4842
5014
  }
5015
+ container.scrollTop = 0;
4843
5016
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4844
5017
  };
4845
5018
  return {
@@ -4859,7 +5032,8 @@ var OpenDocumentPlugin = class {
4859
5032
  applyTransform();
4860
5033
  },
4861
5034
  fitToPage: () => {
4862
- scale = calculateFitScale();
5035
+ fitMode = fitMode === "width" ? "page" : "width";
5036
+ scale = calculateFitScale(fitMode);
4863
5037
  rotation = 0;
4864
5038
  applyTransform();
4865
5039
  },
@@ -5331,20 +5505,28 @@ var DocPlugin = class {
5331
5505
  if (indicator) {
5332
5506
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
5333
5507
  }
5508
+ container.scrollTop = 0;
5334
5509
  ctx.emit("page-change", { page: currentPage, total: totalPages });
5335
5510
  };
5336
5511
  if (totalPages > 1) {
5337
5512
  showPage(1);
5338
5513
  }
5339
- const calculateFitScale = () => {
5514
+ let fitMode = "width";
5515
+ const calculateFitScale = (mode = fitMode) => {
5340
5516
  const elW = 816;
5341
5517
  const elH = 1056;
5342
- const availW = Math.max(200, ctx.container.clientWidth - 48);
5343
- const availH = Math.max(200, ctx.container.clientHeight - 80);
5344
- return Math.min(1.1, Math.min(availW / elW, availH / elH));
5518
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
5519
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
5520
+ const sW = availW / elW;
5521
+ const sH = availH / elH;
5522
+ if (mode === "page") {
5523
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
5524
+ }
5525
+ return Math.max(0.65, Math.min(1.05, sW));
5345
5526
  };
5346
5527
  setTimeout(() => {
5347
- scale = calculateFitScale();
5528
+ fitMode = "width";
5529
+ scale = calculateFitScale("width");
5348
5530
  applyTransform();
5349
5531
  }, 60);
5350
5532
  const cleanup = () => {
@@ -5372,7 +5554,8 @@ var DocPlugin = class {
5372
5554
  applyTransform();
5373
5555
  },
5374
5556
  fitToPage: () => {
5375
- scale = calculateFitScale();
5557
+ fitMode = fitMode === "width" ? "page" : "width";
5558
+ scale = calculateFitScale(fitMode);
5376
5559
  rotation = 0;
5377
5560
  applyTransform();
5378
5561
  },
@@ -5500,45 +5683,50 @@ var DocPlugin = class {
5500
5683
  }
5501
5684
  splitIntoPages(text) {
5502
5685
  if (!text) return [""];
5503
- const explicitParts = text.split(/[\x0C\f]|\r?\n\s*[-=_]{3,}\s*(?:PAGE|Page|page break)[\s\d\w-]*[-=_]{3,}\s*\r?\n/i).map((p) => p.trim()).filter((p) => p.length > 0);
5504
- if (explicitParts.length === 0) explicitParts.push(text);
5505
- const maxLinesPerPage = 48;
5686
+ const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ");
5687
+ 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);
5688
+ if (explicitParts.length === 0) explicitParts.push(normalized);
5689
+ const maxLinesPerPage = 32;
5690
+ const charsPerLine = 80;
5506
5691
  const finalPages = [];
5507
5692
  for (const part of explicitParts) {
5508
- const lines = part.split(/\r?\n/);
5693
+ const lines = part.split("\n");
5509
5694
  let currentLines = [];
5510
5695
  let count = 0;
5511
5696
  for (const line of lines) {
5512
- currentLines.push(line);
5513
- count++;
5514
- if (count >= maxLinesPerPage) {
5697
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
5698
+ if (count + vLines > maxLinesPerPage && currentLines.length > 0) {
5515
5699
  finalPages.push(currentLines.join("\n"));
5516
5700
  currentLines = [];
5517
5701
  count = 0;
5518
5702
  }
5703
+ currentLines.push(line);
5704
+ count += vLines;
5519
5705
  }
5520
5706
  if (currentLines.length > 0) {
5521
5707
  finalPages.push(currentLines.join("\n"));
5522
5708
  }
5523
5709
  }
5524
- return finalPages.length > 0 ? finalPages : [text];
5710
+ return finalPages.length > 0 ? finalPages : [normalized];
5525
5711
  }
5526
5712
  /**
5527
5713
  * Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
5528
5714
  */
5529
5715
  formatDocToHtml(text, filename) {
5530
- const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
5716
+ 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");
5531
5717
  let html = "";
5532
5718
  let inList = false;
5533
5719
  let tableLines = [];
5534
5720
  const flushTable = () => {
5535
5721
  if (tableLines.length > 0) {
5536
- html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
5537
- for (const tLine of tableLines) {
5538
- html += "<tr>";
5539
- const cols = tLine.split(" ");
5722
+ html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 13px; font-family: Calibri, sans-serif;">';
5723
+ for (let rIdx = 0; rIdx < tableLines.length; rIdx++) {
5724
+ const tLine = tableLines[rIdx];
5725
+ const isHeader = rIdx === 0;
5726
+ html += `<tr style="${isHeader ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
5727
+ const cols = tLine.split(" ").filter((c) => c.trim().length > 0);
5540
5728
  for (const col of cols) {
5541
- html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
5729
+ html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
5542
5730
  }
5543
5731
  html += "</tr>";
5544
5732
  }
@@ -5551,27 +5739,18 @@ var DocPlugin = class {
5551
5739
  let line = lines[i];
5552
5740
  let tabCount = (line.match(/\t/g) || []).length;
5553
5741
  if (tabCount > 0) {
5554
- let consecutiveTableLines = 1;
5555
- let j = i + 1;
5556
- while (j < lines.length) {
5557
- const nextTabCount = (lines[j].match(/\t/g) || []).length;
5558
- if (nextTabCount === tabCount) {
5559
- consecutiveTableLines++;
5560
- j++;
5561
- } else {
5562
- break;
5563
- }
5742
+ let j = i;
5743
+ while (j < lines.length && (lines[j].match(/\t/g) || []).length > 0) {
5744
+ j++;
5564
5745
  }
5565
- if (consecutiveTableLines >= 3) {
5566
- if (inList) {
5567
- html += "</ul>";
5568
- inList = false;
5569
- }
5570
- tableLines = lines.slice(i, j);
5571
- flushTable();
5572
- i = j;
5573
- continue;
5746
+ if (inList) {
5747
+ html += "</ul>";
5748
+ inList = false;
5574
5749
  }
5750
+ tableLines = lines.slice(i, j);
5751
+ flushTable();
5752
+ i = j;
5753
+ continue;
5575
5754
  }
5576
5755
  line = line.trim();
5577
5756
  if (!line) {