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