@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 +252 -127
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.js +251 -126
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +253 -128
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +252 -127
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +252 -127
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +251 -126
- package/dist/react.js.map +1 -1
- package/dist/vue.cjs +252 -127
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +251 -126
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import DOMPurify6 from 'dompurify';
|
|
2
2
|
import * as docx from 'docx-preview';
|
|
3
|
+
import { unzipSync, strFromU8, unzip } from 'fflate';
|
|
3
4
|
import * as XLSX from 'xlsx';
|
|
4
5
|
import hljs from 'highlight.js';
|
|
5
|
-
import { unzip, unzipSync, strFromU8 } from 'fflate';
|
|
6
6
|
import { marked } from 'marked';
|
|
7
7
|
import { PptxRenderer } from 'pptx-browser';
|
|
8
8
|
import * as THREE from 'three';
|
|
@@ -339,12 +339,12 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
339
339
|
return { buffer, metadata };
|
|
340
340
|
}
|
|
341
341
|
function sanitizeHTML(html) {
|
|
342
|
-
return
|
|
342
|
+
return DOMPurify6.sanitize(html, {
|
|
343
343
|
USE_PROFILES: { html: true }
|
|
344
344
|
});
|
|
345
345
|
}
|
|
346
346
|
function sanitizeSVG(svg) {
|
|
347
|
-
return
|
|
347
|
+
return DOMPurify6.sanitize(svg, {
|
|
348
348
|
USE_PROFILES: { svg: true, svgFilters: true }
|
|
349
349
|
});
|
|
350
350
|
}
|
|
@@ -459,7 +459,11 @@ var ICON_MAP = {
|
|
|
459
459
|
"close": ICON_CLOSE,
|
|
460
460
|
"copy": ICON_COPY,
|
|
461
461
|
"prev": ICON_PAGE_PREV,
|
|
462
|
-
"next": ICON_PAGE_NEXT
|
|
462
|
+
"next": ICON_PAGE_NEXT,
|
|
463
|
+
"page-prev": ICON_PAGE_PREV,
|
|
464
|
+
"page-next": ICON_PAGE_NEXT,
|
|
465
|
+
"chevron-left": ICON_PAGE_PREV,
|
|
466
|
+
"chevron-right": ICON_PAGE_NEXT
|
|
463
467
|
};
|
|
464
468
|
var ToolbarController = class {
|
|
465
469
|
el;
|
|
@@ -491,7 +495,9 @@ var ToolbarController = class {
|
|
|
491
495
|
view: [],
|
|
492
496
|
actions: []
|
|
493
497
|
};
|
|
494
|
-
|
|
498
|
+
const hasPageNav = this.actions.some((a) => a.type === "page-nav");
|
|
499
|
+
const effectiveActions = hasPageNav ? this.actions.filter((a) => a.id !== "page-prev" && a.id !== "page-next" && a.id !== "prev" && a.id !== "next") : this.actions;
|
|
500
|
+
for (const action of effectiveActions) {
|
|
495
501
|
if (groups[action.group]) {
|
|
496
502
|
groups[action.group].push(action);
|
|
497
503
|
}
|
|
@@ -514,13 +520,26 @@ var ToolbarController = class {
|
|
|
514
520
|
"prev",
|
|
515
521
|
ICON_PAGE_PREV,
|
|
516
522
|
"Previous Page",
|
|
517
|
-
() =>
|
|
523
|
+
() => {
|
|
524
|
+
const cur = parseInt(input.value, 10) || 1;
|
|
525
|
+
if (cur > 1) {
|
|
526
|
+
input.value = (cur - 1).toString();
|
|
527
|
+
action.execute("prev", cur - 1);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
518
530
|
);
|
|
519
531
|
const nextBtn = this.createButton(
|
|
520
532
|
"next",
|
|
521
533
|
ICON_PAGE_NEXT,
|
|
522
534
|
"Next Page",
|
|
523
|
-
() =>
|
|
535
|
+
() => {
|
|
536
|
+
const cur = parseInt(input.value, 10) || 1;
|
|
537
|
+
const max = action.max ?? 1;
|
|
538
|
+
if (cur < max) {
|
|
539
|
+
input.value = (cur + 1).toString();
|
|
540
|
+
action.execute("next", cur + 1);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
524
543
|
);
|
|
525
544
|
const input = createElement("input", {
|
|
526
545
|
className: "fp-toolbar-input",
|
|
@@ -530,7 +549,10 @@ var ToolbarController = class {
|
|
|
530
549
|
max: (action.max ?? 1).toString()
|
|
531
550
|
});
|
|
532
551
|
input.addEventListener("change", () => {
|
|
533
|
-
|
|
552
|
+
const val = parseInt(input.value, 10);
|
|
553
|
+
if (!isNaN(val)) {
|
|
554
|
+
action.execute("go", val);
|
|
555
|
+
}
|
|
534
556
|
});
|
|
535
557
|
const label = createElement("span", { className: "fp-toolbar-label" }, ` / ${action.max ?? 1}`);
|
|
536
558
|
groupEl.appendChild(prevBtn);
|
|
@@ -571,11 +593,11 @@ var ToolbarController = class {
|
|
|
571
593
|
type: "button",
|
|
572
594
|
"data-action-id": id
|
|
573
595
|
});
|
|
574
|
-
const svg = ICON_MAP[iconHtml] || iconHtml;
|
|
575
|
-
if (svg
|
|
596
|
+
const svg = ICON_MAP[iconHtml] || ICON_MAP[id] || (iconHtml && iconHtml.startsWith("<svg") ? iconHtml : null);
|
|
597
|
+
if (svg) {
|
|
576
598
|
btn.innerHTML = sanitizeSVG(svg);
|
|
577
599
|
} else {
|
|
578
|
-
btn.textContent =
|
|
600
|
+
btn.textContent = title || id;
|
|
579
601
|
}
|
|
580
602
|
btn.addEventListener("click", onClick);
|
|
581
603
|
return btn;
|
|
@@ -1318,12 +1340,12 @@ function pdfPlugin() {
|
|
|
1318
1340
|
}
|
|
1319
1341
|
|
|
1320
1342
|
// ../plugins/media/dist/index.js
|
|
1321
|
-
var IMAGE_EXTS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"];
|
|
1322
|
-
var VIDEO_EXTS = [".mp4", ".webm", ".ogg"];
|
|
1323
|
-
var AUDIO_EXTS = [".mp3", ".wav", ".ogg"];
|
|
1343
|
+
var IMAGE_EXTS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg", ".bmp", ".ico", ".tiff", ".tif", ".avif"];
|
|
1344
|
+
var VIDEO_EXTS = [".mp4", ".m4v", ".webm", ".ogv", ".ogg", ".mov", ".avi", ".mkv", ".flv", ".wmv", ".3gp", ".mpg", ".mpeg"];
|
|
1345
|
+
var AUDIO_EXTS = [".mp3", ".wav", ".ogg", ".flac", ".aac", ".m4a", ".wma", ".opus", ".weba"];
|
|
1324
1346
|
var MediaPlugin = class {
|
|
1325
1347
|
id = "media";
|
|
1326
|
-
name = "Media Preview";
|
|
1348
|
+
name = "Media Preview (Image, Video, Audio)";
|
|
1327
1349
|
extensions = [...IMAGE_EXTS, ...VIDEO_EXTS, ...AUDIO_EXTS];
|
|
1328
1350
|
mimeTypes = [
|
|
1329
1351
|
"image/jpeg",
|
|
@@ -1331,12 +1353,29 @@ var MediaPlugin = class {
|
|
|
1331
1353
|
"image/gif",
|
|
1332
1354
|
"image/webp",
|
|
1333
1355
|
"image/svg+xml",
|
|
1356
|
+
"image/bmp",
|
|
1357
|
+
"image/x-icon",
|
|
1358
|
+
"image/tiff",
|
|
1359
|
+
"image/avif",
|
|
1334
1360
|
"video/mp4",
|
|
1335
1361
|
"video/webm",
|
|
1336
1362
|
"video/ogg",
|
|
1363
|
+
"video/quicktime",
|
|
1364
|
+
"video/x-msvideo",
|
|
1365
|
+
"video/x-matroska",
|
|
1366
|
+
"video/x-flv",
|
|
1367
|
+
"video/x-ms-wmv",
|
|
1368
|
+
"video/3gpp",
|
|
1369
|
+
"video/mpeg",
|
|
1337
1370
|
"audio/mpeg",
|
|
1338
1371
|
"audio/wav",
|
|
1339
|
-
"audio/ogg"
|
|
1372
|
+
"audio/ogg",
|
|
1373
|
+
"audio/flac",
|
|
1374
|
+
"audio/aac",
|
|
1375
|
+
"audio/mp4",
|
|
1376
|
+
"audio/x-ms-wma",
|
|
1377
|
+
"audio/opus",
|
|
1378
|
+
"audio/webm"
|
|
1340
1379
|
];
|
|
1341
1380
|
weight = 90;
|
|
1342
1381
|
supports(file) {
|
|
@@ -1469,8 +1508,12 @@ var MediaPlugin = class {
|
|
|
1469
1508
|
const video = document.createElement("video");
|
|
1470
1509
|
video.src = url;
|
|
1471
1510
|
video.controls = true;
|
|
1472
|
-
video.
|
|
1473
|
-
video.style.
|
|
1511
|
+
video.playsInline = true;
|
|
1512
|
+
video.style.maxWidth = "90%";
|
|
1513
|
+
video.style.maxHeight = "90%";
|
|
1514
|
+
video.style.borderRadius = "8px";
|
|
1515
|
+
video.style.boxShadow = "0 8px 30px rgba(0,0,0,0.3)";
|
|
1516
|
+
video.style.backgroundColor = "#000000";
|
|
1474
1517
|
element = video;
|
|
1475
1518
|
mediaElement = video;
|
|
1476
1519
|
} else if (isAudio) {
|
|
@@ -1546,7 +1589,7 @@ function mediaPlugin() {
|
|
|
1546
1589
|
}
|
|
1547
1590
|
var DocxPlugin = class {
|
|
1548
1591
|
id = "docx";
|
|
1549
|
-
name = "Word Document Preview";
|
|
1592
|
+
name = "Word Document Preview (.docx, .docm, .dotx, .dotm)";
|
|
1550
1593
|
extensions = [".docx", ".docm", ".dotx", ".dotm"];
|
|
1551
1594
|
mimeTypes = [
|
|
1552
1595
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
@@ -1568,9 +1611,7 @@ var DocxPlugin = class {
|
|
|
1568
1611
|
label: "Zoom Out",
|
|
1569
1612
|
type: "button",
|
|
1570
1613
|
group: "zoom",
|
|
1571
|
-
execute: () =>
|
|
1572
|
-
instance.zoomOut?.();
|
|
1573
|
-
}
|
|
1614
|
+
execute: () => instance.zoomOut?.()
|
|
1574
1615
|
},
|
|
1575
1616
|
{
|
|
1576
1617
|
id: "zoom-in",
|
|
@@ -1578,9 +1619,7 @@ var DocxPlugin = class {
|
|
|
1578
1619
|
label: "Zoom In",
|
|
1579
1620
|
type: "button",
|
|
1580
1621
|
group: "zoom",
|
|
1581
|
-
execute: () =>
|
|
1582
|
-
instance.zoomIn?.();
|
|
1583
|
-
}
|
|
1622
|
+
execute: () => instance.zoomIn?.()
|
|
1584
1623
|
},
|
|
1585
1624
|
{
|
|
1586
1625
|
id: "fit-page",
|
|
@@ -1588,9 +1627,7 @@ var DocxPlugin = class {
|
|
|
1588
1627
|
label: "Fit to Page",
|
|
1589
1628
|
type: "button",
|
|
1590
1629
|
group: "zoom",
|
|
1591
|
-
execute: () =>
|
|
1592
|
-
instance.fitToPage?.();
|
|
1593
|
-
}
|
|
1630
|
+
execute: () => instance.fitToPage?.()
|
|
1594
1631
|
},
|
|
1595
1632
|
{
|
|
1596
1633
|
id: "download",
|
|
@@ -1598,9 +1635,7 @@ var DocxPlugin = class {
|
|
|
1598
1635
|
label: "Download",
|
|
1599
1636
|
type: "button",
|
|
1600
1637
|
group: "actions",
|
|
1601
|
-
execute: () =>
|
|
1602
|
-
instance.download?.();
|
|
1603
|
-
}
|
|
1638
|
+
execute: () => instance.download?.()
|
|
1604
1639
|
},
|
|
1605
1640
|
{
|
|
1606
1641
|
id: "print",
|
|
@@ -1608,9 +1643,7 @@ var DocxPlugin = class {
|
|
|
1608
1643
|
label: "Print",
|
|
1609
1644
|
type: "button",
|
|
1610
1645
|
group: "actions",
|
|
1611
|
-
execute: () =>
|
|
1612
|
-
instance.print?.();
|
|
1613
|
-
}
|
|
1646
|
+
execute: () => instance.print?.()
|
|
1614
1647
|
}
|
|
1615
1648
|
];
|
|
1616
1649
|
}
|
|
@@ -1619,24 +1652,46 @@ var DocxPlugin = class {
|
|
|
1619
1652
|
wrapper.className = "fp-docx-wrapper";
|
|
1620
1653
|
wrapper.style.transformOrigin = "top center";
|
|
1621
1654
|
wrapper.style.transition = "transform 0.2s ease";
|
|
1622
|
-
wrapper.style.padding = "16px";
|
|
1655
|
+
wrapper.style.padding = "24px 16px";
|
|
1656
|
+
wrapper.style.maxWidth = "900px";
|
|
1657
|
+
wrapper.style.margin = "0 auto";
|
|
1658
|
+
wrapper.style.boxSizing = "border-box";
|
|
1623
1659
|
ctx.container.style.overflow = "auto";
|
|
1660
|
+
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
1624
1661
|
ctx.container.appendChild(wrapper);
|
|
1625
1662
|
let scale = 1;
|
|
1663
|
+
let renderedSuccessfully = false;
|
|
1626
1664
|
try {
|
|
1627
1665
|
await docx.renderAsync(ctx.buffer, wrapper, ctx.container, {
|
|
1628
1666
|
inWrapper: true,
|
|
1629
1667
|
ignoreWidth: false,
|
|
1630
|
-
ignoreHeight: false
|
|
1668
|
+
ignoreHeight: false,
|
|
1669
|
+
ignoreFonts: true,
|
|
1670
|
+
// Avoid crashes on embedded obfuscated fonts
|
|
1671
|
+
breakPages: true,
|
|
1672
|
+
experimental: true
|
|
1631
1673
|
});
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1674
|
+
if (wrapper.children.length > 0 && (wrapper.textContent?.trim().length ?? 0) > 0) {
|
|
1675
|
+
renderedSuccessfully = true;
|
|
1676
|
+
}
|
|
1677
|
+
} catch (err) {
|
|
1678
|
+
console.warn("[DocxPlugin] docx-preview failed, triggering native XML fallback:", err);
|
|
1679
|
+
}
|
|
1680
|
+
if (!renderedSuccessfully) {
|
|
1681
|
+
try {
|
|
1682
|
+
wrapper.innerHTML = "";
|
|
1683
|
+
this.renderXmlFallback(ctx, wrapper);
|
|
1684
|
+
renderedSuccessfully = true;
|
|
1685
|
+
} catch (fallbackErr) {
|
|
1686
|
+
console.error("[DocxPlugin] XML fallback failed:", fallbackErr);
|
|
1687
|
+
wrapper.innerHTML = `
|
|
1688
|
+
<div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
|
|
1689
|
+
<div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
|
|
1690
|
+
<h3 style="margin: 0 0 8px; color: #1e293b;">${ctx.metadata.name || "Word Document"}</h3>
|
|
1691
|
+
<p style="color: #64748b; margin: 0;">Could not parse document content</p>
|
|
1692
|
+
</div>
|
|
1693
|
+
`;
|
|
1694
|
+
}
|
|
1640
1695
|
}
|
|
1641
1696
|
const cleanup = () => {
|
|
1642
1697
|
wrapper.remove();
|
|
@@ -1660,7 +1715,7 @@ var DocxPlugin = class {
|
|
|
1660
1715
|
},
|
|
1661
1716
|
fitToPage: () => {
|
|
1662
1717
|
scale = 1;
|
|
1663
|
-
wrapper.style.transform =
|
|
1718
|
+
wrapper.style.transform = "scale(1)";
|
|
1664
1719
|
},
|
|
1665
1720
|
download: () => {
|
|
1666
1721
|
const blob = new Blob([ctx.buffer], { type: this.mimeTypes[0] });
|
|
@@ -1676,6 +1731,100 @@ var DocxPlugin = class {
|
|
|
1676
1731
|
}
|
|
1677
1732
|
};
|
|
1678
1733
|
}
|
|
1734
|
+
renderXmlFallback(ctx, wrapper) {
|
|
1735
|
+
const unzipped = unzipSync(new Uint8Array(ctx.buffer));
|
|
1736
|
+
const docXmlEntry = unzipped["word/document.xml"];
|
|
1737
|
+
if (!docXmlEntry) throw new Error("Missing word/document.xml in DOCX package");
|
|
1738
|
+
const xmlStr = strFromU8(docXmlEntry);
|
|
1739
|
+
const parser = new DOMParser();
|
|
1740
|
+
const doc = parser.parseFromString(xmlStr, "application/xml");
|
|
1741
|
+
const card = document.createElement("div");
|
|
1742
|
+
card.className = "fp-docx-page-card";
|
|
1743
|
+
card.style.backgroundColor = "#ffffff";
|
|
1744
|
+
card.style.borderRadius = "6px";
|
|
1745
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
1746
|
+
card.style.padding = "48px 56px";
|
|
1747
|
+
card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
1748
|
+
card.style.color = "#1e293b";
|
|
1749
|
+
card.style.lineHeight = "1.6";
|
|
1750
|
+
const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
|
|
1751
|
+
let html = "";
|
|
1752
|
+
for (const child of Array.from(body.children)) {
|
|
1753
|
+
const tag = child.localName || child.nodeName.split(":").pop();
|
|
1754
|
+
if (tag === "p") {
|
|
1755
|
+
const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
|
|
1756
|
+
const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
|
|
1757
|
+
const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
|
|
1758
|
+
const textContent = this.extractParagraphHtml(child);
|
|
1759
|
+
if (!textContent.trim()) {
|
|
1760
|
+
html += '<div style="height: 10px;"></div>';
|
|
1761
|
+
continue;
|
|
1762
|
+
}
|
|
1763
|
+
const lowerStyle = styleVal.toLowerCase();
|
|
1764
|
+
if (lowerStyle.includes("title")) {
|
|
1765
|
+
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>`;
|
|
1766
|
+
} else if (lowerStyle.includes("heading1") || styleVal === "1") {
|
|
1767
|
+
html += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
|
|
1768
|
+
} else if (lowerStyle.includes("heading2") || styleVal === "2") {
|
|
1769
|
+
html += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
|
|
1770
|
+
} else if (lowerStyle.includes("heading3") || styleVal === "3") {
|
|
1771
|
+
html += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
|
|
1772
|
+
} else if (numPr) {
|
|
1773
|
+
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>`;
|
|
1774
|
+
} else {
|
|
1775
|
+
html += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
|
|
1776
|
+
}
|
|
1777
|
+
} else if (tag === "tbl") {
|
|
1778
|
+
html += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
|
|
1779
|
+
const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
|
|
1780
|
+
rows.forEach((tr, rIdx) => {
|
|
1781
|
+
html += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
1782
|
+
const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
|
|
1783
|
+
cells.forEach((tc) => {
|
|
1784
|
+
const cellText = this.extractParagraphHtml(tc);
|
|
1785
|
+
html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || " "}</td>`;
|
|
1786
|
+
});
|
|
1787
|
+
html += "</tr>";
|
|
1788
|
+
});
|
|
1789
|
+
html += "</table>";
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
card.innerHTML = DOMPurify6.sanitize(html, {
|
|
1793
|
+
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "img", "div"],
|
|
1794
|
+
ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
|
|
1795
|
+
});
|
|
1796
|
+
wrapper.appendChild(card);
|
|
1797
|
+
}
|
|
1798
|
+
extractParagraphHtml(pElement) {
|
|
1799
|
+
let result = "";
|
|
1800
|
+
const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
|
|
1801
|
+
if (runs.length === 0) {
|
|
1802
|
+
return DOMPurify6.sanitize(pElement.textContent || "");
|
|
1803
|
+
}
|
|
1804
|
+
for (const r of runs) {
|
|
1805
|
+
const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
|
|
1806
|
+
const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
|
|
1807
|
+
const isItalic = !!rPr?.getElementsByTagNameNS("*", "i")[0];
|
|
1808
|
+
const isUnderline = !!rPr?.getElementsByTagNameNS("*", "u")[0];
|
|
1809
|
+
const colorNode = rPr?.getElementsByTagNameNS("*", "color")[0];
|
|
1810
|
+
const colorVal = colorNode?.getAttribute("w:val") || colorNode?.getAttribute("val");
|
|
1811
|
+
const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
|
|
1812
|
+
let text = texts.map((t) => t.textContent || "").join("");
|
|
1813
|
+
if (!text) continue;
|
|
1814
|
+
text = DOMPurify6.sanitize(text);
|
|
1815
|
+
let styles = "";
|
|
1816
|
+
if (isBold) styles += "font-weight: bold; ";
|
|
1817
|
+
if (isItalic) styles += "font-style: italic; ";
|
|
1818
|
+
if (isUnderline) styles += "text-decoration: underline; ";
|
|
1819
|
+
if (colorVal && colorVal !== "auto") styles += `color: #${colorVal}; `;
|
|
1820
|
+
if (styles) {
|
|
1821
|
+
result += `<span style="${styles}">${text}</span>`;
|
|
1822
|
+
} else {
|
|
1823
|
+
result += text;
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
return result;
|
|
1827
|
+
}
|
|
1679
1828
|
};
|
|
1680
1829
|
function docxPlugin() {
|
|
1681
1830
|
return new DocxPlugin();
|
|
@@ -2487,7 +2636,7 @@ var MarkdownPlugin = class {
|
|
|
2487
2636
|
gfm: true,
|
|
2488
2637
|
breaks: true
|
|
2489
2638
|
});
|
|
2490
|
-
const cleanHtml =
|
|
2639
|
+
const cleanHtml = DOMPurify6.sanitize(rawHtml, {
|
|
2491
2640
|
USE_PROFILES: { html: true }
|
|
2492
2641
|
});
|
|
2493
2642
|
const wrapper = document.createElement("div");
|
|
@@ -2651,35 +2800,27 @@ var PptxPlugin = class {
|
|
|
2651
2800
|
group: "navigation",
|
|
2652
2801
|
execute: () => instance.toggleThumbnails?.()
|
|
2653
2802
|
},
|
|
2654
|
-
{
|
|
2655
|
-
id: "page-prev",
|
|
2656
|
-
icon: "page-prev",
|
|
2657
|
-
label: "Previous Slide",
|
|
2658
|
-
type: "button",
|
|
2659
|
-
group: "navigation",
|
|
2660
|
-
execute: () => {
|
|
2661
|
-
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2662
|
-
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
2663
|
-
}
|
|
2664
|
-
},
|
|
2665
2803
|
{
|
|
2666
2804
|
id: "page-nav",
|
|
2667
2805
|
icon: "",
|
|
2668
|
-
label: "Slide
|
|
2806
|
+
label: "Slide Navigation",
|
|
2669
2807
|
type: "page-nav",
|
|
2670
2808
|
group: "navigation",
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2809
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
2810
|
+
max: instance.getPageCount?.() ?? 1,
|
|
2811
|
+
execute: (action, page) => {
|
|
2812
|
+
if (action === "prev") {
|
|
2813
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2814
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
2815
|
+
} else if (action === "next") {
|
|
2816
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2817
|
+
const total = instance.getPageCount?.() ?? 1;
|
|
2818
|
+
if (cur < total) instance.goToPage?.(cur + 1);
|
|
2819
|
+
} else if (typeof page === "number") {
|
|
2820
|
+
instance.goToPage?.(page);
|
|
2821
|
+
} else if (typeof action === "number") {
|
|
2822
|
+
instance.goToPage?.(action);
|
|
2823
|
+
}
|
|
2683
2824
|
}
|
|
2684
2825
|
},
|
|
2685
2826
|
{
|
|
@@ -3210,7 +3351,7 @@ var HtmlPreviewPlugin = class {
|
|
|
3210
3351
|
}
|
|
3211
3352
|
async render(ctx) {
|
|
3212
3353
|
const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
|
|
3213
|
-
const sanitized =
|
|
3354
|
+
const sanitized = DOMPurify6.sanitize(rawHtml, {
|
|
3214
3355
|
WHOLE_DOCUMENT: true,
|
|
3215
3356
|
ADD_TAGS: ["style", "link"],
|
|
3216
3357
|
ADD_ATTR: ["target", "rel"]
|
|
@@ -3305,35 +3446,27 @@ var OpenDocumentPlugin = class {
|
|
|
3305
3446
|
group: "navigation",
|
|
3306
3447
|
execute: () => instance.toggleThumbnails?.()
|
|
3307
3448
|
},
|
|
3308
|
-
{
|
|
3309
|
-
id: "page-prev",
|
|
3310
|
-
icon: "page-prev",
|
|
3311
|
-
label: "Previous Slide",
|
|
3312
|
-
type: "button",
|
|
3313
|
-
group: "navigation",
|
|
3314
|
-
execute: () => {
|
|
3315
|
-
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3316
|
-
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3317
|
-
}
|
|
3318
|
-
},
|
|
3319
3449
|
{
|
|
3320
3450
|
id: "page-nav",
|
|
3321
3451
|
icon: "",
|
|
3322
|
-
label: "Slide
|
|
3452
|
+
label: "Slide Navigation",
|
|
3323
3453
|
type: "page-nav",
|
|
3324
3454
|
group: "navigation",
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3455
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
3456
|
+
max: instance.getPageCount?.() ?? 1,
|
|
3457
|
+
execute: (action, page) => {
|
|
3458
|
+
if (action === "prev") {
|
|
3459
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3460
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3461
|
+
} else if (action === "next") {
|
|
3462
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3463
|
+
const total = instance.getPageCount?.() ?? 1;
|
|
3464
|
+
if (cur < total) instance.goToPage?.(cur + 1);
|
|
3465
|
+
} else if (typeof page === "number") {
|
|
3466
|
+
instance.goToPage?.(page);
|
|
3467
|
+
} else if (typeof action === "number") {
|
|
3468
|
+
instance.goToPage?.(action);
|
|
3469
|
+
}
|
|
3337
3470
|
}
|
|
3338
3471
|
}
|
|
3339
3472
|
);
|
|
@@ -3461,7 +3594,7 @@ var OpenDocumentPlugin = class {
|
|
|
3461
3594
|
wrapper.style.padding = "48px";
|
|
3462
3595
|
wrapper.style.minHeight = "100%";
|
|
3463
3596
|
const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
|
|
3464
|
-
wrapper.innerHTML =
|
|
3597
|
+
wrapper.innerHTML = DOMPurify6.sanitize(bodyHtml, {
|
|
3465
3598
|
ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub"],
|
|
3466
3599
|
ADD_ATTR: ["style", "colspan", "rowspan"]
|
|
3467
3600
|
});
|
|
@@ -3981,24 +4114,24 @@ var DocPlugin = class {
|
|
|
3981
4114
|
html += "</ul>";
|
|
3982
4115
|
inList = false;
|
|
3983
4116
|
}
|
|
3984
|
-
html += `<h2 style="font-size: 18px; font-weight: 700; color: #1e3a8a; margin: 20px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${
|
|
4117
|
+
html += `<h2 style="font-size: 18px; font-weight: 700; color: #1e3a8a; margin: 20px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify6.sanitize(line)}</h2>`;
|
|
3985
4118
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
3986
4119
|
if (!inList) {
|
|
3987
4120
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
3988
4121
|
inList = true;
|
|
3989
4122
|
}
|
|
3990
4123
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
3991
|
-
html += `<li style="margin: 4px 0; line-height: 1.6;">${
|
|
4124
|
+
html += `<li style="margin: 4px 0; line-height: 1.6;">${DOMPurify6.sanitize(bulletText)}</li>`;
|
|
3992
4125
|
} else {
|
|
3993
4126
|
if (inList) {
|
|
3994
4127
|
html += "</ul>";
|
|
3995
4128
|
inList = false;
|
|
3996
4129
|
}
|
|
3997
|
-
html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${
|
|
4130
|
+
html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${DOMPurify6.sanitize(line)}</p>`;
|
|
3998
4131
|
}
|
|
3999
4132
|
}
|
|
4000
4133
|
if (inList) html += "</ul>";
|
|
4001
|
-
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${
|
|
4134
|
+
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6.sanitize(filename)})</p>`;
|
|
4002
4135
|
}
|
|
4003
4136
|
};
|
|
4004
4137
|
function docPlugin() {
|
|
@@ -4025,35 +4158,27 @@ var PptPlugin = class {
|
|
|
4025
4158
|
group: "navigation",
|
|
4026
4159
|
execute: () => instance.toggleThumbnails?.()
|
|
4027
4160
|
},
|
|
4028
|
-
{
|
|
4029
|
-
id: "page-prev",
|
|
4030
|
-
icon: "page-prev",
|
|
4031
|
-
label: "Previous Slide",
|
|
4032
|
-
type: "button",
|
|
4033
|
-
group: "navigation",
|
|
4034
|
-
execute: () => {
|
|
4035
|
-
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4036
|
-
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
4037
|
-
}
|
|
4038
|
-
},
|
|
4039
4161
|
{
|
|
4040
4162
|
id: "page-nav",
|
|
4041
4163
|
icon: "",
|
|
4042
|
-
label: "Slide
|
|
4164
|
+
label: "Slide Navigation",
|
|
4043
4165
|
type: "page-nav",
|
|
4044
4166
|
group: "navigation",
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4167
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
4168
|
+
max: instance.getPageCount?.() ?? 1,
|
|
4169
|
+
execute: (action, page) => {
|
|
4170
|
+
if (action === "prev") {
|
|
4171
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4172
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
4173
|
+
} else if (action === "next") {
|
|
4174
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4175
|
+
const total = instance.getPageCount?.() ?? 1;
|
|
4176
|
+
if (cur < total) instance.goToPage?.(cur + 1);
|
|
4177
|
+
} else if (typeof page === "number") {
|
|
4178
|
+
instance.goToPage?.(page);
|
|
4179
|
+
} else if (typeof action === "number") {
|
|
4180
|
+
instance.goToPage?.(action);
|
|
4181
|
+
}
|
|
4057
4182
|
}
|
|
4058
4183
|
},
|
|
4059
4184
|
{
|
|
@@ -4161,10 +4286,10 @@ var PptPlugin = class {
|
|
|
4161
4286
|
</div>
|
|
4162
4287
|
<div style="text-align: center; width: 100%;">
|
|
4163
4288
|
<h1 style="font-size: ${idx === 1 ? "36px" : "28px"}; color: #1e3a8a; margin: 0 0 24px; font-family: -apple-system, BlinkMacSystemFont, sans-serif; font-weight: 700;">
|
|
4164
|
-
${
|
|
4289
|
+
${DOMPurify6.sanitize(s.title || `Slide ${idx}`)}
|
|
4165
4290
|
</h1>
|
|
4166
4291
|
<div style="display: flex; flex-direction: column; gap: 12px; max-width: 80%; margin: 0 auto; text-align: ${idx === 1 ? "center" : "left"};">
|
|
4167
|
-
${s.texts.map((t) => `<div style="font-size: 18px; color: #334155; line-height: 1.5; font-family: -apple-system, BlinkMacSystemFont, sans-serif;">${
|
|
4292
|
+
${s.texts.map((t) => `<div style="font-size: 18px; color: #334155; line-height: 1.5; font-family: -apple-system, BlinkMacSystemFont, sans-serif;">${DOMPurify6.sanitize(t)}</div>`).join("")}
|
|
4168
4293
|
</div>
|
|
4169
4294
|
</div>
|
|
4170
4295
|
`;
|