@files-preview-app/preview-file 1.2.1 → 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/angular.cjs CHANGED
@@ -4,11 +4,11 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var core = require('@angular/core');
6
6
  var common = require('@angular/common');
7
- var DOMPurify5 = require('dompurify');
7
+ var DOMPurify6 = require('dompurify');
8
8
  var docx = require('docx-preview');
9
+ var fflate = require('fflate');
9
10
  var XLSX = require('xlsx');
10
11
  var hljs = require('highlight.js');
11
- var fflate = require('fflate');
12
12
  var marked = require('marked');
13
13
  var pptxBrowser = require('pptx-browser');
14
14
  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);
@@ -418,7 +418,7 @@ async function sourceToArrayBuffer(source, signal) {
418
418
  return { buffer, metadata };
419
419
  }
420
420
  function sanitizeSVG(svg) {
421
- return DOMPurify5__default.default.sanitize(svg, {
421
+ return DOMPurify6__default.default.sanitize(svg, {
422
422
  USE_PROFILES: { svg: true, svgFilters: true }
423
423
  });
424
424
  }
@@ -494,7 +494,11 @@ var ICON_MAP = {
494
494
  "close": ICON_CLOSE,
495
495
  "copy": ICON_COPY,
496
496
  "prev": ICON_PAGE_PREV,
497
- "next": ICON_PAGE_NEXT
497
+ "next": ICON_PAGE_NEXT,
498
+ "page-prev": ICON_PAGE_PREV,
499
+ "page-next": ICON_PAGE_NEXT,
500
+ "chevron-left": ICON_PAGE_PREV,
501
+ "chevron-right": ICON_PAGE_NEXT
498
502
  };
499
503
  var ToolbarController = class {
500
504
  el;
@@ -526,7 +530,9 @@ var ToolbarController = class {
526
530
  view: [],
527
531
  actions: []
528
532
  };
529
- for (const action of this.actions) {
533
+ const hasPageNav = this.actions.some((a) => a.type === "page-nav");
534
+ const effectiveActions = hasPageNav ? this.actions.filter((a) => a.id !== "page-prev" && a.id !== "page-next" && a.id !== "prev" && a.id !== "next") : this.actions;
535
+ for (const action of effectiveActions) {
530
536
  if (groups[action.group]) {
531
537
  groups[action.group].push(action);
532
538
  }
@@ -549,13 +555,26 @@ var ToolbarController = class {
549
555
  "prev",
550
556
  ICON_PAGE_PREV,
551
557
  "Previous Page",
552
- () => action.execute("prev")
558
+ () => {
559
+ const cur = parseInt(input.value, 10) || 1;
560
+ if (cur > 1) {
561
+ input.value = (cur - 1).toString();
562
+ action.execute("prev", cur - 1);
563
+ }
564
+ }
553
565
  );
554
566
  const nextBtn = this.createButton(
555
567
  "next",
556
568
  ICON_PAGE_NEXT,
557
569
  "Next Page",
558
- () => action.execute("next")
570
+ () => {
571
+ const cur = parseInt(input.value, 10) || 1;
572
+ const max = action.max ?? 1;
573
+ if (cur < max) {
574
+ input.value = (cur + 1).toString();
575
+ action.execute("next", cur + 1);
576
+ }
577
+ }
559
578
  );
560
579
  const input = createElement("input", {
561
580
  className: "fp-toolbar-input",
@@ -565,7 +584,10 @@ var ToolbarController = class {
565
584
  max: (action.max ?? 1).toString()
566
585
  });
567
586
  input.addEventListener("change", () => {
568
- action.execute("go", parseInt(input.value, 10));
587
+ const val = parseInt(input.value, 10);
588
+ if (!isNaN(val)) {
589
+ action.execute("go", val);
590
+ }
569
591
  });
570
592
  const label = createElement("span", { className: "fp-toolbar-label" }, ` / ${action.max ?? 1}`);
571
593
  groupEl.appendChild(prevBtn);
@@ -606,11 +628,11 @@ var ToolbarController = class {
606
628
  type: "button",
607
629
  "data-action-id": id
608
630
  });
609
- const svg = ICON_MAP[iconHtml] || iconHtml;
610
- if (svg && svg.startsWith("<svg")) {
631
+ const svg = ICON_MAP[iconHtml] || ICON_MAP[id] || (iconHtml && iconHtml.startsWith("<svg") ? iconHtml : null);
632
+ if (svg) {
611
633
  btn.innerHTML = sanitizeSVG(svg);
612
634
  } else {
613
- btn.textContent = svg || title;
635
+ btn.textContent = title || id;
614
636
  }
615
637
  btn.addEventListener("click", onClick);
616
638
  return btn;
@@ -1353,12 +1375,12 @@ function pdfPlugin() {
1353
1375
  }
1354
1376
 
1355
1377
  // ../plugins/media/dist/index.js
1356
- var IMAGE_EXTS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"];
1357
- var VIDEO_EXTS = [".mp4", ".webm", ".ogg"];
1358
- var AUDIO_EXTS = [".mp3", ".wav", ".ogg"];
1378
+ var IMAGE_EXTS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg", ".bmp", ".ico", ".tiff", ".tif", ".avif"];
1379
+ var VIDEO_EXTS = [".mp4", ".m4v", ".webm", ".ogv", ".ogg", ".mov", ".avi", ".mkv", ".flv", ".wmv", ".3gp", ".mpg", ".mpeg"];
1380
+ var AUDIO_EXTS = [".mp3", ".wav", ".ogg", ".flac", ".aac", ".m4a", ".wma", ".opus", ".weba"];
1359
1381
  var MediaPlugin = class {
1360
1382
  id = "media";
1361
- name = "Media Preview";
1383
+ name = "Media Preview (Image, Video, Audio)";
1362
1384
  extensions = [...IMAGE_EXTS, ...VIDEO_EXTS, ...AUDIO_EXTS];
1363
1385
  mimeTypes = [
1364
1386
  "image/jpeg",
@@ -1366,12 +1388,29 @@ var MediaPlugin = class {
1366
1388
  "image/gif",
1367
1389
  "image/webp",
1368
1390
  "image/svg+xml",
1391
+ "image/bmp",
1392
+ "image/x-icon",
1393
+ "image/tiff",
1394
+ "image/avif",
1369
1395
  "video/mp4",
1370
1396
  "video/webm",
1371
1397
  "video/ogg",
1398
+ "video/quicktime",
1399
+ "video/x-msvideo",
1400
+ "video/x-matroska",
1401
+ "video/x-flv",
1402
+ "video/x-ms-wmv",
1403
+ "video/3gpp",
1404
+ "video/mpeg",
1372
1405
  "audio/mpeg",
1373
1406
  "audio/wav",
1374
- "audio/ogg"
1407
+ "audio/ogg",
1408
+ "audio/flac",
1409
+ "audio/aac",
1410
+ "audio/mp4",
1411
+ "audio/x-ms-wma",
1412
+ "audio/opus",
1413
+ "audio/webm"
1375
1414
  ];
1376
1415
  weight = 90;
1377
1416
  supports(file) {
@@ -1504,8 +1543,12 @@ var MediaPlugin = class {
1504
1543
  const video = document.createElement("video");
1505
1544
  video.src = url;
1506
1545
  video.controls = true;
1507
- video.style.maxWidth = "100%";
1508
- video.style.maxHeight = "100%";
1546
+ video.playsInline = true;
1547
+ video.style.maxWidth = "90%";
1548
+ video.style.maxHeight = "90%";
1549
+ video.style.borderRadius = "8px";
1550
+ video.style.boxShadow = "0 8px 30px rgba(0,0,0,0.3)";
1551
+ video.style.backgroundColor = "#000000";
1509
1552
  element = video;
1510
1553
  mediaElement = video;
1511
1554
  } else if (isAudio) {
@@ -1581,7 +1624,7 @@ function mediaPlugin() {
1581
1624
  }
1582
1625
  var DocxPlugin = class {
1583
1626
  id = "docx";
1584
- name = "Word Document Preview";
1627
+ name = "Word Document Preview (.docx, .docm, .dotx, .dotm)";
1585
1628
  extensions = [".docx", ".docm", ".dotx", ".dotm"];
1586
1629
  mimeTypes = [
1587
1630
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
@@ -1603,9 +1646,7 @@ var DocxPlugin = class {
1603
1646
  label: "Zoom Out",
1604
1647
  type: "button",
1605
1648
  group: "zoom",
1606
- execute: () => {
1607
- instance.zoomOut?.();
1608
- }
1649
+ execute: () => instance.zoomOut?.()
1609
1650
  },
1610
1651
  {
1611
1652
  id: "zoom-in",
@@ -1613,9 +1654,7 @@ var DocxPlugin = class {
1613
1654
  label: "Zoom In",
1614
1655
  type: "button",
1615
1656
  group: "zoom",
1616
- execute: () => {
1617
- instance.zoomIn?.();
1618
- }
1657
+ execute: () => instance.zoomIn?.()
1619
1658
  },
1620
1659
  {
1621
1660
  id: "fit-page",
@@ -1623,9 +1662,7 @@ var DocxPlugin = class {
1623
1662
  label: "Fit to Page",
1624
1663
  type: "button",
1625
1664
  group: "zoom",
1626
- execute: () => {
1627
- instance.fitToPage?.();
1628
- }
1665
+ execute: () => instance.fitToPage?.()
1629
1666
  },
1630
1667
  {
1631
1668
  id: "download",
@@ -1633,9 +1670,7 @@ var DocxPlugin = class {
1633
1670
  label: "Download",
1634
1671
  type: "button",
1635
1672
  group: "actions",
1636
- execute: () => {
1637
- instance.download?.();
1638
- }
1673
+ execute: () => instance.download?.()
1639
1674
  },
1640
1675
  {
1641
1676
  id: "print",
@@ -1643,9 +1678,7 @@ var DocxPlugin = class {
1643
1678
  label: "Print",
1644
1679
  type: "button",
1645
1680
  group: "actions",
1646
- execute: () => {
1647
- instance.print?.();
1648
- }
1681
+ execute: () => instance.print?.()
1649
1682
  }
1650
1683
  ];
1651
1684
  }
@@ -1654,24 +1687,46 @@ var DocxPlugin = class {
1654
1687
  wrapper.className = "fp-docx-wrapper";
1655
1688
  wrapper.style.transformOrigin = "top center";
1656
1689
  wrapper.style.transition = "transform 0.2s ease";
1657
- wrapper.style.padding = "16px";
1690
+ wrapper.style.padding = "24px 16px";
1691
+ wrapper.style.maxWidth = "900px";
1692
+ wrapper.style.margin = "0 auto";
1693
+ wrapper.style.boxSizing = "border-box";
1658
1694
  ctx.container.style.overflow = "auto";
1695
+ ctx.container.style.backgroundColor = "#f1f5f9";
1659
1696
  ctx.container.appendChild(wrapper);
1660
1697
  let scale = 1;
1698
+ let renderedSuccessfully = false;
1661
1699
  try {
1662
1700
  await docx__namespace.renderAsync(ctx.buffer, wrapper, ctx.container, {
1663
1701
  inWrapper: true,
1664
1702
  ignoreWidth: false,
1665
- ignoreHeight: false
1703
+ ignoreHeight: false,
1704
+ ignoreFonts: true,
1705
+ // Avoid crashes on embedded obfuscated fonts
1706
+ breakPages: true,
1707
+ experimental: true
1666
1708
  });
1667
- } catch {
1668
- wrapper.innerHTML = `
1669
- <div style="text-align:center; padding: 40px; color: #666;">
1670
- <div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
1671
- <h3>${ctx.metadata.name || "Word Document"}</h3>
1672
- <p>DOCX render preview</p>
1673
- </div>
1674
- `;
1709
+ if (wrapper.children.length > 0 && (wrapper.textContent?.trim().length ?? 0) > 0) {
1710
+ renderedSuccessfully = true;
1711
+ }
1712
+ } catch (err) {
1713
+ console.warn("[DocxPlugin] docx-preview failed, triggering native XML fallback:", err);
1714
+ }
1715
+ if (!renderedSuccessfully) {
1716
+ try {
1717
+ wrapper.innerHTML = "";
1718
+ this.renderXmlFallback(ctx, wrapper);
1719
+ renderedSuccessfully = true;
1720
+ } catch (fallbackErr) {
1721
+ console.error("[DocxPlugin] XML fallback failed:", fallbackErr);
1722
+ wrapper.innerHTML = `
1723
+ <div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
1724
+ <div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
1725
+ <h3 style="margin: 0 0 8px; color: #1e293b;">${ctx.metadata.name || "Word Document"}</h3>
1726
+ <p style="color: #64748b; margin: 0;">Could not parse document content</p>
1727
+ </div>
1728
+ `;
1729
+ }
1675
1730
  }
1676
1731
  const cleanup = () => {
1677
1732
  wrapper.remove();
@@ -1695,7 +1750,7 @@ var DocxPlugin = class {
1695
1750
  },
1696
1751
  fitToPage: () => {
1697
1752
  scale = 1;
1698
- wrapper.style.transform = `scale(1)`;
1753
+ wrapper.style.transform = "scale(1)";
1699
1754
  },
1700
1755
  download: () => {
1701
1756
  const blob = new Blob([ctx.buffer], { type: this.mimeTypes[0] });
@@ -1711,6 +1766,100 @@ var DocxPlugin = class {
1711
1766
  }
1712
1767
  };
1713
1768
  }
1769
+ renderXmlFallback(ctx, wrapper) {
1770
+ const unzipped = fflate.unzipSync(new Uint8Array(ctx.buffer));
1771
+ const docXmlEntry = unzipped["word/document.xml"];
1772
+ if (!docXmlEntry) throw new Error("Missing word/document.xml in DOCX package");
1773
+ const xmlStr = fflate.strFromU8(docXmlEntry);
1774
+ const parser = new DOMParser();
1775
+ const doc = parser.parseFromString(xmlStr, "application/xml");
1776
+ const card = document.createElement("div");
1777
+ card.className = "fp-docx-page-card";
1778
+ card.style.backgroundColor = "#ffffff";
1779
+ card.style.borderRadius = "6px";
1780
+ card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
1781
+ card.style.padding = "48px 56px";
1782
+ card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
1783
+ card.style.color = "#1e293b";
1784
+ card.style.lineHeight = "1.6";
1785
+ const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
1786
+ let html = "";
1787
+ for (const child of Array.from(body.children)) {
1788
+ const tag = child.localName || child.nodeName.split(":").pop();
1789
+ if (tag === "p") {
1790
+ const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
1791
+ const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
1792
+ const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
1793
+ const textContent = this.extractParagraphHtml(child);
1794
+ if (!textContent.trim()) {
1795
+ html += '<div style="height: 10px;"></div>';
1796
+ continue;
1797
+ }
1798
+ const lowerStyle = styleVal.toLowerCase();
1799
+ if (lowerStyle.includes("title")) {
1800
+ 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>`;
1801
+ } else if (lowerStyle.includes("heading1") || styleVal === "1") {
1802
+ html += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
1803
+ } else if (lowerStyle.includes("heading2") || styleVal === "2") {
1804
+ html += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
1805
+ } else if (lowerStyle.includes("heading3") || styleVal === "3") {
1806
+ html += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
1807
+ } else if (numPr) {
1808
+ 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>`;
1809
+ } else {
1810
+ html += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
1811
+ }
1812
+ } else if (tag === "tbl") {
1813
+ html += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
1814
+ const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
1815
+ rows.forEach((tr, rIdx) => {
1816
+ html += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
1817
+ const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
1818
+ cells.forEach((tc) => {
1819
+ const cellText = this.extractParagraphHtml(tc);
1820
+ html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || "&nbsp;"}</td>`;
1821
+ });
1822
+ html += "</tr>";
1823
+ });
1824
+ html += "</table>";
1825
+ }
1826
+ }
1827
+ card.innerHTML = DOMPurify6__default.default.sanitize(html, {
1828
+ ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "img", "div"],
1829
+ ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
1830
+ });
1831
+ wrapper.appendChild(card);
1832
+ }
1833
+ extractParagraphHtml(pElement) {
1834
+ let result = "";
1835
+ const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
1836
+ if (runs.length === 0) {
1837
+ return DOMPurify6__default.default.sanitize(pElement.textContent || "");
1838
+ }
1839
+ for (const r of runs) {
1840
+ const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
1841
+ const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
1842
+ const isItalic = !!rPr?.getElementsByTagNameNS("*", "i")[0];
1843
+ const isUnderline = !!rPr?.getElementsByTagNameNS("*", "u")[0];
1844
+ const colorNode = rPr?.getElementsByTagNameNS("*", "color")[0];
1845
+ const colorVal = colorNode?.getAttribute("w:val") || colorNode?.getAttribute("val");
1846
+ const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
1847
+ let text = texts.map((t) => t.textContent || "").join("");
1848
+ if (!text) continue;
1849
+ text = DOMPurify6__default.default.sanitize(text);
1850
+ let styles = "";
1851
+ if (isBold) styles += "font-weight: bold; ";
1852
+ if (isItalic) styles += "font-style: italic; ";
1853
+ if (isUnderline) styles += "text-decoration: underline; ";
1854
+ if (colorVal && colorVal !== "auto") styles += `color: #${colorVal}; `;
1855
+ if (styles) {
1856
+ result += `<span style="${styles}">${text}</span>`;
1857
+ } else {
1858
+ result += text;
1859
+ }
1860
+ }
1861
+ return result;
1862
+ }
1714
1863
  };
1715
1864
  function docxPlugin() {
1716
1865
  return new DocxPlugin();
@@ -2522,7 +2671,7 @@ var MarkdownPlugin = class {
2522
2671
  gfm: true,
2523
2672
  breaks: true
2524
2673
  });
2525
- const cleanHtml = DOMPurify5__default.default.sanitize(rawHtml, {
2674
+ const cleanHtml = DOMPurify6__default.default.sanitize(rawHtml, {
2526
2675
  USE_PROFILES: { html: true }
2527
2676
  });
2528
2677
  const wrapper = document.createElement("div");
@@ -2686,35 +2835,27 @@ var PptxPlugin = class {
2686
2835
  group: "navigation",
2687
2836
  execute: () => instance.toggleThumbnails?.()
2688
2837
  },
2689
- {
2690
- id: "page-prev",
2691
- icon: "page-prev",
2692
- label: "Previous Slide",
2693
- type: "button",
2694
- group: "navigation",
2695
- execute: () => {
2696
- const cur = instance.getCurrentPage?.() ?? 1;
2697
- if (cur > 1) instance.goToPage?.(cur - 1);
2698
- }
2699
- },
2700
2838
  {
2701
2839
  id: "page-nav",
2702
2840
  icon: "",
2703
- label: "Slide Number",
2841
+ label: "Slide Navigation",
2704
2842
  type: "page-nav",
2705
2843
  group: "navigation",
2706
- execute: (page) => instance.goToPage?.(Number(page))
2707
- },
2708
- {
2709
- id: "page-next",
2710
- icon: "page-next",
2711
- label: "Next Slide",
2712
- type: "button",
2713
- group: "navigation",
2714
- execute: () => {
2715
- const cur = instance.getCurrentPage?.() ?? 1;
2716
- const total = instance.getPageCount?.() ?? 1;
2717
- if (cur < total) instance.goToPage?.(cur + 1);
2844
+ value: instance.getCurrentPage?.() ?? 1,
2845
+ max: instance.getPageCount?.() ?? 1,
2846
+ execute: (action, page) => {
2847
+ if (action === "prev") {
2848
+ const cur = instance.getCurrentPage?.() ?? 1;
2849
+ if (cur > 1) instance.goToPage?.(cur - 1);
2850
+ } else if (action === "next") {
2851
+ const cur = instance.getCurrentPage?.() ?? 1;
2852
+ const total = instance.getPageCount?.() ?? 1;
2853
+ if (cur < total) instance.goToPage?.(cur + 1);
2854
+ } else if (typeof page === "number") {
2855
+ instance.goToPage?.(page);
2856
+ } else if (typeof action === "number") {
2857
+ instance.goToPage?.(action);
2858
+ }
2718
2859
  }
2719
2860
  },
2720
2861
  {
@@ -3245,7 +3386,7 @@ var HtmlPreviewPlugin = class {
3245
3386
  }
3246
3387
  async render(ctx) {
3247
3388
  const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
3248
- const sanitized = DOMPurify5__default.default.sanitize(rawHtml, {
3389
+ const sanitized = DOMPurify6__default.default.sanitize(rawHtml, {
3249
3390
  WHOLE_DOCUMENT: true,
3250
3391
  ADD_TAGS: ["style", "link"],
3251
3392
  ADD_ATTR: ["target", "rel"]
@@ -3340,35 +3481,27 @@ var OpenDocumentPlugin = class {
3340
3481
  group: "navigation",
3341
3482
  execute: () => instance.toggleThumbnails?.()
3342
3483
  },
3343
- {
3344
- id: "page-prev",
3345
- icon: "page-prev",
3346
- label: "Previous Slide",
3347
- type: "button",
3348
- group: "navigation",
3349
- execute: () => {
3350
- const cur = instance.getCurrentPage?.() ?? 1;
3351
- if (cur > 1) instance.goToPage?.(cur - 1);
3352
- }
3353
- },
3354
3484
  {
3355
3485
  id: "page-nav",
3356
3486
  icon: "",
3357
- label: "Slide Number",
3487
+ label: "Slide Navigation",
3358
3488
  type: "page-nav",
3359
3489
  group: "navigation",
3360
- execute: (p) => instance.goToPage?.(Number(p))
3361
- },
3362
- {
3363
- id: "page-next",
3364
- icon: "page-next",
3365
- label: "Next Slide",
3366
- type: "button",
3367
- group: "navigation",
3368
- execute: () => {
3369
- const cur = instance.getCurrentPage?.() ?? 1;
3370
- const total = instance.getPageCount?.() ?? 1;
3371
- if (cur < total) instance.goToPage?.(cur + 1);
3490
+ value: instance.getCurrentPage?.() ?? 1,
3491
+ max: instance.getPageCount?.() ?? 1,
3492
+ execute: (action, page) => {
3493
+ if (action === "prev") {
3494
+ const cur = instance.getCurrentPage?.() ?? 1;
3495
+ if (cur > 1) instance.goToPage?.(cur - 1);
3496
+ } else if (action === "next") {
3497
+ const cur = instance.getCurrentPage?.() ?? 1;
3498
+ const total = instance.getPageCount?.() ?? 1;
3499
+ if (cur < total) instance.goToPage?.(cur + 1);
3500
+ } else if (typeof page === "number") {
3501
+ instance.goToPage?.(page);
3502
+ } else if (typeof action === "number") {
3503
+ instance.goToPage?.(action);
3504
+ }
3372
3505
  }
3373
3506
  }
3374
3507
  );
@@ -3496,7 +3629,7 @@ var OpenDocumentPlugin = class {
3496
3629
  wrapper.style.padding = "48px";
3497
3630
  wrapper.style.minHeight = "100%";
3498
3631
  const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
3499
- wrapper.innerHTML = DOMPurify5__default.default.sanitize(bodyHtml, {
3632
+ wrapper.innerHTML = DOMPurify6__default.default.sanitize(bodyHtml, {
3500
3633
  ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub"],
3501
3634
  ADD_ATTR: ["style", "colspan", "rowspan"]
3502
3635
  });
@@ -4016,24 +4149,24 @@ var DocPlugin = class {
4016
4149
  html += "</ul>";
4017
4150
  inList = false;
4018
4151
  }
4019
- 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>`;
4152
+ 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>`;
4020
4153
  } else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
4021
4154
  if (!inList) {
4022
4155
  html += '<ul style="margin: 8px 0; padding-left: 24px;">';
4023
4156
  inList = true;
4024
4157
  }
4025
4158
  const bulletText = line.replace(/^[•\-\*]\s*/, "");
4026
- html += `<li style="margin: 4px 0; line-height: 1.6;">${DOMPurify5__default.default.sanitize(bulletText)}</li>`;
4159
+ html += `<li style="margin: 4px 0; line-height: 1.6;">${DOMPurify6__default.default.sanitize(bulletText)}</li>`;
4027
4160
  } else {
4028
4161
  if (inList) {
4029
4162
  html += "</ul>";
4030
4163
  inList = false;
4031
4164
  }
4032
- html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${DOMPurify5__default.default.sanitize(line)}</p>`;
4165
+ html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${DOMPurify6__default.default.sanitize(line)}</p>`;
4033
4166
  }
4034
4167
  }
4035
4168
  if (inList) html += "</ul>";
4036
- return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify5__default.default.sanitize(filename)})</p>`;
4169
+ return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6__default.default.sanitize(filename)})</p>`;
4037
4170
  }
4038
4171
  };
4039
4172
  function docPlugin() {
@@ -4060,35 +4193,27 @@ var PptPlugin = class {
4060
4193
  group: "navigation",
4061
4194
  execute: () => instance.toggleThumbnails?.()
4062
4195
  },
4063
- {
4064
- id: "page-prev",
4065
- icon: "page-prev",
4066
- label: "Previous Slide",
4067
- type: "button",
4068
- group: "navigation",
4069
- execute: () => {
4070
- const cur = instance.getCurrentPage?.() ?? 1;
4071
- if (cur > 1) instance.goToPage?.(cur - 1);
4072
- }
4073
- },
4074
4196
  {
4075
4197
  id: "page-nav",
4076
4198
  icon: "",
4077
- label: "Slide Number",
4199
+ label: "Slide Navigation",
4078
4200
  type: "page-nav",
4079
4201
  group: "navigation",
4080
- execute: (p) => instance.goToPage?.(Number(p))
4081
- },
4082
- {
4083
- id: "page-next",
4084
- icon: "page-next",
4085
- label: "Next Slide",
4086
- type: "button",
4087
- group: "navigation",
4088
- execute: () => {
4089
- const cur = instance.getCurrentPage?.() ?? 1;
4090
- const total = instance.getPageCount?.() ?? 1;
4091
- if (cur < total) instance.goToPage?.(cur + 1);
4202
+ value: instance.getCurrentPage?.() ?? 1,
4203
+ max: instance.getPageCount?.() ?? 1,
4204
+ execute: (action, page) => {
4205
+ if (action === "prev") {
4206
+ const cur = instance.getCurrentPage?.() ?? 1;
4207
+ if (cur > 1) instance.goToPage?.(cur - 1);
4208
+ } else if (action === "next") {
4209
+ const cur = instance.getCurrentPage?.() ?? 1;
4210
+ const total = instance.getPageCount?.() ?? 1;
4211
+ if (cur < total) instance.goToPage?.(cur + 1);
4212
+ } else if (typeof page === "number") {
4213
+ instance.goToPage?.(page);
4214
+ } else if (typeof action === "number") {
4215
+ instance.goToPage?.(action);
4216
+ }
4092
4217
  }
4093
4218
  },
4094
4219
  {
@@ -4196,10 +4321,10 @@ var PptPlugin = class {
4196
4321
  </div>
4197
4322
  <div style="text-align: center; width: 100%;">
4198
4323
  <h1 style="font-size: ${idx === 1 ? "36px" : "28px"}; color: #1e3a8a; margin: 0 0 24px; font-family: -apple-system, BlinkMacSystemFont, sans-serif; font-weight: 700;">
4199
- ${DOMPurify5__default.default.sanitize(s.title || `Slide ${idx}`)}
4324
+ ${DOMPurify6__default.default.sanitize(s.title || `Slide ${idx}`)}
4200
4325
  </h1>
4201
4326
  <div style="display: flex; flex-direction: column; gap: 12px; max-width: 80%; margin: 0 auto; text-align: ${idx === 1 ? "center" : "left"};">
4202
- ${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("")}
4327
+ ${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("")}
4203
4328
  </div>
4204
4329
  </div>
4205
4330
  `;