@files-preview-app/preview-file 1.2.0 → 1.2.2

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
@@ -3,11 +3,11 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var react = require('react');
6
- var DOMPurify5 = require('dompurify');
6
+ var DOMPurify6 = require('dompurify');
7
7
  var docx = require('docx-preview');
8
+ var fflate = require('fflate');
8
9
  var XLSX = require('xlsx');
9
10
  var hljs = require('highlight.js');
10
- var fflate = require('fflate');
11
11
  var marked = require('marked');
12
12
  var pptxBrowser = require('pptx-browser');
13
13
  var THREE = require('three');
@@ -37,7 +37,7 @@ function _interopNamespace(e) {
37
37
  return Object.freeze(n);
38
38
  }
39
39
 
40
- var DOMPurify5__default = /*#__PURE__*/_interopDefault(DOMPurify5);
40
+ var DOMPurify6__default = /*#__PURE__*/_interopDefault(DOMPurify6);
41
41
  var docx__namespace = /*#__PURE__*/_interopNamespace(docx);
42
42
  var XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
43
43
  var hljs__default = /*#__PURE__*/_interopDefault(hljs);
@@ -371,7 +371,7 @@ async function sourceToArrayBuffer(source, signal) {
371
371
  return { buffer, metadata };
372
372
  }
373
373
  function sanitizeSVG(svg) {
374
- return DOMPurify5__default.default.sanitize(svg, {
374
+ return DOMPurify6__default.default.sanitize(svg, {
375
375
  USE_PROFILES: { svg: true, svgFilters: true }
376
376
  });
377
377
  }
@@ -447,7 +447,11 @@ var ICON_MAP = {
447
447
  "close": ICON_CLOSE,
448
448
  "copy": ICON_COPY,
449
449
  "prev": ICON_PAGE_PREV,
450
- "next": ICON_PAGE_NEXT
450
+ "next": ICON_PAGE_NEXT,
451
+ "page-prev": ICON_PAGE_PREV,
452
+ "page-next": ICON_PAGE_NEXT,
453
+ "chevron-left": ICON_PAGE_PREV,
454
+ "chevron-right": ICON_PAGE_NEXT
451
455
  };
452
456
  var ToolbarController = class {
453
457
  el;
@@ -479,7 +483,9 @@ var ToolbarController = class {
479
483
  view: [],
480
484
  actions: []
481
485
  };
482
- for (const action of this.actions) {
486
+ const hasPageNav = this.actions.some((a) => a.type === "page-nav");
487
+ const effectiveActions = hasPageNav ? this.actions.filter((a) => a.id !== "page-prev" && a.id !== "page-next" && a.id !== "prev" && a.id !== "next") : this.actions;
488
+ for (const action of effectiveActions) {
483
489
  if (groups[action.group]) {
484
490
  groups[action.group].push(action);
485
491
  }
@@ -502,13 +508,26 @@ var ToolbarController = class {
502
508
  "prev",
503
509
  ICON_PAGE_PREV,
504
510
  "Previous Page",
505
- () => action.execute("prev")
511
+ () => {
512
+ const cur = parseInt(input.value, 10) || 1;
513
+ if (cur > 1) {
514
+ input.value = (cur - 1).toString();
515
+ action.execute("prev", cur - 1);
516
+ }
517
+ }
506
518
  );
507
519
  const nextBtn = this.createButton(
508
520
  "next",
509
521
  ICON_PAGE_NEXT,
510
522
  "Next Page",
511
- () => action.execute("next")
523
+ () => {
524
+ const cur = parseInt(input.value, 10) || 1;
525
+ const max = action.max ?? 1;
526
+ if (cur < max) {
527
+ input.value = (cur + 1).toString();
528
+ action.execute("next", cur + 1);
529
+ }
530
+ }
512
531
  );
513
532
  const input = createElement("input", {
514
533
  className: "fp-toolbar-input",
@@ -518,7 +537,10 @@ var ToolbarController = class {
518
537
  max: (action.max ?? 1).toString()
519
538
  });
520
539
  input.addEventListener("change", () => {
521
- action.execute("go", parseInt(input.value, 10));
540
+ const val = parseInt(input.value, 10);
541
+ if (!isNaN(val)) {
542
+ action.execute("go", val);
543
+ }
522
544
  });
523
545
  const label = createElement("span", { className: "fp-toolbar-label" }, ` / ${action.max ?? 1}`);
524
546
  groupEl.appendChild(prevBtn);
@@ -559,11 +581,11 @@ var ToolbarController = class {
559
581
  type: "button",
560
582
  "data-action-id": id
561
583
  });
562
- const svg = ICON_MAP[iconHtml] || iconHtml;
563
- if (svg && svg.startsWith("<svg")) {
584
+ const svg = ICON_MAP[iconHtml] || ICON_MAP[id] || (iconHtml && iconHtml.startsWith("<svg") ? iconHtml : null);
585
+ if (svg) {
564
586
  btn.innerHTML = sanitizeSVG(svg);
565
587
  } else {
566
- btn.textContent = svg || title;
588
+ btn.textContent = title || id;
567
589
  }
568
590
  btn.addEventListener("click", onClick);
569
591
  return btn;
@@ -1306,12 +1328,12 @@ function pdfPlugin() {
1306
1328
  }
1307
1329
 
1308
1330
  // ../plugins/media/dist/index.js
1309
- var IMAGE_EXTS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"];
1310
- var VIDEO_EXTS = [".mp4", ".webm", ".ogg"];
1311
- var AUDIO_EXTS = [".mp3", ".wav", ".ogg"];
1331
+ var IMAGE_EXTS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg", ".bmp", ".ico", ".tiff", ".tif", ".avif"];
1332
+ var VIDEO_EXTS = [".mp4", ".m4v", ".webm", ".ogv", ".ogg", ".mov", ".avi", ".mkv", ".flv", ".wmv", ".3gp", ".mpg", ".mpeg"];
1333
+ var AUDIO_EXTS = [".mp3", ".wav", ".ogg", ".flac", ".aac", ".m4a", ".wma", ".opus", ".weba"];
1312
1334
  var MediaPlugin = class {
1313
1335
  id = "media";
1314
- name = "Media Preview";
1336
+ name = "Media Preview (Image, Video, Audio)";
1315
1337
  extensions = [...IMAGE_EXTS, ...VIDEO_EXTS, ...AUDIO_EXTS];
1316
1338
  mimeTypes = [
1317
1339
  "image/jpeg",
@@ -1319,12 +1341,29 @@ var MediaPlugin = class {
1319
1341
  "image/gif",
1320
1342
  "image/webp",
1321
1343
  "image/svg+xml",
1344
+ "image/bmp",
1345
+ "image/x-icon",
1346
+ "image/tiff",
1347
+ "image/avif",
1322
1348
  "video/mp4",
1323
1349
  "video/webm",
1324
1350
  "video/ogg",
1351
+ "video/quicktime",
1352
+ "video/x-msvideo",
1353
+ "video/x-matroska",
1354
+ "video/x-flv",
1355
+ "video/x-ms-wmv",
1356
+ "video/3gpp",
1357
+ "video/mpeg",
1325
1358
  "audio/mpeg",
1326
1359
  "audio/wav",
1327
- "audio/ogg"
1360
+ "audio/ogg",
1361
+ "audio/flac",
1362
+ "audio/aac",
1363
+ "audio/mp4",
1364
+ "audio/x-ms-wma",
1365
+ "audio/opus",
1366
+ "audio/webm"
1328
1367
  ];
1329
1368
  weight = 90;
1330
1369
  supports(file) {
@@ -1457,8 +1496,12 @@ var MediaPlugin = class {
1457
1496
  const video = document.createElement("video");
1458
1497
  video.src = url;
1459
1498
  video.controls = true;
1460
- video.style.maxWidth = "100%";
1461
- video.style.maxHeight = "100%";
1499
+ video.playsInline = true;
1500
+ video.style.maxWidth = "90%";
1501
+ video.style.maxHeight = "90%";
1502
+ video.style.borderRadius = "8px";
1503
+ video.style.boxShadow = "0 8px 30px rgba(0,0,0,0.3)";
1504
+ video.style.backgroundColor = "#000000";
1462
1505
  element = video;
1463
1506
  mediaElement = video;
1464
1507
  } else if (isAudio) {
@@ -1534,7 +1577,7 @@ function mediaPlugin() {
1534
1577
  }
1535
1578
  var DocxPlugin = class {
1536
1579
  id = "docx";
1537
- name = "Word Document Preview";
1580
+ name = "Word Document Preview (.docx, .docm, .dotx, .dotm)";
1538
1581
  extensions = [".docx", ".docm", ".dotx", ".dotm"];
1539
1582
  mimeTypes = [
1540
1583
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
@@ -1556,9 +1599,7 @@ var DocxPlugin = class {
1556
1599
  label: "Zoom Out",
1557
1600
  type: "button",
1558
1601
  group: "zoom",
1559
- execute: () => {
1560
- instance.zoomOut?.();
1561
- }
1602
+ execute: () => instance.zoomOut?.()
1562
1603
  },
1563
1604
  {
1564
1605
  id: "zoom-in",
@@ -1566,9 +1607,7 @@ var DocxPlugin = class {
1566
1607
  label: "Zoom In",
1567
1608
  type: "button",
1568
1609
  group: "zoom",
1569
- execute: () => {
1570
- instance.zoomIn?.();
1571
- }
1610
+ execute: () => instance.zoomIn?.()
1572
1611
  },
1573
1612
  {
1574
1613
  id: "fit-page",
@@ -1576,9 +1615,7 @@ var DocxPlugin = class {
1576
1615
  label: "Fit to Page",
1577
1616
  type: "button",
1578
1617
  group: "zoom",
1579
- execute: () => {
1580
- instance.fitToPage?.();
1581
- }
1618
+ execute: () => instance.fitToPage?.()
1582
1619
  },
1583
1620
  {
1584
1621
  id: "download",
@@ -1586,9 +1623,7 @@ var DocxPlugin = class {
1586
1623
  label: "Download",
1587
1624
  type: "button",
1588
1625
  group: "actions",
1589
- execute: () => {
1590
- instance.download?.();
1591
- }
1626
+ execute: () => instance.download?.()
1592
1627
  },
1593
1628
  {
1594
1629
  id: "print",
@@ -1596,9 +1631,7 @@ var DocxPlugin = class {
1596
1631
  label: "Print",
1597
1632
  type: "button",
1598
1633
  group: "actions",
1599
- execute: () => {
1600
- instance.print?.();
1601
- }
1634
+ execute: () => instance.print?.()
1602
1635
  }
1603
1636
  ];
1604
1637
  }
@@ -1607,24 +1640,46 @@ var DocxPlugin = class {
1607
1640
  wrapper.className = "fp-docx-wrapper";
1608
1641
  wrapper.style.transformOrigin = "top center";
1609
1642
  wrapper.style.transition = "transform 0.2s ease";
1610
- wrapper.style.padding = "16px";
1643
+ wrapper.style.padding = "24px 16px";
1644
+ wrapper.style.maxWidth = "900px";
1645
+ wrapper.style.margin = "0 auto";
1646
+ wrapper.style.boxSizing = "border-box";
1611
1647
  ctx.container.style.overflow = "auto";
1648
+ ctx.container.style.backgroundColor = "#f1f5f9";
1612
1649
  ctx.container.appendChild(wrapper);
1613
1650
  let scale = 1;
1651
+ let renderedSuccessfully = false;
1614
1652
  try {
1615
1653
  await docx__namespace.renderAsync(ctx.buffer, wrapper, ctx.container, {
1616
1654
  inWrapper: true,
1617
1655
  ignoreWidth: false,
1618
- ignoreHeight: false
1656
+ ignoreHeight: false,
1657
+ ignoreFonts: true,
1658
+ // Avoid crashes on embedded obfuscated fonts
1659
+ breakPages: true,
1660
+ experimental: true
1619
1661
  });
1620
- } catch {
1621
- wrapper.innerHTML = `
1622
- <div style="text-align:center; padding: 40px; color: #666;">
1623
- <div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
1624
- <h3>${ctx.metadata.name || "Word Document"}</h3>
1625
- <p>DOCX render preview</p>
1626
- </div>
1627
- `;
1662
+ if (wrapper.children.length > 0 && (wrapper.textContent?.trim().length ?? 0) > 0) {
1663
+ renderedSuccessfully = true;
1664
+ }
1665
+ } catch (err) {
1666
+ console.warn("[DocxPlugin] docx-preview failed, triggering native XML fallback:", err);
1667
+ }
1668
+ if (!renderedSuccessfully) {
1669
+ try {
1670
+ wrapper.innerHTML = "";
1671
+ this.renderXmlFallback(ctx, wrapper);
1672
+ renderedSuccessfully = true;
1673
+ } catch (fallbackErr) {
1674
+ console.error("[DocxPlugin] XML fallback failed:", fallbackErr);
1675
+ wrapper.innerHTML = `
1676
+ <div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
1677
+ <div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
1678
+ <h3 style="margin: 0 0 8px; color: #1e293b;">${ctx.metadata.name || "Word Document"}</h3>
1679
+ <p style="color: #64748b; margin: 0;">Could not parse document content</p>
1680
+ </div>
1681
+ `;
1682
+ }
1628
1683
  }
1629
1684
  const cleanup = () => {
1630
1685
  wrapper.remove();
@@ -1648,7 +1703,7 @@ var DocxPlugin = class {
1648
1703
  },
1649
1704
  fitToPage: () => {
1650
1705
  scale = 1;
1651
- wrapper.style.transform = `scale(1)`;
1706
+ wrapper.style.transform = "scale(1)";
1652
1707
  },
1653
1708
  download: () => {
1654
1709
  const blob = new Blob([ctx.buffer], { type: this.mimeTypes[0] });
@@ -1664,6 +1719,100 @@ var DocxPlugin = class {
1664
1719
  }
1665
1720
  };
1666
1721
  }
1722
+ renderXmlFallback(ctx, wrapper) {
1723
+ const unzipped = fflate.unzipSync(new Uint8Array(ctx.buffer));
1724
+ const docXmlEntry = unzipped["word/document.xml"];
1725
+ if (!docXmlEntry) throw new Error("Missing word/document.xml in DOCX package");
1726
+ const xmlStr = fflate.strFromU8(docXmlEntry);
1727
+ const parser = new DOMParser();
1728
+ const doc = parser.parseFromString(xmlStr, "application/xml");
1729
+ const card = document.createElement("div");
1730
+ card.className = "fp-docx-page-card";
1731
+ card.style.backgroundColor = "#ffffff";
1732
+ card.style.borderRadius = "6px";
1733
+ card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
1734
+ card.style.padding = "48px 56px";
1735
+ card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
1736
+ card.style.color = "#1e293b";
1737
+ card.style.lineHeight = "1.6";
1738
+ const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
1739
+ let html = "";
1740
+ for (const child of Array.from(body.children)) {
1741
+ const tag = child.localName || child.nodeName.split(":").pop();
1742
+ if (tag === "p") {
1743
+ const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
1744
+ const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
1745
+ const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
1746
+ const textContent = this.extractParagraphHtml(child);
1747
+ if (!textContent.trim()) {
1748
+ html += '<div style="height: 10px;"></div>';
1749
+ continue;
1750
+ }
1751
+ const lowerStyle = styleVal.toLowerCase();
1752
+ if (lowerStyle.includes("title")) {
1753
+ html += `<h1 style="font-size: 28px; font-weight: 700; color: #1e3a8a; margin: 24px 0 12px; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px;">${textContent}</h1>`;
1754
+ } else if (lowerStyle.includes("heading1") || styleVal === "1") {
1755
+ html += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
1756
+ } else if (lowerStyle.includes("heading2") || styleVal === "2") {
1757
+ html += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
1758
+ } else if (lowerStyle.includes("heading3") || styleVal === "3") {
1759
+ html += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
1760
+ } else if (numPr) {
1761
+ html += `<div style="display: flex; gap: 8px; margin: 4px 0 4px 20px;"><span style="color: #2563eb; font-weight: bold;">\u2022</span><span>${textContent}</span></div>`;
1762
+ } else {
1763
+ html += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
1764
+ }
1765
+ } else if (tag === "tbl") {
1766
+ html += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
1767
+ const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
1768
+ rows.forEach((tr, rIdx) => {
1769
+ html += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
1770
+ const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
1771
+ cells.forEach((tc) => {
1772
+ const cellText = this.extractParagraphHtml(tc);
1773
+ html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || "&nbsp;"}</td>`;
1774
+ });
1775
+ html += "</tr>";
1776
+ });
1777
+ html += "</table>";
1778
+ }
1779
+ }
1780
+ card.innerHTML = DOMPurify6__default.default.sanitize(html, {
1781
+ ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "img", "div"],
1782
+ ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
1783
+ });
1784
+ wrapper.appendChild(card);
1785
+ }
1786
+ extractParagraphHtml(pElement) {
1787
+ let result = "";
1788
+ const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
1789
+ if (runs.length === 0) {
1790
+ return DOMPurify6__default.default.sanitize(pElement.textContent || "");
1791
+ }
1792
+ for (const r of runs) {
1793
+ const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
1794
+ const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
1795
+ const isItalic = !!rPr?.getElementsByTagNameNS("*", "i")[0];
1796
+ const isUnderline = !!rPr?.getElementsByTagNameNS("*", "u")[0];
1797
+ const colorNode = rPr?.getElementsByTagNameNS("*", "color")[0];
1798
+ const colorVal = colorNode?.getAttribute("w:val") || colorNode?.getAttribute("val");
1799
+ const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
1800
+ let text = texts.map((t) => t.textContent || "").join("");
1801
+ if (!text) continue;
1802
+ text = DOMPurify6__default.default.sanitize(text);
1803
+ let styles = "";
1804
+ if (isBold) styles += "font-weight: bold; ";
1805
+ if (isItalic) styles += "font-style: italic; ";
1806
+ if (isUnderline) styles += "text-decoration: underline; ";
1807
+ if (colorVal && colorVal !== "auto") styles += `color: #${colorVal}; `;
1808
+ if (styles) {
1809
+ result += `<span style="${styles}">${text}</span>`;
1810
+ } else {
1811
+ result += text;
1812
+ }
1813
+ }
1814
+ return result;
1815
+ }
1667
1816
  };
1668
1817
  function docxPlugin() {
1669
1818
  return new DocxPlugin();
@@ -2475,7 +2624,7 @@ var MarkdownPlugin = class {
2475
2624
  gfm: true,
2476
2625
  breaks: true
2477
2626
  });
2478
- const cleanHtml = DOMPurify5__default.default.sanitize(rawHtml, {
2627
+ const cleanHtml = DOMPurify6__default.default.sanitize(rawHtml, {
2479
2628
  USE_PROFILES: { html: true }
2480
2629
  });
2481
2630
  const wrapper = document.createElement("div");
@@ -2639,35 +2788,27 @@ var PptxPlugin = class {
2639
2788
  group: "navigation",
2640
2789
  execute: () => instance.toggleThumbnails?.()
2641
2790
  },
2642
- {
2643
- id: "page-prev",
2644
- icon: "page-prev",
2645
- label: "Previous Slide",
2646
- type: "button",
2647
- group: "navigation",
2648
- execute: () => {
2649
- const cur = instance.getCurrentPage?.() ?? 1;
2650
- if (cur > 1) instance.goToPage?.(cur - 1);
2651
- }
2652
- },
2653
2791
  {
2654
2792
  id: "page-nav",
2655
2793
  icon: "",
2656
- label: "Slide Number",
2794
+ label: "Slide Navigation",
2657
2795
  type: "page-nav",
2658
2796
  group: "navigation",
2659
- execute: (page) => instance.goToPage?.(Number(page))
2660
- },
2661
- {
2662
- id: "page-next",
2663
- icon: "page-next",
2664
- label: "Next Slide",
2665
- type: "button",
2666
- group: "navigation",
2667
- execute: () => {
2668
- const cur = instance.getCurrentPage?.() ?? 1;
2669
- const total = instance.getPageCount?.() ?? 1;
2670
- if (cur < total) instance.goToPage?.(cur + 1);
2797
+ value: instance.getCurrentPage?.() ?? 1,
2798
+ max: instance.getPageCount?.() ?? 1,
2799
+ execute: (action, page) => {
2800
+ if (action === "prev") {
2801
+ const cur = instance.getCurrentPage?.() ?? 1;
2802
+ if (cur > 1) instance.goToPage?.(cur - 1);
2803
+ } else if (action === "next") {
2804
+ const cur = instance.getCurrentPage?.() ?? 1;
2805
+ const total = instance.getPageCount?.() ?? 1;
2806
+ if (cur < total) instance.goToPage?.(cur + 1);
2807
+ } else if (typeof page === "number") {
2808
+ instance.goToPage?.(page);
2809
+ } else if (typeof action === "number") {
2810
+ instance.goToPage?.(action);
2811
+ }
2671
2812
  }
2672
2813
  },
2673
2814
  {
@@ -3198,7 +3339,7 @@ var HtmlPreviewPlugin = class {
3198
3339
  }
3199
3340
  async render(ctx) {
3200
3341
  const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
3201
- const sanitized = DOMPurify5__default.default.sanitize(rawHtml, {
3342
+ const sanitized = DOMPurify6__default.default.sanitize(rawHtml, {
3202
3343
  WHOLE_DOCUMENT: true,
3203
3344
  ADD_TAGS: ["style", "link"],
3204
3345
  ADD_ATTR: ["target", "rel"]
@@ -3293,35 +3434,27 @@ var OpenDocumentPlugin = class {
3293
3434
  group: "navigation",
3294
3435
  execute: () => instance.toggleThumbnails?.()
3295
3436
  },
3296
- {
3297
- id: "page-prev",
3298
- icon: "page-prev",
3299
- label: "Previous Slide",
3300
- type: "button",
3301
- group: "navigation",
3302
- execute: () => {
3303
- const cur = instance.getCurrentPage?.() ?? 1;
3304
- if (cur > 1) instance.goToPage?.(cur - 1);
3305
- }
3306
- },
3307
3437
  {
3308
3438
  id: "page-nav",
3309
3439
  icon: "",
3310
- label: "Slide Number",
3440
+ label: "Slide Navigation",
3311
3441
  type: "page-nav",
3312
3442
  group: "navigation",
3313
- execute: (p) => instance.goToPage?.(Number(p))
3314
- },
3315
- {
3316
- id: "page-next",
3317
- icon: "page-next",
3318
- label: "Next Slide",
3319
- type: "button",
3320
- group: "navigation",
3321
- execute: () => {
3322
- const cur = instance.getCurrentPage?.() ?? 1;
3323
- const total = instance.getPageCount?.() ?? 1;
3324
- if (cur < total) instance.goToPage?.(cur + 1);
3443
+ value: instance.getCurrentPage?.() ?? 1,
3444
+ max: instance.getPageCount?.() ?? 1,
3445
+ execute: (action, page) => {
3446
+ if (action === "prev") {
3447
+ const cur = instance.getCurrentPage?.() ?? 1;
3448
+ if (cur > 1) instance.goToPage?.(cur - 1);
3449
+ } else if (action === "next") {
3450
+ const cur = instance.getCurrentPage?.() ?? 1;
3451
+ const total = instance.getPageCount?.() ?? 1;
3452
+ if (cur < total) instance.goToPage?.(cur + 1);
3453
+ } else if (typeof page === "number") {
3454
+ instance.goToPage?.(page);
3455
+ } else if (typeof action === "number") {
3456
+ instance.goToPage?.(action);
3457
+ }
3325
3458
  }
3326
3459
  }
3327
3460
  );
@@ -3449,7 +3582,7 @@ var OpenDocumentPlugin = class {
3449
3582
  wrapper.style.padding = "48px";
3450
3583
  wrapper.style.minHeight = "100%";
3451
3584
  const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
3452
- wrapper.innerHTML = DOMPurify5__default.default.sanitize(bodyHtml, {
3585
+ wrapper.innerHTML = DOMPurify6__default.default.sanitize(bodyHtml, {
3453
3586
  ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub"],
3454
3587
  ADD_ATTR: ["style", "colspan", "rowspan"]
3455
3588
  });
@@ -3969,24 +4102,24 @@ var DocPlugin = class {
3969
4102
  html += "</ul>";
3970
4103
  inList = false;
3971
4104
  }
3972
- html += `<h2 style="font-size: 18px; font-weight: 700; color: #1e3a8a; margin: 20px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify5__default.default.sanitize(line)}</h2>`;
4105
+ html += `<h2 style="font-size: 18px; font-weight: 700; color: #1e3a8a; margin: 20px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify6__default.default.sanitize(line)}</h2>`;
3973
4106
  } else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
3974
4107
  if (!inList) {
3975
4108
  html += '<ul style="margin: 8px 0; padding-left: 24px;">';
3976
4109
  inList = true;
3977
4110
  }
3978
4111
  const bulletText = line.replace(/^[•\-\*]\s*/, "");
3979
- html += `<li style="margin: 4px 0; line-height: 1.6;">${DOMPurify5__default.default.sanitize(bulletText)}</li>`;
4112
+ html += `<li style="margin: 4px 0; line-height: 1.6;">${DOMPurify6__default.default.sanitize(bulletText)}</li>`;
3980
4113
  } else {
3981
4114
  if (inList) {
3982
4115
  html += "</ul>";
3983
4116
  inList = false;
3984
4117
  }
3985
- html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${DOMPurify5__default.default.sanitize(line)}</p>`;
4118
+ html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${DOMPurify6__default.default.sanitize(line)}</p>`;
3986
4119
  }
3987
4120
  }
3988
4121
  if (inList) html += "</ul>";
3989
- return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify5__default.default.sanitize(filename)})</p>`;
4122
+ return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6__default.default.sanitize(filename)})</p>`;
3990
4123
  }
3991
4124
  };
3992
4125
  function docPlugin() {
@@ -4013,35 +4146,27 @@ var PptPlugin = class {
4013
4146
  group: "navigation",
4014
4147
  execute: () => instance.toggleThumbnails?.()
4015
4148
  },
4016
- {
4017
- id: "page-prev",
4018
- icon: "page-prev",
4019
- label: "Previous Slide",
4020
- type: "button",
4021
- group: "navigation",
4022
- execute: () => {
4023
- const cur = instance.getCurrentPage?.() ?? 1;
4024
- if (cur > 1) instance.goToPage?.(cur - 1);
4025
- }
4026
- },
4027
4149
  {
4028
4150
  id: "page-nav",
4029
4151
  icon: "",
4030
- label: "Slide Number",
4152
+ label: "Slide Navigation",
4031
4153
  type: "page-nav",
4032
4154
  group: "navigation",
4033
- execute: (p) => instance.goToPage?.(Number(p))
4034
- },
4035
- {
4036
- id: "page-next",
4037
- icon: "page-next",
4038
- label: "Next Slide",
4039
- type: "button",
4040
- group: "navigation",
4041
- execute: () => {
4042
- const cur = instance.getCurrentPage?.() ?? 1;
4043
- const total = instance.getPageCount?.() ?? 1;
4044
- if (cur < total) instance.goToPage?.(cur + 1);
4155
+ value: instance.getCurrentPage?.() ?? 1,
4156
+ max: instance.getPageCount?.() ?? 1,
4157
+ execute: (action, page) => {
4158
+ if (action === "prev") {
4159
+ const cur = instance.getCurrentPage?.() ?? 1;
4160
+ if (cur > 1) instance.goToPage?.(cur - 1);
4161
+ } else if (action === "next") {
4162
+ const cur = instance.getCurrentPage?.() ?? 1;
4163
+ const total = instance.getPageCount?.() ?? 1;
4164
+ if (cur < total) instance.goToPage?.(cur + 1);
4165
+ } else if (typeof page === "number") {
4166
+ instance.goToPage?.(page);
4167
+ } else if (typeof action === "number") {
4168
+ instance.goToPage?.(action);
4169
+ }
4045
4170
  }
4046
4171
  },
4047
4172
  {
@@ -4149,10 +4274,10 @@ var PptPlugin = class {
4149
4274
  </div>
4150
4275
  <div style="text-align: center; width: 100%;">
4151
4276
  <h1 style="font-size: ${idx === 1 ? "36px" : "28px"}; color: #1e3a8a; margin: 0 0 24px; font-family: -apple-system, BlinkMacSystemFont, sans-serif; font-weight: 700;">
4152
- ${DOMPurify5__default.default.sanitize(s.title || `Slide ${idx}`)}
4277
+ ${DOMPurify6__default.default.sanitize(s.title || `Slide ${idx}`)}
4153
4278
  </h1>
4154
4279
  <div style="display: flex; flex-direction: column; gap: 12px; max-width: 80%; margin: 0 auto; text-align: ${idx === 1 ? "center" : "left"};">
4155
- ${s.texts.map((t) => `<div style="font-size: 18px; color: #334155; line-height: 1.5; font-family: -apple-system, BlinkMacSystemFont, sans-serif;">${DOMPurify5__default.default.sanitize(t)}</div>`).join("")}
4280
+ ${s.texts.map((t) => `<div style="font-size: 18px; color: #334155; line-height: 1.5; font-family: -apple-system, BlinkMacSystemFont, sans-serif;">${DOMPurify6__default.default.sanitize(t)}</div>`).join("")}
4156
4281
  </div>
4157
4282
  </div>
4158
4283
  `;