@files-preview-app/preview-file 1.3.4 → 1.3.6

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
@@ -495,6 +495,7 @@ var ICON_COPY = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" str
495
495
  var ICON_FAST_FORWARD = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 19 22 12 13 5 13 19"></polygon><polygon points="2 19 11 12 2 5 2 19"></polygon></svg>`;
496
496
  var ICON_REWIND = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 19 2 12 11 5 11 19"></polygon><polygon points="22 19 13 12 22 5 22 19"></polygon></svg>`;
497
497
  var ICON_EXTERNAL_WINDOW = `<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="3" y1="8" x2="21" y2="8"></line><circle cx="6" cy="5.5" r="0.75" fill="currentColor"></circle><circle cx="8.5" cy="5.5" r="0.75" fill="currentColor"></circle><polyline points="14 13 18 13 18 17"></polyline><line x1="11" y1="20" x2="18" y2="13"></line></svg>`;
498
+ var ICON_RESET_ZOOM = `<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><path d="M13 11a3 3 0 1 0-3 3"></path><path d="M10 11v3h3"></path></svg>`;
498
499
  var ICON_MAP = {
499
500
  "zoom-in": ICON_ZOOM_IN,
500
501
  "zoom-out": ICON_ZOOM_OUT,
@@ -524,7 +525,10 @@ var ICON_MAP = {
524
525
  "open-window": ICON_EXTERNAL_WINDOW,
525
526
  "external-window": ICON_EXTERNAL_WINDOW,
526
527
  "openWindow": ICON_EXTERNAL_WINDOW,
527
- "openSeparateWindow": ICON_EXTERNAL_WINDOW
528
+ "openSeparateWindow": ICON_EXTERNAL_WINDOW,
529
+ "reset-zoom": ICON_RESET_ZOOM,
530
+ "zoom-reset": ICON_RESET_ZOOM,
531
+ "resetZoom": ICON_RESET_ZOOM
528
532
  };
529
533
  var ToolbarController = class {
530
534
  el;
@@ -557,6 +561,10 @@ var ToolbarController = class {
557
561
  this.config.fitToPage = false;
558
562
  this.config.fitWidth = false;
559
563
  }
564
+ if (actionId === "reset-zoom" || actionId === "zoom-reset" || actionId === "resetZoom") {
565
+ this.config.resetZoom = false;
566
+ this.config.zoomReset = false;
567
+ }
560
568
  if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = false;
561
569
  if (actionId === "fullscreen") this.config.fullscreen = false;
562
570
  if (actionId === "download") this.config.download = false;
@@ -581,6 +589,10 @@ var ToolbarController = class {
581
589
  this.config.fitToPage = true;
582
590
  this.config.fitWidth = true;
583
591
  }
592
+ if (actionId === "reset-zoom" || actionId === "zoom-reset" || actionId === "resetZoom") {
593
+ this.config.resetZoom = true;
594
+ this.config.zoomReset = true;
595
+ }
584
596
  if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = true;
585
597
  if (actionId === "fullscreen") this.config.fullscreen = true;
586
598
  if (actionId === "download") this.config.download = true;
@@ -600,6 +612,7 @@ var ToolbarController = class {
600
612
  if (actionId === "zoomIn") return "zoom-in";
601
613
  if (actionId === "zoomOut") return "zoom-out";
602
614
  if (actionId === "fitPage" || actionId === "fitToPage" || actionId === "fitWidth") return "fit-page";
615
+ if (actionId === "resetZoom" || actionId === "zoomReset") return "reset-zoom";
603
616
  if (actionId === "rotateCW") return "rotate-cw";
604
617
  if (actionId === "rotateCCW") return "rotate-ccw";
605
618
  if (actionId === "openWindow" || actionId === "openSeparateWindow") return "open-window";
@@ -642,6 +655,9 @@ var ToolbarController = class {
642
655
  if ((id === "fit-page" || id === "fit-width" || id === "fit-slide") && (c.fitPage === false || c.fitToPage === false || c.fitWidth === false || c["fit-page"] === false || c["fit-width"] === false)) {
643
656
  return false;
644
657
  }
658
+ if ((id === "reset-zoom" || id === "zoom-reset") && (c.resetZoom === false || c.zoomReset === false || c["reset-zoom"] === false || c["zoom-reset"] === false)) {
659
+ return false;
660
+ }
645
661
  if ((id === "rotate-cw" || id === "rotate-ccw" || id === "rotate") && (c.rotate === false || c.rotateCW === false || c.rotateCCW === false || c["rotate-cw"] === false)) {
646
662
  return false;
647
663
  }
@@ -1088,6 +1104,9 @@ var FilePreviewViewer = class _FilePreviewViewer {
1088
1104
  this.activeInstance = instance;
1089
1105
  instance.openInSeparateWindow = () => this.openInSeparateWindow();
1090
1106
  instance.toggleThumbnails = () => this.toggleThumbnails();
1107
+ if (!instance.resetZoom && instance.fitToPage) {
1108
+ instance.resetZoom = () => instance.fitToPage?.();
1109
+ }
1091
1110
  this.hideLoading();
1092
1111
  this.eventEmitter.emit("loaded", { metadata, plugin: matchedPlugin.id });
1093
1112
  const isToolbarVisible = options.showToolbar !== false && options.toolbar !== false;
@@ -1371,6 +1390,16 @@ var FilePreviewViewer = class _FilePreviewViewer {
1371
1390
  fitToPage() {
1372
1391
  this.activeInstance?.fitToPage?.();
1373
1392
  }
1393
+ /**
1394
+ * Reset zoom level to initial/default fit state.
1395
+ */
1396
+ resetZoom() {
1397
+ if (this.activeInstance?.resetZoom) {
1398
+ this.activeInstance.resetZoom();
1399
+ } else if (this.activeInstance?.fitToPage) {
1400
+ this.activeInstance.fitToPage();
1401
+ }
1402
+ }
1374
1403
  /**
1375
1404
  * Zoom in.
1376
1405
  */
@@ -1992,6 +2021,14 @@ var PdfPlugin = class {
1992
2021
  group: "zoom",
1993
2022
  execute: () => instance.fitToPage?.()
1994
2023
  },
2024
+ {
2025
+ id: "reset-zoom",
2026
+ icon: "reset-zoom",
2027
+ label: "Reset Zoom",
2028
+ type: "button",
2029
+ group: "zoom",
2030
+ execute: () => instance.resetZoom?.()
2031
+ },
1995
2032
  {
1996
2033
  id: "fit-width",
1997
2034
  icon: "fit-width",
@@ -2254,6 +2291,14 @@ var PdfPlugin = class {
2254
2291
  zoomScale = 1;
2255
2292
  renderPage(currentPage);
2256
2293
  },
2294
+ resetZoom: () => {
2295
+ fitMode = "page";
2296
+ zoomScale = 1;
2297
+ rotation = 0;
2298
+ container.scrollTop = 0;
2299
+ container.scrollLeft = 0;
2300
+ renderPage(currentPage);
2301
+ },
2257
2302
  fitToWidth: () => {
2258
2303
  fitMode = "width";
2259
2304
  zoomScale = 1;
@@ -2421,6 +2466,16 @@ var MediaPlugin = class {
2421
2466
  instance.fitToPage?.();
2422
2467
  }
2423
2468
  },
2469
+ {
2470
+ id: "reset-zoom",
2471
+ icon: "reset-zoom",
2472
+ label: "Reset Zoom",
2473
+ type: "button",
2474
+ group: "zoom",
2475
+ execute: () => {
2476
+ instance.resetZoom?.();
2477
+ }
2478
+ },
2424
2479
  {
2425
2480
  id: "rotate-cw",
2426
2481
  icon: "rotate-cw",
@@ -2594,6 +2649,13 @@ var MediaPlugin = class {
2594
2649
  rotation = 0;
2595
2650
  applyTransform();
2596
2651
  } : void 0,
2652
+ resetZoom: isImage ? () => {
2653
+ currentZoom = 1;
2654
+ rotation = 0;
2655
+ ctx.container.scrollTop = 0;
2656
+ ctx.container.scrollLeft = 0;
2657
+ applyTransform();
2658
+ } : void 0,
2597
2659
  rotateCW: isImage || isVideo ? () => {
2598
2660
  rotation = (rotation + 90) % 360;
2599
2661
  applyTransform();
@@ -2710,6 +2772,14 @@ var DocxPlugin = class {
2710
2772
  group: "zoom",
2711
2773
  execute: () => instance.fitToPage?.()
2712
2774
  },
2775
+ {
2776
+ id: "reset-zoom",
2777
+ icon: "reset-zoom",
2778
+ label: "Reset Zoom",
2779
+ type: "button",
2780
+ group: "zoom",
2781
+ execute: () => instance.resetZoom?.()
2782
+ },
2713
2783
  {
2714
2784
  id: "rotate-cw",
2715
2785
  icon: "rotate-cw",
@@ -3026,6 +3096,14 @@ var DocxPlugin = class {
3026
3096
  rotation = 0;
3027
3097
  applyTransform();
3028
3098
  },
3099
+ resetZoom: () => {
3100
+ isUserZoomed = false;
3101
+ scale = calculateFitScale("page");
3102
+ rotation = 0;
3103
+ ctx.container.scrollTop = 0;
3104
+ ctx.container.scrollLeft = 0;
3105
+ applyTransform();
3106
+ },
3029
3107
  rotateCW: () => {
3030
3108
  rotation = (rotation + 90) % 360;
3031
3109
  applyTransform();
@@ -3475,6 +3553,16 @@ var ExcelPlugin = class {
3475
3553
  instance.zoomIn?.();
3476
3554
  }
3477
3555
  },
3556
+ {
3557
+ id: "reset-zoom",
3558
+ icon: "reset-zoom",
3559
+ label: "Reset Zoom",
3560
+ type: "button",
3561
+ group: "zoom",
3562
+ execute: () => {
3563
+ instance.resetZoom?.();
3564
+ }
3565
+ },
3478
3566
  {
3479
3567
  id: "download",
3480
3568
  icon: "download",
@@ -3662,6 +3750,12 @@ var ExcelPlugin = class {
3662
3750
  scale = calculateFitScale();
3663
3751
  applyTransform();
3664
3752
  },
3753
+ resetZoom: () => {
3754
+ scale = calculateFitScale();
3755
+ contentArea.scrollTop = 0;
3756
+ contentArea.scrollLeft = 0;
3757
+ applyTransform();
3758
+ },
3665
3759
  rotateCW: () => {
3666
3760
  },
3667
3761
  rotateCCW: () => {
@@ -3792,6 +3886,16 @@ var CsvPlugin = class {
3792
3886
  instance.zoomIn?.();
3793
3887
  }
3794
3888
  },
3889
+ {
3890
+ id: "reset-zoom",
3891
+ icon: "reset-zoom",
3892
+ label: "Reset Zoom",
3893
+ type: "button",
3894
+ group: "zoom",
3895
+ execute: () => {
3896
+ instance.resetZoom?.();
3897
+ }
3898
+ },
3795
3899
  {
3796
3900
  id: "download",
3797
3901
  icon: "download",
@@ -3981,6 +4085,12 @@ var CsvPlugin = class {
3981
4085
  scale = calculateFitScale();
3982
4086
  applyScale();
3983
4087
  },
4088
+ resetZoom: () => {
4089
+ scale = calculateFitScale();
4090
+ container.scrollTop = 0;
4091
+ container.scrollLeft = 0;
4092
+ applyScale();
4093
+ },
3984
4094
  rotateCW: () => {
3985
4095
  },
3986
4096
  rotateCCW: () => {
@@ -4096,6 +4206,16 @@ var CodePlugin = class {
4096
4206
  instance.zoomIn?.();
4097
4207
  }
4098
4208
  },
4209
+ {
4210
+ id: "reset-zoom",
4211
+ icon: "reset-zoom",
4212
+ label: "Reset Zoom",
4213
+ type: "button",
4214
+ group: "zoom",
4215
+ execute: () => {
4216
+ instance.resetZoom?.();
4217
+ }
4218
+ },
4099
4219
  {
4100
4220
  id: "copy",
4101
4221
  icon: "copy",
@@ -4375,6 +4495,15 @@ var CodePlugin = class {
4375
4495
  zoomLevel = isTxt ? calculateTxtFit() : 1;
4376
4496
  updateTransform();
4377
4497
  },
4498
+ resetZoom: () => {
4499
+ isUserZoomed = false;
4500
+ fontSize = 13;
4501
+ rotation = 0;
4502
+ zoomLevel = isTxt ? calculateTxtFit() : 1;
4503
+ container.scrollTop = 0;
4504
+ container.scrollLeft = 0;
4505
+ updateTransform();
4506
+ },
4378
4507
  rotateCW: () => {
4379
4508
  rotation = (rotation + 90) % 360;
4380
4509
  updateTransform();
@@ -4437,11 +4566,19 @@ var ArchivePlugin = class {
4437
4566
  {
4438
4567
  id: "fit-page",
4439
4568
  icon: "fit-page",
4440
- label: "Reset Zoom",
4569
+ label: "Fit to Page",
4441
4570
  type: "button",
4442
4571
  group: "zoom",
4443
4572
  execute: () => instance.fitToPage?.()
4444
4573
  },
4574
+ {
4575
+ id: "reset-zoom",
4576
+ icon: "reset-zoom",
4577
+ label: "Reset Zoom",
4578
+ type: "button",
4579
+ group: "zoom",
4580
+ execute: () => instance.resetZoom?.()
4581
+ },
4445
4582
  {
4446
4583
  id: "download",
4447
4584
  icon: "download",
@@ -4596,7 +4733,13 @@ var ArchivePlugin = class {
4596
4733
  },
4597
4734
  fitToPage: () => {
4598
4735
  scale = 1;
4599
- wrapper.style.transform = `scale(1)`;
4736
+ wrapper.style.transform = "scale(1)";
4737
+ },
4738
+ resetZoom: () => {
4739
+ scale = 1;
4740
+ wrapper.style.transform = "scale(1)";
4741
+ ctx.container.scrollTop = 0;
4742
+ ctx.container.scrollLeft = 0;
4600
4743
  },
4601
4744
  download: () => {
4602
4745
  downloadFile(ctx.buffer, ctx.metadata.name || "archive.zip", "application/zip");
@@ -4648,6 +4791,14 @@ var MarkdownPlugin = class {
4648
4791
  group: "zoom",
4649
4792
  execute: () => instance.fitToPage?.()
4650
4793
  },
4794
+ {
4795
+ id: "reset-zoom",
4796
+ icon: "reset-zoom",
4797
+ label: "Reset Zoom",
4798
+ type: "button",
4799
+ group: "zoom",
4800
+ execute: () => instance.resetZoom?.()
4801
+ },
4651
4802
  {
4652
4803
  id: "copy",
4653
4804
  icon: "copy",
@@ -4801,6 +4952,12 @@ var MarkdownPlugin = class {
4801
4952
  fontSize = 15;
4802
4953
  wrapper.style.fontSize = "15px";
4803
4954
  },
4955
+ resetZoom: () => {
4956
+ fontSize = 15;
4957
+ wrapper.style.fontSize = "15px";
4958
+ ctx.container.scrollTop = 0;
4959
+ ctx.container.scrollLeft = 0;
4960
+ },
4804
4961
  download: () => {
4805
4962
  downloadFile(ctx.buffer, ctx.metadata.name || "document.md", "text/markdown");
4806
4963
  },
@@ -4894,6 +5051,14 @@ var PptxPlugin = class {
4894
5051
  group: "zoom",
4895
5052
  execute: () => instance.fitToPage?.()
4896
5053
  },
5054
+ {
5055
+ id: "reset-zoom",
5056
+ icon: "reset-zoom",
5057
+ label: "Reset Zoom",
5058
+ type: "button",
5059
+ group: "zoom",
5060
+ execute: () => instance.resetZoom?.()
5061
+ },
4897
5062
  {
4898
5063
  id: "rotate-cw",
4899
5064
  icon: "rotate-cw",
@@ -5013,6 +5178,13 @@ var PptxPlugin = class {
5013
5178
  rotation = 0;
5014
5179
  applyTransform();
5015
5180
  },
5181
+ resetZoom: () => {
5182
+ scale = calculateFitScale();
5183
+ rotation = 0;
5184
+ wrapper.scrollTop = 0;
5185
+ wrapper.scrollLeft = 0;
5186
+ applyTransform();
5187
+ },
5016
5188
  rotateCW: () => {
5017
5189
  rotation = (rotation + 90) % 360;
5018
5190
  applyTransform();
@@ -5088,6 +5260,14 @@ var ThreeDPlugin = class {
5088
5260
  group: "zoom",
5089
5261
  execute: () => instance.fitToPage?.()
5090
5262
  },
5263
+ {
5264
+ id: "reset-zoom",
5265
+ icon: "reset-zoom",
5266
+ label: "Reset Zoom",
5267
+ type: "button",
5268
+ group: "zoom",
5269
+ execute: () => instance.resetZoom?.()
5270
+ },
5091
5271
  {
5092
5272
  id: "rotate-cw",
5093
5273
  icon: "rotate-cw",
@@ -5224,6 +5404,7 @@ var ThreeDPlugin = class {
5224
5404
  controls.update();
5225
5405
  },
5226
5406
  fitToPage: fitCamera,
5407
+ resetZoom: fitCamera,
5227
5408
  rotateCW: () => {
5228
5409
  isWireframe = !isWireframe;
5229
5410
  materials.forEach((m) => {
@@ -5246,7 +5427,7 @@ function cleanRtfText(raw) {
5246
5427
  return String.fromCharCode(num);
5247
5428
  }).replace(/\\'([0-9a-fA-F]{2})/g, (_, hex) => {
5248
5429
  return String.fromCharCode(parseInt(hex, 16));
5249
- }).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();
5430
+ }).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();
5250
5431
  }
5251
5432
  function parseRtfTables(rtfText) {
5252
5433
  const rowSegments = rtfText.split(/\\row\b/);
@@ -5286,17 +5467,12 @@ function parseRtfTables(rtfText) {
5286
5467
  }
5287
5468
  const isNewTable = !currentTable || segmentStart - currentTable.lastEnd > 2500;
5288
5469
  if (isNewTable) {
5289
- const prevTextSlice = rtfText.slice(Math.max(0, segmentStart - 4e3), segmentStart);
5290
- const cleanPrev = cleanRtfText(prevTextSlice);
5291
- const anchorBefore = cleanPrev.slice(-80).trim();
5292
5470
  currentTable = {
5293
5471
  id: `RTF_TABLE_${rawTables.length}`,
5294
5472
  startPos: segmentStart,
5295
5473
  lastEnd: segmentEnd,
5296
5474
  rows: [],
5297
- columnWidths: cellWidths,
5298
- anchorBefore,
5299
- anchorAfter: ""
5475
+ columnWidths: cellWidths
5300
5476
  };
5301
5477
  rawTables.push(currentTable);
5302
5478
  }
@@ -5310,20 +5486,13 @@ function parseRtfTables(rtfText) {
5310
5486
  }
5311
5487
  charOffset += segment.length + 4;
5312
5488
  }
5313
- rawTables.forEach((tbl) => {
5314
- const afterSlice = rtfText.slice(tbl.lastEnd, Math.min(rtfText.length, tbl.lastEnd + 2e3));
5315
- const cleanAfter = cleanRtfText(afterSlice);
5316
- tbl.anchorAfter = cleanAfter.slice(0, 80).trim();
5317
- });
5318
5489
  return rawTables.map((tbl) => {
5319
5490
  const totalW = (tbl.columnWidths || []).reduce((a, b) => a + b, 0);
5320
5491
  const colPercents = totalW > 0 ? tbl.columnWidths.map((w) => Math.round(w / totalW * 100)) : [];
5321
5492
  return {
5322
5493
  id: tbl.id,
5323
5494
  rows: tbl.rows.map((r) => r.cells),
5324
- colPercents,
5325
- anchorBefore: tbl.anchorBefore,
5326
- anchorAfter: tbl.anchorAfter
5495
+ colPercents
5327
5496
  };
5328
5497
  });
5329
5498
  }
@@ -5336,8 +5505,6 @@ function renderRtfTableElement(table) {
5336
5505
  tableEl.style.fontSize = "10pt";
5337
5506
  tableEl.style.lineHeight = "1.5";
5338
5507
  tableEl.style.border = "1px solid #cbd5e1";
5339
- tableEl.style.borderRadius = "4px";
5340
- tableEl.style.boxSizing = "border-box";
5341
5508
  tableEl.style.backgroundColor = "#ffffff";
5342
5509
  const thead = document.createElement("thead");
5343
5510
  const tbody = document.createElement("tbody");
@@ -5346,27 +5513,17 @@ function renderRtfTableElement(table) {
5346
5513
  const isHeader = rIdx === 0;
5347
5514
  if (isHeader) {
5348
5515
  tr.style.backgroundColor = "#f8fafc";
5349
- tr.style.borderBottom = "2px solid #cbd5e1";
5350
- } else {
5351
- tr.style.borderBottom = "1px solid #e2e8f0";
5352
- if (rIdx % 2 === 0) {
5353
- tr.style.backgroundColor = "#fcfdfe";
5354
- }
5355
5516
  }
5356
5517
  rowCells.forEach((cellText, cIdx) => {
5357
5518
  const cellEl = document.createElement(isHeader ? "th" : "td");
5358
5519
  cellEl.style.padding = "8px 12px";
5359
5520
  cellEl.style.border = "1px solid #cbd5e1";
5360
5521
  cellEl.style.verticalAlign = "top";
5361
- cellEl.style.color = isHeader ? "#0f172a" : "#1e293b";
5362
- cellEl.style.fontWeight = isHeader ? "600" : "normal";
5363
5522
  if (table.colPercents && table.colPercents[cIdx]) {
5364
5523
  cellEl.style.width = `${table.colPercents[cIdx]}%`;
5365
5524
  }
5366
5525
  if (/^\d+$/.test(cellText.trim()) || cellText.trim() === "#") {
5367
5526
  cellEl.style.textAlign = "center";
5368
- } else {
5369
- cellEl.style.textAlign = "left";
5370
5527
  }
5371
5528
  cellEl.textContent = cellText;
5372
5529
  tr.appendChild(cellEl);
@@ -5381,23 +5538,19 @@ function renderRtfTableElement(table) {
5381
5538
  tableEl.appendChild(tbody);
5382
5539
  return tableEl;
5383
5540
  }
5384
- function extractMediaFingerprint(el) {
5385
- const img = el.tagName.toLowerCase() === "img" ? el : el.querySelector("img");
5386
- if (img && img.src) {
5387
- const s = img.src;
5388
- return s.length > 300 ? `img_${s.slice(0, 80)}_${s.length}_${s.slice(-80)}` : `img_${s}`;
5389
- }
5390
- const innerImg = el.querySelector("image");
5391
- if (innerImg) {
5392
- const h2 = innerImg.getAttribute("xlink:href") || innerImg.getAttribute("href") || "";
5393
- if (h2) return h2.length > 300 ? `svgimg_${h2.slice(0, 80)}_${h2.length}_${h2.slice(-80)}` : `svgimg_${h2}`;
5394
- }
5395
- const svg = el.tagName.toLowerCase() === "svg" ? el : el.querySelector("svg");
5396
- if (svg) {
5397
- const vb = svg.getAttribute("viewBox") || "";
5398
- return `svg_${vb}_${svg.innerHTML.length}`;
5399
- }
5400
- return null;
5541
+ function isHeadingElement(el) {
5542
+ if (["H1", "H2", "H3", "H4"].includes(el.tagName)) return true;
5543
+ const spans = el.querySelectorAll ? Array.from(el.querySelectorAll("span, b, strong, div")) : [];
5544
+ for (const s of spans) {
5545
+ const hEl = s;
5546
+ const fs = parseFloat(hEl.style.fontSize) || 0;
5547
+ const isBold = hEl.style.fontWeight === "bold" || parseInt(hEl.style.fontWeight, 10) >= 600 || ["B", "STRONG"].includes(hEl.tagName);
5548
+ if (isBold && fs >= 14) return true;
5549
+ }
5550
+ const elFs = parseFloat(el.style.fontSize) || 0;
5551
+ const elBold = el.style.fontWeight === "bold" || parseInt(el.style.fontWeight, 10) >= 600;
5552
+ if (elBold && elFs >= 14) return true;
5553
+ return false;
5401
5554
  }
5402
5555
  var RtfPlugin = class {
5403
5556
  id = "rtf";
@@ -5466,6 +5619,14 @@ var RtfPlugin = class {
5466
5619
  group: "zoom",
5467
5620
  execute: () => instance.fitToPage?.()
5468
5621
  },
5622
+ {
5623
+ id: "reset-zoom",
5624
+ icon: "reset-zoom",
5625
+ label: "Reset Zoom",
5626
+ type: "button",
5627
+ group: "zoom",
5628
+ execute: () => instance.resetZoom?.()
5629
+ },
5469
5630
  {
5470
5631
  id: "rotate-cw",
5471
5632
  icon: "rotate-cw",
@@ -5510,10 +5671,66 @@ var RtfPlugin = class {
5510
5671
  return actions;
5511
5672
  }
5512
5673
  async render(ctx) {
5674
+ const rawRtf = new TextDecoder("latin1").decode(ctx.buffer);
5675
+ const paperwMatch = rawRtf.match(/\\paperw(\d+)/);
5676
+ const paperhMatch = rawRtf.match(/\\paperh(\d+)/);
5677
+ const marglMatch = rawRtf.match(/\\margl(\d+)/);
5678
+ const margrMatch = rawRtf.match(/\\margr(\d+)/);
5679
+ const margtMatch = rawRtf.match(/\\margt(\d+)/);
5680
+ const margbMatch = rawRtf.match(/\\margb(\d+)/);
5681
+ const paperwTwips = paperwMatch ? parseInt(paperwMatch[1], 10) : 11906;
5682
+ const paperhTwips = paperhMatch ? parseInt(paperhMatch[1], 10) : 16838;
5683
+ const marglTwips = marglMatch ? parseInt(marglMatch[1], 10) : 1134;
5684
+ const margrTwips = margrMatch ? parseInt(margrMatch[1], 10) : 1134;
5685
+ const margtTwips = margtMatch ? parseInt(margtMatch[1], 10) : 1134;
5686
+ const margbTwips = margbMatch ? parseInt(margbMatch[1], 10) : 1134;
5687
+ const pageWidth = Math.round(paperwTwips / 15);
5688
+ const pageHeight = Math.round(paperhTwips / 15);
5689
+ const padLeft = Math.round(marglTwips / 15);
5690
+ const padRight = Math.round(margrTwips / 15);
5691
+ const padTop = Math.round(margtTwips / 15);
5692
+ const padBottom = Math.round(margbTwips / 15);
5693
+ const printableHeight = pageHeight - padTop - padBottom;
5694
+ const extractedImages = [];
5695
+ let p = 0;
5696
+ while ((p = rawRtf.indexOf("\\pict", p)) !== -1) {
5697
+ const startP = p;
5698
+ p += 5;
5699
+ const header = rawRtf.substring(startP, startP + 600);
5700
+ let mime = "";
5701
+ let magic = "";
5702
+ if (header.includes("\\pngblip")) {
5703
+ mime = "image/png";
5704
+ magic = "89504e47";
5705
+ } else if (header.includes("\\jpegblip")) {
5706
+ mime = "image/jpeg";
5707
+ magic = "ffd8ff";
5708
+ }
5709
+ if (!mime || !magic) continue;
5710
+ const magicPos = rawRtf.indexOf(magic, startP);
5711
+ if (magicPos === -1 || magicPos - startP > 3e3) continue;
5712
+ let endP = magicPos;
5713
+ while (endP < rawRtf.length && /[0-9a-fA-F\r\n\s]/.test(rawRtf[endP])) {
5714
+ endP++;
5715
+ }
5716
+ const cleanHex = rawRtf.substring(magicPos, endP).replace(/[\r\n\s]/g, "");
5717
+ if (cleanHex.length < 100) continue;
5718
+ const hexLen = cleanHex.length / 2;
5719
+ const u8 = new Uint8Array(hexLen);
5720
+ for (let k = 0; k < hexLen; k++) {
5721
+ u8[k] = parseInt(cleanHex.substr(k * 2, 2), 16);
5722
+ }
5723
+ let bStr = "";
5724
+ for (let k = 0; k < u8.length; k += 8192) {
5725
+ bStr += String.fromCharCode.apply(null, Array.from(u8.subarray(k, k + 8192)));
5726
+ }
5727
+ extractedImages.push({ mime, dataUrl: `data:${mime};base64,${btoa(bStr)}`, offset: startP });
5728
+ }
5729
+ const tables = parseRtfTables(rawRtf);
5513
5730
  const wrapper = document.createElement("div");
5514
5731
  wrapper.className = "fp-rtf-wrapper";
5515
5732
  wrapper.style.padding = "0";
5516
- wrapper.style.width = "816px";
5733
+ wrapper.style.width = `${pageWidth}px`;
5517
5734
  wrapper.style.margin = "0 auto";
5518
5735
  wrapper.style.boxSizing = "border-box";
5519
5736
  wrapper.style.display = "flex";
@@ -5533,9 +5750,8 @@ var RtfPlugin = class {
5533
5750
  let isUserZoomed = false;
5534
5751
  let fitMode = ctx?.options?.fitMode || "width";
5535
5752
  const calculateFitScale = (mode = fitMode) => {
5536
- const activeEl = pageElements[currentPage - 1] || wrapper;
5537
- const elW = 816;
5538
- const singlePageH = activeEl?.offsetHeight || 1056;
5753
+ const elW = pageWidth;
5754
+ const singlePageH = pageHeight;
5539
5755
  const availW = Math.max(280, ctx.container.clientWidth - 32);
5540
5756
  const availH = Math.max(280, ctx.container.clientHeight - 32);
5541
5757
  const sW = availW / elW;
@@ -5548,8 +5764,7 @@ var RtfPlugin = class {
5548
5764
  const applyTransform = () => {
5549
5765
  wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
5550
5766
  wrapper.style.transformOrigin = "top center";
5551
- const activeEl = pageElements[currentPage - 1];
5552
- const baseH = activeEl?.offsetHeight || 1056;
5767
+ const baseH = pageHeight;
5553
5768
  const scaledH = baseH * scale;
5554
5769
  const extraH = Math.max(0, scaledH - baseH);
5555
5770
  wrapper.style.marginBottom = `${extraH + 32}px`;
@@ -5569,193 +5784,220 @@ var RtfPlugin = class {
5569
5784
  if (typeof RTFJS.loggingEnabled === "function") {
5570
5785
  RTFJS.loggingEnabled(false);
5571
5786
  }
5572
- const rawText = new TextDecoder("latin1").decode(ctx.buffer);
5573
- const tables = parseRtfTables(rawText);
5574
- const seenMediaSignatures = /* @__PURE__ */ new Set();
5575
5787
  const doc = new RTFJS.Document(ctx.buffer, {
5576
5788
  onPicture: (isLegacy, createPic) => {
5577
- if (isLegacy === true) {
5578
- return null;
5579
- }
5580
- const pic = createPic();
5581
- if (!pic) return null;
5582
- const fp = extractMediaFingerprint(pic);
5583
- if (fp) {
5584
- if (seenMediaSignatures.has(fp)) {
5585
- return null;
5586
- }
5587
- seenMediaSignatures.add(fp);
5588
- }
5589
- return pic;
5789
+ if (isLegacy === true) return null;
5790
+ return createPic();
5590
5791
  }
5591
5792
  });
5592
- const htmlElements = await doc.render();
5593
- const contentNodes = [];
5594
- const seenInContentBlocks = /* @__PURE__ */ new Set();
5595
- const extractBlocks = (nodes) => {
5596
- for (const item of nodes) {
5597
- if (!item || !(item instanceof HTMLElement)) continue;
5598
- const tag = item.tagName.toLowerCase();
5599
- const hasChildBlocks = Array.from(item.children).some((c) => {
5600
- const ct = c.tagName.toLowerCase();
5601
- return ["p", "div", "table", "h1", "h2", "h3", "h4", "h5", "h6", "section", "article", "ul", "ol"].includes(ct);
5602
- });
5603
- if (hasChildBlocks && !["table", "tr", "td", "th", "ul", "ol", "li"].includes(tag)) {
5604
- extractBlocks(Array.from(item.children));
5605
- } else {
5606
- const fp = extractMediaFingerprint(item);
5607
- if (fp) {
5608
- if (seenInContentBlocks.has(fp)) {
5609
- continue;
5610
- }
5611
- seenInContentBlocks.add(fp);
5612
- }
5613
- const hasMedia = item.querySelector("img, svg, canvas, table") !== null || ["img", "svg", "table"].includes(tag);
5614
- const textContent = (item.textContent || "").trim();
5615
- if (!hasMedia && textContent.length === 0) {
5616
- continue;
5617
- }
5618
- const svgs = item.querySelectorAll("svg, img");
5619
- svgs.forEach((s) => {
5620
- const el = s;
5621
- el.style.maxWidth = "100%";
5622
- el.style.maxHeight = "360px";
5623
- el.style.display = "block";
5624
- el.style.margin = "12px auto";
5625
- if (s.tagName.toLowerCase() === "svg") {
5626
- s.removeAttribute("width");
5627
- s.removeAttribute("height");
5628
- el.style.width = "100%";
5629
- el.style.maxHeight = "360px";
5630
- }
5631
- });
5632
- if (tag === "p" || tag === "div") {
5633
- item.style.display = "block";
5634
- item.style.marginBottom = "12px";
5635
- item.style.lineHeight = "1.6";
5636
- }
5637
- contentNodes.push(item);
5793
+ const elements = await doc.render();
5794
+ let unsupportedIndex = 1;
5795
+ const usedTables = /* @__PURE__ */ new Set();
5796
+ for (let i = 0; i < elements.length; i++) {
5797
+ const el = elements[i];
5798
+ const text = el.textContent || "";
5799
+ if (text.includes("[Unsupported image format]")) {
5800
+ if (extractedImages[unsupportedIndex]) {
5801
+ const img = document.createElement("img");
5802
+ img.src = extractedImages[unsupportedIndex].dataUrl;
5803
+ img.style.width = "100%";
5804
+ img.style.height = "auto";
5805
+ img.style.maxHeight = "430px";
5806
+ img.style.objectFit = "contain";
5807
+ img.style.display = "block";
5808
+ img.style.margin = "12px auto";
5809
+ el.innerHTML = "";
5810
+ el.appendChild(img);
5811
+ unsupportedIndex++;
5638
5812
  }
5639
5813
  }
5640
- };
5641
- extractBlocks(htmlElements);
5642
- tables.forEach((table) => {
5643
- const tableEl = renderRtfTableElement(table);
5644
- let inserted = false;
5645
- if (table.anchorBefore && table.anchorBefore.length > 10) {
5646
- const keyword = table.anchorBefore.slice(-35).trim();
5647
- for (let i = 0; i < contentNodes.length; i++) {
5648
- if (contentNodes[i].textContent?.includes(keyword)) {
5649
- contentNodes.splice(i + 1, 0, tableEl);
5650
- inserted = true;
5651
- break;
5814
+ if (tables.length > 0) {
5815
+ for (let t = 0; t < tables.length; t++) {
5816
+ if (usedTables.has(t)) continue;
5817
+ const tbl = tables[t];
5818
+ if (tbl.rows.length >= 2) {
5819
+ const sampleCell1 = tbl.rows[1]?.[1] || tbl.rows[0]?.[1] || "";
5820
+ const sampleCell2 = tbl.rows[2]?.[1] || tbl.rows[1]?.[0] || "";
5821
+ const match1 = sampleCell1 && text.includes(sampleCell1.slice(0, 15).trim());
5822
+ const match2 = sampleCell2 && text.includes(sampleCell2.slice(0, 15).trim());
5823
+ if (match1 && match2) {
5824
+ el.innerHTML = "";
5825
+ el.appendChild(renderRtfTableElement(tbl));
5826
+ usedTables.add(t);
5827
+ break;
5828
+ }
5652
5829
  }
5653
5830
  }
5654
5831
  }
5655
- if (!inserted && table.anchorAfter && table.anchorAfter.length > 10) {
5656
- const keyword = table.anchorAfter.slice(0, 35).trim();
5657
- for (let i = 0; i < contentNodes.length; i++) {
5658
- if (contentNodes[i].textContent?.includes(keyword)) {
5659
- contentNodes.splice(i, 0, tableEl);
5660
- inserted = true;
5661
- break;
5662
- }
5663
- }
5832
+ }
5833
+ elements.forEach((el) => {
5834
+ const svgs = el.querySelectorAll ? Array.from(el.querySelectorAll("svg")) : [];
5835
+ svgs.forEach((svg) => {
5836
+ svg.removeAttribute("width");
5837
+ svg.removeAttribute("height");
5838
+ svg.style.maxWidth = "100%";
5839
+ svg.style.maxHeight = "430px";
5840
+ svg.style.height = "auto";
5841
+ svg.style.display = "block";
5842
+ svg.style.margin = "12px auto";
5843
+ });
5844
+ const imgs = el.querySelectorAll ? Array.from(el.querySelectorAll("img")) : [];
5845
+ imgs.forEach((img) => {
5846
+ img.style.maxWidth = "100%";
5847
+ img.style.maxHeight = "430px";
5848
+ img.style.height = "auto";
5849
+ img.style.objectFit = "contain";
5850
+ img.style.display = "block";
5851
+ img.style.margin = "12px auto";
5852
+ });
5853
+ });
5854
+ const allImgs = Array.from(document.querySelectorAll("img")).concat(
5855
+ elements.flatMap((el) => Array.from(el.querySelectorAll ? el.querySelectorAll("img") : []))
5856
+ );
5857
+ await Promise.all(allImgs.map((img) => {
5858
+ if (img.complete && img.naturalHeight > 0) return Promise.resolve();
5859
+ if (img.decode) return img.decode().catch(() => {
5860
+ });
5861
+ return new Promise((r) => {
5862
+ img.onload = r;
5863
+ img.onerror = r;
5864
+ });
5865
+ }));
5866
+ elements.forEach((el) => {
5867
+ const text = el.textContent || "";
5868
+ if (text.includes("\uF0B7")) {
5869
+ const cleanText = text.replace(/^[\s\uf0b7\t]+/, "");
5870
+ el.style.display = "flex";
5871
+ el.style.alignItems = "flex-start";
5872
+ el.style.margin = "6px 0 6px 28px";
5873
+ el.style.fontSize = "11pt";
5874
+ el.style.lineHeight = "1.5";
5875
+ el.innerHTML = `<span style="margin-right:10px; user-select:none;">&#9633;</span><span>${cleanText}</span>`;
5664
5876
  }
5665
- if (!inserted) {
5666
- if (contentNodes.length > 2) {
5667
- contentNodes.splice(2, 0, tableEl);
5668
- } else {
5669
- contentNodes.push(tableEl);
5670
- }
5877
+ });
5878
+ elements.forEach((el) => {
5879
+ const text = (el.textContent || "").trim();
5880
+ const hasMedia = el.querySelector("img, svg, canvas, table") !== null || ["IMG", "SVG", "TABLE"].includes(el.tagName);
5881
+ if (isHeadingElement(el)) {
5882
+ el.style.marginTop = "20px";
5883
+ el.style.marginBottom = "10px";
5884
+ el.style.lineHeight = "1.25";
5885
+ } else if (text.length > 0 && !hasMedia) {
5886
+ el.style.marginBottom = "12px";
5887
+ el.style.lineHeight = "1.45";
5671
5888
  }
5672
5889
  });
5673
- const createRtfCard = (pageNum) => {
5890
+ const measureCard = document.createElement("div");
5891
+ measureCard.style.width = `${pageWidth}px`;
5892
+ measureCard.style.padding = `${padTop}px ${padRight}px ${padBottom}px ${padLeft}px`;
5893
+ measureCard.style.boxSizing = "border-box";
5894
+ measureCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
5895
+ measureCard.style.lineHeight = "1.45";
5896
+ measureCard.style.visibility = "hidden";
5897
+ measureCard.style.position = "absolute";
5898
+ measureCard.style.top = "-99999px";
5899
+ document.body.appendChild(measureCard);
5900
+ const createPageCard = (num) => {
5674
5901
  const card = document.createElement("div");
5675
5902
  card.className = "fp-rtf-page-card";
5676
- card.setAttribute("data-page-number", String(pageNum));
5903
+ card.setAttribute("data-page-number", String(num));
5677
5904
  card.style.backgroundColor = "#ffffff";
5678
5905
  card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08), 0 1px 3px rgba(0,0,0,0.04)";
5679
5906
  card.style.borderRadius = "4px";
5680
- card.style.padding = "64px 56px";
5681
- card.style.width = "816px";
5682
- card.style.minHeight = "1056px";
5683
- card.style.maxHeight = "1056px";
5684
- card.style.overflow = "hidden";
5907
+ card.style.width = `${pageWidth}px`;
5908
+ card.style.height = `${pageHeight}px`;
5909
+ card.style.padding = `${padTop}px ${padRight}px ${padBottom}px ${padLeft}px`;
5685
5910
  card.style.boxSizing = "border-box";
5911
+ card.style.overflow = "hidden";
5686
5912
  card.style.marginBottom = "24px";
5687
- card.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
5688
- card.style.lineHeight = "1.6";
5689
5913
  card.style.color = "#1e293b";
5914
+ card.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
5915
+ card.style.lineHeight = "1.45";
5690
5916
  card.style.position = "relative";
5917
+ card.style.textAlign = "left";
5691
5918
  return card;
5692
5919
  };
5693
- wrapper.innerHTML = "";
5694
- const measureCard = createRtfCard(0);
5695
- measureCard.style.maxHeight = "none";
5696
- measureCard.style.height = "auto";
5697
- wrapper.appendChild(measureCard);
5698
- contentNodes.forEach((node) => measureCard.appendChild(node));
5699
- const childHeights = contentNodes.map((c) => {
5700
- const rect = c.getBoundingClientRect ? c.getBoundingClientRect() : null;
5701
- const rectH = rect ? rect.height : 0;
5702
- const offH = c.offsetHeight || 0;
5703
- let realH = Math.max(rectH, offH);
5704
- try {
5705
- const cs = window.getComputedStyle(c);
5706
- realH += (parseFloat(cs.marginTop) || 0) + (parseFloat(cs.marginBottom) || 0);
5707
- } catch {
5708
- }
5709
- const hasMedia = c.querySelector("img, svg") !== null || ["img", "svg"].includes(c.tagName.toLowerCase());
5710
- const hasTable = c.querySelector("table") !== null || c.tagName.toLowerCase() === "table";
5711
- if (hasMedia) {
5712
- realH = Math.max(realH, 300);
5713
- } else if (hasTable) {
5714
- realH = Math.max(realH, 240);
5715
- }
5716
- if (realH > 0) return realH;
5717
- const textLen = c.textContent?.trim().length || 0;
5718
- return Math.max(28, Math.ceil(textLen / 75) * 26 + 16);
5719
- });
5720
- wrapper.innerHTML = "";
5721
- let curCard = createRtfCard(1);
5722
- wrapper.appendChild(curCard);
5723
- pageElements = [curCard];
5724
- let curH = 0;
5725
- const maxH = 860;
5726
- for (let i = 0; i < contentNodes.length; i++) {
5727
- const child = contentNodes[i];
5728
- const chH = childHeights[i];
5729
- const isChildEmpty = (child.textContent || "").trim().length === 0 && !child.querySelector("table, img, svg, canvas");
5730
- if (curH === 0 && isChildEmpty) {
5920
+ const pages = [];
5921
+ let curCard = createPageCard(1);
5922
+ pages.push(curCard);
5923
+ let curHeight = 0;
5924
+ for (let i = 0; i < elements.length; i++) {
5925
+ const el = elements[i];
5926
+ if (!el || !(el instanceof HTMLElement)) continue;
5927
+ const text = (el.textContent || "").trim();
5928
+ const hasMedia = el.querySelector("img, svg, canvas, table") !== null || ["IMG", "SVG", "TABLE"].includes(el.tagName);
5929
+ const isEmptyPar = !hasMedia && text.length === 0;
5930
+ if (isEmptyPar) {
5931
+ const emptyH = 35;
5932
+ if (curHeight + emptyH > printableHeight) {
5933
+ if (curCard.childNodes.length > 0) {
5934
+ curCard = createPageCard(pages.length + 1);
5935
+ pages.push(curCard);
5936
+ curHeight = 0;
5937
+ }
5938
+ }
5939
+ const spacer = document.createElement("div");
5940
+ spacer.style.height = `${emptyH}px`;
5941
+ curCard.appendChild(spacer);
5942
+ curHeight += emptyH;
5731
5943
  continue;
5732
5944
  }
5733
- const isTable = child.querySelector("table") !== null || child.tagName.toLowerCase() === "table";
5734
- const shouldBreakBeforeTable = isTable && curH > 400 && curCard.childNodes.length > 0;
5735
- if ((curH + chH > maxH || shouldBreakBeforeTable) && curCard.childNodes.length > 0) {
5736
- curCard = createRtfCard(pageElements.length + 1);
5737
- wrapper.appendChild(curCard);
5738
- pageElements.push(curCard);
5739
- curH = 0;
5945
+ measureCard.innerHTML = "";
5946
+ const clone = el.cloneNode(true);
5947
+ measureCard.appendChild(clone);
5948
+ const compStyle = window.getComputedStyle(clone);
5949
+ const mt = parseFloat(compStyle.marginTop) || 0;
5950
+ const mb = parseFloat(compStyle.marginBottom) || 0;
5951
+ const elH = clone.offsetHeight + mt + mb;
5952
+ const isHeading = isHeadingElement(el);
5953
+ let nextContentH = 0;
5954
+ if (isHeading || hasMedia) {
5955
+ for (let j = i + 1; j < elements.length; j++) {
5956
+ const nextEl = elements[j];
5957
+ if (nextEl && (nextEl.textContent || "").trim().length > 0) {
5958
+ measureCard.innerHTML = "";
5959
+ const nClone = nextEl.cloneNode(true);
5960
+ measureCard.appendChild(nClone);
5961
+ const nStyle = window.getComputedStyle(nClone);
5962
+ nextContentH = nClone.offsetHeight + (parseFloat(nStyle.marginTop) || 0) + (parseFloat(nStyle.marginBottom) || 0);
5963
+ break;
5964
+ }
5965
+ }
5740
5966
  }
5741
- curCard.appendChild(child);
5742
- curH += chH;
5743
- }
5744
- pageElements = pageElements.filter((card) => {
5967
+ const remainingSpace = printableHeight - curHeight;
5968
+ const isLargeMedia = hasMedia && elH > 300;
5969
+ const keepWithNextOverflow = isHeading && nextContentH > 0 && elH + nextContentH + 20 > remainingSpace;
5970
+ const largeMediaOverflow = isLargeMedia && curHeight > 0 && elH + 80 > remainingSpace;
5971
+ const shouldBreak = (curHeight + elH > printableHeight || keepWithNextOverflow || largeMediaOverflow) && curCard.childNodes.length > 0;
5972
+ if (shouldBreak) {
5973
+ curCard = createPageCard(pages.length + 1);
5974
+ pages.push(curCard);
5975
+ curHeight = 0;
5976
+ }
5977
+ curCard.appendChild(el);
5978
+ curHeight += elH;
5979
+ }
5980
+ measureCard.remove();
5981
+ pageElements = pages.filter((card) => {
5745
5982
  const hasText = (card.textContent || "").trim().length > 0;
5746
- const hasMedia = card.querySelector("table, img, svg, canvas") !== null;
5747
- return hasText || hasMedia;
5983
+ const hasCardMedia = card.querySelector("table, img, svg, canvas") !== null;
5984
+ return hasText || hasCardMedia;
5748
5985
  });
5749
5986
  if (pageElements.length === 0) {
5750
5987
  pageElements = [curCard];
5751
5988
  }
5989
+ wrapper.innerHTML = "";
5990
+ pageElements.forEach((card, idx) => {
5991
+ card.setAttribute("data-page-number", String(idx + 1));
5992
+ card.style.display = idx === 0 ? "block" : "none";
5993
+ wrapper.appendChild(card);
5994
+ });
5752
5995
  } catch (err) {
5753
5996
  console.warn("[RtfPlugin] RTF render error, fallback text:", err);
5754
- const text = new TextDecoder("latin1").decode(ctx.buffer);
5755
- const tables = parseRtfTables(text);
5997
+ const text = rawRtf;
5756
5998
  const rawPages = text.split(/\\page\b/).map((segment) => {
5757
5999
  return segment.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim();
5758
- }).filter((p) => p.length > 0);
6000
+ }).filter((p2) => p2.length > 0);
5759
6001
  const pages = rawPages.length > 0 ? rawPages : [text.replace(/\\par[d]?/g, "\n").replace(/\\[a-zA-Z0-9\-]+/g, "").replace(/[{}]/g, "").trim()];
5760
6002
  for (let i = 0; i < pages.length; i++) {
5761
6003
  const pageCard = document.createElement("div");
@@ -5763,9 +6005,9 @@ var RtfPlugin = class {
5763
6005
  pageCard.style.backgroundColor = "#ffffff";
5764
6006
  pageCard.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)";
5765
6007
  pageCard.style.borderRadius = "4px";
5766
- pageCard.style.padding = "64px 56px";
5767
- pageCard.style.width = "816px";
5768
- pageCard.style.minHeight = "1056px";
6008
+ pageCard.style.padding = `${padTop}px ${padRight}px ${padBottom}px ${padLeft}px`;
6009
+ pageCard.style.width = `${pageWidth}px`;
6010
+ pageCard.style.minHeight = `${pageHeight}px`;
5769
6011
  pageCard.style.boxSizing = "border-box";
5770
6012
  pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
5771
6013
  pageCard.style.fontSize = "12pt";
@@ -5785,11 +6027,9 @@ var RtfPlugin = class {
5785
6027
  let currentPage = 1;
5786
6028
  const showPage = (pageNum) => {
5787
6029
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
5788
- if (totalPages > 1) {
5789
- pageElements.forEach((el, idx) => {
5790
- el.style.display = idx + 1 === currentPage ? "block" : "none";
5791
- });
5792
- }
6030
+ pageElements.forEach((el, idx) => {
6031
+ el.style.display = idx + 1 === currentPage ? "block" : "none";
6032
+ });
5793
6033
  ctx.container.scrollTop = 0;
5794
6034
  ctx.emit("page-change", { page: currentPage, total: totalPages });
5795
6035
  };
@@ -5856,6 +6096,15 @@ var RtfPlugin = class {
5856
6096
  rotation = 0;
5857
6097
  applyTransform();
5858
6098
  },
6099
+ resetZoom: () => {
6100
+ isUserZoomed = false;
6101
+ fitMode = "width";
6102
+ scale = calculateFitScale("width");
6103
+ rotation = 0;
6104
+ ctx.container.scrollTop = 0;
6105
+ ctx.container.scrollLeft = 0;
6106
+ applyTransform();
6107
+ },
5859
6108
  rotateCW: () => {
5860
6109
  rotation = (rotation + 90) % 360;
5861
6110
  applyTransform();
@@ -5923,6 +6172,14 @@ var HtmlPreviewPlugin = class {
5923
6172
  group: "zoom",
5924
6173
  execute: () => instance.fitToPage?.()
5925
6174
  },
6175
+ {
6176
+ id: "reset-zoom",
6177
+ icon: "reset-zoom",
6178
+ label: "Reset Zoom",
6179
+ type: "button",
6180
+ group: "zoom",
6181
+ execute: () => instance.resetZoom?.()
6182
+ },
5926
6183
  {
5927
6184
  id: "copy",
5928
6185
  icon: "copy",
@@ -5995,6 +6252,12 @@ var HtmlPreviewPlugin = class {
5995
6252
  scale = 1;
5996
6253
  iframe.style.transform = "scale(1)";
5997
6254
  },
6255
+ resetZoom: () => {
6256
+ scale = 1;
6257
+ iframe.style.transform = "scale(1)";
6258
+ ctx.container.scrollTop = 0;
6259
+ ctx.container.scrollLeft = 0;
6260
+ },
5998
6261
  copy: () => {
5999
6262
  navigator.clipboard.writeText(rawHtml);
6000
6263
  },
@@ -6095,6 +6358,14 @@ var OpenDocumentPlugin = class {
6095
6358
  group: "zoom",
6096
6359
  execute: () => instance.fitToPage?.()
6097
6360
  },
6361
+ {
6362
+ id: "reset-zoom",
6363
+ icon: "reset-zoom",
6364
+ label: "Reset Zoom",
6365
+ type: "button",
6366
+ group: "zoom",
6367
+ execute: () => instance.resetZoom?.()
6368
+ },
6098
6369
  {
6099
6370
  id: "rotate-cw",
6100
6371
  icon: "rotate-cw",
@@ -6362,6 +6633,15 @@ var OpenDocumentPlugin = class {
6362
6633
  rotation = 0;
6363
6634
  applyTransform();
6364
6635
  },
6636
+ resetZoom: () => {
6637
+ isUserZoomed = false;
6638
+ fitMode = "width";
6639
+ scale = calculateFitScale("width");
6640
+ rotation = 0;
6641
+ container.scrollTop = 0;
6642
+ container.scrollLeft = 0;
6643
+ applyTransform();
6644
+ },
6365
6645
  rotateCW: () => {
6366
6646
  rotation = (rotation + 90) % 360;
6367
6647
  applyTransform();
@@ -6705,6 +6985,14 @@ var DocPlugin = class {
6705
6985
  group: "zoom",
6706
6986
  execute: () => instance.fitToPage?.()
6707
6987
  },
6988
+ {
6989
+ id: "reset-zoom",
6990
+ icon: "reset-zoom",
6991
+ label: "Reset Zoom",
6992
+ type: "button",
6993
+ group: "zoom",
6994
+ execute: () => instance.resetZoom?.()
6995
+ },
6708
6996
  {
6709
6997
  id: "rotate-cw",
6710
6998
  icon: "rotate-cw",
@@ -6911,6 +7199,15 @@ var DocPlugin = class {
6911
7199
  rotation = 0;
6912
7200
  applyTransform();
6913
7201
  },
7202
+ resetZoom: () => {
7203
+ isUserZoomed = false;
7204
+ fitMode = "width";
7205
+ scale = calculateFitScale("width");
7206
+ rotation = 0;
7207
+ ctx.container.scrollTop = 0;
7208
+ ctx.container.scrollLeft = 0;
7209
+ applyTransform();
7210
+ },
6914
7211
  rotateCW: () => {
6915
7212
  rotation = (rotation + 90) % 360;
6916
7213
  applyTransform();
@@ -7391,6 +7688,14 @@ var PptPlugin = class {
7391
7688
  group: "zoom",
7392
7689
  execute: () => instance.fitToPage?.()
7393
7690
  },
7691
+ {
7692
+ id: "reset-zoom",
7693
+ icon: "reset-zoom",
7694
+ label: "Reset Zoom",
7695
+ type: "button",
7696
+ group: "zoom",
7697
+ execute: () => instance.resetZoom?.()
7698
+ },
7394
7699
  {
7395
7700
  id: "rotate-cw",
7396
7701
  icon: "rotate-cw",
@@ -7579,6 +7884,13 @@ var PptPlugin = class {
7579
7884
  rotation = 0;
7580
7885
  applyTransform();
7581
7886
  },
7887
+ resetZoom: () => {
7888
+ scale = calculateFitScale();
7889
+ rotation = 0;
7890
+ container.scrollTop = 0;
7891
+ container.scrollLeft = 0;
7892
+ applyTransform();
7893
+ },
7582
7894
  rotateCW: () => {
7583
7895
  rotation = (rotation + 90) % 360;
7584
7896
  applyTransform();