@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.js CHANGED
@@ -481,7 +481,8 @@ function createElement(tag, attrs, ...children) {
481
481
  }
482
482
  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>`;
483
483
  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>`;
484
- 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>`;
484
+ 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>`;
485
+ 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>`;
485
486
  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>`;
486
487
  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>`;
487
488
  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>`;
@@ -501,6 +502,7 @@ var ICON_MAP = {
501
502
  "zoom-in": ICON_ZOOM_IN,
502
503
  "zoom-out": ICON_ZOOM_OUT,
503
504
  "fit-page": ICON_FIT_PAGE,
505
+ "fit-width": ICON_FIT_WIDTH,
504
506
  "fit-slide": ICON_FIT_PAGE,
505
507
  "rotate-cw": ICON_ROTATE_CW,
506
508
  "rotate-ccw": ICON_ROTATE_CCW,
@@ -1447,6 +1449,7 @@ var PdfPlugin = class {
1447
1449
  let currentPage = 1;
1448
1450
  let zoomScale = 1;
1449
1451
  let rotation = 0;
1452
+ let fitMode = "width";
1450
1453
  let currentRenderTask = null;
1451
1454
  const renderPage = async (pageNum) => {
1452
1455
  if (currentRenderTask) {
@@ -1466,11 +1469,16 @@ var PdfPlugin = class {
1466
1469
  const containerWidth = container.clientWidth || 900;
1467
1470
  const containerHeight = container.clientHeight || 700;
1468
1471
  const unscaledVp = page.getViewport({ scale: 1, rotation });
1469
- const availWidth = Math.max(100, containerWidth - 48);
1470
- const availHeight = Math.max(100, containerHeight - 88);
1472
+ const availWidth = Math.max(280, containerWidth - 48);
1473
+ const availHeight = Math.max(280, containerHeight - 88);
1471
1474
  const scaleW = availWidth / unscaledVp.width;
1472
1475
  const scaleH = availHeight / unscaledVp.height;
1473
- const fitScale = Math.min(scaleW, scaleH);
1476
+ let fitScale;
1477
+ if (fitMode === "page") {
1478
+ fitScale = Math.max(0.5, Math.min(scaleW, scaleH));
1479
+ } else {
1480
+ fitScale = Math.max(0.65, Math.min(1.15, scaleW));
1481
+ }
1474
1482
  const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
1475
1483
  const pixelRatio = window.devicePixelRatio || 1;
1476
1484
  const viewport = page.getViewport({ scale: effectiveScale, rotation });
@@ -1539,6 +1547,7 @@ var PdfPlugin = class {
1539
1547
  renderPage(currentPage);
1540
1548
  },
1541
1549
  fitToPage: () => {
1550
+ fitMode = fitMode === "width" ? "page" : "width";
1542
1551
  zoomScale = 1;
1543
1552
  rotation = 0;
1544
1553
  renderPage(currentPage);
@@ -1555,6 +1564,7 @@ var PdfPlugin = class {
1555
1564
  getPageCount: () => totalPages,
1556
1565
  getCurrentPage: () => currentPage,
1557
1566
  goToPage: (page) => {
1567
+ container.scrollTop = 0;
1558
1568
  renderPage(page);
1559
1569
  },
1560
1570
  download: () => {
@@ -2059,7 +2069,14 @@ var DocxPlugin = class {
2059
2069
  ignoreFonts: true,
2060
2070
  // Avoid crashes on embedded obfuscated fonts
2061
2071
  breakPages: true,
2062
- experimental: true
2072
+ experimental: true,
2073
+ ignoreLastRenderedPageBreak: false,
2074
+ // Honor Word's exact page breaks!
2075
+ renderHeaders: true,
2076
+ renderFooters: true,
2077
+ renderFootnotes: true,
2078
+ renderEndnotes: true,
2079
+ useBase64URL: true
2063
2080
  });
2064
2081
  if (!ctx.container.contains(wrapper)) {
2065
2082
  ctx.container.appendChild(wrapper);
@@ -2080,11 +2097,14 @@ var DocxPlugin = class {
2080
2097
  renderedSuccessfully = true;
2081
2098
  } catch (fallbackErr) {
2082
2099
  console.error("[DocxPlugin] Native fallback failed:", fallbackErr);
2100
+ const isCorrupt = fallbackErr?.message?.includes("invalid zip") || fallbackErr?.message?.includes("corrupted");
2083
2101
  wrapper.innerHTML = `
2084
- <div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
2085
- <div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
2086
- <h3 style="margin: 0 0 8px; color: #1e293b;">${ctx.metadata.name || "Word Document"}</h3>
2087
- <p style="color: #64748b; margin: 0;">Could not parse document content</p>
2102
+ <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;">
2103
+ <div style="font-size:48px; margin-bottom: 16px;">${isCorrupt ? "\u26A0\uFE0F" : "\u{1F4C4}"}</div>
2104
+ <h3 style="margin: 0 0 8px; color: #1e293b; font-size: 18px;">${ctx.metadata.name || "Word Document"}</h3>
2105
+ <p style="color: #64748b; margin: 0 0 16px; font-size: 14px; line-height: 1.5;">
2106
+ ${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."}
2107
+ </p>
2088
2108
  </div>
2089
2109
  `;
2090
2110
  if (!ctx.container.contains(wrapper)) {
@@ -2092,8 +2112,67 @@ var DocxPlugin = class {
2092
2112
  }
2093
2113
  }
2094
2114
  }
2095
- const sections = wrapper.querySelectorAll("section.docx");
2096
- const cards = wrapper.querySelectorAll(".fp-docx-page-card");
2115
+ let sections = Array.from(wrapper.querySelectorAll("section.docx"));
2116
+ const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
2117
+ if (sections.length === 1 && cards.length === 0) {
2118
+ const singleSec = sections[0];
2119
+ const contentContainer = singleSec.querySelector("article") || singleSec;
2120
+ const children = Array.from(contentContainer.children);
2121
+ const pageH = singleSec.offsetHeight > 1300 ? 1122 : Math.max(1056, singleSec.offsetHeight);
2122
+ const secH = singleSec.offsetHeight || singleSec.scrollHeight;
2123
+ if (secH > pageH * 1.25 && children.length > 1) {
2124
+ const childHeights = children.map((c) => {
2125
+ const rectH = c.getBoundingClientRect().height;
2126
+ const offH = c.offsetHeight;
2127
+ const textLen = c.textContent?.trim().length || 0;
2128
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
2129
+ return Math.max(rectH, offH, estH);
2130
+ });
2131
+ const parent = singleSec.parentElement || wrapper;
2132
+ const newSections = [singleSec];
2133
+ const headerEl = singleSec.querySelector("header");
2134
+ const footerEl = singleSec.querySelector("footer");
2135
+ contentContainer.innerHTML = "";
2136
+ singleSec.style.minHeight = `${pageH}px`;
2137
+ singleSec.style.boxSizing = "border-box";
2138
+ let curContent = contentContainer;
2139
+ let curH = 0;
2140
+ const maxH = pageH - 140;
2141
+ for (let i = 0; i < children.length; i++) {
2142
+ const child = children[i];
2143
+ const chH = childHeights[i];
2144
+ curContent.appendChild(child);
2145
+ curH += chH;
2146
+ if (curH >= maxH && i < children.length - 1) {
2147
+ const nextSec = document.createElement("section");
2148
+ nextSec.className = singleSec.className;
2149
+ nextSec.style.cssText = singleSec.style.cssText;
2150
+ nextSec.style.minHeight = `${pageH}px`;
2151
+ nextSec.style.boxSizing = "border-box";
2152
+ nextSec.style.backgroundColor = "#ffffff";
2153
+ nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
2154
+ nextSec.style.borderRadius = "4px";
2155
+ nextSec.style.marginBottom = "24px";
2156
+ if (headerEl) {
2157
+ nextSec.appendChild(headerEl.cloneNode(true));
2158
+ }
2159
+ const nextArticle = document.createElement("article");
2160
+ if (contentContainer.tagName.toLowerCase() === "article") {
2161
+ nextArticle.style.cssText = contentContainer.style.cssText;
2162
+ }
2163
+ nextSec.appendChild(nextArticle);
2164
+ if (footerEl) {
2165
+ nextSec.appendChild(footerEl.cloneNode(true));
2166
+ }
2167
+ parent.appendChild(nextSec);
2168
+ newSections.push(nextSec);
2169
+ curContent = nextArticle;
2170
+ curH = 0;
2171
+ }
2172
+ }
2173
+ sections = newSections;
2174
+ }
2175
+ }
2097
2176
  const pageElements = sections.length > 0 ? sections : cards;
2098
2177
  const totalPages = Math.max(1, pageElements.length);
2099
2178
  let currentPage = 1;
@@ -2130,6 +2209,7 @@ var DocxPlugin = class {
2130
2209
  if (indicator) {
2131
2210
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
2132
2211
  }
2212
+ ctx.container.scrollTop = 0;
2133
2213
  ctx.emit("page-change", { page: currentPage, total: totalPages });
2134
2214
  };
2135
2215
  if (totalPages > 1) {
@@ -2137,22 +2217,27 @@ var DocxPlugin = class {
2137
2217
  }
2138
2218
  scale = 1;
2139
2219
  let rotation = 0;
2140
- const calculateFitScale = () => {
2220
+ let fitMode = "width";
2221
+ const calculateFitScale = (mode = fitMode) => {
2141
2222
  const activeEl = pageElements[currentPage - 1] || wrapper.firstElementChild || wrapper;
2142
2223
  const elW = activeEl.offsetWidth || 816;
2143
- const elH = activeEl.offsetHeight || 1056;
2144
- const availW = Math.max(200, ctx.container.clientWidth - 48);
2145
- const availH = Math.max(200, ctx.container.clientHeight - 80);
2224
+ const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
2225
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
2226
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
2146
2227
  const sW = availW / elW;
2147
- const sH = availH / elH;
2148
- return Math.min(1.1, Math.min(sW, sH));
2228
+ const sH = availH / singlePageH;
2229
+ if (mode === "page") {
2230
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
2231
+ }
2232
+ return Math.max(0.65, Math.min(1.05, sW));
2149
2233
  };
2150
2234
  const applyTransform = () => {
2151
2235
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
2152
2236
  wrapper.style.transformOrigin = "top center";
2153
2237
  };
2154
2238
  setTimeout(() => {
2155
- scale = calculateFitScale();
2239
+ fitMode = "width";
2240
+ scale = calculateFitScale("width");
2156
2241
  applyTransform();
2157
2242
  }, 60);
2158
2243
  const cleanup = () => {
@@ -2186,7 +2271,8 @@ var DocxPlugin = class {
2186
2271
  applyTransform();
2187
2272
  },
2188
2273
  fitToPage: () => {
2189
- scale = calculateFitScale();
2274
+ fitMode = fitMode === "width" ? "page" : "width";
2275
+ scale = calculateFitScale(fitMode);
2190
2276
  rotation = 0;
2191
2277
  applyTransform();
2192
2278
  },
@@ -2630,11 +2716,9 @@ var ExcelPlugin = class {
2630
2716
  const calculateFitScale = () => {
2631
2717
  const table = contentArea.querySelector("table");
2632
2718
  if (!table) return 1;
2633
- const availW = Math.max(200, container.clientWidth - 48);
2634
- const availH = Math.max(200, container.clientHeight - 80);
2719
+ const availW = Math.max(280, container.clientWidth - 48);
2635
2720
  const tW = table.offsetWidth || 800;
2636
- const tH = table.offsetHeight || 600;
2637
- return Math.min(1, Math.min(availW / tW, availH / tH));
2721
+ return Math.max(0.65, Math.min(1, availW / tW));
2638
2722
  };
2639
2723
  try {
2640
2724
  wb = XLSX.read(new Uint8Array(ctx.buffer), { type: "array", cellDates: true });
@@ -3058,17 +3142,39 @@ var CodePlugin = class {
3058
3142
  let rawPages = [];
3059
3143
  if (isTxt) {
3060
3144
  const explicitPages = fullText.split(/(?:\f|\x0C)/);
3145
+ const charsPerLine = 85;
3146
+ const maxVisualLines = 45;
3147
+ const charsPerPage = charsPerLine * maxVisualLines;
3061
3148
  for (const ep of explicitPages) {
3062
3149
  const lines = ep.split(/\r?\n/);
3063
3150
  let currentChunk = [];
3151
+ let currentLines = 0;
3064
3152
  for (let i = 0; i < lines.length; i++) {
3065
- currentChunk.push(lines[i]);
3066
- if (currentChunk.length >= 46) {
3153
+ const line = lines[i];
3154
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
3155
+ if (currentLines + vLines > maxVisualLines && currentChunk.length > 0) {
3067
3156
  rawPages.push(currentChunk.join("\n"));
3068
3157
  currentChunk = [];
3158
+ currentLines = 0;
3159
+ }
3160
+ if (vLines > maxVisualLines) {
3161
+ let remaining = line;
3162
+ while (remaining.length > charsPerPage) {
3163
+ let splitIdx = remaining.lastIndexOf(" ", charsPerPage);
3164
+ if (splitIdx < charsPerPage * 0.75) splitIdx = charsPerPage;
3165
+ rawPages.push(remaining.slice(0, splitIdx));
3166
+ remaining = remaining.slice(splitIdx).trimStart();
3167
+ }
3168
+ if (remaining.length > 0) {
3169
+ currentChunk.push(remaining);
3170
+ currentLines = Math.ceil(remaining.length / charsPerLine);
3171
+ }
3172
+ } else {
3173
+ currentChunk.push(line);
3174
+ currentLines += vLines;
3069
3175
  }
3070
3176
  }
3071
- if (currentChunk.length > 0 || lines.length === 0) {
3177
+ if (currentChunk.length > 0) {
3072
3178
  rawPages.push(currentChunk.join("\n"));
3073
3179
  }
3074
3180
  }
@@ -3178,6 +3284,7 @@ var CodePlugin = class {
3178
3284
  if (indicator) {
3179
3285
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
3180
3286
  }
3287
+ container.scrollTop = 0;
3181
3288
  ctx.emit("page-change", { page: currentPage, total: totalPages });
3182
3289
  };
3183
3290
  if (totalPages > 1) {
@@ -3231,7 +3338,7 @@ var CodePlugin = class {
3231
3338
  fitToPage: () => {
3232
3339
  fontSize = 13;
3233
3340
  rotation = 0;
3234
- zoomLevel = 1;
3341
+ zoomLevel = isTxt ? Math.max(0.65, Math.min(1.05, (container.clientWidth - 48) / 816)) : 1;
3235
3342
  updateTransform();
3236
3343
  },
3237
3344
  rotateCW: () => {
@@ -4213,20 +4320,27 @@ var RtfPlugin = class {
4213
4320
  let scale = 1;
4214
4321
  let rotation = 0;
4215
4322
  let pageElements = [];
4216
- const calculateFitScale = () => {
4323
+ let fitMode = "width";
4324
+ const calculateFitScale = (mode = fitMode) => {
4217
4325
  const activeEl = pageElements[currentPage - 1] || wrapper;
4218
4326
  const elW = activeEl.offsetWidth || 850;
4219
- const elH = activeEl.offsetHeight || 1e3;
4220
- const availW = Math.max(200, ctx.container.clientWidth - 48);
4221
- const availH = Math.max(200, ctx.container.clientHeight - 80);
4222
- return Math.min(1.1, Math.min(availW / elW, availH / elH));
4327
+ const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
4328
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
4329
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
4330
+ const sW = availW / elW;
4331
+ const sH = availH / singlePageH;
4332
+ if (mode === "page") {
4333
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
4334
+ }
4335
+ return Math.max(0.65, Math.min(1.05, sW));
4223
4336
  };
4224
4337
  const applyTransform = () => {
4225
4338
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4226
4339
  wrapper.style.transformOrigin = "top center";
4227
4340
  };
4228
4341
  setTimeout(() => {
4229
- scale = calculateFitScale();
4342
+ fitMode = "width";
4343
+ scale = calculateFitScale("width");
4230
4344
  applyTransform();
4231
4345
  }, 60);
4232
4346
  try {
@@ -4235,11 +4349,60 @@ var RtfPlugin = class {
4235
4349
  }
4236
4350
  const doc = new RTFJS.Document(ctx.buffer, {});
4237
4351
  const htmlElements = await doc.render();
4238
- pageElements = htmlElements;
4239
- for (let i = 0; i < htmlElements.length; i++) {
4240
- const el = htmlElements[i];
4241
- el.style.display = i === 0 ? "block" : "none";
4242
- wrapper.appendChild(el);
4352
+ if (htmlElements.length === 1) {
4353
+ const singleEl = htmlElements[0];
4354
+ wrapper.appendChild(singleEl);
4355
+ const children = Array.from(singleEl.children);
4356
+ const secH = singleEl.offsetHeight || singleEl.scrollHeight;
4357
+ if (secH > 1300 && children.length > 1) {
4358
+ const childHeights = children.map((c) => {
4359
+ const rectH = c.getBoundingClientRect().height;
4360
+ const offH = c.offsetHeight;
4361
+ const textLen = c.textContent?.trim().length || 0;
4362
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
4363
+ return Math.max(rectH, offH, estH);
4364
+ });
4365
+ wrapper.innerHTML = "";
4366
+ const createRtfCard = () => {
4367
+ const card = document.createElement("div");
4368
+ card.className = "fp-rtf-page-card";
4369
+ card.style.backgroundColor = "#ffffff";
4370
+ card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
4371
+ card.style.borderRadius = "4px";
4372
+ card.style.padding = "72px 56px";
4373
+ card.style.width = "816px";
4374
+ card.style.minHeight = "1056px";
4375
+ card.style.boxSizing = "border-box";
4376
+ card.style.marginBottom = "24px";
4377
+ return card;
4378
+ };
4379
+ let curCard = createRtfCard();
4380
+ wrapper.appendChild(curCard);
4381
+ pageElements = [curCard];
4382
+ let curH = 0;
4383
+ const maxH = 920;
4384
+ for (let i = 0; i < children.length; i++) {
4385
+ const child = children[i];
4386
+ const chH = childHeights[i];
4387
+ curCard.appendChild(child);
4388
+ curH += chH;
4389
+ if (curH >= maxH && i < children.length - 1) {
4390
+ curCard = createRtfCard();
4391
+ wrapper.appendChild(curCard);
4392
+ pageElements.push(curCard);
4393
+ curH = 0;
4394
+ }
4395
+ }
4396
+ } else {
4397
+ pageElements = [singleEl];
4398
+ }
4399
+ } else {
4400
+ pageElements = htmlElements;
4401
+ for (let i = 0; i < htmlElements.length; i++) {
4402
+ const el = htmlElements[i];
4403
+ el.style.display = i === 0 ? "block" : "none";
4404
+ wrapper.appendChild(el);
4405
+ }
4243
4406
  }
4244
4407
  } catch (err) {
4245
4408
  console.warn("[RtfPlugin] RTF render error, fallback text:", err);
@@ -4305,6 +4468,7 @@ var RtfPlugin = class {
4305
4468
  if (indicator) {
4306
4469
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4307
4470
  }
4471
+ ctx.container.scrollTop = 0;
4308
4472
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4309
4473
  };
4310
4474
  if (totalPages > 1) {
@@ -4335,7 +4499,8 @@ var RtfPlugin = class {
4335
4499
  applyTransform();
4336
4500
  },
4337
4501
  fitToPage: () => {
4338
- scale = calculateFitScale();
4502
+ fitMode = fitMode === "width" ? "page" : "width";
4503
+ scale = calculateFitScale(fitMode);
4339
4504
  rotation = 0;
4340
4505
  applyTransform();
4341
4506
  },
@@ -4654,19 +4819,29 @@ var OpenDocumentPlugin = class {
4654
4819
  ctx.container.appendChild(container);
4655
4820
  let scale = 1;
4656
4821
  let rotation = 0;
4657
- const calculateFitScale = () => {
4822
+ let fitMode = "width";
4823
+ const calculateFitScale = (mode = fitMode) => {
4658
4824
  const elW = wrapper.offsetWidth || 850;
4659
- const elH = wrapper.offsetHeight || (isPresentation ? 540 : 1e3);
4660
- const availW = Math.max(200, ctx.container.clientWidth - 48);
4661
- const availH = Math.max(200, ctx.container.clientHeight - 80);
4662
- return Math.min(1, Math.min(availW / elW, availH / elH));
4825
+ const singlePageH = Math.min(wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
4826
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
4827
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
4828
+ const sW = availW / elW;
4829
+ const sH = availH / (isPresentation ? 540 : singlePageH);
4830
+ if (isPresentation) {
4831
+ return Math.min(1, Math.min(sW, sH));
4832
+ }
4833
+ if (mode === "page") {
4834
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
4835
+ }
4836
+ return Math.max(0.65, Math.min(1.05, sW));
4663
4837
  };
4664
4838
  const applyTransform = () => {
4665
4839
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4666
4840
  wrapper.style.transformOrigin = "top center";
4667
4841
  };
4668
4842
  setTimeout(() => {
4669
- scale = calculateFitScale();
4843
+ fitMode = "width";
4844
+ scale = calculateFitScale("width");
4670
4845
  applyTransform();
4671
4846
  }, 60);
4672
4847
  let currentPage = 1;
@@ -4765,12 +4940,9 @@ var OpenDocumentPlugin = class {
4765
4940
  page.style.backgroundColor = "#ffffff";
4766
4941
  page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
4767
4942
  page.style.borderRadius = "4px";
4768
- page.style.boxSizing = "border-box";
4769
4943
  page.style.display = idx === 0 ? "block" : "none";
4770
- page.style.position = "absolute";
4771
- page.style.top = "0";
4772
- page.style.left = "50%";
4773
- page.style.transform = "translateX(-50%)";
4944
+ page.style.margin = "0 auto 24px";
4945
+ page.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
4774
4946
  elements.forEach((el) => page.appendChild(el));
4775
4947
  wrapper.appendChild(page);
4776
4948
  slides.push(page);
@@ -4808,6 +4980,7 @@ var OpenDocumentPlugin = class {
4808
4980
  if (indicator) {
4809
4981
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4810
4982
  }
4983
+ container.scrollTop = 0;
4811
4984
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4812
4985
  };
4813
4986
  return {
@@ -4827,7 +5000,8 @@ var OpenDocumentPlugin = class {
4827
5000
  applyTransform();
4828
5001
  },
4829
5002
  fitToPage: () => {
4830
- scale = calculateFitScale();
5003
+ fitMode = fitMode === "width" ? "page" : "width";
5004
+ scale = calculateFitScale(fitMode);
4831
5005
  rotation = 0;
4832
5006
  applyTransform();
4833
5007
  },
@@ -5299,20 +5473,28 @@ var DocPlugin = class {
5299
5473
  if (indicator) {
5300
5474
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
5301
5475
  }
5476
+ container.scrollTop = 0;
5302
5477
  ctx.emit("page-change", { page: currentPage, total: totalPages });
5303
5478
  };
5304
5479
  if (totalPages > 1) {
5305
5480
  showPage(1);
5306
5481
  }
5307
- const calculateFitScale = () => {
5482
+ let fitMode = "width";
5483
+ const calculateFitScale = (mode = fitMode) => {
5308
5484
  const elW = 816;
5309
5485
  const elH = 1056;
5310
- const availW = Math.max(200, ctx.container.clientWidth - 48);
5311
- const availH = Math.max(200, ctx.container.clientHeight - 80);
5312
- return Math.min(1.1, Math.min(availW / elW, availH / elH));
5486
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
5487
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
5488
+ const sW = availW / elW;
5489
+ const sH = availH / elH;
5490
+ if (mode === "page") {
5491
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
5492
+ }
5493
+ return Math.max(0.65, Math.min(1.05, sW));
5313
5494
  };
5314
5495
  setTimeout(() => {
5315
- scale = calculateFitScale();
5496
+ fitMode = "width";
5497
+ scale = calculateFitScale("width");
5316
5498
  applyTransform();
5317
5499
  }, 60);
5318
5500
  const cleanup = () => {
@@ -5340,7 +5522,8 @@ var DocPlugin = class {
5340
5522
  applyTransform();
5341
5523
  },
5342
5524
  fitToPage: () => {
5343
- scale = calculateFitScale();
5525
+ fitMode = fitMode === "width" ? "page" : "width";
5526
+ scale = calculateFitScale(fitMode);
5344
5527
  rotation = 0;
5345
5528
  applyTransform();
5346
5529
  },
@@ -5468,45 +5651,50 @@ var DocPlugin = class {
5468
5651
  }
5469
5652
  splitIntoPages(text) {
5470
5653
  if (!text) return [""];
5471
- 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);
5472
- if (explicitParts.length === 0) explicitParts.push(text);
5473
- const maxLinesPerPage = 48;
5654
+ const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ");
5655
+ 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);
5656
+ if (explicitParts.length === 0) explicitParts.push(normalized);
5657
+ const maxLinesPerPage = 32;
5658
+ const charsPerLine = 80;
5474
5659
  const finalPages = [];
5475
5660
  for (const part of explicitParts) {
5476
- const lines = part.split(/\r?\n/);
5661
+ const lines = part.split("\n");
5477
5662
  let currentLines = [];
5478
5663
  let count = 0;
5479
5664
  for (const line of lines) {
5480
- currentLines.push(line);
5481
- count++;
5482
- if (count >= maxLinesPerPage) {
5665
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
5666
+ if (count + vLines > maxLinesPerPage && currentLines.length > 0) {
5483
5667
  finalPages.push(currentLines.join("\n"));
5484
5668
  currentLines = [];
5485
5669
  count = 0;
5486
5670
  }
5671
+ currentLines.push(line);
5672
+ count += vLines;
5487
5673
  }
5488
5674
  if (currentLines.length > 0) {
5489
5675
  finalPages.push(currentLines.join("\n"));
5490
5676
  }
5491
5677
  }
5492
- return finalPages.length > 0 ? finalPages : [text];
5678
+ return finalPages.length > 0 ? finalPages : [normalized];
5493
5679
  }
5494
5680
  /**
5495
5681
  * Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
5496
5682
  */
5497
5683
  formatDocToHtml(text, filename) {
5498
- const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
5684
+ 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");
5499
5685
  let html = "";
5500
5686
  let inList = false;
5501
5687
  let tableLines = [];
5502
5688
  const flushTable = () => {
5503
5689
  if (tableLines.length > 0) {
5504
- html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
5505
- for (const tLine of tableLines) {
5506
- html += "<tr>";
5507
- const cols = tLine.split(" ");
5690
+ html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 13px; font-family: Calibri, sans-serif;">';
5691
+ for (let rIdx = 0; rIdx < tableLines.length; rIdx++) {
5692
+ const tLine = tableLines[rIdx];
5693
+ const isHeader = rIdx === 0;
5694
+ html += `<tr style="${isHeader ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
5695
+ const cols = tLine.split(" ").filter((c) => c.trim().length > 0);
5508
5696
  for (const col of cols) {
5509
- html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6.sanitize(col.trim())}</td>`;
5697
+ html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px;">${DOMPurify6.sanitize(col.trim())}</td>`;
5510
5698
  }
5511
5699
  html += "</tr>";
5512
5700
  }
@@ -5519,27 +5707,18 @@ var DocPlugin = class {
5519
5707
  let line = lines[i];
5520
5708
  let tabCount = (line.match(/\t/g) || []).length;
5521
5709
  if (tabCount > 0) {
5522
- let consecutiveTableLines = 1;
5523
- let j = i + 1;
5524
- while (j < lines.length) {
5525
- const nextTabCount = (lines[j].match(/\t/g) || []).length;
5526
- if (nextTabCount === tabCount) {
5527
- consecutiveTableLines++;
5528
- j++;
5529
- } else {
5530
- break;
5531
- }
5710
+ let j = i;
5711
+ while (j < lines.length && (lines[j].match(/\t/g) || []).length > 0) {
5712
+ j++;
5532
5713
  }
5533
- if (consecutiveTableLines >= 3) {
5534
- if (inList) {
5535
- html += "</ul>";
5536
- inList = false;
5537
- }
5538
- tableLines = lines.slice(i, j);
5539
- flushTable();
5540
- i = j;
5541
- continue;
5714
+ if (inList) {
5715
+ html += "</ul>";
5716
+ inList = false;
5542
5717
  }
5718
+ tableLines = lines.slice(i, j);
5719
+ flushTable();
5720
+ i = j;
5721
+ continue;
5543
5722
  }
5544
5723
  line = line.trim();
5545
5724
  if (!line) {