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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.cjs CHANGED
@@ -1549,6 +1549,7 @@ var PdfPlugin = class {
1549
1549
  getPageCount: () => totalPages,
1550
1550
  getCurrentPage: () => currentPage,
1551
1551
  goToPage: (page) => {
1552
+ container.scrollTop = 0;
1552
1553
  renderPage(page);
1553
1554
  },
1554
1555
  download: () => {
@@ -2053,7 +2054,14 @@ var DocxPlugin = class {
2053
2054
  ignoreFonts: true,
2054
2055
  // Avoid crashes on embedded obfuscated fonts
2055
2056
  breakPages: true,
2056
- experimental: true
2057
+ experimental: true,
2058
+ ignoreLastRenderedPageBreak: false,
2059
+ // Honor Word's exact page breaks!
2060
+ renderHeaders: true,
2061
+ renderFooters: true,
2062
+ renderFootnotes: true,
2063
+ renderEndnotes: true,
2064
+ useBase64URL: true
2057
2065
  });
2058
2066
  if (!ctx.container.contains(wrapper)) {
2059
2067
  ctx.container.appendChild(wrapper);
@@ -2074,11 +2082,14 @@ var DocxPlugin = class {
2074
2082
  renderedSuccessfully = true;
2075
2083
  } catch (fallbackErr) {
2076
2084
  console.error("[DocxPlugin] Native fallback failed:", fallbackErr);
2085
+ const isCorrupt = fallbackErr?.message?.includes("invalid zip") || fallbackErr?.message?.includes("corrupted");
2077
2086
  wrapper.innerHTML = `
2078
- <div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
2079
- <div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
2080
- <h3 style="margin: 0 0 8px; color: #1e293b;">${ctx.metadata.name || "Word Document"}</h3>
2081
- <p style="color: #64748b; margin: 0;">Could not parse document content</p>
2087
+ <div style="text-align:center; padding: 48px 32px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06); max-width: 600px; margin: 40px auto;">
2088
+ <div style="font-size:48px; margin-bottom: 16px;">${isCorrupt ? "\u26A0\uFE0F" : "\u{1F4C4}"}</div>
2089
+ <h3 style="margin: 0 0 8px; color: #1e293b; font-size: 18px;">${ctx.metadata.name || "Word Document"}</h3>
2090
+ <p style="color: #64748b; margin: 0 0 16px; font-size: 14px; line-height: 1.5;">
2091
+ ${isCorrupt ? "This document appears to be corrupted or contains invalid archive data and cannot be opened (matches Microsoft Word on Windows)." : "Could not render document content. The file structure may be damaged."}
2092
+ </p>
2082
2093
  </div>
2083
2094
  `;
2084
2095
  if (!ctx.container.contains(wrapper)) {
@@ -2090,47 +2101,61 @@ var DocxPlugin = class {
2090
2101
  const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
2091
2102
  if (sections.length === 1 && cards.length === 0) {
2092
2103
  const singleSec = sections[0];
2093
- const pageH = 1056;
2104
+ const contentContainer = singleSec.querySelector("article") || singleSec;
2105
+ const children = Array.from(contentContainer.children);
2106
+ const pageH = singleSec.offsetHeight > 1300 ? 1122 : Math.max(1056, singleSec.offsetHeight);
2094
2107
  const secH = singleSec.offsetHeight || singleSec.scrollHeight;
2095
- if (secH > pageH * 1.25) {
2096
- const children = Array.from(singleSec.children);
2097
- if (children.length > 1) {
2098
- const parent = singleSec.parentElement || wrapper;
2099
- const newSections = [singleSec];
2100
- singleSec.innerHTML = "";
2101
- singleSec.style.minHeight = `${pageH}px`;
2102
- singleSec.style.maxHeight = `${pageH}px`;
2103
- singleSec.style.overflow = "hidden";
2104
- singleSec.style.boxSizing = "border-box";
2105
- let curSec = singleSec;
2106
- let curH = 0;
2107
- const maxH = pageH - 96;
2108
- for (let i = 0; i < children.length; i++) {
2109
- const child = children[i];
2110
- curSec.appendChild(child);
2111
- const chH = child.offsetHeight || 28;
2112
- curH += chH;
2113
- if (curH >= maxH && i < children.length - 1) {
2114
- const nextSec = document.createElement("section");
2115
- nextSec.className = singleSec.className;
2116
- nextSec.style.cssText = singleSec.style.cssText;
2117
- nextSec.style.width = singleSec.style.width || "816px";
2118
- nextSec.style.minHeight = `${pageH}px`;
2119
- nextSec.style.maxHeight = `${pageH}px`;
2120
- nextSec.style.overflow = "hidden";
2121
- nextSec.style.boxSizing = "border-box";
2122
- nextSec.style.backgroundColor = "#ffffff";
2123
- nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
2124
- nextSec.style.borderRadius = "4px";
2125
- nextSec.style.marginBottom = "24px";
2126
- parent.appendChild(nextSec);
2127
- newSections.push(nextSec);
2128
- curSec = nextSec;
2129
- curH = 0;
2108
+ if (secH > pageH * 1.25 && children.length > 1) {
2109
+ const childHeights = children.map((c) => {
2110
+ const rectH = c.getBoundingClientRect().height;
2111
+ const offH = c.offsetHeight;
2112
+ const textLen = c.textContent?.trim().length || 0;
2113
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
2114
+ return Math.max(rectH, offH, estH);
2115
+ });
2116
+ const parent = singleSec.parentElement || wrapper;
2117
+ const newSections = [singleSec];
2118
+ const headerEl = singleSec.querySelector("header");
2119
+ const footerEl = singleSec.querySelector("footer");
2120
+ contentContainer.innerHTML = "";
2121
+ singleSec.style.minHeight = `${pageH}px`;
2122
+ singleSec.style.boxSizing = "border-box";
2123
+ let curContent = contentContainer;
2124
+ let curH = 0;
2125
+ const maxH = pageH - 140;
2126
+ for (let i = 0; i < children.length; i++) {
2127
+ const child = children[i];
2128
+ const chH = childHeights[i];
2129
+ curContent.appendChild(child);
2130
+ curH += chH;
2131
+ if (curH >= maxH && i < children.length - 1) {
2132
+ const nextSec = document.createElement("section");
2133
+ nextSec.className = singleSec.className;
2134
+ nextSec.style.cssText = singleSec.style.cssText;
2135
+ nextSec.style.minHeight = `${pageH}px`;
2136
+ nextSec.style.boxSizing = "border-box";
2137
+ nextSec.style.backgroundColor = "#ffffff";
2138
+ nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
2139
+ nextSec.style.borderRadius = "4px";
2140
+ nextSec.style.marginBottom = "24px";
2141
+ if (headerEl) {
2142
+ nextSec.appendChild(headerEl.cloneNode(true));
2143
+ }
2144
+ const nextArticle = document.createElement("article");
2145
+ if (contentContainer.tagName.toLowerCase() === "article") {
2146
+ nextArticle.style.cssText = contentContainer.style.cssText;
2130
2147
  }
2148
+ nextSec.appendChild(nextArticle);
2149
+ if (footerEl) {
2150
+ nextSec.appendChild(footerEl.cloneNode(true));
2151
+ }
2152
+ parent.appendChild(nextSec);
2153
+ newSections.push(nextSec);
2154
+ curContent = nextArticle;
2155
+ curH = 0;
2131
2156
  }
2132
- sections = newSections;
2133
2157
  }
2158
+ sections = newSections;
2134
2159
  }
2135
2160
  }
2136
2161
  const pageElements = sections.length > 0 ? sections : cards;
@@ -2169,6 +2194,7 @@ var DocxPlugin = class {
2169
2194
  if (indicator) {
2170
2195
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
2171
2196
  }
2197
+ ctx.container.scrollTop = 0;
2172
2198
  ctx.emit("page-change", { page: currentPage, total: totalPages });
2173
2199
  };
2174
2200
  if (totalPages > 1) {
@@ -3101,17 +3127,39 @@ var CodePlugin = class {
3101
3127
  let rawPages = [];
3102
3128
  if (isTxt) {
3103
3129
  const explicitPages = fullText.split(/(?:\f|\x0C)/);
3130
+ const charsPerLine = 85;
3131
+ const maxVisualLines = 45;
3132
+ const charsPerPage = charsPerLine * maxVisualLines;
3104
3133
  for (const ep of explicitPages) {
3105
3134
  const lines = ep.split(/\r?\n/);
3106
3135
  let currentChunk = [];
3136
+ let currentLines = 0;
3107
3137
  for (let i = 0; i < lines.length; i++) {
3108
- currentChunk.push(lines[i]);
3109
- if (currentChunk.length >= 46) {
3138
+ const line = lines[i];
3139
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
3140
+ if (currentLines + vLines > maxVisualLines && currentChunk.length > 0) {
3110
3141
  rawPages.push(currentChunk.join("\n"));
3111
3142
  currentChunk = [];
3143
+ currentLines = 0;
3144
+ }
3145
+ if (vLines > maxVisualLines) {
3146
+ let remaining = line;
3147
+ while (remaining.length > charsPerPage) {
3148
+ let splitIdx = remaining.lastIndexOf(" ", charsPerPage);
3149
+ if (splitIdx < charsPerPage * 0.75) splitIdx = charsPerPage;
3150
+ rawPages.push(remaining.slice(0, splitIdx));
3151
+ remaining = remaining.slice(splitIdx).trimStart();
3152
+ }
3153
+ if (remaining.length > 0) {
3154
+ currentChunk.push(remaining);
3155
+ currentLines = Math.ceil(remaining.length / charsPerLine);
3156
+ }
3157
+ } else {
3158
+ currentChunk.push(line);
3159
+ currentLines += vLines;
3112
3160
  }
3113
3161
  }
3114
- if (currentChunk.length > 0 || lines.length === 0) {
3162
+ if (currentChunk.length > 0) {
3115
3163
  rawPages.push(currentChunk.join("\n"));
3116
3164
  }
3117
3165
  }
@@ -3221,6 +3269,7 @@ var CodePlugin = class {
3221
3269
  if (indicator) {
3222
3270
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
3223
3271
  }
3272
+ container.scrollTop = 0;
3224
3273
  ctx.emit("page-change", { page: currentPage, total: totalPages });
3225
3274
  };
3226
3275
  if (totalPages > 1) {
@@ -4285,11 +4334,60 @@ var RtfPlugin = class {
4285
4334
  }
4286
4335
  const doc = new RTFJS__namespace.Document(ctx.buffer, {});
4287
4336
  const htmlElements = await doc.render();
4288
- pageElements = htmlElements;
4289
- for (let i = 0; i < htmlElements.length; i++) {
4290
- const el = htmlElements[i];
4291
- el.style.display = i === 0 ? "block" : "none";
4292
- wrapper.appendChild(el);
4337
+ if (htmlElements.length === 1) {
4338
+ const singleEl = htmlElements[0];
4339
+ wrapper.appendChild(singleEl);
4340
+ const children = Array.from(singleEl.children);
4341
+ const secH = singleEl.offsetHeight || singleEl.scrollHeight;
4342
+ if (secH > 1300 && children.length > 1) {
4343
+ const childHeights = children.map((c) => {
4344
+ const rectH = c.getBoundingClientRect().height;
4345
+ const offH = c.offsetHeight;
4346
+ const textLen = c.textContent?.trim().length || 0;
4347
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
4348
+ return Math.max(rectH, offH, estH);
4349
+ });
4350
+ wrapper.innerHTML = "";
4351
+ const createRtfCard = () => {
4352
+ const card = document.createElement("div");
4353
+ card.className = "fp-rtf-page-card";
4354
+ card.style.backgroundColor = "#ffffff";
4355
+ card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
4356
+ card.style.borderRadius = "4px";
4357
+ card.style.padding = "72px 56px";
4358
+ card.style.width = "816px";
4359
+ card.style.minHeight = "1056px";
4360
+ card.style.boxSizing = "border-box";
4361
+ card.style.marginBottom = "24px";
4362
+ return card;
4363
+ };
4364
+ let curCard = createRtfCard();
4365
+ wrapper.appendChild(curCard);
4366
+ pageElements = [curCard];
4367
+ let curH = 0;
4368
+ const maxH = 920;
4369
+ for (let i = 0; i < children.length; i++) {
4370
+ const child = children[i];
4371
+ const chH = childHeights[i];
4372
+ curCard.appendChild(child);
4373
+ curH += chH;
4374
+ if (curH >= maxH && i < children.length - 1) {
4375
+ curCard = createRtfCard();
4376
+ wrapper.appendChild(curCard);
4377
+ pageElements.push(curCard);
4378
+ curH = 0;
4379
+ }
4380
+ }
4381
+ } else {
4382
+ pageElements = [singleEl];
4383
+ }
4384
+ } else {
4385
+ pageElements = htmlElements;
4386
+ for (let i = 0; i < htmlElements.length; i++) {
4387
+ const el = htmlElements[i];
4388
+ el.style.display = i === 0 ? "block" : "none";
4389
+ wrapper.appendChild(el);
4390
+ }
4293
4391
  }
4294
4392
  } catch (err) {
4295
4393
  console.warn("[RtfPlugin] RTF render error, fallback text:", err);
@@ -4355,6 +4453,7 @@ var RtfPlugin = class {
4355
4453
  if (indicator) {
4356
4454
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4357
4455
  }
4456
+ ctx.container.scrollTop = 0;
4358
4457
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4359
4458
  };
4360
4459
  if (totalPages > 1) {
@@ -4826,12 +4925,9 @@ var OpenDocumentPlugin = class {
4826
4925
  page.style.backgroundColor = "#ffffff";
4827
4926
  page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
4828
4927
  page.style.borderRadius = "4px";
4829
- page.style.boxSizing = "border-box";
4830
4928
  page.style.display = idx === 0 ? "block" : "none";
4831
- page.style.position = "absolute";
4832
- page.style.top = "0";
4833
- page.style.left = "50%";
4834
- page.style.transform = "translateX(-50%)";
4929
+ page.style.margin = "0 auto 24px";
4930
+ page.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
4835
4931
  elements.forEach((el) => page.appendChild(el));
4836
4932
  wrapper.appendChild(page);
4837
4933
  slides.push(page);
@@ -4869,6 +4965,7 @@ var OpenDocumentPlugin = class {
4869
4965
  if (indicator) {
4870
4966
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4871
4967
  }
4968
+ container.scrollTop = 0;
4872
4969
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4873
4970
  };
4874
4971
  return {
@@ -5361,6 +5458,7 @@ var DocPlugin = class {
5361
5458
  if (indicator) {
5362
5459
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
5363
5460
  }
5461
+ container.scrollTop = 0;
5364
5462
  ctx.emit("page-change", { page: currentPage, total: totalPages });
5365
5463
  };
5366
5464
  if (totalPages > 1) {
@@ -5538,45 +5636,50 @@ var DocPlugin = class {
5538
5636
  }
5539
5637
  splitIntoPages(text) {
5540
5638
  if (!text) return [""];
5541
- 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);
5542
- if (explicitParts.length === 0) explicitParts.push(text);
5543
- const maxLinesPerPage = 48;
5639
+ const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ");
5640
+ const explicitParts = normalized.split(/[\x0C\f]|\n\s*[-=_]{3,}\s*(?:PAGE|Page|page break)[\s\d\w-]*[-=_]{3,}\s*\n/i).map((p) => p.trim()).filter((p) => p.length > 0);
5641
+ if (explicitParts.length === 0) explicitParts.push(normalized);
5642
+ const maxLinesPerPage = 32;
5643
+ const charsPerLine = 80;
5544
5644
  const finalPages = [];
5545
5645
  for (const part of explicitParts) {
5546
- const lines = part.split(/\r?\n/);
5646
+ const lines = part.split("\n");
5547
5647
  let currentLines = [];
5548
5648
  let count = 0;
5549
5649
  for (const line of lines) {
5550
- currentLines.push(line);
5551
- count++;
5552
- if (count >= maxLinesPerPage) {
5650
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
5651
+ if (count + vLines > maxLinesPerPage && currentLines.length > 0) {
5553
5652
  finalPages.push(currentLines.join("\n"));
5554
5653
  currentLines = [];
5555
5654
  count = 0;
5556
5655
  }
5656
+ currentLines.push(line);
5657
+ count += vLines;
5557
5658
  }
5558
5659
  if (currentLines.length > 0) {
5559
5660
  finalPages.push(currentLines.join("\n"));
5560
5661
  }
5561
5662
  }
5562
- return finalPages.length > 0 ? finalPages : [text];
5663
+ return finalPages.length > 0 ? finalPages : [normalized];
5563
5664
  }
5564
5665
  /**
5565
5666
  * Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
5566
5667
  */
5567
5668
  formatDocToHtml(text, filename) {
5568
- const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
5669
+ const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ").split("\n");
5569
5670
  let html = "";
5570
5671
  let inList = false;
5571
5672
  let tableLines = [];
5572
5673
  const flushTable = () => {
5573
5674
  if (tableLines.length > 0) {
5574
- html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
5575
- for (const tLine of tableLines) {
5576
- html += "<tr>";
5577
- const cols = tLine.split(" ");
5675
+ html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 13px; font-family: Calibri, sans-serif;">';
5676
+ for (let rIdx = 0; rIdx < tableLines.length; rIdx++) {
5677
+ const tLine = tableLines[rIdx];
5678
+ const isHeader = rIdx === 0;
5679
+ html += `<tr style="${isHeader ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
5680
+ const cols = tLine.split(" ").filter((c) => c.trim().length > 0);
5578
5681
  for (const col of cols) {
5579
- html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
5682
+ html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
5580
5683
  }
5581
5684
  html += "</tr>";
5582
5685
  }
@@ -5589,27 +5692,18 @@ var DocPlugin = class {
5589
5692
  let line = lines[i];
5590
5693
  let tabCount = (line.match(/\t/g) || []).length;
5591
5694
  if (tabCount > 0) {
5592
- let consecutiveTableLines = 1;
5593
- let j = i + 1;
5594
- while (j < lines.length) {
5595
- const nextTabCount = (lines[j].match(/\t/g) || []).length;
5596
- if (nextTabCount === tabCount) {
5597
- consecutiveTableLines++;
5598
- j++;
5599
- } else {
5600
- break;
5601
- }
5695
+ let j = i;
5696
+ while (j < lines.length && (lines[j].match(/\t/g) || []).length > 0) {
5697
+ j++;
5602
5698
  }
5603
- if (consecutiveTableLines >= 3) {
5604
- if (inList) {
5605
- html += "</ul>";
5606
- inList = false;
5607
- }
5608
- tableLines = lines.slice(i, j);
5609
- flushTable();
5610
- i = j;
5611
- continue;
5699
+ if (inList) {
5700
+ html += "</ul>";
5701
+ inList = false;
5612
5702
  }
5703
+ tableLines = lines.slice(i, j);
5704
+ flushTable();
5705
+ i = j;
5706
+ continue;
5613
5707
  }
5614
5708
  line = line.trim();
5615
5709
  if (!line) {