@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/angular.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Component, ChangeDetectionStrategy, Input, Output, ViewChild, EventEmitter as EventEmitter$1 } from '@angular/core';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
|
-
import
|
|
3
|
+
import DOMPurify2 from 'dompurify';
|
|
4
4
|
import * as docx from 'docx-preview';
|
|
5
5
|
import { unzipSync, strFromU8, unzip } from 'fflate';
|
|
6
6
|
import * as XLSX from 'xlsx';
|
|
@@ -388,7 +388,7 @@ async function sourceToArrayBuffer(source, signal) {
|
|
|
388
388
|
return { buffer, metadata };
|
|
389
389
|
}
|
|
390
390
|
function sanitizeSVG(svg) {
|
|
391
|
-
return
|
|
391
|
+
return DOMPurify2.sanitize(svg, {
|
|
392
392
|
USE_PROFILES: { svg: true, svgFilters: true }
|
|
393
393
|
});
|
|
394
394
|
}
|
|
@@ -448,6 +448,9 @@ var ICON_THUMBNAILS = `<svg width="24" height="24" viewBox="0 0 24 24" fill="non
|
|
|
448
448
|
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>`;
|
|
449
449
|
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>`;
|
|
450
450
|
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>`;
|
|
451
|
+
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>`;
|
|
452
|
+
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>`;
|
|
453
|
+
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>`;
|
|
451
454
|
var ICON_MAP = {
|
|
452
455
|
"zoom-in": ICON_ZOOM_IN,
|
|
453
456
|
"zoom-out": ICON_ZOOM_OUT,
|
|
@@ -468,7 +471,12 @@ var ICON_MAP = {
|
|
|
468
471
|
"page-prev": ICON_PAGE_PREV,
|
|
469
472
|
"page-next": ICON_PAGE_NEXT,
|
|
470
473
|
"chevron-left": ICON_PAGE_PREV,
|
|
471
|
-
"chevron-right": ICON_PAGE_NEXT
|
|
474
|
+
"chevron-right": ICON_PAGE_NEXT,
|
|
475
|
+
"fast-forward": ICON_FAST_FORWARD,
|
|
476
|
+
"forward-10": ICON_FAST_FORWARD,
|
|
477
|
+
"rewind": ICON_REWIND,
|
|
478
|
+
"replay-10": ICON_REWIND,
|
|
479
|
+
"speed": ICON_SPEED
|
|
472
480
|
};
|
|
473
481
|
var ToolbarController = class {
|
|
474
482
|
el;
|
|
@@ -1436,6 +1444,16 @@ var MediaPlugin = class {
|
|
|
1436
1444
|
}
|
|
1437
1445
|
if (instance.play) {
|
|
1438
1446
|
actions.push(
|
|
1447
|
+
{
|
|
1448
|
+
id: "replay-10",
|
|
1449
|
+
icon: "replay-10",
|
|
1450
|
+
label: "Rewind 10s",
|
|
1451
|
+
type: "button",
|
|
1452
|
+
group: "actions",
|
|
1453
|
+
execute: () => {
|
|
1454
|
+
instance.rewind?.(10);
|
|
1455
|
+
}
|
|
1456
|
+
},
|
|
1439
1457
|
{
|
|
1440
1458
|
id: "play",
|
|
1441
1459
|
icon: "play",
|
|
@@ -1455,6 +1473,26 @@ var MediaPlugin = class {
|
|
|
1455
1473
|
execute: () => {
|
|
1456
1474
|
instance.pause?.();
|
|
1457
1475
|
}
|
|
1476
|
+
},
|
|
1477
|
+
{
|
|
1478
|
+
id: "forward-10",
|
|
1479
|
+
icon: "forward-10",
|
|
1480
|
+
label: "Fast Forward 10s",
|
|
1481
|
+
type: "button",
|
|
1482
|
+
group: "actions",
|
|
1483
|
+
execute: () => {
|
|
1484
|
+
instance.fastForward?.(10);
|
|
1485
|
+
}
|
|
1486
|
+
},
|
|
1487
|
+
{
|
|
1488
|
+
id: "speed",
|
|
1489
|
+
icon: "speed",
|
|
1490
|
+
label: "Playback Speed",
|
|
1491
|
+
type: "button",
|
|
1492
|
+
group: "actions",
|
|
1493
|
+
execute: () => {
|
|
1494
|
+
instance.cycleSpeed?.();
|
|
1495
|
+
}
|
|
1458
1496
|
}
|
|
1459
1497
|
);
|
|
1460
1498
|
}
|
|
@@ -1577,6 +1615,28 @@ var MediaPlugin = class {
|
|
|
1577
1615
|
play: mediaElement ? () => mediaElement?.play() : void 0,
|
|
1578
1616
|
pause: mediaElement ? () => mediaElement?.pause() : void 0,
|
|
1579
1617
|
isPlaying: mediaElement ? () => !mediaElement?.paused : void 0,
|
|
1618
|
+
fastForward: mediaElement ? (seconds = 10) => {
|
|
1619
|
+
if (mediaElement) {
|
|
1620
|
+
mediaElement.currentTime = Math.min(mediaElement.duration || Infinity, mediaElement.currentTime + seconds);
|
|
1621
|
+
}
|
|
1622
|
+
} : void 0,
|
|
1623
|
+
rewind: mediaElement ? (seconds = 10) => {
|
|
1624
|
+
if (mediaElement) {
|
|
1625
|
+
mediaElement.currentTime = Math.max(0, mediaElement.currentTime - seconds);
|
|
1626
|
+
}
|
|
1627
|
+
} : void 0,
|
|
1628
|
+
cycleSpeed: mediaElement ? () => {
|
|
1629
|
+
if (mediaElement) {
|
|
1630
|
+
const speeds = [1, 1.25, 1.5, 2, 0.5];
|
|
1631
|
+
const curIndex = speeds.indexOf(mediaElement.playbackRate);
|
|
1632
|
+
const nextIndex = curIndex === -1 ? 0 : (curIndex + 1) % speeds.length;
|
|
1633
|
+
mediaElement.playbackRate = speeds[nextIndex];
|
|
1634
|
+
}
|
|
1635
|
+
} : void 0,
|
|
1636
|
+
setPlaybackRate: mediaElement ? (rate) => {
|
|
1637
|
+
if (mediaElement) mediaElement.playbackRate = rate;
|
|
1638
|
+
} : void 0,
|
|
1639
|
+
getPlaybackRate: mediaElement ? () => mediaElement?.playbackRate ?? 1 : void 0,
|
|
1580
1640
|
download: () => {
|
|
1581
1641
|
const a = document.createElement("a");
|
|
1582
1642
|
a.href = url;
|
|
@@ -1658,16 +1718,35 @@ var DocxPlugin = class {
|
|
|
1658
1718
|
wrapper.style.transformOrigin = "top center";
|
|
1659
1719
|
wrapper.style.transition = "transform 0.2s ease";
|
|
1660
1720
|
wrapper.style.padding = "24px 16px";
|
|
1661
|
-
wrapper.style.maxWidth = "
|
|
1721
|
+
wrapper.style.maxWidth = "950px";
|
|
1662
1722
|
wrapper.style.margin = "0 auto";
|
|
1663
1723
|
wrapper.style.boxSizing = "border-box";
|
|
1664
1724
|
ctx.container.style.overflow = "auto";
|
|
1665
1725
|
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
1666
1726
|
ctx.container.appendChild(wrapper);
|
|
1727
|
+
const styleOverride = document.createElement("style");
|
|
1728
|
+
styleOverride.textContent = `
|
|
1729
|
+
.fp-docx-wrapper .docx-wrapper {
|
|
1730
|
+
background: transparent !important;
|
|
1731
|
+
padding: 0 !important;
|
|
1732
|
+
display: flex !important;
|
|
1733
|
+
flex-direction: column !important;
|
|
1734
|
+
align-items: center !important;
|
|
1735
|
+
box-sizing: border-box !important;
|
|
1736
|
+
}
|
|
1737
|
+
.fp-docx-wrapper section.docx {
|
|
1738
|
+
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08) !important;
|
|
1739
|
+
border-radius: 4px !important;
|
|
1740
|
+
margin-bottom: 24px !important;
|
|
1741
|
+
background-color: #ffffff !important;
|
|
1742
|
+
}
|
|
1743
|
+
`;
|
|
1744
|
+
ctx.container.appendChild(styleOverride);
|
|
1667
1745
|
let scale = 1;
|
|
1668
1746
|
let renderedSuccessfully = false;
|
|
1747
|
+
const createdBlobUrls = [];
|
|
1669
1748
|
try {
|
|
1670
|
-
await docx.renderAsync(ctx.buffer, wrapper,
|
|
1749
|
+
await docx.renderAsync(ctx.buffer, wrapper, wrapper, {
|
|
1671
1750
|
inWrapper: true,
|
|
1672
1751
|
ignoreWidth: false,
|
|
1673
1752
|
ignoreHeight: false,
|
|
@@ -1676,19 +1755,25 @@ var DocxPlugin = class {
|
|
|
1676
1755
|
breakPages: true,
|
|
1677
1756
|
experimental: true
|
|
1678
1757
|
});
|
|
1758
|
+
if (!ctx.container.contains(wrapper)) {
|
|
1759
|
+
ctx.container.appendChild(wrapper);
|
|
1760
|
+
}
|
|
1679
1761
|
if (wrapper.children.length > 0 && (wrapper.textContent?.trim().length ?? 0) > 0) {
|
|
1680
1762
|
renderedSuccessfully = true;
|
|
1681
1763
|
}
|
|
1682
1764
|
} catch (err) {
|
|
1683
|
-
console.warn("[DocxPlugin] docx-preview failed, triggering native
|
|
1765
|
+
console.warn("[DocxPlugin] docx-preview failed, triggering native fallback:", err);
|
|
1684
1766
|
}
|
|
1685
1767
|
if (!renderedSuccessfully) {
|
|
1686
1768
|
try {
|
|
1687
1769
|
wrapper.innerHTML = "";
|
|
1688
|
-
this.renderXmlFallback(ctx, wrapper);
|
|
1770
|
+
this.renderXmlFallback(ctx, wrapper, createdBlobUrls);
|
|
1771
|
+
if (!ctx.container.contains(wrapper)) {
|
|
1772
|
+
ctx.container.appendChild(wrapper);
|
|
1773
|
+
}
|
|
1689
1774
|
renderedSuccessfully = true;
|
|
1690
1775
|
} catch (fallbackErr) {
|
|
1691
|
-
console.error("[DocxPlugin]
|
|
1776
|
+
console.error("[DocxPlugin] Native fallback failed:", fallbackErr);
|
|
1692
1777
|
wrapper.innerHTML = `
|
|
1693
1778
|
<div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
|
|
1694
1779
|
<div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
|
|
@@ -1696,10 +1781,17 @@ var DocxPlugin = class {
|
|
|
1696
1781
|
<p style="color: #64748b; margin: 0;">Could not parse document content</p>
|
|
1697
1782
|
</div>
|
|
1698
1783
|
`;
|
|
1784
|
+
if (!ctx.container.contains(wrapper)) {
|
|
1785
|
+
ctx.container.appendChild(wrapper);
|
|
1786
|
+
}
|
|
1699
1787
|
}
|
|
1700
1788
|
}
|
|
1701
1789
|
const cleanup = () => {
|
|
1790
|
+
for (const url of createdBlobUrls) {
|
|
1791
|
+
URL.revokeObjectURL(url);
|
|
1792
|
+
}
|
|
1702
1793
|
wrapper.remove();
|
|
1794
|
+
styleOverride.remove();
|
|
1703
1795
|
ctx.container.innerHTML = "";
|
|
1704
1796
|
};
|
|
1705
1797
|
ctx.signal.addEventListener("abort", cleanup);
|
|
@@ -1736,13 +1828,50 @@ var DocxPlugin = class {
|
|
|
1736
1828
|
}
|
|
1737
1829
|
};
|
|
1738
1830
|
}
|
|
1739
|
-
renderXmlFallback(ctx, wrapper) {
|
|
1831
|
+
renderXmlFallback(ctx, wrapper, createdBlobUrls) {
|
|
1832
|
+
const magic = new Uint8Array(ctx.buffer.slice(0, 8));
|
|
1833
|
+
if (magic[0] === 208 && magic[1] === 207 && magic[2] === 17 && magic[3] === 224) {
|
|
1834
|
+
this.renderBinaryDocFallback(ctx, wrapper);
|
|
1835
|
+
return;
|
|
1836
|
+
}
|
|
1740
1837
|
const unzipped = unzipSync(new Uint8Array(ctx.buffer));
|
|
1741
|
-
const
|
|
1838
|
+
const docKey = Object.keys(unzipped).find((k) => k.replace(/^[./\\]+/, "").toLowerCase() === "word/document.xml");
|
|
1839
|
+
const docXmlEntry = docKey ? unzipped[docKey] : void 0;
|
|
1742
1840
|
if (!docXmlEntry) throw new Error("Missing word/document.xml in DOCX package");
|
|
1743
1841
|
const xmlStr = strFromU8(docXmlEntry);
|
|
1744
1842
|
const parser = new DOMParser();
|
|
1745
1843
|
const doc = parser.parseFromString(xmlStr, "application/xml");
|
|
1844
|
+
const imageMap = {};
|
|
1845
|
+
const relsKey = Object.keys(unzipped).find((k) => k.replace(/^[./\\]+/, "").toLowerCase() === "word/_rels/document.xml.rels");
|
|
1846
|
+
if (relsKey && unzipped[relsKey]) {
|
|
1847
|
+
try {
|
|
1848
|
+
const relsXml = strFromU8(unzipped[relsKey]);
|
|
1849
|
+
const relsDoc = parser.parseFromString(relsXml, "application/xml");
|
|
1850
|
+
const relEls = Array.from(relsDoc.getElementsByTagName("Relationship"));
|
|
1851
|
+
for (const rel of relEls) {
|
|
1852
|
+
const rId = rel.getAttribute("Id");
|
|
1853
|
+
const target = rel.getAttribute("Target");
|
|
1854
|
+
if (rId && target) {
|
|
1855
|
+
const cleanTarget = target.replace(/^\.\.\//, "").replace(/^\//, "");
|
|
1856
|
+
const fullTargetKey = Object.keys(unzipped).find((k) => {
|
|
1857
|
+
const norm = k.replace(/^[./\\]+/, "").toLowerCase();
|
|
1858
|
+
return norm === ("word/" + cleanTarget).toLowerCase() || norm === cleanTarget.toLowerCase();
|
|
1859
|
+
});
|
|
1860
|
+
if (fullTargetKey && unzipped[fullTargetKey]) {
|
|
1861
|
+
const bytes = unzipped[fullTargetKey];
|
|
1862
|
+
const ext = cleanTarget.split(".").pop()?.toLowerCase() || "png";
|
|
1863
|
+
const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : ext === "gif" ? "image/gif" : ext === "svg" ? "image/svg+xml" : "image/png";
|
|
1864
|
+
const blob = new Blob([bytes], { type: mime });
|
|
1865
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
1866
|
+
imageMap[rId] = blobUrl;
|
|
1867
|
+
createdBlobUrls.push(blobUrl);
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
} catch (relsErr) {
|
|
1872
|
+
console.warn("[DocxPlugin] Error parsing relationships:", relsErr);
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1746
1875
|
const card = document.createElement("div");
|
|
1747
1876
|
card.className = "fp-docx-page-card";
|
|
1748
1877
|
card.style.backgroundColor = "#ffffff";
|
|
@@ -1760,7 +1889,7 @@ var DocxPlugin = class {
|
|
|
1760
1889
|
const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
|
|
1761
1890
|
const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
|
|
1762
1891
|
const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
|
|
1763
|
-
const textContent = this.extractParagraphHtml(child);
|
|
1892
|
+
const textContent = this.extractParagraphHtml(child, imageMap);
|
|
1764
1893
|
if (!textContent.trim()) {
|
|
1765
1894
|
html += '<div style="height: 10px;"></div>';
|
|
1766
1895
|
continue;
|
|
@@ -1786,7 +1915,7 @@ var DocxPlugin = class {
|
|
|
1786
1915
|
html += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
1787
1916
|
const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
|
|
1788
1917
|
cells.forEach((tc) => {
|
|
1789
|
-
const cellText = this.extractParagraphHtml(tc);
|
|
1918
|
+
const cellText = this.extractParagraphHtml(tc, imageMap);
|
|
1790
1919
|
html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || " "}</td>`;
|
|
1791
1920
|
});
|
|
1792
1921
|
html += "</tr>";
|
|
@@ -1794,34 +1923,63 @@ var DocxPlugin = class {
|
|
|
1794
1923
|
html += "</table>";
|
|
1795
1924
|
}
|
|
1796
1925
|
}
|
|
1797
|
-
card.innerHTML =
|
|
1798
|
-
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "img", "div"],
|
|
1926
|
+
card.innerHTML = DOMPurify2.sanitize(html, {
|
|
1927
|
+
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "s", "strike", "img", "div", "br"],
|
|
1799
1928
|
ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
|
|
1800
1929
|
});
|
|
1801
1930
|
wrapper.appendChild(card);
|
|
1802
1931
|
}
|
|
1803
|
-
extractParagraphHtml(pElement) {
|
|
1932
|
+
extractParagraphHtml(pElement, imageMap = {}) {
|
|
1804
1933
|
let result = "";
|
|
1934
|
+
const drawings = Array.from(pElement.getElementsByTagNameNS("*", "drawing"));
|
|
1935
|
+
for (const drawing of drawings) {
|
|
1936
|
+
const blip = drawing.getElementsByTagNameNS("*", "blip")[0];
|
|
1937
|
+
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
1938
|
+
if (rId && imageMap[rId]) {
|
|
1939
|
+
result += `<div style="text-align:center; margin: 12px 0;"><img src="${imageMap[rId]}" style="max-width: 100%; height: auto; border-radius: 4px;" /></div>`;
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1805
1942
|
const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
|
|
1806
|
-
if (runs.length === 0) {
|
|
1807
|
-
return
|
|
1943
|
+
if (runs.length === 0 && !result) {
|
|
1944
|
+
return DOMPurify2.sanitize(pElement.textContent || "");
|
|
1808
1945
|
}
|
|
1809
1946
|
for (const r of runs) {
|
|
1947
|
+
const blip = r.getElementsByTagNameNS("*", "blip")[0] || r.getElementsByTagNameNS("*", "imagedata")[0];
|
|
1948
|
+
const rId = blip?.getAttribute("r:embed") || blip?.getAttribute("r:id");
|
|
1949
|
+
if (rId && imageMap[rId]) {
|
|
1950
|
+
result += `<img src="${imageMap[rId]}" style="max-width: 100%; height: auto; display: inline-block; margin: 4px;" />`;
|
|
1951
|
+
}
|
|
1952
|
+
const brs = r.getElementsByTagNameNS("*", "br");
|
|
1953
|
+
for (let i = 0; i < brs.length; i++) {
|
|
1954
|
+
result += "<br/>";
|
|
1955
|
+
}
|
|
1956
|
+
const tabs = r.getElementsByTagNameNS("*", "tab");
|
|
1957
|
+
if (tabs.length > 0) {
|
|
1958
|
+
result += " ";
|
|
1959
|
+
}
|
|
1810
1960
|
const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
|
|
1811
1961
|
const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
|
|
1812
1962
|
const isItalic = !!rPr?.getElementsByTagNameNS("*", "i")[0];
|
|
1813
1963
|
const isUnderline = !!rPr?.getElementsByTagNameNS("*", "u")[0];
|
|
1964
|
+
const isStrike = !!rPr?.getElementsByTagNameNS("*", "strike")[0];
|
|
1814
1965
|
const colorNode = rPr?.getElementsByTagNameNS("*", "color")[0];
|
|
1815
1966
|
const colorVal = colorNode?.getAttribute("w:val") || colorNode?.getAttribute("val");
|
|
1967
|
+
const szNode = rPr?.getElementsByTagNameNS("*", "sz")[0];
|
|
1968
|
+
const szVal = szNode?.getAttribute("w:val") || szNode?.getAttribute("val");
|
|
1816
1969
|
const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
|
|
1817
1970
|
let text = texts.map((t) => t.textContent || "").join("");
|
|
1818
1971
|
if (!text) continue;
|
|
1819
|
-
text =
|
|
1972
|
+
text = DOMPurify2.sanitize(text);
|
|
1820
1973
|
let styles = "";
|
|
1821
1974
|
if (isBold) styles += "font-weight: bold; ";
|
|
1822
1975
|
if (isItalic) styles += "font-style: italic; ";
|
|
1823
1976
|
if (isUnderline) styles += "text-decoration: underline; ";
|
|
1977
|
+
if (isStrike) styles += "text-decoration: line-through; ";
|
|
1824
1978
|
if (colorVal && colorVal !== "auto") styles += `color: #${colorVal}; `;
|
|
1979
|
+
if (szVal) {
|
|
1980
|
+
const pt = parseInt(szVal, 10) / 2;
|
|
1981
|
+
if (!isNaN(pt) && pt > 0) styles += `font-size: ${pt}pt; `;
|
|
1982
|
+
}
|
|
1825
1983
|
if (styles) {
|
|
1826
1984
|
result += `<span style="${styles}">${text}</span>`;
|
|
1827
1985
|
} else {
|
|
@@ -1830,6 +1988,52 @@ var DocxPlugin = class {
|
|
|
1830
1988
|
}
|
|
1831
1989
|
return result;
|
|
1832
1990
|
}
|
|
1991
|
+
renderBinaryDocFallback(ctx, wrapper) {
|
|
1992
|
+
const card = document.createElement("div");
|
|
1993
|
+
card.className = "fp-docx-page-card";
|
|
1994
|
+
card.style.backgroundColor = "#ffffff";
|
|
1995
|
+
card.style.borderRadius = "6px";
|
|
1996
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
1997
|
+
card.style.padding = "48px 56px";
|
|
1998
|
+
card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
1999
|
+
card.style.color = "#1e293b";
|
|
2000
|
+
card.style.lineHeight = "1.6";
|
|
2001
|
+
try {
|
|
2002
|
+
const cfbf = new CfbfReader(ctx.buffer);
|
|
2003
|
+
const wordDocStream = cfbf.readStream("WordDocument");
|
|
2004
|
+
if (wordDocStream && wordDocStream.length >= 512) {
|
|
2005
|
+
const text2 = this.extractReadableStrings(wordDocStream);
|
|
2006
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify2.sanitize(text2)}</div>`;
|
|
2007
|
+
wrapper.appendChild(card);
|
|
2008
|
+
return;
|
|
2009
|
+
}
|
|
2010
|
+
} catch {
|
|
2011
|
+
}
|
|
2012
|
+
const text = this.extractReadableStrings(new Uint8Array(ctx.buffer));
|
|
2013
|
+
card.innerHTML = `<div style="white-space: pre-wrap;">${DOMPurify2.sanitize(text)}</div>`;
|
|
2014
|
+
wrapper.appendChild(card);
|
|
2015
|
+
}
|
|
2016
|
+
extractReadableStrings(bytes) {
|
|
2017
|
+
let result = "";
|
|
2018
|
+
let current = "";
|
|
2019
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
2020
|
+
const b = bytes[i];
|
|
2021
|
+
if (b >= 32 && b <= 126 || b === 10 || b === 13 || b === 9) {
|
|
2022
|
+
current += String.fromCharCode(b);
|
|
2023
|
+
} else if (b === 0 && i + 1 < bytes.length && bytes[i + 1] >= 32 && bytes[i + 1] <= 126) {
|
|
2024
|
+
continue;
|
|
2025
|
+
} else {
|
|
2026
|
+
if (current.trim().length > 3) {
|
|
2027
|
+
result += current.trim() + "\n\n";
|
|
2028
|
+
}
|
|
2029
|
+
current = "";
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
if (current.trim().length > 3) {
|
|
2033
|
+
result += current.trim();
|
|
2034
|
+
}
|
|
2035
|
+
return result;
|
|
2036
|
+
}
|
|
1833
2037
|
};
|
|
1834
2038
|
function docxPlugin() {
|
|
1835
2039
|
return new DocxPlugin();
|
|
@@ -2641,7 +2845,7 @@ var MarkdownPlugin = class {
|
|
|
2641
2845
|
gfm: true,
|
|
2642
2846
|
breaks: true
|
|
2643
2847
|
});
|
|
2644
|
-
const cleanHtml =
|
|
2848
|
+
const cleanHtml = DOMPurify2.sanitize(rawHtml, {
|
|
2645
2849
|
USE_PROFILES: { html: true }
|
|
2646
2850
|
});
|
|
2647
2851
|
const wrapper = document.createElement("div");
|
|
@@ -3356,7 +3560,7 @@ var HtmlPreviewPlugin = class {
|
|
|
3356
3560
|
}
|
|
3357
3561
|
async render(ctx) {
|
|
3358
3562
|
const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
|
|
3359
|
-
const sanitized =
|
|
3563
|
+
const sanitized = DOMPurify2.sanitize(rawHtml, {
|
|
3360
3564
|
WHOLE_DOCUMENT: true,
|
|
3361
3565
|
ADD_TAGS: ["style", "link"],
|
|
3362
3566
|
ADD_ATTR: ["target", "rel"]
|
|
@@ -3599,7 +3803,7 @@ var OpenDocumentPlugin = class {
|
|
|
3599
3803
|
wrapper.style.padding = "48px";
|
|
3600
3804
|
wrapper.style.minHeight = "100%";
|
|
3601
3805
|
const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
|
|
3602
|
-
wrapper.innerHTML =
|
|
3806
|
+
wrapper.innerHTML = DOMPurify2.sanitize(bodyHtml, {
|
|
3603
3807
|
ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub"],
|
|
3604
3808
|
ADD_ATTR: ["style", "colspan", "rowspan"]
|
|
3605
3809
|
});
|
|
@@ -4119,24 +4323,24 @@ var DocPlugin = class {
|
|
|
4119
4323
|
html += "</ul>";
|
|
4120
4324
|
inList = false;
|
|
4121
4325
|
}
|
|
4122
|
-
html += `<h2 style="font-size: 18px; font-weight: 700; color: #1e3a8a; margin: 20px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${
|
|
4326
|
+
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>`;
|
|
4123
4327
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
4124
4328
|
if (!inList) {
|
|
4125
4329
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
4126
4330
|
inList = true;
|
|
4127
4331
|
}
|
|
4128
4332
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
4129
|
-
html += `<li style="margin: 4px 0; line-height: 1.6;">${
|
|
4333
|
+
html += `<li style="margin: 4px 0; line-height: 1.6;">${DOMPurify2.sanitize(bulletText)}</li>`;
|
|
4130
4334
|
} else {
|
|
4131
4335
|
if (inList) {
|
|
4132
4336
|
html += "</ul>";
|
|
4133
4337
|
inList = false;
|
|
4134
4338
|
}
|
|
4135
|
-
html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${
|
|
4339
|
+
html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${DOMPurify2.sanitize(line)}</p>`;
|
|
4136
4340
|
}
|
|
4137
4341
|
}
|
|
4138
4342
|
if (inList) html += "</ul>";
|
|
4139
|
-
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${
|
|
4343
|
+
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify2.sanitize(filename)})</p>`;
|
|
4140
4344
|
}
|
|
4141
4345
|
};
|
|
4142
4346
|
function docPlugin() {
|
|
@@ -4291,10 +4495,10 @@ var PptPlugin = class {
|
|
|
4291
4495
|
</div>
|
|
4292
4496
|
<div style="text-align: center; width: 100%;">
|
|
4293
4497
|
<h1 style="font-size: ${idx === 1 ? "36px" : "28px"}; color: #1e3a8a; margin: 0 0 24px; font-family: -apple-system, BlinkMacSystemFont, sans-serif; font-weight: 700;">
|
|
4294
|
-
${
|
|
4498
|
+
${DOMPurify2.sanitize(s.title || `Slide ${idx}`)}
|
|
4295
4499
|
</h1>
|
|
4296
4500
|
<div style="display: flex; flex-direction: column; gap: 12px; max-width: 80%; margin: 0 auto; text-align: ${idx === 1 ? "center" : "left"};">
|
|
4297
|
-
${s.texts.map((t) => `<div style="font-size: 18px; color: #334155; line-height: 1.5; font-family: -apple-system, BlinkMacSystemFont, sans-serif;">${
|
|
4501
|
+
${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("")}
|
|
4298
4502
|
</div>
|
|
4299
4503
|
</div>
|
|
4300
4504
|
`;
|