@files-preview-app/preview-file 1.3.3 → 1.3.5

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.js CHANGED
@@ -5247,7 +5247,7 @@ function cleanRtfText(raw) {
5247
5247
  return String.fromCharCode(num);
5248
5248
  }).replace(/\\'([0-9a-fA-F]{2})/g, (_, hex) => {
5249
5249
  return String.fromCharCode(parseInt(hex, 16));
5250
- }).replace(/\\tab\b/g, " ").replace(/\\emdash\b/g, "\u2014").replace(/\\endash\b/g, "\u2013").replace(/\\bullet\b/g, "\u2022").replace(/\\lquote\b/g, "\u2018").replace(/\\rquote\b/g, "\u2019").replace(/\\ldblquote\b/g, "\u201C").replace(/\\rdblquote\b/g, "\u201D").replace(/\\\w+(?:-?\d+)?\s?/g, " ").replace(/[{}\r\n]/g, " ").replace(/\s+/g, " ").trim();
5250
+ }).replace(/\\tab\b/g, " ").replace(/\\emdash\b/g, "\u2014").replace(/\\endash\b/g, "\u2013").replace(/\\bullet\b/g, "\u2022").replace(/\\lquote\b/g, "\u2018").replace(/\\rquote\b/g, "\u2019").replace(/\\ldblquote\b/g, "\u201C").replace(/\\rdblquote\b/g, "\u201D").replace(/\\[a-zA-Z]+-?\d*\s?/g, " ").replace(/[{}\r\n]/g, " ").replace(/\s+/g, " ").trim();
5251
5251
  }
5252
5252
  function parseRtfTables(rtfText) {
5253
5253
  const rowSegments = rtfText.split(/\\row\b/);
@@ -5287,17 +5287,12 @@ function parseRtfTables(rtfText) {
5287
5287
  }
5288
5288
  const isNewTable = !currentTable || segmentStart - currentTable.lastEnd > 2500;
5289
5289
  if (isNewTable) {
5290
- const prevTextSlice = rtfText.slice(Math.max(0, segmentStart - 4e3), segmentStart);
5291
- const cleanPrev = cleanRtfText(prevTextSlice);
5292
- const anchorBefore = cleanPrev.slice(-80).trim();
5293
5290
  currentTable = {
5294
5291
  id: `RTF_TABLE_${rawTables.length}`,
5295
5292
  startPos: segmentStart,
5296
5293
  lastEnd: segmentEnd,
5297
5294
  rows: [],
5298
- columnWidths: cellWidths,
5299
- anchorBefore,
5300
- anchorAfter: ""
5295
+ columnWidths: cellWidths
5301
5296
  };
5302
5297
  rawTables.push(currentTable);
5303
5298
  }
@@ -5311,20 +5306,13 @@ function parseRtfTables(rtfText) {
5311
5306
  }
5312
5307
  charOffset += segment.length + 4;
5313
5308
  }
5314
- rawTables.forEach((tbl) => {
5315
- const afterSlice = rtfText.slice(tbl.lastEnd, Math.min(rtfText.length, tbl.lastEnd + 2e3));
5316
- const cleanAfter = cleanRtfText(afterSlice);
5317
- tbl.anchorAfter = cleanAfter.slice(0, 80).trim();
5318
- });
5319
5309
  return rawTables.map((tbl) => {
5320
5310
  const totalW = (tbl.columnWidths || []).reduce((a, b) => a + b, 0);
5321
5311
  const colPercents = totalW > 0 ? tbl.columnWidths.map((w) => Math.round(w / totalW * 100)) : [];
5322
5312
  return {
5323
5313
  id: tbl.id,
5324
5314
  rows: tbl.rows.map((r) => r.cells),
5325
- colPercents,
5326
- anchorBefore: tbl.anchorBefore,
5327
- anchorAfter: tbl.anchorAfter
5315
+ colPercents
5328
5316
  };
5329
5317
  });
5330
5318
  }
@@ -5337,8 +5325,6 @@ function renderRtfTableElement(table) {
5337
5325
  tableEl.style.fontSize = "10pt";
5338
5326
  tableEl.style.lineHeight = "1.5";
5339
5327
  tableEl.style.border = "1px solid #cbd5e1";
5340
- tableEl.style.borderRadius = "4px";
5341
- tableEl.style.boxSizing = "border-box";
5342
5328
  tableEl.style.backgroundColor = "#ffffff";
5343
5329
  const thead = document.createElement("thead");
5344
5330
  const tbody = document.createElement("tbody");
@@ -5347,27 +5333,17 @@ function renderRtfTableElement(table) {
5347
5333
  const isHeader = rIdx === 0;
5348
5334
  if (isHeader) {
5349
5335
  tr.style.backgroundColor = "#f8fafc";
5350
- tr.style.borderBottom = "2px solid #cbd5e1";
5351
- } else {
5352
- tr.style.borderBottom = "1px solid #e2e8f0";
5353
- if (rIdx % 2 === 0) {
5354
- tr.style.backgroundColor = "#fcfdfe";
5355
- }
5356
5336
  }
5357
5337
  rowCells.forEach((cellText, cIdx) => {
5358
5338
  const cellEl = document.createElement(isHeader ? "th" : "td");
5359
5339
  cellEl.style.padding = "8px 12px";
5360
5340
  cellEl.style.border = "1px solid #cbd5e1";
5361
5341
  cellEl.style.verticalAlign = "top";
5362
- cellEl.style.color = isHeader ? "#0f172a" : "#1e293b";
5363
- cellEl.style.fontWeight = isHeader ? "600" : "normal";
5364
5342
  if (table.colPercents && table.colPercents[cIdx]) {
5365
5343
  cellEl.style.width = `${table.colPercents[cIdx]}%`;
5366
5344
  }
5367
5345
  if (/^\d+$/.test(cellText.trim()) || cellText.trim() === "#") {
5368
5346
  cellEl.style.textAlign = "center";
5369
- } else {
5370
- cellEl.style.textAlign = "left";
5371
5347
  }
5372
5348
  cellEl.textContent = cellText;
5373
5349
  tr.appendChild(cellEl);
@@ -5382,6 +5358,20 @@ function renderRtfTableElement(table) {
5382
5358
  tableEl.appendChild(tbody);
5383
5359
  return tableEl;
5384
5360
  }
5361
+ function isHeadingElement(el) {
5362
+ if (["H1", "H2", "H3", "H4"].includes(el.tagName)) return true;
5363
+ const spans = el.querySelectorAll ? Array.from(el.querySelectorAll("span, b, strong, div")) : [];
5364
+ for (const s of spans) {
5365
+ const hEl = s;
5366
+ const fs = parseFloat(hEl.style.fontSize) || 0;
5367
+ const isBold = hEl.style.fontWeight === "bold" || parseInt(hEl.style.fontWeight, 10) >= 600 || ["B", "STRONG"].includes(hEl.tagName);
5368
+ if (isBold && fs >= 14) return true;
5369
+ }
5370
+ const elFs = parseFloat(el.style.fontSize) || 0;
5371
+ const elBold = el.style.fontWeight === "bold" || parseInt(el.style.fontWeight, 10) >= 600;
5372
+ if (elBold && elFs >= 14) return true;
5373
+ return false;
5374
+ }
5385
5375
  var RtfPlugin = class {
5386
5376
  id = "rtf";
5387
5377
  name = "Rich Text Format (RTF)";
@@ -5493,10 +5483,66 @@ var RtfPlugin = class {
5493
5483
  return actions;
5494
5484
  }
5495
5485
  async render(ctx) {
5486
+ const rawRtf = new TextDecoder("latin1").decode(ctx.buffer);
5487
+ const paperwMatch = rawRtf.match(/\\paperw(\d+)/);
5488
+ const paperhMatch = rawRtf.match(/\\paperh(\d+)/);
5489
+ const marglMatch = rawRtf.match(/\\margl(\d+)/);
5490
+ const margrMatch = rawRtf.match(/\\margr(\d+)/);
5491
+ const margtMatch = rawRtf.match(/\\margt(\d+)/);
5492
+ const margbMatch = rawRtf.match(/\\margb(\d+)/);
5493
+ const paperwTwips = paperwMatch ? parseInt(paperwMatch[1], 10) : 11906;
5494
+ const paperhTwips = paperhMatch ? parseInt(paperhMatch[1], 10) : 16838;
5495
+ const marglTwips = marglMatch ? parseInt(marglMatch[1], 10) : 1134;
5496
+ const margrTwips = margrMatch ? parseInt(margrMatch[1], 10) : 1134;
5497
+ const margtTwips = margtMatch ? parseInt(margtMatch[1], 10) : 1134;
5498
+ const margbTwips = margbMatch ? parseInt(margbMatch[1], 10) : 1134;
5499
+ const pageWidth = Math.round(paperwTwips / 15);
5500
+ const pageHeight = Math.round(paperhTwips / 15);
5501
+ const padLeft = Math.round(marglTwips / 15);
5502
+ const padRight = Math.round(margrTwips / 15);
5503
+ const padTop = Math.round(margtTwips / 15);
5504
+ const padBottom = Math.round(margbTwips / 15);
5505
+ const printableHeight = pageHeight - padTop - padBottom;
5506
+ const extractedImages = [];
5507
+ let p = 0;
5508
+ while ((p = rawRtf.indexOf("\\pict", p)) !== -1) {
5509
+ const startP = p;
5510
+ p += 5;
5511
+ const header = rawRtf.substring(startP, startP + 600);
5512
+ let mime = "";
5513
+ let magic = "";
5514
+ if (header.includes("\\pngblip")) {
5515
+ mime = "image/png";
5516
+ magic = "89504e47";
5517
+ } else if (header.includes("\\jpegblip")) {
5518
+ mime = "image/jpeg";
5519
+ magic = "ffd8ff";
5520
+ }
5521
+ if (!mime || !magic) continue;
5522
+ const magicPos = rawRtf.indexOf(magic, startP);
5523
+ if (magicPos === -1 || magicPos - startP > 3e3) continue;
5524
+ let endP = magicPos;
5525
+ while (endP < rawRtf.length && /[0-9a-fA-F\r\n\s]/.test(rawRtf[endP])) {
5526
+ endP++;
5527
+ }
5528
+ const cleanHex = rawRtf.substring(magicPos, endP).replace(/[\r\n\s]/g, "");
5529
+ if (cleanHex.length < 100) continue;
5530
+ const hexLen = cleanHex.length / 2;
5531
+ const u8 = new Uint8Array(hexLen);
5532
+ for (let k = 0; k < hexLen; k++) {
5533
+ u8[k] = parseInt(cleanHex.substr(k * 2, 2), 16);
5534
+ }
5535
+ let bStr = "";
5536
+ for (let k = 0; k < u8.length; k += 8192) {
5537
+ bStr += String.fromCharCode.apply(null, Array.from(u8.subarray(k, k + 8192)));
5538
+ }
5539
+ extractedImages.push({ mime, dataUrl: `data:${mime};base64,${btoa(bStr)}`, offset: startP });
5540
+ }
5541
+ const tables = parseRtfTables(rawRtf);
5496
5542
  const wrapper = document.createElement("div");
5497
5543
  wrapper.className = "fp-rtf-wrapper";
5498
5544
  wrapper.style.padding = "0";
5499
- wrapper.style.width = "816px";
5545
+ wrapper.style.width = `${pageWidth}px`;
5500
5546
  wrapper.style.margin = "0 auto";
5501
5547
  wrapper.style.boxSizing = "border-box";
5502
5548
  wrapper.style.display = "flex";
@@ -5516,9 +5562,8 @@ var RtfPlugin = class {
5516
5562
  let isUserZoomed = false;
5517
5563
  let fitMode = ctx?.options?.fitMode || "width";
5518
5564
  const calculateFitScale = (mode = fitMode) => {
5519
- const activeEl = pageElements[currentPage - 1] || wrapper;
5520
- const elW = 816;
5521
- const singlePageH = activeEl?.offsetHeight || 1056;
5565
+ const elW = pageWidth;
5566
+ const singlePageH = pageHeight;
5522
5567
  const availW = Math.max(280, ctx.container.clientWidth - 32);
5523
5568
  const availH = Math.max(280, ctx.container.clientHeight - 32);
5524
5569
  const sW = availW / elW;
@@ -5531,8 +5576,7 @@ var RtfPlugin = class {
5531
5576
  const applyTransform = () => {
5532
5577
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
5533
5578
  wrapper.style.transformOrigin = "top center";
5534
- const activeEl = pageElements[currentPage - 1];
5535
- const baseH = activeEl?.offsetHeight || 1056;
5579
+ const baseH = pageHeight;
5536
5580
  const scaledH = baseH * scale;
5537
5581
  const extraH = Math.max(0, scaledH - baseH);
5538
5582
  wrapper.style.marginBottom = `${extraH + 32}px`;
@@ -5552,140 +5596,220 @@ var RtfPlugin = class {
5552
5596
  if (typeof RTFJS.loggingEnabled === "function") {
5553
5597
  RTFJS.loggingEnabled(false);
5554
5598
  }
5555
- const rawText = new TextDecoder("latin1").decode(ctx.buffer);
5556
- const tables = parseRtfTables(rawText);
5557
- const doc = new RTFJS.Document(ctx.buffer, {});
5558
- const htmlElements = await doc.render();
5559
- const contentNodes = [];
5560
- const extractBlocks = (nodes) => {
5561
- for (const item of nodes) {
5562
- if (!item || !(item instanceof HTMLElement)) continue;
5563
- const tag = item.tagName.toLowerCase();
5564
- const hasChildBlocks = Array.from(item.children).some((c) => {
5565
- const ct = c.tagName.toLowerCase();
5566
- return ["p", "div", "table", "h1", "h2", "h3", "h4", "h5", "h6", "section", "article", "ul", "ol"].includes(ct);
5567
- });
5568
- if (hasChildBlocks && !["table", "tr", "td", "th", "ul", "ol", "li"].includes(tag)) {
5569
- extractBlocks(Array.from(item.children));
5570
- } else {
5571
- const svgs = item.querySelectorAll("svg, img");
5572
- svgs.forEach((s) => {
5573
- const el = s;
5574
- el.style.maxWidth = "100%";
5575
- el.style.maxHeight = "360px";
5576
- el.style.display = "block";
5577
- el.style.margin = "12px auto";
5578
- if (s.tagName.toLowerCase() === "svg") {
5579
- s.removeAttribute("width");
5580
- s.removeAttribute("height");
5581
- el.style.width = "100%";
5582
- el.style.maxHeight = "360px";
5583
- }
5584
- });
5585
- if (tag === "p" || tag === "div") {
5586
- item.style.display = "block";
5587
- item.style.marginBottom = "12px";
5588
- item.style.lineHeight = "1.6";
5589
- }
5590
- contentNodes.push(item);
5591
- }
5599
+ const doc = new RTFJS.Document(ctx.buffer, {
5600
+ onPicture: (isLegacy, createPic) => {
5601
+ if (isLegacy === true) return null;
5602
+ return createPic();
5592
5603
  }
5593
- };
5594
- extractBlocks(htmlElements);
5595
- tables.forEach((table) => {
5596
- const tableEl = renderRtfTableElement(table);
5597
- let inserted = false;
5598
- if (table.anchorBefore && table.anchorBefore.length > 10) {
5599
- const keyword = table.anchorBefore.slice(-35).trim();
5600
- for (let i = 0; i < contentNodes.length; i++) {
5601
- if (contentNodes[i].textContent?.includes(keyword)) {
5602
- contentNodes.splice(i + 1, 0, tableEl);
5603
- inserted = true;
5604
- break;
5605
- }
5604
+ });
5605
+ const elements = await doc.render();
5606
+ let unsupportedIndex = 1;
5607
+ const usedTables = /* @__PURE__ */ new Set();
5608
+ for (let i = 0; i < elements.length; i++) {
5609
+ const el = elements[i];
5610
+ const text = el.textContent || "";
5611
+ if (text.includes("[Unsupported image format]")) {
5612
+ if (extractedImages[unsupportedIndex]) {
5613
+ const img = document.createElement("img");
5614
+ img.src = extractedImages[unsupportedIndex].dataUrl;
5615
+ img.style.width = "100%";
5616
+ img.style.height = "auto";
5617
+ img.style.maxHeight = "430px";
5618
+ img.style.objectFit = "contain";
5619
+ img.style.display = "block";
5620
+ img.style.margin = "12px auto";
5621
+ el.innerHTML = "";
5622
+ el.appendChild(img);
5623
+ unsupportedIndex++;
5606
5624
  }
5607
5625
  }
5608
- if (!inserted && table.anchorAfter && table.anchorAfter.length > 10) {
5609
- const keyword = table.anchorAfter.slice(0, 35).trim();
5610
- for (let i = 0; i < contentNodes.length; i++) {
5611
- if (contentNodes[i].textContent?.includes(keyword)) {
5612
- contentNodes.splice(i, 0, tableEl);
5613
- inserted = true;
5614
- break;
5626
+ if (tables.length > 0) {
5627
+ for (let t = 0; t < tables.length; t++) {
5628
+ if (usedTables.has(t)) continue;
5629
+ const tbl = tables[t];
5630
+ if (tbl.rows.length >= 2) {
5631
+ const sampleCell1 = tbl.rows[1]?.[1] || tbl.rows[0]?.[1] || "";
5632
+ const sampleCell2 = tbl.rows[2]?.[1] || tbl.rows[1]?.[0] || "";
5633
+ const match1 = sampleCell1 && text.includes(sampleCell1.slice(0, 15).trim());
5634
+ const match2 = sampleCell2 && text.includes(sampleCell2.slice(0, 15).trim());
5635
+ if (match1 && match2) {
5636
+ el.innerHTML = "";
5637
+ el.appendChild(renderRtfTableElement(tbl));
5638
+ usedTables.add(t);
5639
+ break;
5640
+ }
5615
5641
  }
5616
5642
  }
5617
5643
  }
5618
- if (!inserted) {
5619
- if (contentNodes.length > 2) {
5620
- contentNodes.splice(2, 0, tableEl);
5621
- } else {
5622
- contentNodes.push(tableEl);
5623
- }
5644
+ }
5645
+ elements.forEach((el) => {
5646
+ const svgs = el.querySelectorAll ? Array.from(el.querySelectorAll("svg")) : [];
5647
+ svgs.forEach((svg) => {
5648
+ svg.removeAttribute("width");
5649
+ svg.removeAttribute("height");
5650
+ svg.style.maxWidth = "100%";
5651
+ svg.style.maxHeight = "430px";
5652
+ svg.style.height = "auto";
5653
+ svg.style.display = "block";
5654
+ svg.style.margin = "12px auto";
5655
+ });
5656
+ const imgs = el.querySelectorAll ? Array.from(el.querySelectorAll("img")) : [];
5657
+ imgs.forEach((img) => {
5658
+ img.style.maxWidth = "100%";
5659
+ img.style.maxHeight = "430px";
5660
+ img.style.height = "auto";
5661
+ img.style.objectFit = "contain";
5662
+ img.style.display = "block";
5663
+ img.style.margin = "12px auto";
5664
+ });
5665
+ });
5666
+ const allImgs = Array.from(document.querySelectorAll("img")).concat(
5667
+ elements.flatMap((el) => Array.from(el.querySelectorAll ? el.querySelectorAll("img") : []))
5668
+ );
5669
+ await Promise.all(allImgs.map((img) => {
5670
+ if (img.complete && img.naturalHeight > 0) return Promise.resolve();
5671
+ if (img.decode) return img.decode().catch(() => {
5672
+ });
5673
+ return new Promise((r) => {
5674
+ img.onload = r;
5675
+ img.onerror = r;
5676
+ });
5677
+ }));
5678
+ elements.forEach((el) => {
5679
+ const text = el.textContent || "";
5680
+ if (text.includes("\uF0B7")) {
5681
+ const cleanText = text.replace(/^[\s\uf0b7\t]+/, "");
5682
+ el.style.display = "flex";
5683
+ el.style.alignItems = "flex-start";
5684
+ el.style.margin = "6px 0 6px 28px";
5685
+ el.style.fontSize = "11pt";
5686
+ el.style.lineHeight = "1.5";
5687
+ el.innerHTML = `<span style="margin-right:10px; user-select:none;">&#9633;</span><span>${cleanText}</span>`;
5624
5688
  }
5625
5689
  });
5626
- wrapper.innerHTML = "";
5627
- contentNodes.forEach((node) => wrapper.appendChild(node));
5628
- const childHeights = contentNodes.map((c) => {
5629
- const rectH = c.getBoundingClientRect ? c.getBoundingClientRect().height : 0;
5630
- const offH = c.offsetHeight || 0;
5631
- const realH = Math.max(rectH, offH);
5632
- if (realH > 0) return realH;
5633
- const textLen = c.textContent?.trim().length || 0;
5634
- return Math.max(24, Math.ceil(textLen / 95) * 22 + 12);
5690
+ elements.forEach((el) => {
5691
+ const text = (el.textContent || "").trim();
5692
+ const hasMedia = el.querySelector("img, svg, canvas, table") !== null || ["IMG", "SVG", "TABLE"].includes(el.tagName);
5693
+ if (isHeadingElement(el)) {
5694
+ el.style.marginTop = "20px";
5695
+ el.style.marginBottom = "10px";
5696
+ el.style.lineHeight = "1.25";
5697
+ } else if (text.length > 0 && !hasMedia) {
5698
+ el.style.marginBottom = "12px";
5699
+ el.style.lineHeight = "1.45";
5700
+ }
5635
5701
  });
5636
- wrapper.innerHTML = "";
5637
- const createRtfCard = () => {
5702
+ const measureCard = document.createElement("div");
5703
+ measureCard.style.width = `${pageWidth}px`;
5704
+ measureCard.style.padding = `${padTop}px ${padRight}px ${padBottom}px ${padLeft}px`;
5705
+ measureCard.style.boxSizing = "border-box";
5706
+ measureCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
5707
+ measureCard.style.lineHeight = "1.45";
5708
+ measureCard.style.visibility = "hidden";
5709
+ measureCard.style.position = "absolute";
5710
+ measureCard.style.top = "-99999px";
5711
+ document.body.appendChild(measureCard);
5712
+ const createPageCard = (num) => {
5638
5713
  const card = document.createElement("div");
5639
5714
  card.className = "fp-rtf-page-card";
5715
+ card.setAttribute("data-page-number", String(num));
5640
5716
  card.style.backgroundColor = "#ffffff";
5641
- card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
5717
+ card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08), 0 1px 3px rgba(0,0,0,0.04)";
5642
5718
  card.style.borderRadius = "4px";
5643
- card.style.padding = "64px 56px";
5644
- card.style.width = "816px";
5645
- card.style.minHeight = "1056px";
5719
+ card.style.width = `${pageWidth}px`;
5720
+ card.style.height = `${pageHeight}px`;
5721
+ card.style.padding = `${padTop}px ${padRight}px ${padBottom}px ${padLeft}px`;
5646
5722
  card.style.boxSizing = "border-box";
5723
+ card.style.overflow = "hidden";
5647
5724
  card.style.marginBottom = "24px";
5648
- card.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
5649
- card.style.lineHeight = "1.6";
5650
5725
  card.style.color = "#1e293b";
5726
+ card.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
5727
+ card.style.lineHeight = "1.45";
5728
+ card.style.position = "relative";
5729
+ card.style.textAlign = "left";
5651
5730
  return card;
5652
5731
  };
5653
- let curCard = createRtfCard();
5654
- wrapper.appendChild(curCard);
5655
- pageElements = [curCard];
5656
- let curH = 0;
5657
- const maxH = 928;
5658
- for (let i = 0; i < contentNodes.length; i++) {
5659
- const child = contentNodes[i];
5660
- const chH = childHeights[i];
5661
- const isChildEmpty = (child.textContent || "").trim().length === 0 && !child.querySelector("table, img, svg, canvas");
5662
- if (curH === 0 && isChildEmpty) {
5732
+ const pages = [];
5733
+ let curCard = createPageCard(1);
5734
+ pages.push(curCard);
5735
+ let curHeight = 0;
5736
+ for (let i = 0; i < elements.length; i++) {
5737
+ const el = elements[i];
5738
+ if (!el || !(el instanceof HTMLElement)) continue;
5739
+ const text = (el.textContent || "").trim();
5740
+ const hasMedia = el.querySelector("img, svg, canvas, table") !== null || ["IMG", "SVG", "TABLE"].includes(el.tagName);
5741
+ const isEmptyPar = !hasMedia && text.length === 0;
5742
+ if (isEmptyPar) {
5743
+ const emptyH = 35;
5744
+ if (curHeight + emptyH > printableHeight) {
5745
+ if (curCard.childNodes.length > 0) {
5746
+ curCard = createPageCard(pages.length + 1);
5747
+ pages.push(curCard);
5748
+ curHeight = 0;
5749
+ }
5750
+ }
5751
+ const spacer = document.createElement("div");
5752
+ spacer.style.height = `${emptyH}px`;
5753
+ curCard.appendChild(spacer);
5754
+ curHeight += emptyH;
5663
5755
  continue;
5664
5756
  }
5665
- if (curH + chH > maxH && curCard.childNodes.length > 0) {
5666
- curCard = createRtfCard();
5667
- wrapper.appendChild(curCard);
5668
- pageElements.push(curCard);
5669
- curH = 0;
5757
+ measureCard.innerHTML = "";
5758
+ const clone = el.cloneNode(true);
5759
+ measureCard.appendChild(clone);
5760
+ const compStyle = window.getComputedStyle(clone);
5761
+ const mt = parseFloat(compStyle.marginTop) || 0;
5762
+ const mb = parseFloat(compStyle.marginBottom) || 0;
5763
+ const elH = clone.offsetHeight + mt + mb;
5764
+ const isHeading = isHeadingElement(el);
5765
+ let nextContentH = 0;
5766
+ if (isHeading || hasMedia) {
5767
+ for (let j = i + 1; j < elements.length; j++) {
5768
+ const nextEl = elements[j];
5769
+ if (nextEl && (nextEl.textContent || "").trim().length > 0) {
5770
+ measureCard.innerHTML = "";
5771
+ const nClone = nextEl.cloneNode(true);
5772
+ measureCard.appendChild(nClone);
5773
+ const nStyle = window.getComputedStyle(nClone);
5774
+ nextContentH = nClone.offsetHeight + (parseFloat(nStyle.marginTop) || 0) + (parseFloat(nStyle.marginBottom) || 0);
5775
+ break;
5776
+ }
5777
+ }
5670
5778
  }
5671
- curCard.appendChild(child);
5672
- curH += chH;
5673
- }
5674
- pageElements = pageElements.filter((card) => {
5779
+ const remainingSpace = printableHeight - curHeight;
5780
+ const isLargeMedia = hasMedia && elH > 300;
5781
+ const keepWithNextOverflow = isHeading && nextContentH > 0 && elH + nextContentH + 20 > remainingSpace;
5782
+ const largeMediaOverflow = isLargeMedia && curHeight > 0 && elH + 80 > remainingSpace;
5783
+ const shouldBreak = (curHeight + elH > printableHeight || keepWithNextOverflow || largeMediaOverflow) && curCard.childNodes.length > 0;
5784
+ if (shouldBreak) {
5785
+ curCard = createPageCard(pages.length + 1);
5786
+ pages.push(curCard);
5787
+ curHeight = 0;
5788
+ }
5789
+ curCard.appendChild(el);
5790
+ curHeight += elH;
5791
+ }
5792
+ measureCard.remove();
5793
+ pageElements = pages.filter((card) => {
5675
5794
  const hasText = (card.textContent || "").trim().length > 0;
5676
- const hasMedia = card.querySelector("table, img, svg, canvas") !== null;
5677
- return hasText || hasMedia;
5795
+ const hasCardMedia = card.querySelector("table, img, svg, canvas") !== null;
5796
+ return hasText || hasCardMedia;
5678
5797
  });
5679
5798
  if (pageElements.length === 0) {
5680
5799
  pageElements = [curCard];
5681
5800
  }
5801
+ wrapper.innerHTML = "";
5802
+ pageElements.forEach((card, idx) => {
5803
+ card.setAttribute("data-page-number", String(idx + 1));
5804
+ card.style.display = idx === 0 ? "block" : "none";
5805
+ wrapper.appendChild(card);
5806
+ });
5682
5807
  } catch (err) {
5683
5808
  console.warn("[RtfPlugin] RTF render error, fallback text:", err);
5684
- const text = new TextDecoder("latin1").decode(ctx.buffer);
5685
- const tables = parseRtfTables(text);
5809
+ const text = rawRtf;
5686
5810
  const rawPages = text.split(/\\page\b/).map((segment) => {
5687
5811
  return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
5688
- }).filter((p) => p.length > 0);
5812
+ }).filter((p2) => p2.length > 0);
5689
5813
  const pages = rawPages.length > 0 ? rawPages : [text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim()];
5690
5814
  for (let i = 0; i < pages.length; i++) {
5691
5815
  const pageCard = document.createElement("div");
@@ -5693,9 +5817,9 @@ var RtfPlugin = class {
5693
5817
  pageCard.style.backgroundColor = "#ffffff";
5694
5818
  pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
5695
5819
  pageCard.style.borderRadius = "4px";
5696
- pageCard.style.padding = "64px 56px";
5697
- pageCard.style.width = "816px";
5698
- pageCard.style.minHeight = "1056px";
5820
+ pageCard.style.padding = `${padTop}px ${padRight}px ${padBottom}px ${padLeft}px`;
5821
+ pageCard.style.width = `${pageWidth}px`;
5822
+ pageCard.style.minHeight = `${pageHeight}px`;
5699
5823
  pageCard.style.boxSizing = "border-box";
5700
5824
  pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
5701
5825
  pageCard.style.fontSize = "12pt";
@@ -5715,11 +5839,9 @@ var RtfPlugin = class {
5715
5839
  let currentPage = 1;
5716
5840
  const showPage = (pageNum) => {
5717
5841
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
5718
- if (totalPages > 1) {
5719
- pageElements.forEach((el, idx) => {
5720
- el.style.display = idx + 1 === currentPage ? "block" : "none";
5721
- });
5722
- }
5842
+ pageElements.forEach((el, idx) => {
5843
+ el.style.display = idx + 1 === currentPage ? "block" : "none";
5844
+ });
5723
5845
  ctx.container.scrollTop = 0;
5724
5846
  ctx.emit("page-change", { page: currentPage, total: totalPages });
5725
5847
  };