@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/react.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { memo, forwardRef, useRef, useImperativeHandle, useEffect } from 'react';
|
|
2
|
-
import
|
|
2
|
+
import DOMPurify6 from 'dompurify';
|
|
3
3
|
import * as docx from 'docx-preview';
|
|
4
|
+
import { unzipSync, strFromU8, unzip } from 'fflate';
|
|
4
5
|
import * as XLSX from 'xlsx';
|
|
5
6
|
import hljs from 'highlight.js';
|
|
6
|
-
import { unzipSync, strFromU8, unzip } from 'fflate';
|
|
7
7
|
import { marked } from 'marked';
|
|
8
8
|
import { PptxRenderer } from 'pptx-browser';
|
|
9
9
|
import * as THREE from 'three';
|
|
@@ -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 DOMPurify6.sanitize(svg, {
|
|
345
345
|
USE_PROFILES: { svg: true, svgFilters: true }
|
|
346
346
|
});
|
|
347
347
|
}
|
|
@@ -417,7 +417,11 @@ var ICON_MAP = {
|
|
|
417
417
|
"close": ICON_CLOSE,
|
|
418
418
|
"copy": ICON_COPY,
|
|
419
419
|
"prev": ICON_PAGE_PREV,
|
|
420
|
-
"next": ICON_PAGE_NEXT
|
|
420
|
+
"next": ICON_PAGE_NEXT,
|
|
421
|
+
"page-prev": ICON_PAGE_PREV,
|
|
422
|
+
"page-next": ICON_PAGE_NEXT,
|
|
423
|
+
"chevron-left": ICON_PAGE_PREV,
|
|
424
|
+
"chevron-right": ICON_PAGE_NEXT
|
|
421
425
|
};
|
|
422
426
|
var ToolbarController = class {
|
|
423
427
|
el;
|
|
@@ -449,7 +453,9 @@ var ToolbarController = class {
|
|
|
449
453
|
view: [],
|
|
450
454
|
actions: []
|
|
451
455
|
};
|
|
452
|
-
|
|
456
|
+
const hasPageNav = this.actions.some((a) => a.type === "page-nav");
|
|
457
|
+
const effectiveActions = hasPageNav ? this.actions.filter((a) => a.id !== "page-prev" && a.id !== "page-next" && a.id !== "prev" && a.id !== "next") : this.actions;
|
|
458
|
+
for (const action of effectiveActions) {
|
|
453
459
|
if (groups[action.group]) {
|
|
454
460
|
groups[action.group].push(action);
|
|
455
461
|
}
|
|
@@ -472,13 +478,26 @@ var ToolbarController = class {
|
|
|
472
478
|
"prev",
|
|
473
479
|
ICON_PAGE_PREV,
|
|
474
480
|
"Previous Page",
|
|
475
|
-
() =>
|
|
481
|
+
() => {
|
|
482
|
+
const cur = parseInt(input.value, 10) || 1;
|
|
483
|
+
if (cur > 1) {
|
|
484
|
+
input.value = (cur - 1).toString();
|
|
485
|
+
action.execute("prev", cur - 1);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
476
488
|
);
|
|
477
489
|
const nextBtn = this.createButton(
|
|
478
490
|
"next",
|
|
479
491
|
ICON_PAGE_NEXT,
|
|
480
492
|
"Next Page",
|
|
481
|
-
() =>
|
|
493
|
+
() => {
|
|
494
|
+
const cur = parseInt(input.value, 10) || 1;
|
|
495
|
+
const max = action.max ?? 1;
|
|
496
|
+
if (cur < max) {
|
|
497
|
+
input.value = (cur + 1).toString();
|
|
498
|
+
action.execute("next", cur + 1);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
482
501
|
);
|
|
483
502
|
const input = createElement("input", {
|
|
484
503
|
className: "fp-toolbar-input",
|
|
@@ -488,7 +507,10 @@ var ToolbarController = class {
|
|
|
488
507
|
max: (action.max ?? 1).toString()
|
|
489
508
|
});
|
|
490
509
|
input.addEventListener("change", () => {
|
|
491
|
-
|
|
510
|
+
const val = parseInt(input.value, 10);
|
|
511
|
+
if (!isNaN(val)) {
|
|
512
|
+
action.execute("go", val);
|
|
513
|
+
}
|
|
492
514
|
});
|
|
493
515
|
const label = createElement("span", { className: "fp-toolbar-label" }, ` / ${action.max ?? 1}`);
|
|
494
516
|
groupEl.appendChild(prevBtn);
|
|
@@ -529,11 +551,11 @@ var ToolbarController = class {
|
|
|
529
551
|
type: "button",
|
|
530
552
|
"data-action-id": id
|
|
531
553
|
});
|
|
532
|
-
const svg = ICON_MAP[iconHtml] || iconHtml;
|
|
533
|
-
if (svg
|
|
554
|
+
const svg = ICON_MAP[iconHtml] || ICON_MAP[id] || (iconHtml && iconHtml.startsWith("<svg") ? iconHtml : null);
|
|
555
|
+
if (svg) {
|
|
534
556
|
btn.innerHTML = sanitizeSVG(svg);
|
|
535
557
|
} else {
|
|
536
|
-
btn.textContent =
|
|
558
|
+
btn.textContent = title || id;
|
|
537
559
|
}
|
|
538
560
|
btn.addEventListener("click", onClick);
|
|
539
561
|
return btn;
|
|
@@ -1276,12 +1298,12 @@ function pdfPlugin() {
|
|
|
1276
1298
|
}
|
|
1277
1299
|
|
|
1278
1300
|
// ../plugins/media/dist/index.js
|
|
1279
|
-
var IMAGE_EXTS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"];
|
|
1280
|
-
var VIDEO_EXTS = [".mp4", ".webm", ".ogg"];
|
|
1281
|
-
var AUDIO_EXTS = [".mp3", ".wav", ".ogg"];
|
|
1301
|
+
var IMAGE_EXTS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg", ".bmp", ".ico", ".tiff", ".tif", ".avif"];
|
|
1302
|
+
var VIDEO_EXTS = [".mp4", ".m4v", ".webm", ".ogv", ".ogg", ".mov", ".avi", ".mkv", ".flv", ".wmv", ".3gp", ".mpg", ".mpeg"];
|
|
1303
|
+
var AUDIO_EXTS = [".mp3", ".wav", ".ogg", ".flac", ".aac", ".m4a", ".wma", ".opus", ".weba"];
|
|
1282
1304
|
var MediaPlugin = class {
|
|
1283
1305
|
id = "media";
|
|
1284
|
-
name = "Media Preview";
|
|
1306
|
+
name = "Media Preview (Image, Video, Audio)";
|
|
1285
1307
|
extensions = [...IMAGE_EXTS, ...VIDEO_EXTS, ...AUDIO_EXTS];
|
|
1286
1308
|
mimeTypes = [
|
|
1287
1309
|
"image/jpeg",
|
|
@@ -1289,12 +1311,29 @@ var MediaPlugin = class {
|
|
|
1289
1311
|
"image/gif",
|
|
1290
1312
|
"image/webp",
|
|
1291
1313
|
"image/svg+xml",
|
|
1314
|
+
"image/bmp",
|
|
1315
|
+
"image/x-icon",
|
|
1316
|
+
"image/tiff",
|
|
1317
|
+
"image/avif",
|
|
1292
1318
|
"video/mp4",
|
|
1293
1319
|
"video/webm",
|
|
1294
1320
|
"video/ogg",
|
|
1321
|
+
"video/quicktime",
|
|
1322
|
+
"video/x-msvideo",
|
|
1323
|
+
"video/x-matroska",
|
|
1324
|
+
"video/x-flv",
|
|
1325
|
+
"video/x-ms-wmv",
|
|
1326
|
+
"video/3gpp",
|
|
1327
|
+
"video/mpeg",
|
|
1295
1328
|
"audio/mpeg",
|
|
1296
1329
|
"audio/wav",
|
|
1297
|
-
"audio/ogg"
|
|
1330
|
+
"audio/ogg",
|
|
1331
|
+
"audio/flac",
|
|
1332
|
+
"audio/aac",
|
|
1333
|
+
"audio/mp4",
|
|
1334
|
+
"audio/x-ms-wma",
|
|
1335
|
+
"audio/opus",
|
|
1336
|
+
"audio/webm"
|
|
1298
1337
|
];
|
|
1299
1338
|
weight = 90;
|
|
1300
1339
|
supports(file) {
|
|
@@ -1427,8 +1466,12 @@ var MediaPlugin = class {
|
|
|
1427
1466
|
const video = document.createElement("video");
|
|
1428
1467
|
video.src = url;
|
|
1429
1468
|
video.controls = true;
|
|
1430
|
-
video.
|
|
1431
|
-
video.style.
|
|
1469
|
+
video.playsInline = true;
|
|
1470
|
+
video.style.maxWidth = "90%";
|
|
1471
|
+
video.style.maxHeight = "90%";
|
|
1472
|
+
video.style.borderRadius = "8px";
|
|
1473
|
+
video.style.boxShadow = "0 8px 30px rgba(0,0,0,0.3)";
|
|
1474
|
+
video.style.backgroundColor = "#000000";
|
|
1432
1475
|
element = video;
|
|
1433
1476
|
mediaElement = video;
|
|
1434
1477
|
} else if (isAudio) {
|
|
@@ -1504,7 +1547,7 @@ function mediaPlugin() {
|
|
|
1504
1547
|
}
|
|
1505
1548
|
var DocxPlugin = class {
|
|
1506
1549
|
id = "docx";
|
|
1507
|
-
name = "Word Document Preview";
|
|
1550
|
+
name = "Word Document Preview (.docx, .docm, .dotx, .dotm)";
|
|
1508
1551
|
extensions = [".docx", ".docm", ".dotx", ".dotm"];
|
|
1509
1552
|
mimeTypes = [
|
|
1510
1553
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
@@ -1526,9 +1569,7 @@ var DocxPlugin = class {
|
|
|
1526
1569
|
label: "Zoom Out",
|
|
1527
1570
|
type: "button",
|
|
1528
1571
|
group: "zoom",
|
|
1529
|
-
execute: () =>
|
|
1530
|
-
instance.zoomOut?.();
|
|
1531
|
-
}
|
|
1572
|
+
execute: () => instance.zoomOut?.()
|
|
1532
1573
|
},
|
|
1533
1574
|
{
|
|
1534
1575
|
id: "zoom-in",
|
|
@@ -1536,9 +1577,7 @@ var DocxPlugin = class {
|
|
|
1536
1577
|
label: "Zoom In",
|
|
1537
1578
|
type: "button",
|
|
1538
1579
|
group: "zoom",
|
|
1539
|
-
execute: () =>
|
|
1540
|
-
instance.zoomIn?.();
|
|
1541
|
-
}
|
|
1580
|
+
execute: () => instance.zoomIn?.()
|
|
1542
1581
|
},
|
|
1543
1582
|
{
|
|
1544
1583
|
id: "fit-page",
|
|
@@ -1546,9 +1585,7 @@ var DocxPlugin = class {
|
|
|
1546
1585
|
label: "Fit to Page",
|
|
1547
1586
|
type: "button",
|
|
1548
1587
|
group: "zoom",
|
|
1549
|
-
execute: () =>
|
|
1550
|
-
instance.fitToPage?.();
|
|
1551
|
-
}
|
|
1588
|
+
execute: () => instance.fitToPage?.()
|
|
1552
1589
|
},
|
|
1553
1590
|
{
|
|
1554
1591
|
id: "download",
|
|
@@ -1556,9 +1593,7 @@ var DocxPlugin = class {
|
|
|
1556
1593
|
label: "Download",
|
|
1557
1594
|
type: "button",
|
|
1558
1595
|
group: "actions",
|
|
1559
|
-
execute: () =>
|
|
1560
|
-
instance.download?.();
|
|
1561
|
-
}
|
|
1596
|
+
execute: () => instance.download?.()
|
|
1562
1597
|
},
|
|
1563
1598
|
{
|
|
1564
1599
|
id: "print",
|
|
@@ -1566,9 +1601,7 @@ var DocxPlugin = class {
|
|
|
1566
1601
|
label: "Print",
|
|
1567
1602
|
type: "button",
|
|
1568
1603
|
group: "actions",
|
|
1569
|
-
execute: () =>
|
|
1570
|
-
instance.print?.();
|
|
1571
|
-
}
|
|
1604
|
+
execute: () => instance.print?.()
|
|
1572
1605
|
}
|
|
1573
1606
|
];
|
|
1574
1607
|
}
|
|
@@ -1577,24 +1610,46 @@ var DocxPlugin = class {
|
|
|
1577
1610
|
wrapper.className = "fp-docx-wrapper";
|
|
1578
1611
|
wrapper.style.transformOrigin = "top center";
|
|
1579
1612
|
wrapper.style.transition = "transform 0.2s ease";
|
|
1580
|
-
wrapper.style.padding = "16px";
|
|
1613
|
+
wrapper.style.padding = "24px 16px";
|
|
1614
|
+
wrapper.style.maxWidth = "900px";
|
|
1615
|
+
wrapper.style.margin = "0 auto";
|
|
1616
|
+
wrapper.style.boxSizing = "border-box";
|
|
1581
1617
|
ctx.container.style.overflow = "auto";
|
|
1618
|
+
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
1582
1619
|
ctx.container.appendChild(wrapper);
|
|
1583
1620
|
let scale = 1;
|
|
1621
|
+
let renderedSuccessfully = false;
|
|
1584
1622
|
try {
|
|
1585
1623
|
await docx.renderAsync(ctx.buffer, wrapper, ctx.container, {
|
|
1586
1624
|
inWrapper: true,
|
|
1587
1625
|
ignoreWidth: false,
|
|
1588
|
-
ignoreHeight: false
|
|
1626
|
+
ignoreHeight: false,
|
|
1627
|
+
ignoreFonts: true,
|
|
1628
|
+
// Avoid crashes on embedded obfuscated fonts
|
|
1629
|
+
breakPages: true,
|
|
1630
|
+
experimental: true
|
|
1589
1631
|
});
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1632
|
+
if (wrapper.children.length > 0 && (wrapper.textContent?.trim().length ?? 0) > 0) {
|
|
1633
|
+
renderedSuccessfully = true;
|
|
1634
|
+
}
|
|
1635
|
+
} catch (err) {
|
|
1636
|
+
console.warn("[DocxPlugin] docx-preview failed, triggering native XML fallback:", err);
|
|
1637
|
+
}
|
|
1638
|
+
if (!renderedSuccessfully) {
|
|
1639
|
+
try {
|
|
1640
|
+
wrapper.innerHTML = "";
|
|
1641
|
+
this.renderXmlFallback(ctx, wrapper);
|
|
1642
|
+
renderedSuccessfully = true;
|
|
1643
|
+
} catch (fallbackErr) {
|
|
1644
|
+
console.error("[DocxPlugin] XML fallback failed:", fallbackErr);
|
|
1645
|
+
wrapper.innerHTML = `
|
|
1646
|
+
<div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
|
|
1647
|
+
<div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
|
|
1648
|
+
<h3 style="margin: 0 0 8px; color: #1e293b;">${ctx.metadata.name || "Word Document"}</h3>
|
|
1649
|
+
<p style="color: #64748b; margin: 0;">Could not parse document content</p>
|
|
1650
|
+
</div>
|
|
1651
|
+
`;
|
|
1652
|
+
}
|
|
1598
1653
|
}
|
|
1599
1654
|
const cleanup = () => {
|
|
1600
1655
|
wrapper.remove();
|
|
@@ -1618,7 +1673,7 @@ var DocxPlugin = class {
|
|
|
1618
1673
|
},
|
|
1619
1674
|
fitToPage: () => {
|
|
1620
1675
|
scale = 1;
|
|
1621
|
-
wrapper.style.transform =
|
|
1676
|
+
wrapper.style.transform = "scale(1)";
|
|
1622
1677
|
},
|
|
1623
1678
|
download: () => {
|
|
1624
1679
|
const blob = new Blob([ctx.buffer], { type: this.mimeTypes[0] });
|
|
@@ -1634,6 +1689,100 @@ var DocxPlugin = class {
|
|
|
1634
1689
|
}
|
|
1635
1690
|
};
|
|
1636
1691
|
}
|
|
1692
|
+
renderXmlFallback(ctx, wrapper) {
|
|
1693
|
+
const unzipped = unzipSync(new Uint8Array(ctx.buffer));
|
|
1694
|
+
const docXmlEntry = unzipped["word/document.xml"];
|
|
1695
|
+
if (!docXmlEntry) throw new Error("Missing word/document.xml in DOCX package");
|
|
1696
|
+
const xmlStr = strFromU8(docXmlEntry);
|
|
1697
|
+
const parser = new DOMParser();
|
|
1698
|
+
const doc = parser.parseFromString(xmlStr, "application/xml");
|
|
1699
|
+
const card = document.createElement("div");
|
|
1700
|
+
card.className = "fp-docx-page-card";
|
|
1701
|
+
card.style.backgroundColor = "#ffffff";
|
|
1702
|
+
card.style.borderRadius = "6px";
|
|
1703
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
1704
|
+
card.style.padding = "48px 56px";
|
|
1705
|
+
card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
1706
|
+
card.style.color = "#1e293b";
|
|
1707
|
+
card.style.lineHeight = "1.6";
|
|
1708
|
+
const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
|
|
1709
|
+
let html = "";
|
|
1710
|
+
for (const child of Array.from(body.children)) {
|
|
1711
|
+
const tag = child.localName || child.nodeName.split(":").pop();
|
|
1712
|
+
if (tag === "p") {
|
|
1713
|
+
const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
|
|
1714
|
+
const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
|
|
1715
|
+
const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
|
|
1716
|
+
const textContent = this.extractParagraphHtml(child);
|
|
1717
|
+
if (!textContent.trim()) {
|
|
1718
|
+
html += '<div style="height: 10px;"></div>';
|
|
1719
|
+
continue;
|
|
1720
|
+
}
|
|
1721
|
+
const lowerStyle = styleVal.toLowerCase();
|
|
1722
|
+
if (lowerStyle.includes("title")) {
|
|
1723
|
+
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>`;
|
|
1724
|
+
} else if (lowerStyle.includes("heading1") || styleVal === "1") {
|
|
1725
|
+
html += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
|
|
1726
|
+
} else if (lowerStyle.includes("heading2") || styleVal === "2") {
|
|
1727
|
+
html += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
|
|
1728
|
+
} else if (lowerStyle.includes("heading3") || styleVal === "3") {
|
|
1729
|
+
html += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
|
|
1730
|
+
} else if (numPr) {
|
|
1731
|
+
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>`;
|
|
1732
|
+
} else {
|
|
1733
|
+
html += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
|
|
1734
|
+
}
|
|
1735
|
+
} else if (tag === "tbl") {
|
|
1736
|
+
html += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
|
|
1737
|
+
const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
|
|
1738
|
+
rows.forEach((tr, rIdx) => {
|
|
1739
|
+
html += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
1740
|
+
const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
|
|
1741
|
+
cells.forEach((tc) => {
|
|
1742
|
+
const cellText = this.extractParagraphHtml(tc);
|
|
1743
|
+
html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || " "}</td>`;
|
|
1744
|
+
});
|
|
1745
|
+
html += "</tr>";
|
|
1746
|
+
});
|
|
1747
|
+
html += "</table>";
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
card.innerHTML = DOMPurify6.sanitize(html, {
|
|
1751
|
+
ADD_TAGS: ["h1", "h2", "h3", "h4", "p", "table", "tr", "td", "span", "b", "i", "u", "img", "div"],
|
|
1752
|
+
ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
|
|
1753
|
+
});
|
|
1754
|
+
wrapper.appendChild(card);
|
|
1755
|
+
}
|
|
1756
|
+
extractParagraphHtml(pElement) {
|
|
1757
|
+
let result = "";
|
|
1758
|
+
const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
|
|
1759
|
+
if (runs.length === 0) {
|
|
1760
|
+
return DOMPurify6.sanitize(pElement.textContent || "");
|
|
1761
|
+
}
|
|
1762
|
+
for (const r of runs) {
|
|
1763
|
+
const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
|
|
1764
|
+
const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
|
|
1765
|
+
const isItalic = !!rPr?.getElementsByTagNameNS("*", "i")[0];
|
|
1766
|
+
const isUnderline = !!rPr?.getElementsByTagNameNS("*", "u")[0];
|
|
1767
|
+
const colorNode = rPr?.getElementsByTagNameNS("*", "color")[0];
|
|
1768
|
+
const colorVal = colorNode?.getAttribute("w:val") || colorNode?.getAttribute("val");
|
|
1769
|
+
const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
|
|
1770
|
+
let text = texts.map((t) => t.textContent || "").join("");
|
|
1771
|
+
if (!text) continue;
|
|
1772
|
+
text = DOMPurify6.sanitize(text);
|
|
1773
|
+
let styles = "";
|
|
1774
|
+
if (isBold) styles += "font-weight: bold; ";
|
|
1775
|
+
if (isItalic) styles += "font-style: italic; ";
|
|
1776
|
+
if (isUnderline) styles += "text-decoration: underline; ";
|
|
1777
|
+
if (colorVal && colorVal !== "auto") styles += `color: #${colorVal}; `;
|
|
1778
|
+
if (styles) {
|
|
1779
|
+
result += `<span style="${styles}">${text}</span>`;
|
|
1780
|
+
} else {
|
|
1781
|
+
result += text;
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
return result;
|
|
1785
|
+
}
|
|
1637
1786
|
};
|
|
1638
1787
|
function docxPlugin() {
|
|
1639
1788
|
return new DocxPlugin();
|
|
@@ -2445,7 +2594,7 @@ var MarkdownPlugin = class {
|
|
|
2445
2594
|
gfm: true,
|
|
2446
2595
|
breaks: true
|
|
2447
2596
|
});
|
|
2448
|
-
const cleanHtml =
|
|
2597
|
+
const cleanHtml = DOMPurify6.sanitize(rawHtml, {
|
|
2449
2598
|
USE_PROFILES: { html: true }
|
|
2450
2599
|
});
|
|
2451
2600
|
const wrapper = document.createElement("div");
|
|
@@ -2609,35 +2758,27 @@ var PptxPlugin = class {
|
|
|
2609
2758
|
group: "navigation",
|
|
2610
2759
|
execute: () => instance.toggleThumbnails?.()
|
|
2611
2760
|
},
|
|
2612
|
-
{
|
|
2613
|
-
id: "page-prev",
|
|
2614
|
-
icon: "page-prev",
|
|
2615
|
-
label: "Previous Slide",
|
|
2616
|
-
type: "button",
|
|
2617
|
-
group: "navigation",
|
|
2618
|
-
execute: () => {
|
|
2619
|
-
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2620
|
-
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
2621
|
-
}
|
|
2622
|
-
},
|
|
2623
2761
|
{
|
|
2624
2762
|
id: "page-nav",
|
|
2625
2763
|
icon: "",
|
|
2626
|
-
label: "Slide
|
|
2764
|
+
label: "Slide Navigation",
|
|
2627
2765
|
type: "page-nav",
|
|
2628
2766
|
group: "navigation",
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2767
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
2768
|
+
max: instance.getPageCount?.() ?? 1,
|
|
2769
|
+
execute: (action, page) => {
|
|
2770
|
+
if (action === "prev") {
|
|
2771
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2772
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
2773
|
+
} else if (action === "next") {
|
|
2774
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2775
|
+
const total = instance.getPageCount?.() ?? 1;
|
|
2776
|
+
if (cur < total) instance.goToPage?.(cur + 1);
|
|
2777
|
+
} else if (typeof page === "number") {
|
|
2778
|
+
instance.goToPage?.(page);
|
|
2779
|
+
} else if (typeof action === "number") {
|
|
2780
|
+
instance.goToPage?.(action);
|
|
2781
|
+
}
|
|
2641
2782
|
}
|
|
2642
2783
|
},
|
|
2643
2784
|
{
|
|
@@ -3168,7 +3309,7 @@ var HtmlPreviewPlugin = class {
|
|
|
3168
3309
|
}
|
|
3169
3310
|
async render(ctx) {
|
|
3170
3311
|
const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
|
|
3171
|
-
const sanitized =
|
|
3312
|
+
const sanitized = DOMPurify6.sanitize(rawHtml, {
|
|
3172
3313
|
WHOLE_DOCUMENT: true,
|
|
3173
3314
|
ADD_TAGS: ["style", "link"],
|
|
3174
3315
|
ADD_ATTR: ["target", "rel"]
|
|
@@ -3263,35 +3404,27 @@ var OpenDocumentPlugin = class {
|
|
|
3263
3404
|
group: "navigation",
|
|
3264
3405
|
execute: () => instance.toggleThumbnails?.()
|
|
3265
3406
|
},
|
|
3266
|
-
{
|
|
3267
|
-
id: "page-prev",
|
|
3268
|
-
icon: "page-prev",
|
|
3269
|
-
label: "Previous Slide",
|
|
3270
|
-
type: "button",
|
|
3271
|
-
group: "navigation",
|
|
3272
|
-
execute: () => {
|
|
3273
|
-
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3274
|
-
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3275
|
-
}
|
|
3276
|
-
},
|
|
3277
3407
|
{
|
|
3278
3408
|
id: "page-nav",
|
|
3279
3409
|
icon: "",
|
|
3280
|
-
label: "Slide
|
|
3410
|
+
label: "Slide Navigation",
|
|
3281
3411
|
type: "page-nav",
|
|
3282
3412
|
group: "navigation",
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3413
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
3414
|
+
max: instance.getPageCount?.() ?? 1,
|
|
3415
|
+
execute: (action, page) => {
|
|
3416
|
+
if (action === "prev") {
|
|
3417
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3418
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3419
|
+
} else if (action === "next") {
|
|
3420
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3421
|
+
const total = instance.getPageCount?.() ?? 1;
|
|
3422
|
+
if (cur < total) instance.goToPage?.(cur + 1);
|
|
3423
|
+
} else if (typeof page === "number") {
|
|
3424
|
+
instance.goToPage?.(page);
|
|
3425
|
+
} else if (typeof action === "number") {
|
|
3426
|
+
instance.goToPage?.(action);
|
|
3427
|
+
}
|
|
3295
3428
|
}
|
|
3296
3429
|
}
|
|
3297
3430
|
);
|
|
@@ -3419,7 +3552,7 @@ var OpenDocumentPlugin = class {
|
|
|
3419
3552
|
wrapper.style.padding = "48px";
|
|
3420
3553
|
wrapper.style.minHeight = "100%";
|
|
3421
3554
|
const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
|
|
3422
|
-
wrapper.innerHTML =
|
|
3555
|
+
wrapper.innerHTML = DOMPurify6.sanitize(bodyHtml, {
|
|
3423
3556
|
ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub"],
|
|
3424
3557
|
ADD_ATTR: ["style", "colspan", "rowspan"]
|
|
3425
3558
|
});
|
|
@@ -3939,24 +4072,24 @@ var DocPlugin = class {
|
|
|
3939
4072
|
html += "</ul>";
|
|
3940
4073
|
inList = false;
|
|
3941
4074
|
}
|
|
3942
|
-
html += `<h2 style="font-size: 18px; font-weight: 700; color: #1e3a8a; margin: 20px 0 8px; border-bottom: 1px solid #e2e8f0; padding-bottom: 4px;">${
|
|
4075
|
+
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>`;
|
|
3943
4076
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
3944
4077
|
if (!inList) {
|
|
3945
4078
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
3946
4079
|
inList = true;
|
|
3947
4080
|
}
|
|
3948
4081
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
3949
|
-
html += `<li style="margin: 4px 0; line-height: 1.6;">${
|
|
4082
|
+
html += `<li style="margin: 4px 0; line-height: 1.6;">${DOMPurify6.sanitize(bulletText)}</li>`;
|
|
3950
4083
|
} else {
|
|
3951
4084
|
if (inList) {
|
|
3952
4085
|
html += "</ul>";
|
|
3953
4086
|
inList = false;
|
|
3954
4087
|
}
|
|
3955
|
-
html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${
|
|
4088
|
+
html += `<p style="line-height: 1.7; margin: 10px 0; font-size: 14px; text-align: justify;">${DOMPurify6.sanitize(line)}</p>`;
|
|
3956
4089
|
}
|
|
3957
4090
|
}
|
|
3958
4091
|
if (inList) html += "</ul>";
|
|
3959
|
-
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${
|
|
4092
|
+
return html || `<p style="color: #64748b; font-style: italic;">(No readable text found in ${DOMPurify6.sanitize(filename)})</p>`;
|
|
3960
4093
|
}
|
|
3961
4094
|
};
|
|
3962
4095
|
function docPlugin() {
|
|
@@ -3983,35 +4116,27 @@ var PptPlugin = class {
|
|
|
3983
4116
|
group: "navigation",
|
|
3984
4117
|
execute: () => instance.toggleThumbnails?.()
|
|
3985
4118
|
},
|
|
3986
|
-
{
|
|
3987
|
-
id: "page-prev",
|
|
3988
|
-
icon: "page-prev",
|
|
3989
|
-
label: "Previous Slide",
|
|
3990
|
-
type: "button",
|
|
3991
|
-
group: "navigation",
|
|
3992
|
-
execute: () => {
|
|
3993
|
-
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3994
|
-
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3995
|
-
}
|
|
3996
|
-
},
|
|
3997
4119
|
{
|
|
3998
4120
|
id: "page-nav",
|
|
3999
4121
|
icon: "",
|
|
4000
|
-
label: "Slide
|
|
4122
|
+
label: "Slide Navigation",
|
|
4001
4123
|
type: "page-nav",
|
|
4002
4124
|
group: "navigation",
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4125
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
4126
|
+
max: instance.getPageCount?.() ?? 1,
|
|
4127
|
+
execute: (action, page) => {
|
|
4128
|
+
if (action === "prev") {
|
|
4129
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4130
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
4131
|
+
} else if (action === "next") {
|
|
4132
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4133
|
+
const total = instance.getPageCount?.() ?? 1;
|
|
4134
|
+
if (cur < total) instance.goToPage?.(cur + 1);
|
|
4135
|
+
} else if (typeof page === "number") {
|
|
4136
|
+
instance.goToPage?.(page);
|
|
4137
|
+
} else if (typeof action === "number") {
|
|
4138
|
+
instance.goToPage?.(action);
|
|
4139
|
+
}
|
|
4015
4140
|
}
|
|
4016
4141
|
},
|
|
4017
4142
|
{
|
|
@@ -4119,10 +4244,10 @@ var PptPlugin = class {
|
|
|
4119
4244
|
</div>
|
|
4120
4245
|
<div style="text-align: center; width: 100%;">
|
|
4121
4246
|
<h1 style="font-size: ${idx === 1 ? "36px" : "28px"}; color: #1e3a8a; margin: 0 0 24px; font-family: -apple-system, BlinkMacSystemFont, sans-serif; font-weight: 700;">
|
|
4122
|
-
${
|
|
4247
|
+
${DOMPurify6.sanitize(s.title || `Slide ${idx}`)}
|
|
4123
4248
|
</h1>
|
|
4124
4249
|
<div style="display: flex; flex-direction: column; gap: 12px; max-width: 80%; margin: 0 auto; text-align: ${idx === 1 ? "center" : "left"};">
|
|
4125
|
-
${s.texts.map((t) => `<div style="font-size: 18px; color: #334155; line-height: 1.5; font-family: -apple-system, BlinkMacSystemFont, sans-serif;">${
|
|
4250
|
+
${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("")}
|
|
4126
4251
|
</div>
|
|
4127
4252
|
</div>
|
|
4128
4253
|
`;
|