@files-preview-app/preview-file 1.2.2 → 1.2.3
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 +232 -28
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.js +231 -27
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +233 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +232 -28
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +232 -28
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +231 -27
- package/dist/react.js.map +1 -1
- package/dist/vue.cjs +232 -28
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +231 -27
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { memo, forwardRef, useRef, useImperativeHandle, useEffect } from 'react';
|
|
2
|
-
import
|
|
2
|
+
import DOMPurify2 from 'dompurify';
|
|
3
3
|
import * as docx from 'docx-preview';
|
|
4
4
|
import { unzipSync, strFromU8, unzip } from 'fflate';
|
|
5
5
|
import * as XLSX from 'xlsx';
|
|
@@ -341,7 +341,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
341
341
|
return { buffer, metadata };
|
|
342
342
|
}
|
|
343
343
|
function sanitizeSVG(svg) {
|
|
344
|
-
return
|
|
344
|
+
return DOMPurify2.sanitize(svg, {
|
|
345
345
|
USE_PROFILES: { svg: true, svgFilters: true }
|
|
346
346
|
});
|
|
347
347
|
}
|
|
@@ -401,6 +401,9 @@ var ICON_THUMBNAILS = `<svg width="24" height="24" viewBox="0 0 24 24" fill="non
|
|
|
401
401
|
var ICON_CLOSE = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>`;
|
|
402
402
|
var ICON_FULLSCREEN = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"></path></svg>`;
|
|
403
403
|
var ICON_COPY = `<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="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>`;
|
|
404
|
+
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>`;
|
|
405
|
+
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>`;
|
|
406
|
+
var ICON_SPEED = `<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="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>`;
|
|
404
407
|
var ICON_MAP = {
|
|
405
408
|
"zoom-in": ICON_ZOOM_IN,
|
|
406
409
|
"zoom-out": ICON_ZOOM_OUT,
|
|
@@ -421,7 +424,12 @@ var ICON_MAP = {
|
|
|
421
424
|
"page-prev": ICON_PAGE_PREV,
|
|
422
425
|
"page-next": ICON_PAGE_NEXT,
|
|
423
426
|
"chevron-left": ICON_PAGE_PREV,
|
|
424
|
-
"chevron-right": ICON_PAGE_NEXT
|
|
427
|
+
"chevron-right": ICON_PAGE_NEXT,
|
|
428
|
+
"fast-forward": ICON_FAST_FORWARD,
|
|
429
|
+
"forward-10": ICON_FAST_FORWARD,
|
|
430
|
+
"rewind": ICON_REWIND,
|
|
431
|
+
"replay-10": ICON_REWIND,
|
|
432
|
+
"speed": ICON_SPEED
|
|
425
433
|
};
|
|
426
434
|
var ToolbarController = class {
|
|
427
435
|
el;
|
|
@@ -1389,6 +1397,16 @@ var MediaPlugin = class {
|
|
|
1389
1397
|
}
|
|
1390
1398
|
if (instance.play) {
|
|
1391
1399
|
actions.push(
|
|
1400
|
+
{
|
|
1401
|
+
id: "replay-10",
|
|
1402
|
+
icon: "replay-10",
|
|
1403
|
+
label: "Rewind 10s",
|
|
1404
|
+
type: "button",
|
|
1405
|
+
group: "actions",
|
|
1406
|
+
execute: () => {
|
|
1407
|
+
instance.rewind?.(10);
|
|
1408
|
+
}
|
|
1409
|
+
},
|
|
1392
1410
|
{
|
|
1393
1411
|
id: "play",
|
|
1394
1412
|
icon: "play",
|
|
@@ -1408,6 +1426,26 @@ var MediaPlugin = class {
|
|
|
1408
1426
|
execute: () => {
|
|
1409
1427
|
instance.pause?.();
|
|
1410
1428
|
}
|
|
1429
|
+
},
|
|
1430
|
+
{
|
|
1431
|
+
id: "forward-10",
|
|
1432
|
+
icon: "forward-10",
|
|
1433
|
+
label: "Fast Forward 10s",
|
|
1434
|
+
type: "button",
|
|
1435
|
+
group: "actions",
|
|
1436
|
+
execute: () => {
|
|
1437
|
+
instance.fastForward?.(10);
|
|
1438
|
+
}
|
|
1439
|
+
},
|
|
1440
|
+
{
|
|
1441
|
+
id: "speed",
|
|
1442
|
+
icon: "speed",
|
|
1443
|
+
label: "Playback Speed",
|
|
1444
|
+
type: "button",
|
|
1445
|
+
group: "actions",
|
|
1446
|
+
execute: () => {
|
|
1447
|
+
instance.cycleSpeed?.();
|
|
1448
|
+
}
|
|
1411
1449
|
}
|
|
1412
1450
|
);
|
|
1413
1451
|
}
|
|
@@ -1530,6 +1568,28 @@ var MediaPlugin = class {
|
|
|
1530
1568
|
play: mediaElement ? () => mediaElement?.play() : void 0,
|
|
1531
1569
|
pause: mediaElement ? () => mediaElement?.pause() : void 0,
|
|
1532
1570
|
isPlaying: mediaElement ? () => !mediaElement?.paused : void 0,
|
|
1571
|
+
fastForward: mediaElement ? (seconds = 10) => {
|
|
1572
|
+
if (mediaElement) {
|
|
1573
|
+
mediaElement.currentTime = Math.min(mediaElement.duration || Infinity, mediaElement.currentTime + seconds);
|
|
1574
|
+
}
|
|
1575
|
+
} : void 0,
|
|
1576
|
+
rewind: mediaElement ? (seconds = 10) => {
|
|
1577
|
+
if (mediaElement) {
|
|
1578
|
+
mediaElement.currentTime = Math.max(0, mediaElement.currentTime - seconds);
|
|
1579
|
+
}
|
|
1580
|
+
} : void 0,
|
|
1581
|
+
cycleSpeed: mediaElement ? () => {
|
|
1582
|
+
if (mediaElement) {
|
|
1583
|
+
const speeds = [1, 1.25, 1.5, 2, 0.5];
|
|
1584
|
+
const curIndex = speeds.indexOf(mediaElement.playbackRate);
|
|
1585
|
+
const nextIndex = curIndex === -1 ? 0 : (curIndex + 1) % speeds.length;
|
|
1586
|
+
mediaElement.playbackRate = speeds[nextIndex];
|
|
1587
|
+
}
|
|
1588
|
+
} : void 0,
|
|
1589
|
+
setPlaybackRate: mediaElement ? (rate) => {
|
|
1590
|
+
if (mediaElement) mediaElement.playbackRate = rate;
|
|
1591
|
+
} : void 0,
|
|
1592
|
+
getPlaybackRate: mediaElement ? () => mediaElement?.playbackRate ?? 1 : void 0,
|
|
1533
1593
|
download: () => {
|
|
1534
1594
|
const a = document.createElement("a");
|
|
1535
1595
|
a.href = url;
|
|
@@ -1611,16 +1671,35 @@ var DocxPlugin = class {
|
|
|
1611
1671
|
wrapper.style.transformOrigin = "top center";
|
|
1612
1672
|
wrapper.style.transition = "transform 0.2s ease";
|
|
1613
1673
|
wrapper.style.padding = "24px 16px";
|
|
1614
|
-
wrapper.style.maxWidth = "
|
|
1674
|
+
wrapper.style.maxWidth = "950px";
|
|
1615
1675
|
wrapper.style.margin = "0 auto";
|
|
1616
1676
|
wrapper.style.boxSizing = "border-box";
|
|
1617
1677
|
ctx.container.style.overflow = "auto";
|
|
1618
1678
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
1619
1679
|
ctx.container.appendChild(wrapper);
|
|
1680
|
+
const styleOverride = document.createElement("style");
|
|
1681
|
+
styleOverride.textContent = `
|
|
1682
|
+
.fp-docx-wrapper .docx-wrapper {
|
|
1683
|
+
background: transparent !important;
|
|
1684
|
+
padding: 0 !important;
|
|
1685
|
+
display: flex !important;
|
|
1686
|
+
flex-direction: column !important;
|
|
1687
|
+
align-items: center !important;
|
|
1688
|
+
box-sizing: border-box !important;
|
|
1689
|
+
}
|
|
1690
|
+
.fp-docx-wrapper section.docx {
|
|
1691
|
+
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08) !important;
|
|
1692
|
+
border-radius: 4px !important;
|
|
1693
|
+
margin-bottom: 24px !important;
|
|
1694
|
+
background-color: #ffffff !important;
|
|
1695
|
+
}
|
|
1696
|
+
`;
|
|
1697
|
+
ctx.container.appendChild(styleOverride);
|
|
1620
1698
|
let scale = 1;
|
|
1621
1699
|
let renderedSuccessfully = false;
|
|
1700
|
+
const createdBlobUrls = [];
|
|
1622
1701
|
try {
|
|
1623
|
-
await docx.renderAsync(ctx.buffer, wrapper,
|
|
1702
|
+
await docx.renderAsync(ctx.buffer, wrapper, wrapper, {
|
|
1624
1703
|
inWrapper: true,
|
|
1625
1704
|
ignoreWidth: false,
|
|
1626
1705
|
ignoreHeight: false,
|
|
@@ -1629,19 +1708,25 @@ var DocxPlugin = class {
|
|
|
1629
1708
|
breakPages: true,
|
|
1630
1709
|
experimental: true
|
|
1631
1710
|
});
|
|
1711
|
+
if (!ctx.container.contains(wrapper)) {
|
|
1712
|
+
ctx.container.appendChild(wrapper);
|
|
1713
|
+
}
|
|
1632
1714
|
if (wrapper.children.length > 0 && (wrapper.textContent?.trim().length ?? 0) > 0) {
|
|
1633
1715
|
renderedSuccessfully = true;
|
|
1634
1716
|
}
|
|
1635
1717
|
} catch (err) {
|
|
1636
|
-
console.warn("[DocxPlugin] docx-preview failed, triggering native
|
|
1718
|
+
console.warn("[DocxPlugin] docx-preview failed, triggering native fallback:", err);
|
|
1637
1719
|
}
|
|
1638
1720
|
if (!renderedSuccessfully) {
|
|
1639
1721
|
try {
|
|
1640
1722
|
wrapper.innerHTML = "";
|
|
1641
|
-
this.renderXmlFallback(ctx, wrapper);
|
|
1723
|
+
this.renderXmlFallback(ctx, wrapper, createdBlobUrls);
|
|
1724
|
+
if (!ctx.container.contains(wrapper)) {
|
|
1725
|
+
ctx.container.appendChild(wrapper);
|
|
1726
|
+
}
|
|
1642
1727
|
renderedSuccessfully = true;
|
|
1643
1728
|
} catch (fallbackErr) {
|
|
1644
|
-
console.error("[DocxPlugin]
|
|
1729
|
+
console.error("[DocxPlugin] Native fallback failed:", fallbackErr);
|
|
1645
1730
|
wrapper.innerHTML = `
|
|
1646
1731
|
<div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
|
|
1647
1732
|
<div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
|
|
@@ -1649,10 +1734,17 @@ var DocxPlugin = class {
|
|
|
1649
1734
|
<p style="color: #64748b; margin: 0;">Could not parse document content</p>
|
|
1650
1735
|
</div>
|
|
1651
1736
|
`;
|
|
1737
|
+
if (!ctx.container.contains(wrapper)) {
|
|
1738
|
+
ctx.container.appendChild(wrapper);
|
|
1739
|
+
}
|
|
1652
1740
|
}
|
|
1653
1741
|
}
|
|
1654
1742
|
const cleanup = () => {
|
|
1743
|
+
for (const url of createdBlobUrls) {
|
|
1744
|
+
URL.revokeObjectURL(url);
|
|
1745
|
+
}
|
|
1655
1746
|
wrapper.remove();
|
|
1747
|
+
styleOverride.remove();
|
|
1656
1748
|
ctx.container.innerHTML = "";
|
|
1657
1749
|
};
|
|
1658
1750
|
ctx.signal.addEventListener("abort", cleanup);
|
|
@@ -1689,13 +1781,50 @@ var DocxPlugin = class {
|
|
|
1689
1781
|
}
|
|
1690
1782
|
};
|
|
1691
1783
|
}
|
|
1692
|
-
renderXmlFallback(ctx, wrapper) {
|
|
1784
|
+
renderXmlFallback(ctx, wrapper, createdBlobUrls) {
|
|
1785
|
+
const magic = new Uint8Array(ctx.buffer.slice(0, 8));
|
|
1786
|
+
if (magic[0] === 208 && magic[1] === 207 && magic[2] === 17 && magic[3] === 224) {
|
|
1787
|
+
this.renderBinaryDocFallback(ctx, wrapper);
|
|
1788
|
+
return;
|
|
1789
|
+
}
|
|
1693
1790
|
const unzipped = unzipSync(new Uint8Array(ctx.buffer));
|
|
1694
|
-
const
|
|
1791
|
+
const docKey = Object.keys(unzipped).find((k) => k.replace(/^[./\\]+/, "").toLowerCase() === "word/document.xml");
|
|
1792
|
+
const docXmlEntry = docKey ? unzipped[docKey] : void 0;
|
|
1695
1793
|
if (!docXmlEntry) throw new Error("Missing word/document.xml in DOCX package");
|
|
1696
1794
|
const xmlStr = strFromU8(docXmlEntry);
|
|
1697
1795
|
const parser = new DOMParser();
|
|
1698
1796
|
const doc = parser.parseFromString(xmlStr, "application/xml");
|
|
1797
|
+
const imageMap = {};
|
|
1798
|
+
const relsKey = Object.keys(unzipped).find((k) => k.replace(/^[./\\]+/, "").toLowerCase() === "word/_rels/document.xml.rels");
|
|
1799
|
+
if (relsKey && unzipped[relsKey]) {
|
|
1800
|
+
try {
|
|
1801
|
+
const relsXml = strFromU8(unzipped[relsKey]);
|
|
1802
|
+
const relsDoc = parser.parseFromString(relsXml, "application/xml");
|
|
1803
|
+
const relEls = Array.from(relsDoc.getElementsByTagName("Relationship"));
|
|
1804
|
+
for (const rel of relEls) {
|
|
1805
|
+
const rId = rel.getAttribute("Id");
|
|
1806
|
+
const target = rel.getAttribute("Target");
|
|
1807
|
+
if (rId && target) {
|
|
1808
|
+
const cleanTarget = target.replace(/^\.\.\//, "").replace(/^\//, "");
|
|
1809
|
+
const fullTargetKey = Object.keys(unzipped).find((k) => {
|
|
1810
|
+
const norm = k.replace(/^[./\\]+/, "").toLowerCase();
|
|
1811
|
+
return norm === ("word/" + cleanTarget).toLowerCase() || norm === cleanTarget.toLowerCase();
|
|
1812
|
+
});
|
|
1813
|
+
if (fullTargetKey && unzipped[fullTargetKey]) {
|
|
1814
|
+
const bytes = unzipped[fullTargetKey];
|
|
1815
|
+
const ext = cleanTarget.split(".").pop()?.toLowerCase() || "png";
|
|
1816
|
+
const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : ext === "gif" ? "image/gif" : ext === "svg" ? "image/svg+xml" : "image/png";
|
|
1817
|
+
const blob = new Blob([bytes], { type: mime });
|
|
1818
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
1819
|
+
imageMap[rId] = blobUrl;
|
|
1820
|
+
createdBlobUrls.push(blobUrl);
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
} catch (relsErr) {
|
|
1825
|
+
console.warn("[DocxPlugin] Error parsing relationships:", relsErr);
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1699
1828
|
const card = document.createElement("div");
|
|
1700
1829
|
card.className = "fp-docx-page-card";
|
|
1701
1830
|
card.style.backgroundColor = "#ffffff";
|
|
@@ -1713,7 +1842,7 @@ var DocxPlugin = class {
|
|
|
1713
1842
|
const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
|
|
1714
1843
|
const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
|
|
1715
1844
|
const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
|
|
1716
|
-
const textContent = this.extractParagraphHtml(child);
|
|
1845
|
+
const textContent = this.extractParagraphHtml(child, imageMap);
|
|
1717
1846
|
if (!textContent.trim()) {
|
|
1718
1847
|
html += '<div style="height: 10px;"></div>';
|
|
1719
1848
|
continue;
|
|
@@ -1739,7 +1868,7 @@ var DocxPlugin = class {
|
|
|
1739
1868
|
html += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
1740
1869
|
const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
|
|
1741
1870
|
cells.forEach((tc) => {
|
|
1742
|
-
const cellText = this.extractParagraphHtml(tc);
|
|
1871
|
+
const cellText = this.extractParagraphHtml(tc, imageMap);
|
|
1743
1872
|
html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || " "}</td>`;
|
|
1744
1873
|
});
|
|
1745
1874
|
html += "</tr>";
|
|
@@ -1747,34 +1876,63 @@ var DocxPlugin = class {
|
|
|
1747
1876
|
html += "</table>";
|
|
1748
1877
|
}
|
|
1749
1878
|
}
|
|
1750
|
-
card.innerHTML =
|
|
1751
|
-
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "img", "div"],
|
|
1879
|
+
card.innerHTML = DOMPurify2.sanitize(html, {
|
|
1880
|
+
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
|
|
1752
1881
|
ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
|
|
1753
1882
|
});
|
|
1754
1883
|
wrapper.appendChild(card);
|
|
1755
1884
|
}
|
|
1756
|
-
extractParagraphHtml(pElement) {
|
|
1885
|
+
extractParagraphHtml(pElement, imageMap = {}) {
|
|
1757
1886
|
let result = "";
|
|
1887
|
+
const drawings = Array.from(pElement.getElementsByTagNameNS("*", "drawing"));
|
|
1888
|
+
for (const drawing of drawings) {
|
|
1889
|
+
const blip = drawing.getElementsByTagNameNS("*", "blip")[0];
|
|
1890
|
+
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
1891
|
+
if (rId && imageMap[rId]) {
|
|
1892
|
+
result += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1758
1895
|
const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
|
|
1759
|
-
if (runs.length === 0) {
|
|
1760
|
-
return
|
|
1896
|
+
if (runs.length === 0 && !result) {
|
|
1897
|
+
return DOMPurify2.sanitize(pElement.textContent || "");
|
|
1761
1898
|
}
|
|
1762
1899
|
for (const r of runs) {
|
|
1900
|
+
const blip = r.getElementsByTagNameNS("*", "blip")[0] || r.getElementsByTagNameNS("*", "imagedata")[0];
|
|
1901
|
+
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
1902
|
+
if (rId && imageMap[rId]) {
|
|
1903
|
+
result += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
|
|
1904
|
+
}
|
|
1905
|
+
const brs = r.getElementsByTagNameNS("*", "br");
|
|
1906
|
+
for (let i = 0; i < brs.length; i++) {
|
|
1907
|
+
result += "<br/>";
|
|
1908
|
+
}
|
|
1909
|
+
const tabs = r.getElementsByTagNameNS("*", "tab");
|
|
1910
|
+
if (tabs.length > 0) {
|
|
1911
|
+
result += " ";
|
|
1912
|
+
}
|
|
1763
1913
|
const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
|
|
1764
1914
|
const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
|
|
1765
1915
|
const isItalic = !!rPr?.getElementsByTagNameNS("*", "i")[0];
|
|
1766
1916
|
const isUnderline = !!rPr?.getElementsByTagNameNS("*", "u")[0];
|
|
1917
|
+
const isStrike = !!rPr?.getElementsByTagNameNS("*", "strike")[0];
|
|
1767
1918
|
const colorNode = rPr?.getElementsByTagNameNS("*", "color")[0];
|
|
1768
1919
|
const colorVal = colorNode?.getAttribute("w:val") || colorNode?.getAttribute("val");
|
|
1920
|
+
const szNode = rPr?.getElementsByTagNameNS("*", "sz")[0];
|
|
1921
|
+
const szVal = szNode?.getAttribute("w:val") || szNode?.getAttribute("val");
|
|
1769
1922
|
const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
|
|
1770
1923
|
let text = texts.map((t) => t.textContent || "").join("");
|
|
1771
1924
|
if (!text) continue;
|
|
1772
|
-
text =
|
|
1925
|
+
text = DOMPurify2.sanitize(text);
|
|
1773
1926
|
let styles = "";
|
|
1774
1927
|
if (isBold) styles += "font-weight: bold; ";
|
|
1775
1928
|
if (isItalic) styles += "font-style: italic; ";
|
|
1776
1929
|
if (isUnderline) styles += "text-decoration: underline; ";
|
|
1930
|
+
if (isStrike) styles += "text-decoration: line-through; ";
|
|
1777
1931
|
if (colorVal && colorVal !== "auto") styles += `color: #${colorVal}; `;
|
|
1932
|
+
if (szVal) {
|
|
1933
|
+
const pt = parseInt(szVal, 10) / 2;
|
|
1934
|
+
if (!isNaN(pt) && pt > 0) styles += `font-size: ${pt}pt; `;
|
|
1935
|
+
}
|
|
1778
1936
|
if (styles) {
|
|
1779
1937
|
result += `<span style="${styles}">${text}</span>`;
|
|
1780
1938
|
} else {
|
|
@@ -1783,6 +1941,52 @@ var DocxPlugin = class {
|
|
|
1783
1941
|
}
|
|
1784
1942
|
return result;
|
|
1785
1943
|
}
|
|
1944
|
+
renderBinaryDocFallback(ctx, wrapper) {
|
|
1945
|
+
const card = document.createElement("div");
|
|
1946
|
+
card.className = "fp-docx-page-card";
|
|
1947
|
+
card.style.backgroundColor = "#ffffff";
|
|
1948
|
+
card.style.borderRadius = "6px";
|
|
1949
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
1950
|
+
card.style.padding = "48px 56px";
|
|
1951
|
+
card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
1952
|
+
card.style.color = "#1e293b";
|
|
1953
|
+
card.style.lineHeight = "1.6";
|
|
1954
|
+
try {
|
|
1955
|
+
const cfbf = new CfbfReader(ctx.buffer);
|
|
1956
|
+
const wordDocStream = cfbf.readStream("WordDocument");
|
|
1957
|
+
if (wordDocStream && wordDocStream.length >= 512) {
|
|
1958
|
+
const text2 = this.extractReadableStrings(wordDocStream);
|
|
1959
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify2.sanitize(text2)}</div>`;
|
|
1960
|
+
wrapper.appendChild(card);
|
|
1961
|
+
return;
|
|
1962
|
+
}
|
|
1963
|
+
} catch {
|
|
1964
|
+
}
|
|
1965
|
+
const text = this.extractReadableStrings(new Uint8Array(ctx.buffer));
|
|
1966
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify2.sanitize(text)}</div>`;
|
|
1967
|
+
wrapper.appendChild(card);
|
|
1968
|
+
}
|
|
1969
|
+
extractReadableStrings(bytes) {
|
|
1970
|
+
let result = "";
|
|
1971
|
+
let current = "";
|
|
1972
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
1973
|
+
const b = bytes[i];
|
|
1974
|
+
if (b >= 32 && b <= 126 || b === 10 || b === 13 || b === 9) {
|
|
1975
|
+
current += String.fromCharCode(b);
|
|
1976
|
+
} else if (b === 0 && i + 1 < bytes.length && bytes[i + 1] >= 32 && bytes[i + 1] <= 126) {
|
|
1977
|
+
continue;
|
|
1978
|
+
} else {
|
|
1979
|
+
if (current.trim().length > 3) {
|
|
1980
|
+
result += current.trim() + "\n\n";
|
|
1981
|
+
}
|
|
1982
|
+
current = "";
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
if (current.trim().length > 3) {
|
|
1986
|
+
result += current.trim();
|
|
1987
|
+
}
|
|
1988
|
+
return result;
|
|
1989
|
+
}
|
|
1786
1990
|
};
|
|
1787
1991
|
function docxPlugin() {
|
|
1788
1992
|
return new DocxPlugin();
|
|
@@ -2594,7 +2798,7 @@ var MarkdownPlugin = class {
|
|
|
2594
2798
|
gfm: true,
|
|
2595
2799
|
breaks: true
|
|
2596
2800
|
});
|
|
2597
|
-
const cleanHtml =
|
|
2801
|
+
const cleanHtml = DOMPurify2.sanitize(rawHtml, {
|
|
2598
2802
|
USE_PROFILES: { html: true }
|
|
2599
2803
|
});
|
|
2600
2804
|
const wrapper = document.createElement("div");
|
|
@@ -3309,7 +3513,7 @@ var HtmlPreviewPlugin = class {
|
|
|
3309
3513
|
}
|
|
3310
3514
|
async render(ctx) {
|
|
3311
3515
|
const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
|
|
3312
|
-
const sanitized =
|
|
3516
|
+
const sanitized = DOMPurify2.sanitize(rawHtml, {
|
|
3313
3517
|
WHOLE_DOCUMENT: true,
|
|
3314
3518
|
ADD_TAGS: ["style", "link"],
|
|
3315
3519
|
ADD_ATTR: ["target", "rel"]
|
|
@@ -3552,7 +3756,7 @@ var OpenDocumentPlugin = class {
|
|
|
3552
3756
|
wrapper.style.padding = "48px";
|
|
3553
3757
|
wrapper.style.minHeight = "100%";
|
|
3554
3758
|
const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
|
|
3555
|
-
wrapper.innerHTML =
|
|
3759
|
+
wrapper.innerHTML = DOMPurify2.sanitize(bodyHtml, {
|
|
3556
3760
|
ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub"],
|
|
3557
3761
|
ADD_ATTR: ["style", "colspan", "rowspan"]
|
|
3558
3762
|
});
|
|
@@ -4072,24 +4276,24 @@ var DocPlugin = class {
|
|
|
4072
4276
|
html += "</ul>";
|
|
4073
4277
|
inList = false;
|
|
4074
4278
|
}
|
|
4075
|
-
html += `<h2 style="font-size: 18px; font-weight: 700; color: #1e3a8a; margin: 20px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${
|
|
4279
|
+
html += `<h2 style="font-size: 18px; font-weight: 700; color: #1e3a8a; margin: 20px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${DOMPurify2.sanitize(line)}</h2>`;
|
|
4076
4280
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
4077
4281
|
if (!inList) {
|
|
4078
4282
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
4079
4283
|
inList = true;
|
|
4080
4284
|
}
|
|
4081
4285
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
4082
|
-
html += `<li style="margin: 4px 0; line-height: 1.6;">${
|
|
4286
|
+
html += `<li style="margin: 4px 0; line-height: 1.6;">${DOMPurify2.sanitize(bulletText)}</li>`;
|
|
4083
4287
|
} else {
|
|
4084
4288
|
if (inList) {
|
|
4085
4289
|
html += "</ul>";
|
|
4086
4290
|
inList = false;
|
|
4087
4291
|
}
|
|
4088
|
-
html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${
|
|
4292
|
+
html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${DOMPurify2.sanitize(line)}</p>`;
|
|
4089
4293
|
}
|
|
4090
4294
|
}
|
|
4091
4295
|
if (inList) html += "</ul>";
|
|
4092
|
-
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${
|
|
4296
|
+
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify2.sanitize(filename)})</p>`;
|
|
4093
4297
|
}
|
|
4094
4298
|
};
|
|
4095
4299
|
function docPlugin() {
|
|
@@ -4244,10 +4448,10 @@ var PptPlugin = class {
|
|
|
4244
4448
|
</div>
|
|
4245
4449
|
<div style="text-align: center; width: 100%;">
|
|
4246
4450
|
<h1 style="font-size: ${idx === 1 ? "36px" : "28px"}; color: #1e3a8a; margin: 0 0 24px; font-family: -apple-system, BlinkMacSystemFont, sans-serif; font-weight: 700;">
|
|
4247
|
-
${
|
|
4451
|
+
${DOMPurify2.sanitize(s.title || `Slide ${idx}`)}
|
|
4248
4452
|
</h1>
|
|
4249
4453
|
<div style="display: flex; flex-direction: column; gap: 12px; max-width: 80%; margin: 0 auto; text-align: ${idx === 1 ? "center" : "left"};">
|
|
4250
|
-
${s.texts.map((t) => `<div style="font-size: 18px; color: #334155; line-height: 1.5; font-family: -apple-system, BlinkMacSystemFont, sans-serif;">${
|
|
4454
|
+
${s.texts.map((t) => `<div style="font-size: 18px; color: #334155; line-height: 1.5; font-family: -apple-system, BlinkMacSystemFont, sans-serif;">${DOMPurify2.sanitize(t)}</div>`).join("")}
|
|
4251
4455
|
</div>
|
|
4252
4456
|
</div>
|
|
4253
4457
|
`;
|