@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/vue.js CHANGED
@@ -433,7 +433,8 @@ function createElement(tag, attrs, ...children) {
433
433
  }
434
434
  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>`;
435
435
  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>`;
436
- 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>`;
436
+ 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>`;
437
+ 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>`;
437
438
  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>`;
438
439
  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>`;
439
440
  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>`;
@@ -453,6 +454,7 @@ var ICON_MAP = {
453
454
  "zoom-in": ICON_ZOOM_IN,
454
455
  "zoom-out": ICON_ZOOM_OUT,
455
456
  "fit-page": ICON_FIT_PAGE,
457
+ "fit-width": ICON_FIT_WIDTH,
456
458
  "fit-slide": ICON_FIT_PAGE,
457
459
  "rotate-cw": ICON_ROTATE_CW,
458
460
  "rotate-ccw": ICON_ROTATE_CCW,
@@ -1399,6 +1401,7 @@ var PdfPlugin = class {
1399
1401
  let currentPage = 1;
1400
1402
  let zoomScale = 1;
1401
1403
  let rotation = 0;
1404
+ let fitMode = "width";
1402
1405
  let currentRenderTask = null;
1403
1406
  const renderPage = async (pageNum) => {
1404
1407
  if (currentRenderTask) {
@@ -1418,11 +1421,16 @@ var PdfPlugin = class {
1418
1421
  const containerWidth = container.clientWidth || 900;
1419
1422
  const containerHeight = container.clientHeight || 700;
1420
1423
  const unscaledVp = page.getViewport({ scale: 1, rotation });
1421
- const availWidth = Math.max(100, containerWidth - 48);
1422
- const availHeight = Math.max(100, containerHeight - 88);
1424
+ const availWidth = Math.max(280, containerWidth - 48);
1425
+ const availHeight = Math.max(280, containerHeight - 88);
1423
1426
  const scaleW = availWidth / unscaledVp.width;
1424
1427
  const scaleH = availHeight / unscaledVp.height;
1425
- const fitScale = Math.min(scaleW, scaleH);
1428
+ let fitScale;
1429
+ if (fitMode === "page") {
1430
+ fitScale = Math.max(0.5, Math.min(scaleW, scaleH));
1431
+ } else {
1432
+ fitScale = Math.max(0.65, Math.min(1.15, scaleW));
1433
+ }
1426
1434
  const effectiveScale = (fitScale > 0 ? fitScale : 1) * zoomScale;
1427
1435
  const pixelRatio = window.devicePixelRatio || 1;
1428
1436
  const viewport = page.getViewport({ scale: effectiveScale, rotation });
@@ -1491,6 +1499,7 @@ var PdfPlugin = class {
1491
1499
  renderPage(currentPage);
1492
1500
  },
1493
1501
  fitToPage: () => {
1502
+ fitMode = fitMode === "width" ? "page" : "width";
1494
1503
  zoomScale = 1;
1495
1504
  rotation = 0;
1496
1505
  renderPage(currentPage);
@@ -1507,6 +1516,7 @@ var PdfPlugin = class {
1507
1516
  getPageCount: () => totalPages,
1508
1517
  getCurrentPage: () => currentPage,
1509
1518
  goToPage: (page) => {
1519
+ container.scrollTop = 0;
1510
1520
  renderPage(page);
1511
1521
  },
1512
1522
  download: () => {
@@ -2011,7 +2021,14 @@ var DocxPlugin = class {
2011
2021
  ignoreFonts: true,
2012
2022
  // Avoid crashes on embedded obfuscated fonts
2013
2023
  breakPages: true,
2014
- experimental: true
2024
+ experimental: true,
2025
+ ignoreLastRenderedPageBreak: false,
2026
+ // Honor Word's exact page breaks!
2027
+ renderHeaders: true,
2028
+ renderFooters: true,
2029
+ renderFootnotes: true,
2030
+ renderEndnotes: true,
2031
+ useBase64URL: true
2015
2032
  });
2016
2033
  if (!ctx.container.contains(wrapper)) {
2017
2034
  ctx.container.appendChild(wrapper);
@@ -2032,11 +2049,14 @@ var DocxPlugin = class {
2032
2049
  renderedSuccessfully = true;
2033
2050
  } catch (fallbackErr) {
2034
2051
  console.error("[DocxPlugin] Native fallback failed:", fallbackErr);
2052
+ const isCorrupt = fallbackErr?.message?.includes("invalid zip") || fallbackErr?.message?.includes("corrupted");
2035
2053
  wrapper.innerHTML = `
2036
- <div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
2037
- <div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
2038
- <h3 style="margin: 0 0 8px; color: #1e293b;">${ctx.metadata.name || "Word Document"}</h3>
2039
- <p style="color: #64748b; margin: 0;">Could not parse document content</p>
2054
+ <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;">
2055
+ <div style="font-size:48px; margin-bottom: 16px;">${isCorrupt ? "\u26A0\uFE0F" : "\u{1F4C4}"}</div>
2056
+ <h3 style="margin: 0 0 8px; color: #1e293b; font-size: 18px;">${ctx.metadata.name || "Word Document"}</h3>
2057
+ <p style="color: #64748b; margin: 0 0 16px; font-size: 14px; line-height: 1.5;">
2058
+ ${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."}
2059
+ </p>
2040
2060
  </div>
2041
2061
  `;
2042
2062
  if (!ctx.container.contains(wrapper)) {
@@ -2044,8 +2064,67 @@ var DocxPlugin = class {
2044
2064
  }
2045
2065
  }
2046
2066
  }
2047
- const sections = wrapper.querySelectorAll("section.docx");
2048
- const cards = wrapper.querySelectorAll(".fp-docx-page-card");
2067
+ let sections = Array.from(wrapper.querySelectorAll("section.docx"));
2068
+ const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
2069
+ if (sections.length === 1 && cards.length === 0) {
2070
+ const singleSec = sections[0];
2071
+ const contentContainer = singleSec.querySelector("article") || singleSec;
2072
+ const children = Array.from(contentContainer.children);
2073
+ const pageH = singleSec.offsetHeight > 1300 ? 1122 : Math.max(1056, singleSec.offsetHeight);
2074
+ const secH = singleSec.offsetHeight || singleSec.scrollHeight;
2075
+ if (secH > pageH * 1.25 && children.length > 1) {
2076
+ const childHeights = children.map((c) => {
2077
+ const rectH = c.getBoundingClientRect().height;
2078
+ const offH = c.offsetHeight;
2079
+ const textLen = c.textContent?.trim().length || 0;
2080
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
2081
+ return Math.max(rectH, offH, estH);
2082
+ });
2083
+ const parent = singleSec.parentElement || wrapper;
2084
+ const newSections = [singleSec];
2085
+ const headerEl = singleSec.querySelector("header");
2086
+ const footerEl = singleSec.querySelector("footer");
2087
+ contentContainer.innerHTML = "";
2088
+ singleSec.style.minHeight = `${pageH}px`;
2089
+ singleSec.style.boxSizing = "border-box";
2090
+ let curContent = contentContainer;
2091
+ let curH = 0;
2092
+ const maxH = pageH - 140;
2093
+ for (let i = 0; i < children.length; i++) {
2094
+ const child = children[i];
2095
+ const chH = childHeights[i];
2096
+ curContent.appendChild(child);
2097
+ curH += chH;
2098
+ if (curH >= maxH && i < children.length - 1) {
2099
+ const nextSec = document.createElement("section");
2100
+ nextSec.className = singleSec.className;
2101
+ nextSec.style.cssText = singleSec.style.cssText;
2102
+ nextSec.style.minHeight = `${pageH}px`;
2103
+ nextSec.style.boxSizing = "border-box";
2104
+ nextSec.style.backgroundColor = "#ffffff";
2105
+ nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
2106
+ nextSec.style.borderRadius = "4px";
2107
+ nextSec.style.marginBottom = "24px";
2108
+ if (headerEl) {
2109
+ nextSec.appendChild(headerEl.cloneNode(true));
2110
+ }
2111
+ const nextArticle = document.createElement("article");
2112
+ if (contentContainer.tagName.toLowerCase() === "article") {
2113
+ nextArticle.style.cssText = contentContainer.style.cssText;
2114
+ }
2115
+ nextSec.appendChild(nextArticle);
2116
+ if (footerEl) {
2117
+ nextSec.appendChild(footerEl.cloneNode(true));
2118
+ }
2119
+ parent.appendChild(nextSec);
2120
+ newSections.push(nextSec);
2121
+ curContent = nextArticle;
2122
+ curH = 0;
2123
+ }
2124
+ }
2125
+ sections = newSections;
2126
+ }
2127
+ }
2049
2128
  const pageElements = sections.length > 0 ? sections : cards;
2050
2129
  const totalPages = Math.max(1, pageElements.length);
2051
2130
  let currentPage = 1;
@@ -2082,6 +2161,7 @@ var DocxPlugin = class {
2082
2161
  if (indicator) {
2083
2162
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
2084
2163
  }
2164
+ ctx.container.scrollTop = 0;
2085
2165
  ctx.emit("page-change", { page: currentPage, total: totalPages });
2086
2166
  };
2087
2167
  if (totalPages > 1) {
@@ -2089,22 +2169,27 @@ var DocxPlugin = class {
2089
2169
  }
2090
2170
  scale = 1;
2091
2171
  let rotation = 0;
2092
- const calculateFitScale = () => {
2172
+ let fitMode = "width";
2173
+ const calculateFitScale = (mode = fitMode) => {
2093
2174
  const activeEl = pageElements[currentPage - 1] || wrapper.firstElementChild || wrapper;
2094
2175
  const elW = activeEl.offsetWidth || 816;
2095
- const elH = activeEl.offsetHeight || 1056;
2096
- const availW = Math.max(200, ctx.container.clientWidth - 48);
2097
- const availH = Math.max(200, ctx.container.clientHeight - 80);
2176
+ const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
2177
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
2178
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
2098
2179
  const sW = availW / elW;
2099
- const sH = availH / elH;
2100
- return Math.min(1.1, Math.min(sW, sH));
2180
+ const sH = availH / singlePageH;
2181
+ if (mode === "page") {
2182
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
2183
+ }
2184
+ return Math.max(0.65, Math.min(1.05, sW));
2101
2185
  };
2102
2186
  const applyTransform = () => {
2103
2187
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
2104
2188
  wrapper.style.transformOrigin = "top center";
2105
2189
  };
2106
2190
  setTimeout(() => {
2107
- scale = calculateFitScale();
2191
+ fitMode = "width";
2192
+ scale = calculateFitScale("width");
2108
2193
  applyTransform();
2109
2194
  }, 60);
2110
2195
  const cleanup = () => {
@@ -2138,7 +2223,8 @@ var DocxPlugin = class {
2138
2223
  applyTransform();
2139
2224
  },
2140
2225
  fitToPage: () => {
2141
- scale = calculateFitScale();
2226
+ fitMode = fitMode === "width" ? "page" : "width";
2227
+ scale = calculateFitScale(fitMode);
2142
2228
  rotation = 0;
2143
2229
  applyTransform();
2144
2230
  },
@@ -2582,11 +2668,9 @@ var ExcelPlugin = class {
2582
2668
  const calculateFitScale = () => {
2583
2669
  const table = contentArea.querySelector("table");
2584
2670
  if (!table) return 1;
2585
- const availW = Math.max(200, container.clientWidth - 48);
2586
- const availH = Math.max(200, container.clientHeight - 80);
2671
+ const availW = Math.max(280, container.clientWidth - 48);
2587
2672
  const tW = table.offsetWidth || 800;
2588
- const tH = table.offsetHeight || 600;
2589
- return Math.min(1, Math.min(availW / tW, availH / tH));
2673
+ return Math.max(0.65, Math.min(1, availW / tW));
2590
2674
  };
2591
2675
  try {
2592
2676
  wb = XLSX.read(new Uint8Array(ctx.buffer), { type: "array", cellDates: true });
@@ -3010,17 +3094,39 @@ var CodePlugin = class {
3010
3094
  let rawPages = [];
3011
3095
  if (isTxt) {
3012
3096
  const explicitPages = fullText.split(/(?:\f|\x0C)/);
3097
+ const charsPerLine = 85;
3098
+ const maxVisualLines = 45;
3099
+ const charsPerPage = charsPerLine * maxVisualLines;
3013
3100
  for (const ep of explicitPages) {
3014
3101
  const lines = ep.split(/\r?\n/);
3015
3102
  let currentChunk = [];
3103
+ let currentLines = 0;
3016
3104
  for (let i = 0; i < lines.length; i++) {
3017
- currentChunk.push(lines[i]);
3018
- if (currentChunk.length >= 46) {
3105
+ const line = lines[i];
3106
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
3107
+ if (currentLines + vLines > maxVisualLines && currentChunk.length > 0) {
3019
3108
  rawPages.push(currentChunk.join("\n"));
3020
3109
  currentChunk = [];
3110
+ currentLines = 0;
3111
+ }
3112
+ if (vLines > maxVisualLines) {
3113
+ let remaining = line;
3114
+ while (remaining.length > charsPerPage) {
3115
+ let splitIdx = remaining.lastIndexOf(" ", charsPerPage);
3116
+ if (splitIdx < charsPerPage * 0.75) splitIdx = charsPerPage;
3117
+ rawPages.push(remaining.slice(0, splitIdx));
3118
+ remaining = remaining.slice(splitIdx).trimStart();
3119
+ }
3120
+ if (remaining.length > 0) {
3121
+ currentChunk.push(remaining);
3122
+ currentLines = Math.ceil(remaining.length / charsPerLine);
3123
+ }
3124
+ } else {
3125
+ currentChunk.push(line);
3126
+ currentLines += vLines;
3021
3127
  }
3022
3128
  }
3023
- if (currentChunk.length > 0 || lines.length === 0) {
3129
+ if (currentChunk.length > 0) {
3024
3130
  rawPages.push(currentChunk.join("\n"));
3025
3131
  }
3026
3132
  }
@@ -3130,6 +3236,7 @@ var CodePlugin = class {
3130
3236
  if (indicator) {
3131
3237
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
3132
3238
  }
3239
+ container.scrollTop = 0;
3133
3240
  ctx.emit("page-change", { page: currentPage, total: totalPages });
3134
3241
  };
3135
3242
  if (totalPages > 1) {
@@ -3183,7 +3290,7 @@ var CodePlugin = class {
3183
3290
  fitToPage: () => {
3184
3291
  fontSize = 13;
3185
3292
  rotation = 0;
3186
- zoomLevel = 1;
3293
+ zoomLevel = isTxt ? Math.max(0.65, Math.min(1.05, (container.clientWidth - 48) / 816)) : 1;
3187
3294
  updateTransform();
3188
3295
  },
3189
3296
  rotateCW: () => {
@@ -4165,20 +4272,27 @@ var RtfPlugin = class {
4165
4272
  let scale = 1;
4166
4273
  let rotation = 0;
4167
4274
  let pageElements = [];
4168
- const calculateFitScale = () => {
4275
+ let fitMode = "width";
4276
+ const calculateFitScale = (mode = fitMode) => {
4169
4277
  const activeEl = pageElements[currentPage - 1] || wrapper;
4170
4278
  const elW = activeEl.offsetWidth || 850;
4171
- const elH = activeEl.offsetHeight || 1e3;
4172
- const availW = Math.max(200, ctx.container.clientWidth - 48);
4173
- const availH = Math.max(200, ctx.container.clientHeight - 80);
4174
- return Math.min(1.1, Math.min(availW / elW, availH / elH));
4279
+ const singlePageH = Math.min(activeEl.offsetHeight || 1056, Math.round(elW * 1.32));
4280
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
4281
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
4282
+ const sW = availW / elW;
4283
+ const sH = availH / singlePageH;
4284
+ if (mode === "page") {
4285
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
4286
+ }
4287
+ return Math.max(0.65, Math.min(1.05, sW));
4175
4288
  };
4176
4289
  const applyTransform = () => {
4177
4290
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4178
4291
  wrapper.style.transformOrigin = "top center";
4179
4292
  };
4180
4293
  setTimeout(() => {
4181
- scale = calculateFitScale();
4294
+ fitMode = "width";
4295
+ scale = calculateFitScale("width");
4182
4296
  applyTransform();
4183
4297
  }, 60);
4184
4298
  try {
@@ -4187,11 +4301,60 @@ var RtfPlugin = class {
4187
4301
  }
4188
4302
  const doc = new RTFJS.Document(ctx.buffer, {});
4189
4303
  const htmlElements = await doc.render();
4190
- pageElements = htmlElements;
4191
- for (let i = 0; i < htmlElements.length; i++) {
4192
- const el = htmlElements[i];
4193
- el.style.display = i === 0 ? "block" : "none";
4194
- wrapper.appendChild(el);
4304
+ if (htmlElements.length === 1) {
4305
+ const singleEl = htmlElements[0];
4306
+ wrapper.appendChild(singleEl);
4307
+ const children = Array.from(singleEl.children);
4308
+ const secH = singleEl.offsetHeight || singleEl.scrollHeight;
4309
+ if (secH > 1300 && children.length > 1) {
4310
+ const childHeights = children.map((c) => {
4311
+ const rectH = c.getBoundingClientRect().height;
4312
+ const offH = c.offsetHeight;
4313
+ const textLen = c.textContent?.trim().length || 0;
4314
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
4315
+ return Math.max(rectH, offH, estH);
4316
+ });
4317
+ wrapper.innerHTML = "";
4318
+ const createRtfCard = () => {
4319
+ const card = document.createElement("div");
4320
+ card.className = "fp-rtf-page-card";
4321
+ card.style.backgroundColor = "#ffffff";
4322
+ card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
4323
+ card.style.borderRadius = "4px";
4324
+ card.style.padding = "72px 56px";
4325
+ card.style.width = "816px";
4326
+ card.style.minHeight = "1056px";
4327
+ card.style.boxSizing = "border-box";
4328
+ card.style.marginBottom = "24px";
4329
+ return card;
4330
+ };
4331
+ let curCard = createRtfCard();
4332
+ wrapper.appendChild(curCard);
4333
+ pageElements = [curCard];
4334
+ let curH = 0;
4335
+ const maxH = 920;
4336
+ for (let i = 0; i < children.length; i++) {
4337
+ const child = children[i];
4338
+ const chH = childHeights[i];
4339
+ curCard.appendChild(child);
4340
+ curH += chH;
4341
+ if (curH >= maxH && i < children.length - 1) {
4342
+ curCard = createRtfCard();
4343
+ wrapper.appendChild(curCard);
4344
+ pageElements.push(curCard);
4345
+ curH = 0;
4346
+ }
4347
+ }
4348
+ } else {
4349
+ pageElements = [singleEl];
4350
+ }
4351
+ } else {
4352
+ pageElements = htmlElements;
4353
+ for (let i = 0; i < htmlElements.length; i++) {
4354
+ const el = htmlElements[i];
4355
+ el.style.display = i === 0 ? "block" : "none";
4356
+ wrapper.appendChild(el);
4357
+ }
4195
4358
  }
4196
4359
  } catch (err) {
4197
4360
  console.warn("[RtfPlugin] RTF render error, fallback text:", err);
@@ -4257,6 +4420,7 @@ var RtfPlugin = class {
4257
4420
  if (indicator) {
4258
4421
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4259
4422
  }
4423
+ ctx.container.scrollTop = 0;
4260
4424
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4261
4425
  };
4262
4426
  if (totalPages > 1) {
@@ -4287,7 +4451,8 @@ var RtfPlugin = class {
4287
4451
  applyTransform();
4288
4452
  },
4289
4453
  fitToPage: () => {
4290
- scale = calculateFitScale();
4454
+ fitMode = fitMode === "width" ? "page" : "width";
4455
+ scale = calculateFitScale(fitMode);
4291
4456
  rotation = 0;
4292
4457
  applyTransform();
4293
4458
  },
@@ -4606,19 +4771,29 @@ var OpenDocumentPlugin = class {
4606
4771
  ctx.container.appendChild(container);
4607
4772
  let scale = 1;
4608
4773
  let rotation = 0;
4609
- const calculateFitScale = () => {
4774
+ let fitMode = "width";
4775
+ const calculateFitScale = (mode = fitMode) => {
4610
4776
  const elW = wrapper.offsetWidth || 850;
4611
- const elH = wrapper.offsetHeight || (isPresentation ? 540 : 1e3);
4612
- const availW = Math.max(200, ctx.container.clientWidth - 48);
4613
- const availH = Math.max(200, ctx.container.clientHeight - 80);
4614
- return Math.min(1, Math.min(availW / elW, availH / elH));
4777
+ const singlePageH = Math.min(wrapper.offsetHeight || 1056, Math.round(elW * 1.32));
4778
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
4779
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
4780
+ const sW = availW / elW;
4781
+ const sH = availH / (isPresentation ? 540 : singlePageH);
4782
+ if (isPresentation) {
4783
+ return Math.min(1, Math.min(sW, sH));
4784
+ }
4785
+ if (mode === "page") {
4786
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
4787
+ }
4788
+ return Math.max(0.65, Math.min(1.05, sW));
4615
4789
  };
4616
4790
  const applyTransform = () => {
4617
4791
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
4618
4792
  wrapper.style.transformOrigin = "top center";
4619
4793
  };
4620
4794
  setTimeout(() => {
4621
- scale = calculateFitScale();
4795
+ fitMode = "width";
4796
+ scale = calculateFitScale("width");
4622
4797
  applyTransform();
4623
4798
  }, 60);
4624
4799
  let currentPage = 1;
@@ -4717,12 +4892,9 @@ var OpenDocumentPlugin = class {
4717
4892
  page.style.backgroundColor = "#ffffff";
4718
4893
  page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
4719
4894
  page.style.borderRadius = "4px";
4720
- page.style.boxSizing = "border-box";
4721
4895
  page.style.display = idx === 0 ? "block" : "none";
4722
- page.style.position = "absolute";
4723
- page.style.top = "0";
4724
- page.style.left = "50%";
4725
- page.style.transform = "translateX(-50%)";
4896
+ page.style.margin = "0 auto 24px";
4897
+ page.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
4726
4898
  elements.forEach((el) => page.appendChild(el));
4727
4899
  wrapper.appendChild(page);
4728
4900
  slides.push(page);
@@ -4760,6 +4932,7 @@ var OpenDocumentPlugin = class {
4760
4932
  if (indicator) {
4761
4933
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4762
4934
  }
4935
+ container.scrollTop = 0;
4763
4936
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4764
4937
  };
4765
4938
  return {
@@ -4779,7 +4952,8 @@ var OpenDocumentPlugin = class {
4779
4952
  applyTransform();
4780
4953
  },
4781
4954
  fitToPage: () => {
4782
- scale = calculateFitScale();
4955
+ fitMode = fitMode === "width" ? "page" : "width";
4956
+ scale = calculateFitScale(fitMode);
4783
4957
  rotation = 0;
4784
4958
  applyTransform();
4785
4959
  },
@@ -5251,20 +5425,28 @@ var DocPlugin = class {
5251
5425
  if (indicator) {
5252
5426
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
5253
5427
  }
5428
+ container.scrollTop = 0;
5254
5429
  ctx.emit("page-change", { page: currentPage, total: totalPages });
5255
5430
  };
5256
5431
  if (totalPages > 1) {
5257
5432
  showPage(1);
5258
5433
  }
5259
- const calculateFitScale = () => {
5434
+ let fitMode = "width";
5435
+ const calculateFitScale = (mode = fitMode) => {
5260
5436
  const elW = 816;
5261
5437
  const elH = 1056;
5262
- const availW = Math.max(200, ctx.container.clientWidth - 48);
5263
- const availH = Math.max(200, ctx.container.clientHeight - 80);
5264
- return Math.min(1.1, Math.min(availW / elW, availH / elH));
5438
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
5439
+ const availH = Math.max(280, ctx.container.clientHeight - 80);
5440
+ const sW = availW / elW;
5441
+ const sH = availH / elH;
5442
+ if (mode === "page") {
5443
+ return Math.max(0.55, Math.min(1.15, Math.min(sW, sH)));
5444
+ }
5445
+ return Math.max(0.65, Math.min(1.05, sW));
5265
5446
  };
5266
5447
  setTimeout(() => {
5267
- scale = calculateFitScale();
5448
+ fitMode = "width";
5449
+ scale = calculateFitScale("width");
5268
5450
  applyTransform();
5269
5451
  }, 60);
5270
5452
  const cleanup = () => {
@@ -5292,7 +5474,8 @@ var DocPlugin = class {
5292
5474
  applyTransform();
5293
5475
  },
5294
5476
  fitToPage: () => {
5295
- scale = calculateFitScale();
5477
+ fitMode = fitMode === "width" ? "page" : "width";
5478
+ scale = calculateFitScale(fitMode);
5296
5479
  rotation = 0;
5297
5480
  applyTransform();
5298
5481
  },
@@ -5420,45 +5603,50 @@ var DocPlugin = class {
5420
5603
  }
5421
5604
  splitIntoPages(text) {
5422
5605
  if (!text) return [""];
5423
- 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);
5424
- if (explicitParts.length === 0) explicitParts.push(text);
5425
- const maxLinesPerPage = 48;
5606
+ const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ");
5607
+ 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);
5608
+ if (explicitParts.length === 0) explicitParts.push(normalized);
5609
+ const maxLinesPerPage = 32;
5610
+ const charsPerLine = 80;
5426
5611
  const finalPages = [];
5427
5612
  for (const part of explicitParts) {
5428
- const lines = part.split(/\r?\n/);
5613
+ const lines = part.split("\n");
5429
5614
  let currentLines = [];
5430
5615
  let count = 0;
5431
5616
  for (const line of lines) {
5432
- currentLines.push(line);
5433
- count++;
5434
- if (count >= maxLinesPerPage) {
5617
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
5618
+ if (count + vLines > maxLinesPerPage && currentLines.length > 0) {
5435
5619
  finalPages.push(currentLines.join("\n"));
5436
5620
  currentLines = [];
5437
5621
  count = 0;
5438
5622
  }
5623
+ currentLines.push(line);
5624
+ count += vLines;
5439
5625
  }
5440
5626
  if (currentLines.length > 0) {
5441
5627
  finalPages.push(currentLines.join("\n"));
5442
5628
  }
5443
5629
  }
5444
- return finalPages.length > 0 ? finalPages : [text];
5630
+ return finalPages.length > 0 ? finalPages : [normalized];
5445
5631
  }
5446
5632
  /**
5447
5633
  * Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
5448
5634
  */
5449
5635
  formatDocToHtml(text, filename) {
5450
- const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
5636
+ 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");
5451
5637
  let html = "";
5452
5638
  let inList = false;
5453
5639
  let tableLines = [];
5454
5640
  const flushTable = () => {
5455
5641
  if (tableLines.length > 0) {
5456
- html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
5457
- for (const tLine of tableLines) {
5458
- html += "<tr>";
5459
- const cols = tLine.split(" ");
5642
+ html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 13px; font-family: Calibri, sans-serif;">';
5643
+ for (let rIdx = 0; rIdx < tableLines.length; rIdx++) {
5644
+ const tLine = tableLines[rIdx];
5645
+ const isHeader = rIdx === 0;
5646
+ html += `<tr style="${isHeader ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
5647
+ const cols = tLine.split(" ").filter((c) => c.trim().length > 0);
5460
5648
  for (const col of cols) {
5461
- html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6.sanitize(col.trim())}</td>`;
5649
+ html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px;">${DOMPurify6.sanitize(col.trim())}</td>`;
5462
5650
  }
5463
5651
  html += "</tr>";
5464
5652
  }
@@ -5471,27 +5659,18 @@ var DocPlugin = class {
5471
5659
  let line = lines[i];
5472
5660
  let tabCount = (line.match(/\t/g) || []).length;
5473
5661
  if (tabCount > 0) {
5474
- let consecutiveTableLines = 1;
5475
- let j = i + 1;
5476
- while (j < lines.length) {
5477
- const nextTabCount = (lines[j].match(/\t/g) || []).length;
5478
- if (nextTabCount === tabCount) {
5479
- consecutiveTableLines++;
5480
- j++;
5481
- } else {
5482
- break;
5483
- }
5662
+ let j = i;
5663
+ while (j < lines.length && (lines[j].match(/\t/g) || []).length > 0) {
5664
+ j++;
5484
5665
  }
5485
- if (consecutiveTableLines >= 3) {
5486
- if (inList) {
5487
- html += "</ul>";
5488
- inList = false;
5489
- }
5490
- tableLines = lines.slice(i, j);
5491
- flushTable();
5492
- i = j;
5493
- continue;
5666
+ if (inList) {
5667
+ html += "</ul>";
5668
+ inList = false;
5494
5669
  }
5670
+ tableLines = lines.slice(i, j);
5671
+ flushTable();
5672
+ i = j;
5673
+ continue;
5495
5674
  }
5496
5675
  line = line.trim();
5497
5676
  if (!line) {