@files-preview-app/preview-file 1.2.1 → 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 +457 -128
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.js +456 -127
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +458 -129
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +457 -128
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +457 -128
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +456 -127
- package/dist/react.js.map +1 -1
- package/dist/vue.cjs +457 -128
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +456 -127
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
package/dist/angular.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
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
|
+
import { unzipSync, strFromU8, unzip } from 'fflate';
|
|
5
6
|
import * as XLSX from 'xlsx';
|
|
6
7
|
import hljs from 'highlight.js';
|
|
7
|
-
import { unzipSync, strFromU8, unzip } from 'fflate';
|
|
8
8
|
import { marked } from 'marked';
|
|
9
9
|
import { PptxRenderer } from 'pptx-browser';
|
|
10
10
|
import * as THREE from 'three';
|
|
@@ -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,
|
|
@@ -464,7 +467,16 @@ var ICON_MAP = {
|
|
|
464
467
|
"close": ICON_CLOSE,
|
|
465
468
|
"copy": ICON_COPY,
|
|
466
469
|
"prev": ICON_PAGE_PREV,
|
|
467
|
-
"next": ICON_PAGE_NEXT
|
|
470
|
+
"next": ICON_PAGE_NEXT,
|
|
471
|
+
"page-prev": ICON_PAGE_PREV,
|
|
472
|
+
"page-next": ICON_PAGE_NEXT,
|
|
473
|
+
"chevron-left": ICON_PAGE_PREV,
|
|
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
|
|
468
480
|
};
|
|
469
481
|
var ToolbarController = class {
|
|
470
482
|
el;
|
|
@@ -496,7 +508,9 @@ var ToolbarController = class {
|
|
|
496
508
|
view: [],
|
|
497
509
|
actions: []
|
|
498
510
|
};
|
|
499
|
-
|
|
511
|
+
const hasPageNav = this.actions.some((a) => a.type === "page-nav");
|
|
512
|
+
const effectiveActions = hasPageNav ? this.actions.filter((a) => a.id !== "page-prev" && a.id !== "page-next" && a.id !== "prev" && a.id !== "next") : this.actions;
|
|
513
|
+
for (const action of effectiveActions) {
|
|
500
514
|
if (groups[action.group]) {
|
|
501
515
|
groups[action.group].push(action);
|
|
502
516
|
}
|
|
@@ -519,13 +533,26 @@ var ToolbarController = class {
|
|
|
519
533
|
"prev",
|
|
520
534
|
ICON_PAGE_PREV,
|
|
521
535
|
"Previous Page",
|
|
522
|
-
() =>
|
|
536
|
+
() => {
|
|
537
|
+
const cur = parseInt(input.value, 10) || 1;
|
|
538
|
+
if (cur > 1) {
|
|
539
|
+
input.value = (cur - 1).toString();
|
|
540
|
+
action.execute("prev", cur - 1);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
523
543
|
);
|
|
524
544
|
const nextBtn = this.createButton(
|
|
525
545
|
"next",
|
|
526
546
|
ICON_PAGE_NEXT,
|
|
527
547
|
"Next Page",
|
|
528
|
-
() =>
|
|
548
|
+
() => {
|
|
549
|
+
const cur = parseInt(input.value, 10) || 1;
|
|
550
|
+
const max = action.max ?? 1;
|
|
551
|
+
if (cur < max) {
|
|
552
|
+
input.value = (cur + 1).toString();
|
|
553
|
+
action.execute("next", cur + 1);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
529
556
|
);
|
|
530
557
|
const input = createElement("input", {
|
|
531
558
|
className: "fp-toolbar-input",
|
|
@@ -535,7 +562,10 @@ var ToolbarController = class {
|
|
|
535
562
|
max: (action.max ?? 1).toString()
|
|
536
563
|
});
|
|
537
564
|
input.addEventListener("change", () => {
|
|
538
|
-
|
|
565
|
+
const val = parseInt(input.value, 10);
|
|
566
|
+
if (!isNaN(val)) {
|
|
567
|
+
action.execute("go", val);
|
|
568
|
+
}
|
|
539
569
|
});
|
|
540
570
|
const label = createElement("span", { className: "fp-toolbar-label" }, ` / ${action.max ?? 1}`);
|
|
541
571
|
groupEl.appendChild(prevBtn);
|
|
@@ -576,11 +606,11 @@ var ToolbarController = class {
|
|
|
576
606
|
type: "button",
|
|
577
607
|
"data-action-id": id
|
|
578
608
|
});
|
|
579
|
-
const svg = ICON_MAP[iconHtml] || iconHtml;
|
|
580
|
-
if (svg
|
|
609
|
+
const svg = ICON_MAP[iconHtml] || ICON_MAP[id] || (iconHtml && iconHtml.startsWith("<svg") ? iconHtml : null);
|
|
610
|
+
if (svg) {
|
|
581
611
|
btn.innerHTML = sanitizeSVG(svg);
|
|
582
612
|
} else {
|
|
583
|
-
btn.textContent =
|
|
613
|
+
btn.textContent = title || id;
|
|
584
614
|
}
|
|
585
615
|
btn.addEventListener("click", onClick);
|
|
586
616
|
return btn;
|
|
@@ -1323,12 +1353,12 @@ function pdfPlugin() {
|
|
|
1323
1353
|
}
|
|
1324
1354
|
|
|
1325
1355
|
// ../plugins/media/dist/index.js
|
|
1326
|
-
var IMAGE_EXTS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"];
|
|
1327
|
-
var VIDEO_EXTS = [".mp4", ".webm", ".ogg"];
|
|
1328
|
-
var AUDIO_EXTS = [".mp3", ".wav", ".ogg"];
|
|
1356
|
+
var IMAGE_EXTS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg", ".bmp", ".ico", ".tiff", ".tif", ".avif"];
|
|
1357
|
+
var VIDEO_EXTS = [".mp4", ".m4v", ".webm", ".ogv", ".ogg", ".mov", ".avi", ".mkv", ".flv", ".wmv", ".3gp", ".mpg", ".mpeg"];
|
|
1358
|
+
var AUDIO_EXTS = [".mp3", ".wav", ".ogg", ".flac", ".aac", ".m4a", ".wma", ".opus", ".weba"];
|
|
1329
1359
|
var MediaPlugin = class {
|
|
1330
1360
|
id = "media";
|
|
1331
|
-
name = "Media Preview";
|
|
1361
|
+
name = "Media Preview (Image, Video, Audio)";
|
|
1332
1362
|
extensions = [...IMAGE_EXTS, ...VIDEO_EXTS, ...AUDIO_EXTS];
|
|
1333
1363
|
mimeTypes = [
|
|
1334
1364
|
"image/jpeg",
|
|
@@ -1336,12 +1366,29 @@ var MediaPlugin = class {
|
|
|
1336
1366
|
"image/gif",
|
|
1337
1367
|
"image/webp",
|
|
1338
1368
|
"image/svg+xml",
|
|
1369
|
+
"image/bmp",
|
|
1370
|
+
"image/x-icon",
|
|
1371
|
+
"image/tiff",
|
|
1372
|
+
"image/avif",
|
|
1339
1373
|
"video/mp4",
|
|
1340
1374
|
"video/webm",
|
|
1341
1375
|
"video/ogg",
|
|
1376
|
+
"video/quicktime",
|
|
1377
|
+
"video/x-msvideo",
|
|
1378
|
+
"video/x-matroska",
|
|
1379
|
+
"video/x-flv",
|
|
1380
|
+
"video/x-ms-wmv",
|
|
1381
|
+
"video/3gpp",
|
|
1382
|
+
"video/mpeg",
|
|
1342
1383
|
"audio/mpeg",
|
|
1343
1384
|
"audio/wav",
|
|
1344
|
-
"audio/ogg"
|
|
1385
|
+
"audio/ogg",
|
|
1386
|
+
"audio/flac",
|
|
1387
|
+
"audio/aac",
|
|
1388
|
+
"audio/mp4",
|
|
1389
|
+
"audio/x-ms-wma",
|
|
1390
|
+
"audio/opus",
|
|
1391
|
+
"audio/webm"
|
|
1345
1392
|
];
|
|
1346
1393
|
weight = 90;
|
|
1347
1394
|
supports(file) {
|
|
@@ -1397,6 +1444,16 @@ var MediaPlugin = class {
|
|
|
1397
1444
|
}
|
|
1398
1445
|
if (instance.play) {
|
|
1399
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
|
+
},
|
|
1400
1457
|
{
|
|
1401
1458
|
id: "play",
|
|
1402
1459
|
icon: "play",
|
|
@@ -1416,6 +1473,26 @@ var MediaPlugin = class {
|
|
|
1416
1473
|
execute: () => {
|
|
1417
1474
|
instance.pause?.();
|
|
1418
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
|
+
}
|
|
1419
1496
|
}
|
|
1420
1497
|
);
|
|
1421
1498
|
}
|
|
@@ -1474,8 +1551,12 @@ var MediaPlugin = class {
|
|
|
1474
1551
|
const video = document.createElement("video");
|
|
1475
1552
|
video.src = url;
|
|
1476
1553
|
video.controls = true;
|
|
1477
|
-
video.
|
|
1478
|
-
video.style.
|
|
1554
|
+
video.playsInline = true;
|
|
1555
|
+
video.style.maxWidth = "90%";
|
|
1556
|
+
video.style.maxHeight = "90%";
|
|
1557
|
+
video.style.borderRadius = "8px";
|
|
1558
|
+
video.style.boxShadow = "0 8px 30px rgba(0,0,0,0.3)";
|
|
1559
|
+
video.style.backgroundColor = "#000000";
|
|
1479
1560
|
element = video;
|
|
1480
1561
|
mediaElement = video;
|
|
1481
1562
|
} else if (isAudio) {
|
|
@@ -1534,6 +1615,28 @@ var MediaPlugin = class {
|
|
|
1534
1615
|
play: mediaElement ? () => mediaElement?.play() : void 0,
|
|
1535
1616
|
pause: mediaElement ? () => mediaElement?.pause() : void 0,
|
|
1536
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,
|
|
1537
1640
|
download: () => {
|
|
1538
1641
|
const a = document.createElement("a");
|
|
1539
1642
|
a.href = url;
|
|
@@ -1551,7 +1654,7 @@ function mediaPlugin() {
|
|
|
1551
1654
|
}
|
|
1552
1655
|
var DocxPlugin = class {
|
|
1553
1656
|
id = "docx";
|
|
1554
|
-
name = "Word Document Preview";
|
|
1657
|
+
name = "Word Document Preview (.docx, .docm, .dotx, .dotm)";
|
|
1555
1658
|
extensions = [".docx", ".docm", ".dotx", ".dotm"];
|
|
1556
1659
|
mimeTypes = [
|
|
1557
1660
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
@@ -1573,9 +1676,7 @@ var DocxPlugin = class {
|
|
|
1573
1676
|
label: "Zoom Out",
|
|
1574
1677
|
type: "button",
|
|
1575
1678
|
group: "zoom",
|
|
1576
|
-
execute: () =>
|
|
1577
|
-
instance.zoomOut?.();
|
|
1578
|
-
}
|
|
1679
|
+
execute: () => instance.zoomOut?.()
|
|
1579
1680
|
},
|
|
1580
1681
|
{
|
|
1581
1682
|
id: "zoom-in",
|
|
@@ -1583,9 +1684,7 @@ var DocxPlugin = class {
|
|
|
1583
1684
|
label: "Zoom In",
|
|
1584
1685
|
type: "button",
|
|
1585
1686
|
group: "zoom",
|
|
1586
|
-
execute: () =>
|
|
1587
|
-
instance.zoomIn?.();
|
|
1588
|
-
}
|
|
1687
|
+
execute: () => instance.zoomIn?.()
|
|
1589
1688
|
},
|
|
1590
1689
|
{
|
|
1591
1690
|
id: "fit-page",
|
|
@@ -1593,9 +1692,7 @@ var DocxPlugin = class {
|
|
|
1593
1692
|
label: "Fit to Page",
|
|
1594
1693
|
type: "button",
|
|
1595
1694
|
group: "zoom",
|
|
1596
|
-
execute: () =>
|
|
1597
|
-
instance.fitToPage?.();
|
|
1598
|
-
}
|
|
1695
|
+
execute: () => instance.fitToPage?.()
|
|
1599
1696
|
},
|
|
1600
1697
|
{
|
|
1601
1698
|
id: "download",
|
|
@@ -1603,9 +1700,7 @@ var DocxPlugin = class {
|
|
|
1603
1700
|
label: "Download",
|
|
1604
1701
|
type: "button",
|
|
1605
1702
|
group: "actions",
|
|
1606
|
-
execute: () =>
|
|
1607
|
-
instance.download?.();
|
|
1608
|
-
}
|
|
1703
|
+
execute: () => instance.download?.()
|
|
1609
1704
|
},
|
|
1610
1705
|
{
|
|
1611
1706
|
id: "print",
|
|
@@ -1613,9 +1708,7 @@ var DocxPlugin = class {
|
|
|
1613
1708
|
label: "Print",
|
|
1614
1709
|
type: "button",
|
|
1615
1710
|
group: "actions",
|
|
1616
|
-
execute: () =>
|
|
1617
|
-
instance.print?.();
|
|
1618
|
-
}
|
|
1711
|
+
execute: () => instance.print?.()
|
|
1619
1712
|
}
|
|
1620
1713
|
];
|
|
1621
1714
|
}
|
|
@@ -1624,27 +1717,81 @@ var DocxPlugin = class {
|
|
|
1624
1717
|
wrapper.className = "fp-docx-wrapper";
|
|
1625
1718
|
wrapper.style.transformOrigin = "top center";
|
|
1626
1719
|
wrapper.style.transition = "transform 0.2s ease";
|
|
1627
|
-
wrapper.style.padding = "16px";
|
|
1720
|
+
wrapper.style.padding = "24px 16px";
|
|
1721
|
+
wrapper.style.maxWidth = "950px";
|
|
1722
|
+
wrapper.style.margin = "0 auto";
|
|
1723
|
+
wrapper.style.boxSizing = "border-box";
|
|
1628
1724
|
ctx.container.style.overflow = "auto";
|
|
1725
|
+
ctx.container.style.backgroundColor = "#f1f5f9";
|
|
1629
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);
|
|
1630
1745
|
let scale = 1;
|
|
1746
|
+
let renderedSuccessfully = false;
|
|
1747
|
+
const createdBlobUrls = [];
|
|
1631
1748
|
try {
|
|
1632
|
-
await docx.renderAsync(ctx.buffer, wrapper,
|
|
1749
|
+
await docx.renderAsync(ctx.buffer, wrapper, wrapper, {
|
|
1633
1750
|
inWrapper: true,
|
|
1634
1751
|
ignoreWidth: false,
|
|
1635
|
-
ignoreHeight: false
|
|
1752
|
+
ignoreHeight: false,
|
|
1753
|
+
ignoreFonts: true,
|
|
1754
|
+
// Avoid crashes on embedded obfuscated fonts
|
|
1755
|
+
breakPages: true,
|
|
1756
|
+
experimental: true
|
|
1636
1757
|
});
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1758
|
+
if (!ctx.container.contains(wrapper)) {
|
|
1759
|
+
ctx.container.appendChild(wrapper);
|
|
1760
|
+
}
|
|
1761
|
+
if (wrapper.children.length > 0 && (wrapper.textContent?.trim().length ?? 0) > 0) {
|
|
1762
|
+
renderedSuccessfully = true;
|
|
1763
|
+
}
|
|
1764
|
+
} catch (err) {
|
|
1765
|
+
console.warn("[DocxPlugin] docx-preview failed, triggering native fallback:", err);
|
|
1766
|
+
}
|
|
1767
|
+
if (!renderedSuccessfully) {
|
|
1768
|
+
try {
|
|
1769
|
+
wrapper.innerHTML = "";
|
|
1770
|
+
this.renderXmlFallback(ctx, wrapper, createdBlobUrls);
|
|
1771
|
+
if (!ctx.container.contains(wrapper)) {
|
|
1772
|
+
ctx.container.appendChild(wrapper);
|
|
1773
|
+
}
|
|
1774
|
+
renderedSuccessfully = true;
|
|
1775
|
+
} catch (fallbackErr) {
|
|
1776
|
+
console.error("[DocxPlugin] Native fallback failed:", fallbackErr);
|
|
1777
|
+
wrapper.innerHTML = `
|
|
1778
|
+
<div style="text-align:center; padding: 48px; background: #fff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.06);">
|
|
1779
|
+
<div style="font-size:48px; margin-bottom: 16px;">\u{1F4C4}</div>
|
|
1780
|
+
<h3 style="margin: 0 0 8px; color: #1e293b;">${ctx.metadata.name || "Word Document"}</h3>
|
|
1781
|
+
<p style="color: #64748b; margin: 0;">Could not parse document content</p>
|
|
1782
|
+
</div>
|
|
1783
|
+
`;
|
|
1784
|
+
if (!ctx.container.contains(wrapper)) {
|
|
1785
|
+
ctx.container.appendChild(wrapper);
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1645
1788
|
}
|
|
1646
1789
|
const cleanup = () => {
|
|
1790
|
+
for (const url of createdBlobUrls) {
|
|
1791
|
+
URL.revokeObjectURL(url);
|
|
1792
|
+
}
|
|
1647
1793
|
wrapper.remove();
|
|
1794
|
+
styleOverride.remove();
|
|
1648
1795
|
ctx.container.innerHTML = "";
|
|
1649
1796
|
};
|
|
1650
1797
|
ctx.signal.addEventListener("abort", cleanup);
|
|
@@ -1665,7 +1812,7 @@ var DocxPlugin = class {
|
|
|
1665
1812
|
},
|
|
1666
1813
|
fitToPage: () => {
|
|
1667
1814
|
scale = 1;
|
|
1668
|
-
wrapper.style.transform =
|
|
1815
|
+
wrapper.style.transform = "scale(1)";
|
|
1669
1816
|
},
|
|
1670
1817
|
download: () => {
|
|
1671
1818
|
const blob = new Blob([ctx.buffer], { type: this.mimeTypes[0] });
|
|
@@ -1681,6 +1828,212 @@ var DocxPlugin = class {
|
|
|
1681
1828
|
}
|
|
1682
1829
|
};
|
|
1683
1830
|
}
|
|
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
|
+
}
|
|
1837
|
+
const unzipped = unzipSync(new Uint8Array(ctx.buffer));
|
|
1838
|
+
const docKey = Object.keys(unzipped).find((k) => k.replace(/^[./\\]+/, "").toLowerCase() === "word/document.xml");
|
|
1839
|
+
const docXmlEntry = docKey ? unzipped[docKey] : void 0;
|
|
1840
|
+
if (!docXmlEntry) throw new Error("Missing word/document.xml in DOCX package");
|
|
1841
|
+
const xmlStr = strFromU8(docXmlEntry);
|
|
1842
|
+
const parser = new DOMParser();
|
|
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
|
+
}
|
|
1875
|
+
const card = document.createElement("div");
|
|
1876
|
+
card.className = "fp-docx-page-card";
|
|
1877
|
+
card.style.backgroundColor = "#ffffff";
|
|
1878
|
+
card.style.borderRadius = "6px";
|
|
1879
|
+
card.style.boxShadow = "0 4px 24px rgba(0,0,0,0.08)";
|
|
1880
|
+
card.style.padding = "48px 56px";
|
|
1881
|
+
card.style.fontFamily = 'Calibri, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
1882
|
+
card.style.color = "#1e293b";
|
|
1883
|
+
card.style.lineHeight = "1.6";
|
|
1884
|
+
const body = doc.getElementsByTagNameNS("*", "body")[0] || doc.documentElement;
|
|
1885
|
+
let html = "";
|
|
1886
|
+
for (const child of Array.from(body.children)) {
|
|
1887
|
+
const tag = child.localName || child.nodeName.split(":").pop();
|
|
1888
|
+
if (tag === "p") {
|
|
1889
|
+
const pStyle = child.getElementsByTagNameNS("*", "pStyle")[0];
|
|
1890
|
+
const styleVal = pStyle?.getAttribute("w:val") || pStyle?.getAttribute("val") || "";
|
|
1891
|
+
const numPr = child.getElementsByTagNameNS("*", "numPr")[0];
|
|
1892
|
+
const textContent = this.extractParagraphHtml(child, imageMap);
|
|
1893
|
+
if (!textContent.trim()) {
|
|
1894
|
+
html += '<div style="height: 10px;"></div>';
|
|
1895
|
+
continue;
|
|
1896
|
+
}
|
|
1897
|
+
const lowerStyle = styleVal.toLowerCase();
|
|
1898
|
+
if (lowerStyle.includes("title")) {
|
|
1899
|
+
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>`;
|
|
1900
|
+
} else if (lowerStyle.includes("heading1") || styleVal === "1") {
|
|
1901
|
+
html += `<h2 style="font-size: 22px; font-weight: 700; color: #1e40af; margin: 20px 0 10px;">${textContent}</h2>`;
|
|
1902
|
+
} else if (lowerStyle.includes("heading2") || styleVal === "2") {
|
|
1903
|
+
html += `<h3 style="font-size: 18px; font-weight: 600; color: #2563eb; margin: 16px 0 8px;">${textContent}</h3>`;
|
|
1904
|
+
} else if (lowerStyle.includes("heading3") || styleVal === "3") {
|
|
1905
|
+
html += `<h4 style="font-size: 15px; font-weight: 600; color: #334155; margin: 12px 0 6px;">${textContent}</h4>`;
|
|
1906
|
+
} else if (numPr) {
|
|
1907
|
+
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>`;
|
|
1908
|
+
} else {
|
|
1909
|
+
html += `<p style="margin: 8px 0; font-size: 14px;">${textContent}</p>`;
|
|
1910
|
+
}
|
|
1911
|
+
} else if (tag === "tbl") {
|
|
1912
|
+
html += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #cbd5e1;">';
|
|
1913
|
+
const rows = Array.from(child.getElementsByTagNameNS("*", "tr"));
|
|
1914
|
+
rows.forEach((tr, rIdx) => {
|
|
1915
|
+
html += `<tr style="${rIdx === 0 ? "background-color: #f8fafc; font-weight: 600;" : ""}">`;
|
|
1916
|
+
const cells = Array.from(tr.getElementsByTagNameNS("*", "tc"));
|
|
1917
|
+
cells.forEach((tc) => {
|
|
1918
|
+
const cellText = this.extractParagraphHtml(tc, imageMap);
|
|
1919
|
+
html += `<td style="border: 1px solid #cbd5e1; padding: 8px 12px; font-size: 13px;">${cellText || " "}</td>`;
|
|
1920
|
+
});
|
|
1921
|
+
html += "</tr>";
|
|
1922
|
+
});
|
|
1923
|
+
html += "</table>";
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
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"],
|
|
1928
|
+
ADD_ATTR: ["style", "src", "alt", "colspan", "rowspan"]
|
|
1929
|
+
});
|
|
1930
|
+
wrapper.appendChild(card);
|
|
1931
|
+
}
|
|
1932
|
+
extractParagraphHtml(pElement, imageMap = {}) {
|
|
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
|
+
}
|
|
1942
|
+
const runs = Array.from(pElement.getElementsByTagNameNS("*", "r"));
|
|
1943
|
+
if (runs.length === 0 && !result) {
|
|
1944
|
+
return DOMPurify2.sanitize(pElement.textContent || "");
|
|
1945
|
+
}
|
|
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
|
+
}
|
|
1960
|
+
const rPr = r.getElementsByTagNameNS("*", "rPr")[0];
|
|
1961
|
+
const isBold = !!rPr?.getElementsByTagNameNS("*", "b")[0];
|
|
1962
|
+
const isItalic = !!rPr?.getElementsByTagNameNS("*", "i")[0];
|
|
1963
|
+
const isUnderline = !!rPr?.getElementsByTagNameNS("*", "u")[0];
|
|
1964
|
+
const isStrike = !!rPr?.getElementsByTagNameNS("*", "strike")[0];
|
|
1965
|
+
const colorNode = rPr?.getElementsByTagNameNS("*", "color")[0];
|
|
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");
|
|
1969
|
+
const texts = Array.from(r.getElementsByTagNameNS("*", "t"));
|
|
1970
|
+
let text = texts.map((t) => t.textContent || "").join("");
|
|
1971
|
+
if (!text) continue;
|
|
1972
|
+
text = DOMPurify2.sanitize(text);
|
|
1973
|
+
let styles = "";
|
|
1974
|
+
if (isBold) styles += "font-weight: bold; ";
|
|
1975
|
+
if (isItalic) styles += "font-style: italic; ";
|
|
1976
|
+
if (isUnderline) styles += "text-decoration: underline; ";
|
|
1977
|
+
if (isStrike) styles += "text-decoration: line-through; ";
|
|
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
|
+
}
|
|
1983
|
+
if (styles) {
|
|
1984
|
+
result += `<span style="${styles}">${text}</span>`;
|
|
1985
|
+
} else {
|
|
1986
|
+
result += text;
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
return result;
|
|
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
|
+
}
|
|
1684
2037
|
};
|
|
1685
2038
|
function docxPlugin() {
|
|
1686
2039
|
return new DocxPlugin();
|
|
@@ -2492,7 +2845,7 @@ var MarkdownPlugin = class {
|
|
|
2492
2845
|
gfm: true,
|
|
2493
2846
|
breaks: true
|
|
2494
2847
|
});
|
|
2495
|
-
const cleanHtml =
|
|
2848
|
+
const cleanHtml = DOMPurify2.sanitize(rawHtml, {
|
|
2496
2849
|
USE_PROFILES: { html: true }
|
|
2497
2850
|
});
|
|
2498
2851
|
const wrapper = document.createElement("div");
|
|
@@ -2656,35 +3009,27 @@ var PptxPlugin = class {
|
|
|
2656
3009
|
group: "navigation",
|
|
2657
3010
|
execute: () => instance.toggleThumbnails?.()
|
|
2658
3011
|
},
|
|
2659
|
-
{
|
|
2660
|
-
id: "page-prev",
|
|
2661
|
-
icon: "page-prev",
|
|
2662
|
-
label: "Previous Slide",
|
|
2663
|
-
type: "button",
|
|
2664
|
-
group: "navigation",
|
|
2665
|
-
execute: () => {
|
|
2666
|
-
const cur = instance.getCurrentPage?.() ?? 1;
|
|
2667
|
-
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
2668
|
-
}
|
|
2669
|
-
},
|
|
2670
3012
|
{
|
|
2671
3013
|
id: "page-nav",
|
|
2672
3014
|
icon: "",
|
|
2673
|
-
label: "Slide
|
|
3015
|
+
label: "Slide Navigation",
|
|
2674
3016
|
type: "page-nav",
|
|
2675
3017
|
group: "navigation",
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
3018
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
3019
|
+
max: instance.getPageCount?.() ?? 1,
|
|
3020
|
+
execute: (action, page) => {
|
|
3021
|
+
if (action === "prev") {
|
|
3022
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3023
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3024
|
+
} else if (action === "next") {
|
|
3025
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3026
|
+
const total = instance.getPageCount?.() ?? 1;
|
|
3027
|
+
if (cur < total) instance.goToPage?.(cur + 1);
|
|
3028
|
+
} else if (typeof page === "number") {
|
|
3029
|
+
instance.goToPage?.(page);
|
|
3030
|
+
} else if (typeof action === "number") {
|
|
3031
|
+
instance.goToPage?.(action);
|
|
3032
|
+
}
|
|
2688
3033
|
}
|
|
2689
3034
|
},
|
|
2690
3035
|
{
|
|
@@ -3215,7 +3560,7 @@ var HtmlPreviewPlugin = class {
|
|
|
3215
3560
|
}
|
|
3216
3561
|
async render(ctx) {
|
|
3217
3562
|
const rawHtml = new TextDecoder("utf-8").decode(ctx.buffer);
|
|
3218
|
-
const sanitized =
|
|
3563
|
+
const sanitized = DOMPurify2.sanitize(rawHtml, {
|
|
3219
3564
|
WHOLE_DOCUMENT: true,
|
|
3220
3565
|
ADD_TAGS: ["style", "link"],
|
|
3221
3566
|
ADD_ATTR: ["target", "rel"]
|
|
@@ -3310,35 +3655,27 @@ var OpenDocumentPlugin = class {
|
|
|
3310
3655
|
group: "navigation",
|
|
3311
3656
|
execute: () => instance.toggleThumbnails?.()
|
|
3312
3657
|
},
|
|
3313
|
-
{
|
|
3314
|
-
id: "page-prev",
|
|
3315
|
-
icon: "page-prev",
|
|
3316
|
-
label: "Previous Slide",
|
|
3317
|
-
type: "button",
|
|
3318
|
-
group: "navigation",
|
|
3319
|
-
execute: () => {
|
|
3320
|
-
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3321
|
-
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3322
|
-
}
|
|
3323
|
-
},
|
|
3324
3658
|
{
|
|
3325
3659
|
id: "page-nav",
|
|
3326
3660
|
icon: "",
|
|
3327
|
-
label: "Slide
|
|
3661
|
+
label: "Slide Navigation",
|
|
3328
3662
|
type: "page-nav",
|
|
3329
3663
|
group: "navigation",
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3664
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
3665
|
+
max: instance.getPageCount?.() ?? 1,
|
|
3666
|
+
execute: (action, page) => {
|
|
3667
|
+
if (action === "prev") {
|
|
3668
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3669
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
3670
|
+
} else if (action === "next") {
|
|
3671
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
3672
|
+
const total = instance.getPageCount?.() ?? 1;
|
|
3673
|
+
if (cur < total) instance.goToPage?.(cur + 1);
|
|
3674
|
+
} else if (typeof page === "number") {
|
|
3675
|
+
instance.goToPage?.(page);
|
|
3676
|
+
} else if (typeof action === "number") {
|
|
3677
|
+
instance.goToPage?.(action);
|
|
3678
|
+
}
|
|
3342
3679
|
}
|
|
3343
3680
|
}
|
|
3344
3681
|
);
|
|
@@ -3466,7 +3803,7 @@ var OpenDocumentPlugin = class {
|
|
|
3466
3803
|
wrapper.style.padding = "48px";
|
|
3467
3804
|
wrapper.style.minHeight = "100%";
|
|
3468
3805
|
const bodyHtml = this.renderOdfBody(contentDoc, styleMap, imageUrls);
|
|
3469
|
-
wrapper.innerHTML =
|
|
3806
|
+
wrapper.innerHTML = DOMPurify2.sanitize(bodyHtml, {
|
|
3470
3807
|
ADD_TAGS: ["math", "semantics", "mrow", "mi", "mo", "mn", "msup", "msub"],
|
|
3471
3808
|
ADD_ATTR: ["style", "colspan", "rowspan"]
|
|
3472
3809
|
});
|
|
@@ -3986,24 +4323,24 @@ var DocPlugin = class {
|
|
|
3986
4323
|
html += "</ul>";
|
|
3987
4324
|
inList = false;
|
|
3988
4325
|
}
|
|
3989
|
-
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>`;
|
|
3990
4327
|
} else if (line.startsWith("\u2022") || line.startsWith("-") || line.startsWith("*")) {
|
|
3991
4328
|
if (!inList) {
|
|
3992
4329
|
html += '<ul style="margin: 8px 0; padding-left: 24px;">';
|
|
3993
4330
|
inList = true;
|
|
3994
4331
|
}
|
|
3995
4332
|
const bulletText = line.replace(/^[•\-\*]\s*/, "");
|
|
3996
|
-
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>`;
|
|
3997
4334
|
} else {
|
|
3998
4335
|
if (inList) {
|
|
3999
4336
|
html += "</ul>";
|
|
4000
4337
|
inList = false;
|
|
4001
4338
|
}
|
|
4002
|
-
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>`;
|
|
4003
4340
|
}
|
|
4004
4341
|
}
|
|
4005
4342
|
if (inList) html += "</ul>";
|
|
4006
|
-
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>`;
|
|
4007
4344
|
}
|
|
4008
4345
|
};
|
|
4009
4346
|
function docPlugin() {
|
|
@@ -4030,35 +4367,27 @@ var PptPlugin = class {
|
|
|
4030
4367
|
group: "navigation",
|
|
4031
4368
|
execute: () => instance.toggleThumbnails?.()
|
|
4032
4369
|
},
|
|
4033
|
-
{
|
|
4034
|
-
id: "page-prev",
|
|
4035
|
-
icon: "page-prev",
|
|
4036
|
-
label: "Previous Slide",
|
|
4037
|
-
type: "button",
|
|
4038
|
-
group: "navigation",
|
|
4039
|
-
execute: () => {
|
|
4040
|
-
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4041
|
-
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
4042
|
-
}
|
|
4043
|
-
},
|
|
4044
4370
|
{
|
|
4045
4371
|
id: "page-nav",
|
|
4046
4372
|
icon: "",
|
|
4047
|
-
label: "Slide
|
|
4373
|
+
label: "Slide Navigation",
|
|
4048
4374
|
type: "page-nav",
|
|
4049
4375
|
group: "navigation",
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4376
|
+
value: instance.getCurrentPage?.() ?? 1,
|
|
4377
|
+
max: instance.getPageCount?.() ?? 1,
|
|
4378
|
+
execute: (action, page) => {
|
|
4379
|
+
if (action === "prev") {
|
|
4380
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4381
|
+
if (cur > 1) instance.goToPage?.(cur - 1);
|
|
4382
|
+
} else if (action === "next") {
|
|
4383
|
+
const cur = instance.getCurrentPage?.() ?? 1;
|
|
4384
|
+
const total = instance.getPageCount?.() ?? 1;
|
|
4385
|
+
if (cur < total) instance.goToPage?.(cur + 1);
|
|
4386
|
+
} else if (typeof page === "number") {
|
|
4387
|
+
instance.goToPage?.(page);
|
|
4388
|
+
} else if (typeof action === "number") {
|
|
4389
|
+
instance.goToPage?.(action);
|
|
4390
|
+
}
|
|
4062
4391
|
}
|
|
4063
4392
|
},
|
|
4064
4393
|
{
|
|
@@ -4166,10 +4495,10 @@ var PptPlugin = class {
|
|
|
4166
4495
|
</div>
|
|
4167
4496
|
<div style="text-align: center; width: 100%;">
|
|
4168
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;">
|
|
4169
|
-
${
|
|
4498
|
+
${DOMPurify2.sanitize(s.title || `Slide ${idx}`)}
|
|
4170
4499
|
</h1>
|
|
4171
4500
|
<div style="display: flex; flex-direction: column; gap: 12px; max-width: 80%; margin: 0 auto; text-align: ${idx === 1 ? "center" : "left"};">
|
|
4172
|
-
${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("")}
|
|
4173
4502
|
</div>
|
|
4174
4503
|
</div>
|
|
4175
4504
|
`;
|