@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/index.cjs CHANGED
@@ -1589,6 +1589,7 @@ var PdfPlugin = class {
1589
1589
  getPageCount: () => totalPages,
1590
1590
  getCurrentPage: () => currentPage,
1591
1591
  goToPage: (page) => {
1592
+ container.scrollTop = 0;
1592
1593
  renderPage(page);
1593
1594
  },
1594
1595
  download: () => {
@@ -2093,7 +2094,14 @@ var DocxPlugin = class {
2093
2094
  ignoreFonts: true,
2094
2095
  // Avoid crashes on embedded obfuscated fonts
2095
2096
  breakPages: true,
2096
- experimental: true
2097
+ experimental: true,
2098
+ ignoreLastRenderedPageBreak: false,
2099
+ // Honor Word's exact page breaks!
2100
+ renderHeaders: true,
2101
+ renderFooters: true,
2102
+ renderFootnotes: true,
2103
+ renderEndnotes: true,
2104
+ useBase64URL: true
2097
2105
  });
2098
2106
  if (!ctx.container.contains(wrapper)) {
2099
2107
  ctx.container.appendChild(wrapper);
@@ -2114,11 +2122,14 @@ var DocxPlugin = class {
2114
2122
  renderedSuccessfully = true;
2115
2123
  } catch (fallbackErr) {
2116
2124
  console.error("[DocxPlugin] Native fallback failed:", fallbackErr);
2125
+ const isCorrupt = fallbackErr?.message?.includes("invalid zip") || fallbackErr?.message?.includes("corrupted");
2117
2126
  wrapper.innerHTML = `
2118
- <div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
2119
- <div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
2120
- <h3 style="margin: 0 0 8px; color: #1e293b;">${ctx.metadata.name || "Word Document"}</h3>
2121
- <p style="color: #64748b; margin: 0;">Could not parse document content</p>
2127
+ <div style="text-align:center; padding: 48px 32px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06); max-width: 600px; margin: 40px auto;">
2128
+ <div style="font-size:48px; margin-bottom: 16px;">${isCorrupt ? "\u26A0\uFE0F" : "\u{1F4C4}"}</div>
2129
+ <h3 style="margin: 0 0 8px; color: #1e293b; font-size: 18px;">${ctx.metadata.name || "Word Document"}</h3>
2130
+ <p style="color: #64748b; margin: 0 0 16px; font-size: 14px; line-height: 1.5;">
2131
+ ${isCorrupt ? "This document appears to be corrupted or contains invalid archive data and cannot be opened (matches Microsoft Word on Windows)." : "Could not render document content. The file structure may be damaged."}
2132
+ </p>
2122
2133
  </div>
2123
2134
  `;
2124
2135
  if (!ctx.container.contains(wrapper)) {
@@ -2130,47 +2141,61 @@ var DocxPlugin = class {
2130
2141
  const cards = Array.from(wrapper.querySelectorAll(".fp-docx-page-card"));
2131
2142
  if (sections.length === 1 && cards.length === 0) {
2132
2143
  const singleSec = sections[0];
2133
- const pageH = 1056;
2144
+ const contentContainer = singleSec.querySelector("article") || singleSec;
2145
+ const children = Array.from(contentContainer.children);
2146
+ const pageH = singleSec.offsetHeight > 1300 ? 1122 : Math.max(1056, singleSec.offsetHeight);
2134
2147
  const secH = singleSec.offsetHeight || singleSec.scrollHeight;
2135
- if (secH > pageH * 1.25) {
2136
- const children = Array.from(singleSec.children);
2137
- if (children.length > 1) {
2138
- const parent = singleSec.parentElement || wrapper;
2139
- const newSections = [singleSec];
2140
- singleSec.innerHTML = "";
2141
- singleSec.style.minHeight = `${pageH}px`;
2142
- singleSec.style.maxHeight = `${pageH}px`;
2143
- singleSec.style.overflow = "hidden";
2144
- singleSec.style.boxSizing = "border-box";
2145
- let curSec = singleSec;
2146
- let curH = 0;
2147
- const maxH = pageH - 96;
2148
- for (let i = 0; i < children.length; i++) {
2149
- const child = children[i];
2150
- curSec.appendChild(child);
2151
- const chH = child.offsetHeight || 28;
2152
- curH += chH;
2153
- if (curH >= maxH && i < children.length - 1) {
2154
- const nextSec = document.createElement("section");
2155
- nextSec.className = singleSec.className;
2156
- nextSec.style.cssText = singleSec.style.cssText;
2157
- nextSec.style.width = singleSec.style.width || "816px";
2158
- nextSec.style.minHeight = `${pageH}px`;
2159
- nextSec.style.maxHeight = `${pageH}px`;
2160
- nextSec.style.overflow = "hidden";
2161
- nextSec.style.boxSizing = "border-box";
2162
- nextSec.style.backgroundColor = "#ffffff";
2163
- nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
2164
- nextSec.style.borderRadius = "4px";
2165
- nextSec.style.marginBottom = "24px";
2166
- parent.appendChild(nextSec);
2167
- newSections.push(nextSec);
2168
- curSec = nextSec;
2169
- curH = 0;
2148
+ if (secH > pageH * 1.25 && children.length > 1) {
2149
+ const childHeights = children.map((c) => {
2150
+ const rectH = c.getBoundingClientRect().height;
2151
+ const offH = c.offsetHeight;
2152
+ const textLen = c.textContent?.trim().length || 0;
2153
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
2154
+ return Math.max(rectH, offH, estH);
2155
+ });
2156
+ const parent = singleSec.parentElement || wrapper;
2157
+ const newSections = [singleSec];
2158
+ const headerEl = singleSec.querySelector("header");
2159
+ const footerEl = singleSec.querySelector("footer");
2160
+ contentContainer.innerHTML = "";
2161
+ singleSec.style.minHeight = `${pageH}px`;
2162
+ singleSec.style.boxSizing = "border-box";
2163
+ let curContent = contentContainer;
2164
+ let curH = 0;
2165
+ const maxH = pageH - 140;
2166
+ for (let i = 0; i < children.length; i++) {
2167
+ const child = children[i];
2168
+ const chH = childHeights[i];
2169
+ curContent.appendChild(child);
2170
+ curH += chH;
2171
+ if (curH >= maxH && i < children.length - 1) {
2172
+ const nextSec = document.createElement("section");
2173
+ nextSec.className = singleSec.className;
2174
+ nextSec.style.cssText = singleSec.style.cssText;
2175
+ nextSec.style.minHeight = `${pageH}px`;
2176
+ nextSec.style.boxSizing = "border-box";
2177
+ nextSec.style.backgroundColor = "#ffffff";
2178
+ nextSec.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
2179
+ nextSec.style.borderRadius = "4px";
2180
+ nextSec.style.marginBottom = "24px";
2181
+ if (headerEl) {
2182
+ nextSec.appendChild(headerEl.cloneNode(true));
2183
+ }
2184
+ const nextArticle = document.createElement("article");
2185
+ if (contentContainer.tagName.toLowerCase() === "article") {
2186
+ nextArticle.style.cssText = contentContainer.style.cssText;
2170
2187
  }
2188
+ nextSec.appendChild(nextArticle);
2189
+ if (footerEl) {
2190
+ nextSec.appendChild(footerEl.cloneNode(true));
2191
+ }
2192
+ parent.appendChild(nextSec);
2193
+ newSections.push(nextSec);
2194
+ curContent = nextArticle;
2195
+ curH = 0;
2171
2196
  }
2172
- sections = newSections;
2173
2197
  }
2198
+ sections = newSections;
2174
2199
  }
2175
2200
  }
2176
2201
  const pageElements = sections.length > 0 ? sections : cards;
@@ -2209,6 +2234,7 @@ var DocxPlugin = class {
2209
2234
  if (indicator) {
2210
2235
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
2211
2236
  }
2237
+ ctx.container.scrollTop = 0;
2212
2238
  ctx.emit("page-change", { page: currentPage, total: totalPages });
2213
2239
  };
2214
2240
  if (totalPages > 1) {
@@ -3141,17 +3167,39 @@ var CodePlugin = class {
3141
3167
  let rawPages = [];
3142
3168
  if (isTxt) {
3143
3169
  const explicitPages = fullText.split(/(?:\f|\x0C)/);
3170
+ const charsPerLine = 85;
3171
+ const maxVisualLines = 45;
3172
+ const charsPerPage = charsPerLine * maxVisualLines;
3144
3173
  for (const ep of explicitPages) {
3145
3174
  const lines = ep.split(/\r?\n/);
3146
3175
  let currentChunk = [];
3176
+ let currentLines = 0;
3147
3177
  for (let i = 0; i < lines.length; i++) {
3148
- currentChunk.push(lines[i]);
3149
- if (currentChunk.length >= 46) {
3178
+ const line = lines[i];
3179
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
3180
+ if (currentLines + vLines > maxVisualLines && currentChunk.length > 0) {
3150
3181
  rawPages.push(currentChunk.join("\n"));
3151
3182
  currentChunk = [];
3183
+ currentLines = 0;
3184
+ }
3185
+ if (vLines > maxVisualLines) {
3186
+ let remaining = line;
3187
+ while (remaining.length > charsPerPage) {
3188
+ let splitIdx = remaining.lastIndexOf(" ", charsPerPage);
3189
+ if (splitIdx < charsPerPage * 0.75) splitIdx = charsPerPage;
3190
+ rawPages.push(remaining.slice(0, splitIdx));
3191
+ remaining = remaining.slice(splitIdx).trimStart();
3192
+ }
3193
+ if (remaining.length > 0) {
3194
+ currentChunk.push(remaining);
3195
+ currentLines = Math.ceil(remaining.length / charsPerLine);
3196
+ }
3197
+ } else {
3198
+ currentChunk.push(line);
3199
+ currentLines += vLines;
3152
3200
  }
3153
3201
  }
3154
- if (currentChunk.length > 0 || lines.length === 0) {
3202
+ if (currentChunk.length > 0) {
3155
3203
  rawPages.push(currentChunk.join("\n"));
3156
3204
  }
3157
3205
  }
@@ -3261,6 +3309,7 @@ var CodePlugin = class {
3261
3309
  if (indicator) {
3262
3310
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
3263
3311
  }
3312
+ container.scrollTop = 0;
3264
3313
  ctx.emit("page-change", { page: currentPage, total: totalPages });
3265
3314
  };
3266
3315
  if (totalPages > 1) {
@@ -4325,11 +4374,60 @@ var RtfPlugin = class {
4325
4374
  }
4326
4375
  const doc = new RTFJS__namespace.Document(ctx.buffer, {});
4327
4376
  const htmlElements = await doc.render();
4328
- pageElements = htmlElements;
4329
- for (let i = 0; i < htmlElements.length; i++) {
4330
- const el = htmlElements[i];
4331
- el.style.display = i === 0 ? "block" : "none";
4332
- wrapper.appendChild(el);
4377
+ if (htmlElements.length === 1) {
4378
+ const singleEl = htmlElements[0];
4379
+ wrapper.appendChild(singleEl);
4380
+ const children = Array.from(singleEl.children);
4381
+ const secH = singleEl.offsetHeight || singleEl.scrollHeight;
4382
+ if (secH > 1300 && children.length > 1) {
4383
+ const childHeights = children.map((c) => {
4384
+ const rectH = c.getBoundingClientRect().height;
4385
+ const offH = c.offsetHeight;
4386
+ const textLen = c.textContent?.trim().length || 0;
4387
+ const estH = Math.max(24, Math.ceil(textLen / 80) * 22 + 16);
4388
+ return Math.max(rectH, offH, estH);
4389
+ });
4390
+ wrapper.innerHTML = "";
4391
+ const createRtfCard = () => {
4392
+ const card = document.createElement("div");
4393
+ card.className = "fp-rtf-page-card";
4394
+ card.style.backgroundColor = "#ffffff";
4395
+ card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
4396
+ card.style.borderRadius = "4px";
4397
+ card.style.padding = "72px 56px";
4398
+ card.style.width = "816px";
4399
+ card.style.minHeight = "1056px";
4400
+ card.style.boxSizing = "border-box";
4401
+ card.style.marginBottom = "24px";
4402
+ return card;
4403
+ };
4404
+ let curCard = createRtfCard();
4405
+ wrapper.appendChild(curCard);
4406
+ pageElements = [curCard];
4407
+ let curH = 0;
4408
+ const maxH = 920;
4409
+ for (let i = 0; i < children.length; i++) {
4410
+ const child = children[i];
4411
+ const chH = childHeights[i];
4412
+ curCard.appendChild(child);
4413
+ curH += chH;
4414
+ if (curH >= maxH && i < children.length - 1) {
4415
+ curCard = createRtfCard();
4416
+ wrapper.appendChild(curCard);
4417
+ pageElements.push(curCard);
4418
+ curH = 0;
4419
+ }
4420
+ }
4421
+ } else {
4422
+ pageElements = [singleEl];
4423
+ }
4424
+ } else {
4425
+ pageElements = htmlElements;
4426
+ for (let i = 0; i < htmlElements.length; i++) {
4427
+ const el = htmlElements[i];
4428
+ el.style.display = i === 0 ? "block" : "none";
4429
+ wrapper.appendChild(el);
4430
+ }
4333
4431
  }
4334
4432
  } catch (err) {
4335
4433
  console.warn("[RtfPlugin] RTF render error, fallback text:", err);
@@ -4395,6 +4493,7 @@ var RtfPlugin = class {
4395
4493
  if (indicator) {
4396
4494
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4397
4495
  }
4496
+ ctx.container.scrollTop = 0;
4398
4497
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4399
4498
  };
4400
4499
  if (totalPages > 1) {
@@ -4866,12 +4965,9 @@ var OpenDocumentPlugin = class {
4866
4965
  page.style.backgroundColor = "#ffffff";
4867
4966
  page.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
4868
4967
  page.style.borderRadius = "4px";
4869
- page.style.boxSizing = "border-box";
4870
4968
  page.style.display = idx === 0 ? "block" : "none";
4871
- page.style.position = "absolute";
4872
- page.style.top = "0";
4873
- page.style.left = "50%";
4874
- page.style.transform = "translateX(-50%)";
4969
+ page.style.margin = "0 auto 24px";
4970
+ page.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
4875
4971
  elements.forEach((el) => page.appendChild(el));
4876
4972
  wrapper.appendChild(page);
4877
4973
  slides.push(page);
@@ -4909,6 +5005,7 @@ var OpenDocumentPlugin = class {
4909
5005
  if (indicator) {
4910
5006
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
4911
5007
  }
5008
+ container.scrollTop = 0;
4912
5009
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4913
5010
  };
4914
5011
  return {
@@ -5401,6 +5498,7 @@ var DocPlugin = class {
5401
5498
  if (indicator) {
5402
5499
  indicator.textContent = `Page ${currentPage} of ${totalPages}`;
5403
5500
  }
5501
+ container.scrollTop = 0;
5404
5502
  ctx.emit("page-change", { page: currentPage, total: totalPages });
5405
5503
  };
5406
5504
  if (totalPages > 1) {
@@ -5578,45 +5676,50 @@ var DocPlugin = class {
5578
5676
  }
5579
5677
  splitIntoPages(text) {
5580
5678
  if (!text) return [""];
5581
- 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);
5582
- if (explicitParts.length === 0) explicitParts.push(text);
5583
- const maxLinesPerPage = 48;
5679
+ const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ");
5680
+ const explicitParts = normalized.split(/[\x0C\f]|\n\s*[-=_]{3,}\s*(?:PAGE|Page|page break)[\s\d\w-]*[-=_]{3,}\s*\n/i).map((p) => p.trim()).filter((p) => p.length > 0);
5681
+ if (explicitParts.length === 0) explicitParts.push(normalized);
5682
+ const maxLinesPerPage = 32;
5683
+ const charsPerLine = 80;
5584
5684
  const finalPages = [];
5585
5685
  for (const part of explicitParts) {
5586
- const lines = part.split(/\r?\n/);
5686
+ const lines = part.split("\n");
5587
5687
  let currentLines = [];
5588
5688
  let count = 0;
5589
5689
  for (const line of lines) {
5590
- currentLines.push(line);
5591
- count++;
5592
- if (count >= maxLinesPerPage) {
5690
+ const vLines = Math.max(1, Math.ceil((line.length || 1) / charsPerLine));
5691
+ if (count + vLines > maxLinesPerPage && currentLines.length > 0) {
5593
5692
  finalPages.push(currentLines.join("\n"));
5594
5693
  currentLines = [];
5595
5694
  count = 0;
5596
5695
  }
5696
+ currentLines.push(line);
5697
+ count += vLines;
5597
5698
  }
5598
5699
  if (currentLines.length > 0) {
5599
5700
  finalPages.push(currentLines.join("\n"));
5600
5701
  }
5601
5702
  }
5602
- return finalPages.length > 0 ? finalPages : [text];
5703
+ return finalPages.length > 0 ? finalPages : [normalized];
5603
5704
  }
5604
5705
  /**
5605
5706
  * Format cleaned extracted text into attractive HTML paragraphs, headings, and lists
5606
5707
  */
5607
5708
  formatDocToHtml(text, filename) {
5608
- const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").split("\n");
5709
+ const lines = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\x0B/g, "\n").replace(/\x07\n/g, "\n").replace(/\x07/g, " ").split("\n");
5609
5710
  let html = "";
5610
5711
  let inList = false;
5611
5712
  let tableLines = [];
5612
5713
  const flushTable = () => {
5613
5714
  if (tableLines.length > 0) {
5614
- html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12px;">';
5615
- for (const tLine of tableLines) {
5616
- html += "<tr>";
5617
- const cols = tLine.split(" ");
5715
+ html += '<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 13px; font-family: Calibri, sans-serif;">';
5716
+ for (let rIdx = 0; rIdx < tableLines.length; rIdx++) {
5717
+ const tLine = tableLines[rIdx];
5718
+ const isHeader = rIdx === 0;
5719
+ html += `<tr style="${isHeader ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
5720
+ const cols = tLine.split(" ").filter((c) => c.trim().length > 0);
5618
5721
  for (const col of cols) {
5619
- html += `<td style="border: 1px solid #cbd5e1; padding: 6px 8px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
5722
+ html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px;">${DOMPurify6__default.default.sanitize(col.trim())}</td>`;
5620
5723
  }
5621
5724
  html += "</tr>";
5622
5725
  }
@@ -5629,27 +5732,18 @@ var DocPlugin = class {
5629
5732
  let line = lines[i];
5630
5733
  let tabCount = (line.match(/\t/g) || []).length;
5631
5734
  if (tabCount > 0) {
5632
- let consecutiveTableLines = 1;
5633
- let j = i + 1;
5634
- while (j < lines.length) {
5635
- const nextTabCount = (lines[j].match(/\t/g) || []).length;
5636
- if (nextTabCount === tabCount) {
5637
- consecutiveTableLines++;
5638
- j++;
5639
- } else {
5640
- break;
5641
- }
5735
+ let j = i;
5736
+ while (j < lines.length && (lines[j].match(/\t/g) || []).length > 0) {
5737
+ j++;
5642
5738
  }
5643
- if (consecutiveTableLines >= 3) {
5644
- if (inList) {
5645
- html += "</ul>";
5646
- inList = false;
5647
- }
5648
- tableLines = lines.slice(i, j);
5649
- flushTable();
5650
- i = j;
5651
- continue;
5739
+ if (inList) {
5740
+ html += "</ul>";
5741
+ inList = false;
5652
5742
  }
5743
+ tableLines = lines.slice(i, j);
5744
+ flushTable();
5745
+ i = j;
5746
+ continue;
5653
5747
  }
5654
5748
  line = line.trim();
5655
5749
  if (!line) {