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