pptx-react-viewer 1.1.4 → 1.1.5
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/index.js +512 -96
- package/dist/index.mjs +512 -97
- package/dist/viewer/index.js +530 -102
- package/dist/viewer/index.mjs +530 -103
- package/node_modules/emf-converter/dist/index.d.mts +2 -2
- package/node_modules/emf-converter/dist/index.d.ts +2 -2
- package/node_modules/emf-converter/dist/index.js +91 -33
- package/node_modules/emf-converter/dist/index.mjs +91 -33
- package/node_modules/emf-converter/package.json +1 -1
- package/node_modules/mtx-decompressor/dist/index.js +39 -9
- package/node_modules/mtx-decompressor/dist/index.mjs +39 -9
- package/node_modules/mtx-decompressor/package.json +1 -1
- package/node_modules/pptx-viewer-core/dist/cli/index.js +0 -0
- package/node_modules/pptx-viewer-core/dist/cli/index.mjs +0 -0
- package/node_modules/pptx-viewer-core/dist/converter/index.js +0 -0
- package/node_modules/pptx-viewer-core/dist/converter/index.mjs +0 -0
- package/node_modules/pptx-viewer-core/dist/index.d.mts +95 -11
- package/node_modules/pptx-viewer-core/dist/index.d.ts +95 -11
- package/node_modules/pptx-viewer-core/dist/index.js +795 -257
- package/node_modules/pptx-viewer-core/dist/index.mjs +791 -258
- package/node_modules/pptx-viewer-core/dist/{signature-inspection-status-BcJSdOvb.d.mts → signature-inspection-status-BCUpfCQh.d.mts} +13 -2
- package/node_modules/pptx-viewer-core/dist/{signature-inspection-status-BcJSdOvb.d.ts → signature-inspection-status-BCUpfCQh.d.ts} +13 -2
- package/node_modules/pptx-viewer-core/dist/signature-node/index.d.mts +2 -2
- package/node_modules/pptx-viewer-core/dist/signature-node/index.d.ts +2 -2
- package/node_modules/pptx-viewer-core/dist/signature-node/index.js +17 -3
- package/node_modules/pptx-viewer-core/dist/signature-node/index.mjs +16 -4
- package/node_modules/pptx-viewer-core/package.json +1 -1
- package/package.json +6 -4
package/dist/viewer/index.mjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import * as React10 from 'react';
|
|
2
|
-
import React10__default, { createContext, useState, useEffect, useMemo, Suspense, useCallback, forwardRef, useRef, useSyncExternalStore, useImperativeHandle, useContext, useLayoutEffect } from 'react';
|
|
2
|
+
import React10__default, { createContext, useState, useEffect, useMemo, Suspense, useCallback, forwardRef, useRef, useSyncExternalStore, useImperativeHandle, useContext, useLayoutEffect, useDeferredValue } from 'react';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import * as ReactDOM from 'react-dom/client';
|
|
5
5
|
import { clsx } from 'clsx';
|
|
6
6
|
import { twMerge } from 'tailwind-merge';
|
|
7
7
|
import { LuMessageSquare, LuEyeOff, LuSettings, LuX, LuCast, LuShieldCheck, LuPlus, LuPanelLeftClose, LuStickyNote, LuMonitor, LuColumns2, LuPresentation, LuMinus, LuClock, LuDownload, LuTrash2, LuCheck, LuLock, LuEye, LuFileText, LuType, LuLoader, LuShieldAlert, LuSignature, LuInfo, LuTriangleAlert, LuPrinter, LuPenTool, LuWifi, LuWifiOff, LuUsers, LuCopy, LuMonitorOff, LuChevronLeft, LuChevronRight, LuPlay, LuPause, LuPanelLeft, LuUndo, LuRedo, LuSearch, LuShare2, LuPanelRight, LuFolderOpen, LuVideo, LuImage, LuClipboardPaste, LuScissors, LuPaintbrush, LuChevronDown, LuSquare, LuDatabase, LuLayers, LuAArrowUp, LuAArrowDown, LuRemoveFormatting, LuHighlighter, LuList, LuListOrdered, LuIndentDecrease, LuIndentIncrease, LuChevronUp, LuPalette, LuPencil, LuPaintBucket, LuSparkles, LuCaptions, LuSpellCheck, LuGitCompare, LuPipette, LuCaseSensitive, LuReplace, LuTimer, LuMousePointer2, LuEraser, LuGripVertical, LuUpload, LuBold, LuItalic, LuUnderline, LuStrikethrough, LuLink, LuGrid2X2, LuCopyPlus, LuEllipsis, LuCircle, LuMoveRight, LuTriangle, LuDiamond, LuAlignLeft, LuAlignCenter, LuAlignRight, LuAlignJustify, LuSpline, LuSettings2, LuMove, LuRadio, LuArrowDown, LuArrowUp, LuArrowRight, LuArrowLeft, LuReply, LuRotateCw, LuBookmark } from 'react-icons/lu';
|
|
8
8
|
import { hasShapeProperties, hasTextProperties, SWITCHABLE_LAYOUT_TYPES, isCalloutShape, getCalloutLeaderLineGeometry, buildCalloutLeaderLineSvgPath, getCalloutViewBoxBounds, isInkElement, getLinkedTextBoxSegments, isImageLikeElement, getSubstituteFontFamily, PptxHandler, EncryptedFileError, guidePxToEmu, guideEmuToPx, THEME_COLOR_SCHEME_KEYS, hslToRgb, PRESET_COLOR_MAP, elementActionToPptxAction, mergeShapes, SvgExporter, applyDrawingColorTransforms as applyDrawingColorTransforms$1, getPresetShapeClipPath, svgPathToPolygons, polygonsToSvgPath, EMU_PER_PX as EMU_PER_PX$1, chartDataChangeType, chartDataUpdatePoint, chartDataAddCategory, chartDataRemoveCategory, chartDataAddSeries, chartDataRemoveSeries, getOleObjectTypeLabel, pptxActionToElementAction, hasNonTrivialOverride, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, addSmartArtNodeAsChild, updateSmartArtNodeText, removeSmartArtNode, switchSmartArtLayout, applyThemeToData, THEME_PRESETS } from 'pptx-viewer-core';
|
|
9
|
+
import DOMPurify from 'dompurify';
|
|
9
10
|
import { useTranslation } from 'react-i18next';
|
|
10
11
|
import html2canvasPro from 'html2canvas-pro';
|
|
11
12
|
import JSZip from 'jszip';
|
|
@@ -43570,7 +43571,7 @@ var require_use_sync_external_store_shim_development = __commonJS({
|
|
|
43570
43571
|
return x2 === y && (0 !== x2 || 1 / x2 === 1 / y) || x2 !== x2 && y !== y;
|
|
43571
43572
|
}
|
|
43572
43573
|
function useSyncExternalStore$2(subscribe3, getSnapshot2) {
|
|
43573
|
-
didWarnOld18Alpha || void 0 ===
|
|
43574
|
+
didWarnOld18Alpha || void 0 === React100.startTransition || (didWarnOld18Alpha = true, console.error(
|
|
43574
43575
|
"You are using an outdated, pre-release alpha of React 18 that does not support useSyncExternalStore. The use-sync-external-store shim will not work correctly. Upgrade to a newer pre-release."
|
|
43575
43576
|
));
|
|
43576
43577
|
var value = getSnapshot2();
|
|
@@ -43580,7 +43581,7 @@ var require_use_sync_external_store_shim_development = __commonJS({
|
|
|
43580
43581
|
"The result of getSnapshot should be cached to avoid an infinite loop"
|
|
43581
43582
|
), didWarnUncachedGetSnapshot = true);
|
|
43582
43583
|
}
|
|
43583
|
-
cachedValue =
|
|
43584
|
+
cachedValue = useState86({
|
|
43584
43585
|
inst: { value, getSnapshot: getSnapshot2 }
|
|
43585
43586
|
});
|
|
43586
43587
|
var inst = cachedValue[0].inst, forceUpdate = cachedValue[1];
|
|
@@ -43618,8 +43619,8 @@ var require_use_sync_external_store_shim_development = __commonJS({
|
|
|
43618
43619
|
return getSnapshot2();
|
|
43619
43620
|
}
|
|
43620
43621
|
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
|
43621
|
-
var
|
|
43622
|
-
exports$1.useSyncExternalStore = void 0 !==
|
|
43622
|
+
var React100 = __require("react"), objectIs = "function" === typeof Object.is ? Object.is : is2, useState86 = React100.useState, useEffect72 = React100.useEffect, useLayoutEffect7 = React100.useLayoutEffect, useDebugValue = React100.useDebugValue, didWarnOld18Alpha = false, didWarnUncachedGetSnapshot = false, shim = "undefined" === typeof window || "undefined" === typeof window.document || "undefined" === typeof window.document.createElement ? useSyncExternalStore$1 : useSyncExternalStore$2;
|
|
43623
|
+
exports$1.useSyncExternalStore = void 0 !== React100.useSyncExternalStore ? React100.useSyncExternalStore : shim;
|
|
43623
43624
|
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
|
|
43624
43625
|
})();
|
|
43625
43626
|
}
|
|
@@ -43642,7 +43643,7 @@ var require_with_selector_development = __commonJS({
|
|
|
43642
43643
|
return x2 === y && (0 !== x2 || 1 / x2 === 1 / y) || x2 !== x2 && y !== y;
|
|
43643
43644
|
}
|
|
43644
43645
|
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
|
43645
|
-
var
|
|
43646
|
+
var React100 = __require("react"), shim = require_shim(), objectIs = "function" === typeof Object.is ? Object.is : is2, useSyncExternalStore3 = shim.useSyncExternalStore, useRef73 = React100.useRef, useEffect72 = React100.useEffect, useMemo42 = React100.useMemo, useDebugValue = React100.useDebugValue;
|
|
43646
43647
|
exports$1.useSyncExternalStoreWithSelector = function(subscribe3, getSnapshot2, getServerSnapshot2, selector, isEqual) {
|
|
43647
43648
|
var instRef = useRef73(null);
|
|
43648
43649
|
if (null === instRef.current) {
|
|
@@ -74063,6 +74064,13 @@ function hasDistinctScriptFonts(fonts) {
|
|
|
74063
74064
|
}
|
|
74064
74065
|
return Boolean(fonts.eastAsia) && fonts.eastAsia !== base || Boolean(fonts.complexScript) && fonts.complexScript !== base || Boolean(fonts.symbol) && fonts.symbol !== base;
|
|
74065
74066
|
}
|
|
74067
|
+
function sanitizeMathMl(markup) {
|
|
74068
|
+
const purify = DOMPurify;
|
|
74069
|
+
if (typeof purify.sanitize !== "function") {
|
|
74070
|
+
return markup;
|
|
74071
|
+
}
|
|
74072
|
+
return purify.sanitize(markup, { USE_PROFILES: { mathMl: true, svg: true } });
|
|
74073
|
+
}
|
|
74066
74074
|
function renderScriptAwareText(text2, needsScriptFonts, scriptFonts, baseFontFamily, keyPrefix) {
|
|
74067
74075
|
if (!needsScriptFonts || !text2) {
|
|
74068
74076
|
return text2;
|
|
@@ -74153,14 +74161,15 @@ function renderSegmentContent(elementId, segmentIndex, textValue, lines, needsSc
|
|
|
74153
74161
|
}
|
|
74154
74162
|
function renderEquationSegment(elementId, segmentIndex, equationXml, equationNumber) {
|
|
74155
74163
|
const mathml = convertOmmlToMathMl(equationXml);
|
|
74156
|
-
const
|
|
74164
|
+
const safeMathml = mathml ? sanitizeMathMl(mathml) : "";
|
|
74165
|
+
const equationContent = safeMathml ? /* @__PURE__ */ jsx(
|
|
74157
74166
|
"span",
|
|
74158
74167
|
{
|
|
74159
74168
|
className: "inline-block align-middle",
|
|
74160
74169
|
style: {
|
|
74161
74170
|
fontFamily: '"Cambria Math", "STIX Two Math", serif'
|
|
74162
74171
|
},
|
|
74163
|
-
dangerouslySetInnerHTML: { __html:
|
|
74172
|
+
dangerouslySetInnerHTML: { __html: safeMathml }
|
|
74164
74173
|
}
|
|
74165
74174
|
) : /* @__PURE__ */ jsx("span", { className: "inline-block px-1 py-0.5 rounded text-xs bg-gray-200/20 text-gray-400 italic", children: "Equation" });
|
|
74166
74175
|
if (equationNumber) {
|
|
@@ -86517,7 +86526,7 @@ function ResizeHandle({
|
|
|
86517
86526
|
}
|
|
86518
86527
|
);
|
|
86519
86528
|
}
|
|
86520
|
-
function
|
|
86529
|
+
function SlideThumbnailImpl({
|
|
86521
86530
|
slide,
|
|
86522
86531
|
templateElements,
|
|
86523
86532
|
canvasSize
|
|
@@ -86755,6 +86764,37 @@ function ThumbnailTable({
|
|
|
86755
86764
|
}
|
|
86756
86765
|
return /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-[10px] text-muted-foreground pointer-events-none", children: "Table" });
|
|
86757
86766
|
}
|
|
86767
|
+
function arePropsEqual(prev, next) {
|
|
86768
|
+
if (prev.slide.id !== next.slide.id) {
|
|
86769
|
+
return false;
|
|
86770
|
+
}
|
|
86771
|
+
if (prev.slide.isDirty !== next.slide.isDirty) {
|
|
86772
|
+
return false;
|
|
86773
|
+
}
|
|
86774
|
+
if (prev.slide.hidden !== next.slide.hidden) {
|
|
86775
|
+
return false;
|
|
86776
|
+
}
|
|
86777
|
+
if (prev.slide.elements !== next.slide.elements) {
|
|
86778
|
+
return false;
|
|
86779
|
+
}
|
|
86780
|
+
if (prev.slide.backgroundColor !== next.slide.backgroundColor) {
|
|
86781
|
+
return false;
|
|
86782
|
+
}
|
|
86783
|
+
if (prev.slide.backgroundImage !== next.slide.backgroundImage) {
|
|
86784
|
+
return false;
|
|
86785
|
+
}
|
|
86786
|
+
if (prev.slide.backgroundGradient !== next.slide.backgroundGradient) {
|
|
86787
|
+
return false;
|
|
86788
|
+
}
|
|
86789
|
+
if (prev.templateElements !== next.templateElements) {
|
|
86790
|
+
return false;
|
|
86791
|
+
}
|
|
86792
|
+
if (prev.canvasSize.width !== next.canvasSize.width || prev.canvasSize.height !== next.canvasSize.height) {
|
|
86793
|
+
return false;
|
|
86794
|
+
}
|
|
86795
|
+
return true;
|
|
86796
|
+
}
|
|
86797
|
+
var SlideThumbnail = React10__default.memo(SlideThumbnailImpl, arePropsEqual);
|
|
86758
86798
|
function ContextMenu({
|
|
86759
86799
|
contextMenuState,
|
|
86760
86800
|
mode,
|
|
@@ -90488,7 +90528,7 @@ function BendingProcessRenderer({
|
|
|
90488
90528
|
}
|
|
90489
90529
|
);
|
|
90490
90530
|
}
|
|
90491
|
-
function
|
|
90531
|
+
function SmartArtRendererImpl({
|
|
90492
90532
|
element: element2,
|
|
90493
90533
|
className = ""
|
|
90494
90534
|
}) {
|
|
@@ -90599,6 +90639,30 @@ function renderLayout(layoutType, element2, nodes, palette, style) {
|
|
|
90599
90639
|
}
|
|
90600
90640
|
return /* @__PURE__ */ jsx(ListRenderer, { element: element2, nodes, palette, style });
|
|
90601
90641
|
}
|
|
90642
|
+
function arePropsEqual2(prev, next) {
|
|
90643
|
+
if (prev.className !== next.className) {
|
|
90644
|
+
return false;
|
|
90645
|
+
}
|
|
90646
|
+
if (prev.element.id !== next.element.id) {
|
|
90647
|
+
return false;
|
|
90648
|
+
}
|
|
90649
|
+
if (prev.element.type !== next.element.type) {
|
|
90650
|
+
return false;
|
|
90651
|
+
}
|
|
90652
|
+
if (prev.element.width !== next.element.width || prev.element.height !== next.element.height) {
|
|
90653
|
+
return false;
|
|
90654
|
+
}
|
|
90655
|
+
if (prev.element.x !== next.element.x || prev.element.y !== next.element.y) {
|
|
90656
|
+
return false;
|
|
90657
|
+
}
|
|
90658
|
+
const prevData = prev.element.type === "smartArt" ? prev.element.smartArtData : void 0;
|
|
90659
|
+
const nextData = next.element.type === "smartArt" ? next.element.smartArtData : void 0;
|
|
90660
|
+
if (prevData !== nextData) {
|
|
90661
|
+
return false;
|
|
90662
|
+
}
|
|
90663
|
+
return true;
|
|
90664
|
+
}
|
|
90665
|
+
var SmartArtRenderer = React10__default.memo(SmartArtRendererImpl, arePropsEqual2);
|
|
90602
90666
|
function ZoomElementRenderer({
|
|
90603
90667
|
element: element2,
|
|
90604
90668
|
slides,
|
|
@@ -93637,7 +93701,7 @@ function SectionBlock({
|
|
|
93637
93701
|
)
|
|
93638
93702
|
] });
|
|
93639
93703
|
}
|
|
93640
|
-
function
|
|
93704
|
+
function SlideCardImpl({
|
|
93641
93705
|
slide,
|
|
93642
93706
|
index,
|
|
93643
93707
|
isActive,
|
|
@@ -93691,6 +93755,49 @@ function SlideCard({
|
|
|
93691
93755
|
}
|
|
93692
93756
|
);
|
|
93693
93757
|
}
|
|
93758
|
+
function arePropsEqual3(prev, next) {
|
|
93759
|
+
if (prev.slide.id !== next.slide.id) {
|
|
93760
|
+
return false;
|
|
93761
|
+
}
|
|
93762
|
+
if (prev.slide.isDirty !== next.slide.isDirty) {
|
|
93763
|
+
return false;
|
|
93764
|
+
}
|
|
93765
|
+
if (prev.slide.hidden !== next.slide.hidden) {
|
|
93766
|
+
return false;
|
|
93767
|
+
}
|
|
93768
|
+
if (prev.slide.elements !== next.slide.elements) {
|
|
93769
|
+
return false;
|
|
93770
|
+
}
|
|
93771
|
+
if (prev.index !== next.index) {
|
|
93772
|
+
return false;
|
|
93773
|
+
}
|
|
93774
|
+
if (prev.isActive !== next.isActive) {
|
|
93775
|
+
return false;
|
|
93776
|
+
}
|
|
93777
|
+
if (prev.isDragTarget !== next.isDragTarget) {
|
|
93778
|
+
return false;
|
|
93779
|
+
}
|
|
93780
|
+
if (prev.isSelected !== next.isSelected) {
|
|
93781
|
+
return false;
|
|
93782
|
+
}
|
|
93783
|
+
if (prev.selectedCount !== next.selectedCount) {
|
|
93784
|
+
return false;
|
|
93785
|
+
}
|
|
93786
|
+
if (prev.selectionOrder !== next.selectionOrder) {
|
|
93787
|
+
return false;
|
|
93788
|
+
}
|
|
93789
|
+
if (prev.canEdit !== next.canEdit) {
|
|
93790
|
+
return false;
|
|
93791
|
+
}
|
|
93792
|
+
if (prev.canvasSize.width !== next.canvasSize.width || prev.canvasSize.height !== next.canvasSize.height) {
|
|
93793
|
+
return false;
|
|
93794
|
+
}
|
|
93795
|
+
if (prev.onSlideClick !== next.onSlideClick || prev.onDoubleClick !== next.onDoubleClick || prev.onContextMenu !== next.onContextMenu || prev.onDragStart !== next.onDragStart || prev.onDragOver !== next.onDragOver || prev.onDragLeave !== next.onDragLeave || prev.onDrop !== next.onDrop) {
|
|
93796
|
+
return false;
|
|
93797
|
+
}
|
|
93798
|
+
return true;
|
|
93799
|
+
}
|
|
93800
|
+
var SlideCard = React10__default.memo(SlideCardImpl, arePropsEqual3);
|
|
93694
93801
|
function SorterContextMenu({
|
|
93695
93802
|
x: x2,
|
|
93696
93803
|
y,
|
|
@@ -94484,6 +94591,14 @@ function getCurrentParagraphIndex(editorEl, segments) {
|
|
|
94484
94591
|
}
|
|
94485
94592
|
return paraIdx;
|
|
94486
94593
|
}
|
|
94594
|
+
var CSS_VALUE_SAFE = /^[a-zA-Z0-9 _,.\-+#'%/]{1,100}$/;
|
|
94595
|
+
function isCssValueSafe(value) {
|
|
94596
|
+
if (value === void 0 || value === null) {
|
|
94597
|
+
return false;
|
|
94598
|
+
}
|
|
94599
|
+
const str = String(value);
|
|
94600
|
+
return str.length > 0 && CSS_VALUE_SAFE.test(str);
|
|
94601
|
+
}
|
|
94487
94602
|
function deriveStyleFromElement(element2, inheritedStyle) {
|
|
94488
94603
|
const style = { ...inheritedStyle };
|
|
94489
94604
|
const tagName = element2.tagName.toLowerCase();
|
|
@@ -94616,17 +94731,17 @@ function segmentsToEditorHtml(segments) {
|
|
|
94616
94731
|
if (segment.style.strikethrough) {
|
|
94617
94732
|
inlineStyles.push("text-decoration:line-through");
|
|
94618
94733
|
}
|
|
94619
|
-
if (segment.style.color) {
|
|
94734
|
+
if (segment.style.color && isCssValueSafe(segment.style.color)) {
|
|
94620
94735
|
inlineStyles.push(`color:${segment.style.color}`);
|
|
94621
94736
|
}
|
|
94622
|
-
if (segment.style.fontSize) {
|
|
94623
|
-
inlineStyles.push(`font-size:${segment.style.fontSize}pt`);
|
|
94737
|
+
if (segment.style.fontSize && Number.isFinite(Number(segment.style.fontSize))) {
|
|
94738
|
+
inlineStyles.push(`font-size:${Number(segment.style.fontSize)}pt`);
|
|
94624
94739
|
}
|
|
94625
|
-
if (segment.style.fontFamily) {
|
|
94740
|
+
if (segment.style.fontFamily && isCssValueSafe(segment.style.fontFamily)) {
|
|
94626
94741
|
inlineStyles.push(`font-family:${segment.style.fontFamily}`);
|
|
94627
94742
|
}
|
|
94628
94743
|
const text2 = escapeHtml(segment.text);
|
|
94629
|
-
if (segment.style.hyperlink) {
|
|
94744
|
+
if (segment.style.hyperlink && isUrlSafe(segment.style.hyperlink)) {
|
|
94630
94745
|
const href = escapeHtml(segment.style.hyperlink);
|
|
94631
94746
|
return `<a href="${href}" style="color:#4a9eff;text-decoration:underline;cursor:pointer" data-hyperlink="${href}">${text2}</a>`;
|
|
94632
94747
|
}
|
|
@@ -94709,7 +94824,8 @@ function renderRichNotesSegments(segments) {
|
|
|
94709
94824
|
if (segment.style.fontFamily) {
|
|
94710
94825
|
style.fontFamily = segment.style.fontFamily;
|
|
94711
94826
|
}
|
|
94712
|
-
if (segment.style.hyperlink) {
|
|
94827
|
+
if (segment.style.hyperlink && isUrlSafe(segment.style.hyperlink)) {
|
|
94828
|
+
const safeHref = segment.style.hyperlink;
|
|
94713
94829
|
style.color = "#4a9eff";
|
|
94714
94830
|
style.textDecoration = "underline";
|
|
94715
94831
|
style.cursor = "pointer";
|
|
@@ -94717,11 +94833,11 @@ function renderRichNotesSegments(segments) {
|
|
|
94717
94833
|
/* @__PURE__ */ jsx(
|
|
94718
94834
|
"a",
|
|
94719
94835
|
{
|
|
94720
|
-
href:
|
|
94836
|
+
href: safeHref,
|
|
94721
94837
|
style,
|
|
94722
94838
|
onClick: (e2) => {
|
|
94723
94839
|
e2.preventDefault();
|
|
94724
|
-
|
|
94840
|
+
safeOpenUrl(safeHref);
|
|
94725
94841
|
},
|
|
94726
94842
|
children: segment.text
|
|
94727
94843
|
},
|
|
@@ -95273,7 +95389,7 @@ function useSlideNotes({
|
|
|
95273
95389
|
const href = target.getAttribute("data-hyperlink") || target.getAttribute("href");
|
|
95274
95390
|
if (href && (e2.ctrlKey || e2.metaKey)) {
|
|
95275
95391
|
e2.preventDefault();
|
|
95276
|
-
|
|
95392
|
+
safeOpenUrl(href);
|
|
95277
95393
|
}
|
|
95278
95394
|
}, []);
|
|
95279
95395
|
return {
|
|
@@ -96946,7 +97062,7 @@ function renderNotesSegments(segments) {
|
|
|
96946
97062
|
return React10__default.createElement("span", { key: `seg-${index}`, style }, segment.text);
|
|
96947
97063
|
});
|
|
96948
97064
|
}
|
|
96949
|
-
function
|
|
97065
|
+
function ScaledSlidePreviewImpl({
|
|
96950
97066
|
slide,
|
|
96951
97067
|
templateElements,
|
|
96952
97068
|
canvasSize,
|
|
@@ -97093,6 +97209,40 @@ function ScaledSlidePreview({
|
|
|
97093
97209
|
}
|
|
97094
97210
|
);
|
|
97095
97211
|
}
|
|
97212
|
+
function arePropsEqual4(prev, next) {
|
|
97213
|
+
if (prev.slide.id !== next.slide.id) {
|
|
97214
|
+
return false;
|
|
97215
|
+
}
|
|
97216
|
+
if (prev.slide.isDirty !== next.slide.isDirty) {
|
|
97217
|
+
return false;
|
|
97218
|
+
}
|
|
97219
|
+
if (prev.slide.hidden !== next.slide.hidden) {
|
|
97220
|
+
return false;
|
|
97221
|
+
}
|
|
97222
|
+
if (prev.slide.elements !== next.slide.elements) {
|
|
97223
|
+
return false;
|
|
97224
|
+
}
|
|
97225
|
+
if (prev.slide.backgroundColor !== next.slide.backgroundColor) {
|
|
97226
|
+
return false;
|
|
97227
|
+
}
|
|
97228
|
+
if (prev.slide.backgroundImage !== next.slide.backgroundImage) {
|
|
97229
|
+
return false;
|
|
97230
|
+
}
|
|
97231
|
+
if (prev.slide.backgroundGradient !== next.slide.backgroundGradient) {
|
|
97232
|
+
return false;
|
|
97233
|
+
}
|
|
97234
|
+
if (prev.templateElements !== next.templateElements) {
|
|
97235
|
+
return false;
|
|
97236
|
+
}
|
|
97237
|
+
if (prev.canvasSize.width !== next.canvasSize.width || prev.canvasSize.height !== next.canvasSize.height) {
|
|
97238
|
+
return false;
|
|
97239
|
+
}
|
|
97240
|
+
if (prev.className !== next.className) {
|
|
97241
|
+
return false;
|
|
97242
|
+
}
|
|
97243
|
+
return true;
|
|
97244
|
+
}
|
|
97245
|
+
var ScaledSlidePreview = React10__default.memo(ScaledSlidePreviewImpl, arePropsEqual4);
|
|
97096
97246
|
function PresenterView({
|
|
97097
97247
|
slides,
|
|
97098
97248
|
currentSlideIndex,
|
|
@@ -111396,6 +111546,13 @@ function convertOmmlToLatex(omml) {
|
|
|
111396
111546
|
}
|
|
111397
111547
|
return ommlChildrenToLatex(oMath);
|
|
111398
111548
|
}
|
|
111549
|
+
function sanitizeMathMl2(markup) {
|
|
111550
|
+
const purify = DOMPurify;
|
|
111551
|
+
if (typeof purify.sanitize !== "function") {
|
|
111552
|
+
return markup;
|
|
111553
|
+
}
|
|
111554
|
+
return purify.sanitize(markup, { USE_PROFILES: { mathMl: true, svg: true } });
|
|
111555
|
+
}
|
|
111399
111556
|
var TEMPLATES = [
|
|
111400
111557
|
{
|
|
111401
111558
|
label: "Fraction",
|
|
@@ -111461,7 +111618,8 @@ var TEMPLATES = [
|
|
|
111461
111618
|
var TEMPLATE_MATHML = TEMPLATES.map((tmpl) => {
|
|
111462
111619
|
try {
|
|
111463
111620
|
const tmplOmml = convertLatexToOmml(tmpl.latex);
|
|
111464
|
-
|
|
111621
|
+
const raw = convertOmmlToMathMl(tmplOmml);
|
|
111622
|
+
return raw ? sanitizeMathMl2(raw) : "";
|
|
111465
111623
|
} catch {
|
|
111466
111624
|
return "";
|
|
111467
111625
|
}
|
|
@@ -111473,7 +111631,7 @@ function MathMlPreview({ mathml }) {
|
|
|
111473
111631
|
return;
|
|
111474
111632
|
}
|
|
111475
111633
|
if (mathml) {
|
|
111476
|
-
containerRef.current.innerHTML = mathml;
|
|
111634
|
+
containerRef.current.innerHTML = sanitizeMathMl2(mathml);
|
|
111477
111635
|
} else {
|
|
111478
111636
|
containerRef.current.innerHTML = "";
|
|
111479
111637
|
}
|
|
@@ -111501,6 +111659,7 @@ function EquationEditorDialog({
|
|
|
111501
111659
|
return convertOmmlToLatex(existingOmml);
|
|
111502
111660
|
}, [existingOmml]);
|
|
111503
111661
|
const [latex, setLatex] = useState(initialLatex);
|
|
111662
|
+
const deferredLatex = useDeferredValue(latex);
|
|
111504
111663
|
const textareaRef = useRef(null);
|
|
111505
111664
|
useEffect(() => {
|
|
111506
111665
|
if (isOpen) {
|
|
@@ -111509,17 +111668,17 @@ function EquationEditorDialog({
|
|
|
111509
111668
|
}
|
|
111510
111669
|
}, [isOpen, initialLatex]);
|
|
111511
111670
|
const { mathml, omml } = useMemo(() => {
|
|
111512
|
-
if (!
|
|
111671
|
+
if (!deferredLatex.trim()) {
|
|
111513
111672
|
return { mathml: "", omml: {} };
|
|
111514
111673
|
}
|
|
111515
111674
|
try {
|
|
111516
|
-
const ommlObj = convertLatexToOmml(
|
|
111675
|
+
const ommlObj = convertLatexToOmml(deferredLatex);
|
|
111517
111676
|
const mathmlStr = convertOmmlToMathMl(ommlObj);
|
|
111518
111677
|
return { mathml: mathmlStr, omml: ommlObj };
|
|
111519
111678
|
} catch {
|
|
111520
111679
|
return { mathml: "", omml: {} };
|
|
111521
111680
|
}
|
|
111522
|
-
}, [
|
|
111681
|
+
}, [deferredLatex]);
|
|
111523
111682
|
const handleInsert = useCallback(() => {
|
|
111524
111683
|
if (!latex.trim()) {
|
|
111525
111684
|
return;
|
|
@@ -114283,6 +114442,7 @@ function useEditorHistory(input) {
|
|
|
114283
114442
|
const historyFutureRef = useRef([]);
|
|
114284
114443
|
const lastHistorySnapshotRef = useRef(null);
|
|
114285
114444
|
const lastHistorySerializedRef = useRef("");
|
|
114445
|
+
const lastCheapHashRef = useRef("");
|
|
114286
114446
|
const isApplyingHistoryRef = useRef(false);
|
|
114287
114447
|
const unlockHistoryTimerRef = useRef(null);
|
|
114288
114448
|
const [canUndo, setCanUndo] = useState(false);
|
|
@@ -114424,15 +114584,21 @@ function useEditorHistory(input) {
|
|
|
114424
114584
|
if (hasActivePointerInteraction()) {
|
|
114425
114585
|
return;
|
|
114426
114586
|
}
|
|
114587
|
+
const cheapHash = `${slides.length}|${activeSlideIndex}|${canvasSize.width}x${canvasSize.height}|${slides.map((s) => `${s.id}:${s.elements.length}`).join("/")}`;
|
|
114588
|
+
if (cheapHash === lastCheapHashRef.current) {
|
|
114589
|
+
return;
|
|
114590
|
+
}
|
|
114427
114591
|
const snapshot2 = buildHistorySnapshot();
|
|
114428
114592
|
const serialized = JSON.stringify(snapshot2);
|
|
114429
114593
|
if (serialized === lastHistorySerializedRef.current) {
|
|
114594
|
+
lastCheapHashRef.current = cheapHash;
|
|
114430
114595
|
return;
|
|
114431
114596
|
}
|
|
114432
114597
|
const previousSnapshot = lastHistorySnapshotRef.current;
|
|
114433
114598
|
if (!previousSnapshot) {
|
|
114434
114599
|
lastHistorySnapshotRef.current = cloneHistorySnapshot(snapshot2);
|
|
114435
114600
|
lastHistorySerializedRef.current = serialized;
|
|
114601
|
+
lastCheapHashRef.current = cheapHash;
|
|
114436
114602
|
updateHistoryAvailability();
|
|
114437
114603
|
return;
|
|
114438
114604
|
}
|
|
@@ -114443,13 +114609,18 @@ function useEditorHistory(input) {
|
|
|
114443
114609
|
historyFutureRef.current = [];
|
|
114444
114610
|
lastHistorySnapshotRef.current = cloneHistorySnapshot(snapshot2);
|
|
114445
114611
|
lastHistorySerializedRef.current = serialized;
|
|
114612
|
+
lastCheapHashRef.current = cheapHash;
|
|
114446
114613
|
updateHistoryAvailability();
|
|
114447
114614
|
}, [
|
|
114615
|
+
activeSlideIndex,
|
|
114448
114616
|
buildHistorySnapshot,
|
|
114617
|
+
canvasSize.height,
|
|
114618
|
+
canvasSize.width,
|
|
114449
114619
|
error2,
|
|
114450
114620
|
hasActivePointerInteraction,
|
|
114451
114621
|
loading2,
|
|
114452
114622
|
pointerCommitNonce,
|
|
114623
|
+
slides,
|
|
114453
114624
|
updateHistoryAvailability
|
|
114454
114625
|
]);
|
|
114455
114626
|
return {
|
|
@@ -118142,6 +118313,7 @@ var DB_NAME2 = "pptx-viewer-audience";
|
|
|
118142
118313
|
var DB_VERSION2 = 1;
|
|
118143
118314
|
var STORE_NAME2 = "content";
|
|
118144
118315
|
var CONTENT_KEY = "pptx-bytes";
|
|
118316
|
+
var MAX_CONTENT_AGE_MS = 5 * 60 * 1e3;
|
|
118145
118317
|
function openDb() {
|
|
118146
118318
|
return new Promise((resolve2, reject) => {
|
|
118147
118319
|
const request = indexedDB.open(DB_NAME2, DB_VERSION2);
|
|
@@ -118161,7 +118333,8 @@ async function storeAudienceContent(content) {
|
|
|
118161
118333
|
const tx = db.transaction(STORE_NAME2, "readwrite");
|
|
118162
118334
|
const store = tx.objectStore(STORE_NAME2);
|
|
118163
118335
|
const bytes = content instanceof Uint8Array ? content : new Uint8Array(content);
|
|
118164
|
-
|
|
118336
|
+
const record = { bytes, createdAt: Date.now() };
|
|
118337
|
+
store.put(record, CONTENT_KEY);
|
|
118165
118338
|
tx.oncomplete = () => {
|
|
118166
118339
|
db.close();
|
|
118167
118340
|
resolve2();
|
|
@@ -118182,13 +118355,24 @@ async function loadAudienceContent() {
|
|
|
118182
118355
|
request.onsuccess = () => {
|
|
118183
118356
|
db.close();
|
|
118184
118357
|
const result = request.result;
|
|
118185
|
-
if (result
|
|
118186
|
-
|
|
118187
|
-
|
|
118188
|
-
|
|
118189
|
-
|
|
118190
|
-
|
|
118358
|
+
if (result && typeof result === "object" && "bytes" in result && "createdAt" in result) {
|
|
118359
|
+
const record = result;
|
|
118360
|
+
const age = Date.now() - record.createdAt;
|
|
118361
|
+
if (age > MAX_CONTENT_AGE_MS) {
|
|
118362
|
+
resolve2(null);
|
|
118363
|
+
return;
|
|
118364
|
+
}
|
|
118365
|
+
const raw = record.bytes;
|
|
118366
|
+
if (raw instanceof Uint8Array) {
|
|
118367
|
+
resolve2(raw);
|
|
118368
|
+
} else if (raw instanceof ArrayBuffer) {
|
|
118369
|
+
resolve2(new Uint8Array(raw));
|
|
118370
|
+
} else {
|
|
118371
|
+
resolve2(null);
|
|
118372
|
+
}
|
|
118373
|
+
return;
|
|
118191
118374
|
}
|
|
118375
|
+
resolve2(null);
|
|
118192
118376
|
};
|
|
118193
118377
|
request.onerror = () => {
|
|
118194
118378
|
db.close();
|
|
@@ -118221,14 +118405,34 @@ async function clearAudienceContent() {
|
|
|
118221
118405
|
var PRESENTER_CHANNEL_NAME = "pptx-viewer-presenter";
|
|
118222
118406
|
var AUDIENCE_HASH = "#pptx-audience";
|
|
118223
118407
|
var PRESENTER_MSG_ORIGIN = "pptx-viewer-presenter";
|
|
118408
|
+
var AUDIENCE_NONCE_KEY = "nonce";
|
|
118409
|
+
function generateSessionId() {
|
|
118410
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
118411
|
+
return crypto.randomUUID();
|
|
118412
|
+
}
|
|
118413
|
+
return `s${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
|
|
118414
|
+
}
|
|
118415
|
+
function parseAudienceNonce() {
|
|
118416
|
+
const hash = window.location.hash;
|
|
118417
|
+
if (!hash.startsWith(AUDIENCE_HASH)) {
|
|
118418
|
+
return null;
|
|
118419
|
+
}
|
|
118420
|
+
const trailing = hash.slice(AUDIENCE_HASH.length);
|
|
118421
|
+
if (!trailing) {
|
|
118422
|
+
return null;
|
|
118423
|
+
}
|
|
118424
|
+
const params2 = new URLSearchParams(trailing.replace(/^[&;?]/, ""));
|
|
118425
|
+
return params2.get(AUDIENCE_NONCE_KEY);
|
|
118426
|
+
}
|
|
118224
118427
|
function isAudienceTab() {
|
|
118225
|
-
return window.location.hash
|
|
118428
|
+
return window.location.hash.startsWith(AUDIENCE_HASH);
|
|
118226
118429
|
}
|
|
118227
118430
|
function usePresenterWindow(input) {
|
|
118228
118431
|
const { currentSlideIndex, isPresenterMode, content } = input;
|
|
118229
118432
|
const audienceWindowRef = useRef(null);
|
|
118230
118433
|
const channelRef = useRef(null);
|
|
118231
118434
|
const pollTimerRef = useRef(null);
|
|
118435
|
+
const sessionIdRef = useRef("");
|
|
118232
118436
|
const getChannel2 = useCallback(() => {
|
|
118233
118437
|
if (!channelRef.current) {
|
|
118234
118438
|
channelRef.current = new BroadcastChannel(PRESENTER_CHANNEL_NAME);
|
|
@@ -118240,10 +118444,14 @@ function usePresenterWindow(input) {
|
|
|
118240
118444
|
}, []);
|
|
118241
118445
|
const syncSlideToAudience = useCallback(
|
|
118242
118446
|
(slideIndex) => {
|
|
118447
|
+
if (!sessionIdRef.current) {
|
|
118448
|
+
return;
|
|
118449
|
+
}
|
|
118243
118450
|
const msg = {
|
|
118244
118451
|
origin: PRESENTER_MSG_ORIGIN,
|
|
118245
118452
|
type: "presenter-slide-change",
|
|
118246
|
-
slideIndex
|
|
118453
|
+
slideIndex,
|
|
118454
|
+
sessionId: sessionIdRef.current
|
|
118247
118455
|
};
|
|
118248
118456
|
try {
|
|
118249
118457
|
getChannel2().postMessage(msg);
|
|
@@ -118253,13 +118461,16 @@ function usePresenterWindow(input) {
|
|
|
118253
118461
|
[getChannel2]
|
|
118254
118462
|
);
|
|
118255
118463
|
const closeAudienceWindow = useCallback(() => {
|
|
118256
|
-
|
|
118257
|
-
|
|
118258
|
-
|
|
118259
|
-
|
|
118260
|
-
|
|
118261
|
-
|
|
118262
|
-
|
|
118464
|
+
if (sessionIdRef.current) {
|
|
118465
|
+
try {
|
|
118466
|
+
const exitMsg = {
|
|
118467
|
+
origin: PRESENTER_MSG_ORIGIN,
|
|
118468
|
+
type: "presenter-exit",
|
|
118469
|
+
sessionId: sessionIdRef.current
|
|
118470
|
+
};
|
|
118471
|
+
getChannel2().postMessage(exitMsg);
|
|
118472
|
+
} catch {
|
|
118473
|
+
}
|
|
118263
118474
|
}
|
|
118264
118475
|
const win = audienceWindowRef.current;
|
|
118265
118476
|
if (win && !win.closed) {
|
|
@@ -118269,6 +118480,7 @@ function usePresenterWindow(input) {
|
|
|
118269
118480
|
}
|
|
118270
118481
|
}
|
|
118271
118482
|
audienceWindowRef.current = null;
|
|
118483
|
+
sessionIdRef.current = "";
|
|
118272
118484
|
if (pollTimerRef.current !== null) {
|
|
118273
118485
|
clearInterval(pollTimerRef.current);
|
|
118274
118486
|
pollTimerRef.current = null;
|
|
@@ -118279,20 +118491,53 @@ function usePresenterWindow(input) {
|
|
|
118279
118491
|
if (isAudienceWindowOpen()) {
|
|
118280
118492
|
closeAudienceWindow();
|
|
118281
118493
|
}
|
|
118282
|
-
|
|
118283
|
-
|
|
118284
|
-
}
|
|
118285
|
-
const url = new URL(window.location.href);
|
|
118286
|
-
url.hash = AUDIENCE_HASH;
|
|
118287
|
-
const win = window.open(url.toString(), "_blank");
|
|
118288
|
-
if (!win) {
|
|
118494
|
+
const blankWin = window.open("about:blank", "_blank");
|
|
118495
|
+
if (!blankWin) {
|
|
118289
118496
|
return false;
|
|
118290
118497
|
}
|
|
118291
|
-
audienceWindowRef.current =
|
|
118498
|
+
audienceWindowRef.current = blankWin;
|
|
118499
|
+
const sessionId = generateSessionId();
|
|
118500
|
+
sessionIdRef.current = sessionId;
|
|
118501
|
+
const audienceUrl = new URL(window.location.href);
|
|
118502
|
+
const params2 = new URLSearchParams();
|
|
118503
|
+
params2.set(AUDIENCE_NONCE_KEY, sessionId);
|
|
118504
|
+
audienceUrl.hash = `${AUDIENCE_HASH}&${params2.toString()}`;
|
|
118505
|
+
const navigateOrClose = (ok) => {
|
|
118506
|
+
const win = audienceWindowRef.current;
|
|
118507
|
+
if (!win || win.closed) {
|
|
118508
|
+
return;
|
|
118509
|
+
}
|
|
118510
|
+
if (!ok) {
|
|
118511
|
+
try {
|
|
118512
|
+
win.close();
|
|
118513
|
+
} catch {
|
|
118514
|
+
}
|
|
118515
|
+
audienceWindowRef.current = null;
|
|
118516
|
+
sessionIdRef.current = "";
|
|
118517
|
+
return;
|
|
118518
|
+
}
|
|
118519
|
+
try {
|
|
118520
|
+
win.location.replace(audienceUrl.toString());
|
|
118521
|
+
} catch {
|
|
118522
|
+
try {
|
|
118523
|
+
win.close();
|
|
118524
|
+
} catch {
|
|
118525
|
+
}
|
|
118526
|
+
audienceWindowRef.current = null;
|
|
118527
|
+
sessionIdRef.current = "";
|
|
118528
|
+
}
|
|
118529
|
+
};
|
|
118530
|
+
if (content) {
|
|
118531
|
+
void storeAudienceContent(content).then(() => navigateOrClose(true)).catch(() => navigateOrClose(false));
|
|
118532
|
+
} else {
|
|
118533
|
+
navigateOrClose(true);
|
|
118534
|
+
}
|
|
118292
118535
|
window.setTimeout(() => syncSlideToAudience(currentSlideIndex), 1500);
|
|
118293
118536
|
pollTimerRef.current = setInterval(() => {
|
|
118294
|
-
|
|
118537
|
+
const win = audienceWindowRef.current;
|
|
118538
|
+
if (!win || win.closed) {
|
|
118295
118539
|
audienceWindowRef.current = null;
|
|
118540
|
+
sessionIdRef.current = "";
|
|
118296
118541
|
if (pollTimerRef.current !== null) {
|
|
118297
118542
|
clearInterval(pollTimerRef.current);
|
|
118298
118543
|
pollTimerRef.current = null;
|
|
@@ -118320,6 +118565,13 @@ function usePresenterWindow(input) {
|
|
|
118320
118565
|
closeAudienceWindow();
|
|
118321
118566
|
}
|
|
118322
118567
|
}, [isPresenterMode, closeAudienceWindow]);
|
|
118568
|
+
useEffect(() => {
|
|
118569
|
+
const handleBeforeUnload = () => {
|
|
118570
|
+
void clearAudienceContent();
|
|
118571
|
+
};
|
|
118572
|
+
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
118573
|
+
return () => window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
118574
|
+
}, []);
|
|
118323
118575
|
return {
|
|
118324
118576
|
openAudienceWindow,
|
|
118325
118577
|
closeAudienceWindow,
|
|
@@ -118357,6 +118609,7 @@ function useAudienceMode(input) {
|
|
|
118357
118609
|
if (!isAudienceTab()) {
|
|
118358
118610
|
return;
|
|
118359
118611
|
}
|
|
118612
|
+
const expectedSessionId = parseAudienceNonce();
|
|
118360
118613
|
let channel;
|
|
118361
118614
|
try {
|
|
118362
118615
|
channel = new BroadcastChannel(PRESENTER_CHANNEL_NAME);
|
|
@@ -118368,6 +118621,9 @@ function useAudienceMode(input) {
|
|
|
118368
118621
|
if (!data || data.origin !== PRESENTER_MSG_ORIGIN) {
|
|
118369
118622
|
return;
|
|
118370
118623
|
}
|
|
118624
|
+
if (expectedSessionId && data.sessionId !== expectedSessionId) {
|
|
118625
|
+
return;
|
|
118626
|
+
}
|
|
118371
118627
|
if (data.type === "presenter-slide-change") {
|
|
118372
118628
|
onSetActiveSlideIndex(data.slideIndex);
|
|
118373
118629
|
}
|
|
@@ -119301,6 +119557,12 @@ function useTouchGestures(input) {
|
|
|
119301
119557
|
callbacksRef.current = callbacks;
|
|
119302
119558
|
const scaleRef = useRef(currentScale);
|
|
119303
119559
|
scaleRef.current = currentScale;
|
|
119560
|
+
const [targetVersion, setTargetVersion] = useState(0);
|
|
119561
|
+
const lastTargetRef = useRef(null);
|
|
119562
|
+
if (targetRef.current !== lastTargetRef.current) {
|
|
119563
|
+
lastTargetRef.current = targetRef.current;
|
|
119564
|
+
queueMicrotask(() => setTargetVersion((v) => v + 1));
|
|
119565
|
+
}
|
|
119304
119566
|
useEffect(() => {
|
|
119305
119567
|
const el = targetRef.current;
|
|
119306
119568
|
if (!el || !enabled) {
|
|
@@ -119389,7 +119651,7 @@ function useTouchGestures(input) {
|
|
|
119389
119651
|
el.removeEventListener("touchcancel", handleTouchCancel);
|
|
119390
119652
|
cancelLongPress();
|
|
119391
119653
|
};
|
|
119392
|
-
}, [targetRef, enabled]);
|
|
119654
|
+
}, [targetRef, enabled, targetVersion]);
|
|
119393
119655
|
}
|
|
119394
119656
|
|
|
119395
119657
|
// src/viewer/utils/dom-helpers.ts
|
|
@@ -119410,11 +119672,31 @@ function safeConfirm(message) {
|
|
|
119410
119672
|
return false;
|
|
119411
119673
|
}
|
|
119412
119674
|
}
|
|
119675
|
+
function sanitizeDownloadFilename(input) {
|
|
119676
|
+
if (typeof input !== "string" || input.trim().length === 0) {
|
|
119677
|
+
return "presentation.pptx";
|
|
119678
|
+
}
|
|
119679
|
+
let cleaned = input.replace(/[\x00-\x1f\x7f"\\/:*?<>|]/g, "_").replace(/\.\./g, "__").replace(/^\.+/, "").trim();
|
|
119680
|
+
if (cleaned.length === 0) {
|
|
119681
|
+
return "presentation.pptx";
|
|
119682
|
+
}
|
|
119683
|
+
if (cleaned.length > 200) {
|
|
119684
|
+
const dot = cleaned.lastIndexOf(".");
|
|
119685
|
+
if (dot > 0 && cleaned.length - dot <= 16) {
|
|
119686
|
+
const ext = cleaned.slice(dot);
|
|
119687
|
+
cleaned = cleaned.slice(0, 200 - ext.length) + ext;
|
|
119688
|
+
} else {
|
|
119689
|
+
cleaned = cleaned.slice(0, 200);
|
|
119690
|
+
}
|
|
119691
|
+
}
|
|
119692
|
+
return cleaned;
|
|
119693
|
+
}
|
|
119413
119694
|
function downloadBlob(blob, filename) {
|
|
119695
|
+
const safeName = sanitizeDownloadFilename(filename);
|
|
119414
119696
|
const url = URL.createObjectURL(blob);
|
|
119415
119697
|
const a2 = document.createElement("a");
|
|
119416
119698
|
a2.href = url;
|
|
119417
|
-
a2.download =
|
|
119699
|
+
a2.download = safeName;
|
|
119418
119700
|
document.body.appendChild(a2);
|
|
119419
119701
|
a2.click();
|
|
119420
119702
|
setTimeout(() => {
|
|
@@ -119845,27 +120127,82 @@ function openAutosaveDb2() {
|
|
|
119845
120127
|
req.onerror = () => reject(req.error);
|
|
119846
120128
|
});
|
|
119847
120129
|
}
|
|
119848
|
-
async function
|
|
120130
|
+
async function deleteOldestAutosaveEntry() {
|
|
119849
120131
|
const db = await openAutosaveDb2();
|
|
119850
|
-
return new Promise((resolve2
|
|
119851
|
-
|
|
119852
|
-
|
|
119853
|
-
|
|
119854
|
-
|
|
119855
|
-
|
|
119856
|
-
|
|
119857
|
-
|
|
119858
|
-
|
|
119859
|
-
|
|
119860
|
-
|
|
119861
|
-
|
|
119862
|
-
|
|
119863
|
-
|
|
119864
|
-
|
|
119865
|
-
|
|
119866
|
-
|
|
120132
|
+
return new Promise((resolve2) => {
|
|
120133
|
+
try {
|
|
120134
|
+
const tx = db.transaction(STORE_NAME3, "readwrite");
|
|
120135
|
+
const store = tx.objectStore(STORE_NAME3);
|
|
120136
|
+
let oldestKey = null;
|
|
120137
|
+
let oldestTimestamp = Infinity;
|
|
120138
|
+
const cursorReq = store.openCursor();
|
|
120139
|
+
cursorReq.onsuccess = () => {
|
|
120140
|
+
const cursor = cursorReq.result;
|
|
120141
|
+
if (cursor) {
|
|
120142
|
+
const value = cursor.value;
|
|
120143
|
+
if (typeof value.timestamp === "number" && value.timestamp < oldestTimestamp) {
|
|
120144
|
+
oldestTimestamp = value.timestamp;
|
|
120145
|
+
oldestKey = cursor.primaryKey;
|
|
120146
|
+
}
|
|
120147
|
+
cursor.continue();
|
|
120148
|
+
} else if (oldestKey !== null) {
|
|
120149
|
+
store.delete(oldestKey);
|
|
120150
|
+
}
|
|
120151
|
+
};
|
|
120152
|
+
tx.oncomplete = () => {
|
|
120153
|
+
db.close();
|
|
120154
|
+
resolve2(oldestKey !== null);
|
|
120155
|
+
};
|
|
120156
|
+
tx.onerror = () => {
|
|
120157
|
+
db.close();
|
|
120158
|
+
resolve2(false);
|
|
120159
|
+
};
|
|
120160
|
+
} catch {
|
|
120161
|
+
try {
|
|
120162
|
+
db.close();
|
|
120163
|
+
} catch {
|
|
120164
|
+
}
|
|
120165
|
+
resolve2(false);
|
|
120166
|
+
}
|
|
119867
120167
|
});
|
|
119868
120168
|
}
|
|
120169
|
+
function putAutosaveRecord(filePath, data) {
|
|
120170
|
+
return openAutosaveDb2().then(
|
|
120171
|
+
(db) => new Promise((resolve2, reject) => {
|
|
120172
|
+
const tx = db.transaction(STORE_NAME3, "readwrite");
|
|
120173
|
+
const store = tx.objectStore(STORE_NAME3);
|
|
120174
|
+
store.put({
|
|
120175
|
+
key: filePath,
|
|
120176
|
+
data,
|
|
120177
|
+
timestamp: Date.now(),
|
|
120178
|
+
size: data.byteLength
|
|
120179
|
+
});
|
|
120180
|
+
tx.oncomplete = () => {
|
|
120181
|
+
db.close();
|
|
120182
|
+
resolve2(true);
|
|
120183
|
+
};
|
|
120184
|
+
tx.onerror = () => {
|
|
120185
|
+
db.close();
|
|
120186
|
+
reject(tx.error);
|
|
120187
|
+
};
|
|
120188
|
+
})
|
|
120189
|
+
);
|
|
120190
|
+
}
|
|
120191
|
+
async function saveToIndexedDb(filePath, data) {
|
|
120192
|
+
try {
|
|
120193
|
+
return await putAutosaveRecord(filePath, data);
|
|
120194
|
+
} catch (err) {
|
|
120195
|
+
const errName = err instanceof Error || err instanceof DOMException ? err.name : "";
|
|
120196
|
+
if (errName !== "QuotaExceededError") {
|
|
120197
|
+
throw err;
|
|
120198
|
+
}
|
|
120199
|
+
const deleted = await deleteOldestAutosaveEntry();
|
|
120200
|
+
if (!deleted) {
|
|
120201
|
+
throw err;
|
|
120202
|
+
}
|
|
120203
|
+
return putAutosaveRecord(filePath, data);
|
|
120204
|
+
}
|
|
120205
|
+
}
|
|
119869
120206
|
function useAutosave(input) {
|
|
119870
120207
|
const {
|
|
119871
120208
|
isDirty,
|
|
@@ -119982,6 +120319,25 @@ function collectReferencedFontFamilies(slides) {
|
|
|
119982
120319
|
}
|
|
119983
120320
|
return families;
|
|
119984
120321
|
}
|
|
120322
|
+
var FONT_NAME_UNSAFE_CHARS = /["\\\n\r;}<>]/;
|
|
120323
|
+
var FONT_FORMAT_ALLOWED = /* @__PURE__ */ new Set([
|
|
120324
|
+
"truetype",
|
|
120325
|
+
"opentype",
|
|
120326
|
+
"woff",
|
|
120327
|
+
"woff2",
|
|
120328
|
+
"svg",
|
|
120329
|
+
"embedded-opentype"
|
|
120330
|
+
]);
|
|
120331
|
+
var FONT_DATA_URL_PATTERN = /^data:font\/[a-z0-9+.-]+(?:;charset=[a-z0-9-]+)?;base64,[A-Za-z0-9+/=]+$/i;
|
|
120332
|
+
function isFontDataUrlSafe(url) {
|
|
120333
|
+
if (typeof url !== "string" || url.length === 0) {
|
|
120334
|
+
return false;
|
|
120335
|
+
}
|
|
120336
|
+
if (url.startsWith("blob:")) {
|
|
120337
|
+
return true;
|
|
120338
|
+
}
|
|
120339
|
+
return FONT_DATA_URL_PATTERN.test(url);
|
|
120340
|
+
}
|
|
119985
120341
|
function useFontInjection({ embeddedFonts, slides }) {
|
|
119986
120342
|
useEffect(() => {
|
|
119987
120343
|
if (!embeddedFonts.length) {
|
|
@@ -119989,17 +120345,28 @@ function useFontInjection({ embeddedFonts, slides }) {
|
|
|
119989
120345
|
}
|
|
119990
120346
|
const styleEl = document.createElement("style");
|
|
119991
120347
|
styleEl.id = EMBEDDED_FONTS_STYLE_ID;
|
|
119992
|
-
const cssRules = embeddedFonts.
|
|
120348
|
+
const cssRules = embeddedFonts.flatMap((font) => {
|
|
120349
|
+
if (typeof font.name !== "string" || font.name.length === 0 || FONT_NAME_UNSAFE_CHARS.test(font.name)) {
|
|
120350
|
+
return [];
|
|
120351
|
+
}
|
|
120352
|
+
if (!isFontDataUrlSafe(font.dataUrl)) {
|
|
120353
|
+
return [];
|
|
120354
|
+
}
|
|
120355
|
+
const fontFormat = font.format ?? "truetype";
|
|
120356
|
+
if (!FONT_FORMAT_ALLOWED.has(fontFormat)) {
|
|
120357
|
+
return [];
|
|
120358
|
+
}
|
|
119993
120359
|
const fontWeight = font.bold ? "700" : "400";
|
|
119994
120360
|
const fontStyleCss = font.italic ? "italic" : "normal";
|
|
119995
|
-
|
|
119996
|
-
|
|
120361
|
+
return [
|
|
120362
|
+
`@font-face {
|
|
119997
120363
|
font-family: "${font.name}";
|
|
119998
120364
|
src: url("${font.dataUrl}") format("${fontFormat}");
|
|
119999
120365
|
font-weight: ${fontWeight};
|
|
120000
120366
|
font-style: ${fontStyleCss};
|
|
120001
120367
|
font-display: swap;
|
|
120002
|
-
}
|
|
120368
|
+
}`
|
|
120369
|
+
];
|
|
120003
120370
|
}).join("\n");
|
|
120004
120371
|
styleEl.textContent = cssRules;
|
|
120005
120372
|
document.head.appendChild(styleEl);
|
|
@@ -120028,7 +120395,7 @@ function useFontInjection({ embeddedFonts, slides }) {
|
|
|
120028
120395
|
const linkEl = document.createElement("link");
|
|
120029
120396
|
linkEl.id = GOOGLE_FONTS_LINK_ID;
|
|
120030
120397
|
linkEl.rel = "stylesheet";
|
|
120031
|
-
linkEl.href = `https://fonts.googleapis.com/css2?${googleFamilies.map((f) => `family=${GOOGLE_FONTS_AVAILABLE[f]}`).join("&")}&display=swap`;
|
|
120398
|
+
linkEl.href = `https://fonts.googleapis.com/css2?${googleFamilies.map((f) => `family=${encodeURIComponent(GOOGLE_FONTS_AVAILABLE[f])}`).join("&")}&display=swap`;
|
|
120032
120399
|
document.head.appendChild(linkEl);
|
|
120033
120400
|
return () => {
|
|
120034
120401
|
const existing = document.getElementById(GOOGLE_FONTS_LINK_ID);
|
|
@@ -120044,13 +120411,18 @@ function useFontInjection({ embeddedFonts, slides }) {
|
|
|
120044
120411
|
}
|
|
120045
120412
|
const styleEl = document.createElement("style");
|
|
120046
120413
|
styleEl.id = SYMBOL_FONTS_STYLE_ID;
|
|
120047
|
-
const rules = neededSymbolFonts.
|
|
120048
|
-
(font
|
|
120414
|
+
const rules = neededSymbolFonts.flatMap((font) => {
|
|
120415
|
+
if (typeof font !== "string" || FONT_NAME_UNSAFE_CHARS.test(font)) {
|
|
120416
|
+
return [];
|
|
120417
|
+
}
|
|
120418
|
+
return [
|
|
120419
|
+
`@font-face {
|
|
120049
120420
|
font-family: "${font}";
|
|
120050
120421
|
src: local("${font}"), local("${font} Regular");
|
|
120051
120422
|
font-display: swap;
|
|
120052
120423
|
}`
|
|
120053
|
-
|
|
120424
|
+
];
|
|
120425
|
+
}).join("\n");
|
|
120054
120426
|
styleEl.textContent = rules;
|
|
120055
120427
|
document.head.appendChild(styleEl);
|
|
120056
120428
|
return () => {
|
|
@@ -120193,16 +120565,17 @@ function useLoadContent({
|
|
|
120193
120565
|
`[pptx] Large file detected (${fileSizeMB.toFixed(1)} MB). Loading may use significant memory.`
|
|
120194
120566
|
);
|
|
120195
120567
|
}
|
|
120196
|
-
|
|
120197
|
-
handlerRef.current.dispose();
|
|
120198
|
-
handlerRef.current = null;
|
|
120199
|
-
}
|
|
120568
|
+
const previousHandler = handlerRef.current;
|
|
120200
120569
|
const handler = new PptxHandler();
|
|
120201
120570
|
const parsed = await handler.load(buffer);
|
|
120202
120571
|
if (cancelled || token !== renderTokenRef.current) {
|
|
120203
120572
|
handler.dispose();
|
|
120204
120573
|
return;
|
|
120205
120574
|
}
|
|
120575
|
+
if (previousHandler) {
|
|
120576
|
+
previousHandler.dispose();
|
|
120577
|
+
}
|
|
120578
|
+
handlerRef.current = null;
|
|
120206
120579
|
const mediaElements = [];
|
|
120207
120580
|
for (const slide of parsed.slides) {
|
|
120208
120581
|
collectMediaElements(slide.elements, mediaElements);
|
|
@@ -120247,6 +120620,7 @@ function useLoadContent({
|
|
|
120247
120620
|
})
|
|
120248
120621
|
);
|
|
120249
120622
|
const { paths: imagePaths, refs: imageRefs } = collectImagePaths(parsed.slides);
|
|
120623
|
+
let nextSlides = parsed.slides;
|
|
120250
120624
|
if (imagePaths.size > 0) {
|
|
120251
120625
|
const resolvedMap = /* @__PURE__ */ new Map();
|
|
120252
120626
|
await Promise.all(
|
|
@@ -120260,15 +120634,47 @@ function useLoadContent({
|
|
|
120260
120634
|
}
|
|
120261
120635
|
})
|
|
120262
120636
|
);
|
|
120637
|
+
const elementPatches = /* @__PURE__ */ new Map();
|
|
120263
120638
|
for (const ref of imageRefs) {
|
|
120264
120639
|
const url = resolvedMap.get(ref.path);
|
|
120265
|
-
if (url) {
|
|
120266
|
-
|
|
120640
|
+
if (!url) {
|
|
120641
|
+
continue;
|
|
120267
120642
|
}
|
|
120643
|
+
const id2 = ref.element.id;
|
|
120644
|
+
const existing = elementPatches.get(id2) ?? {};
|
|
120645
|
+
existing[ref.field] = url;
|
|
120646
|
+
elementPatches.set(id2, existing);
|
|
120647
|
+
}
|
|
120648
|
+
if (elementPatches.size > 0) {
|
|
120649
|
+
const patchElements = (elements) => {
|
|
120650
|
+
let mutated = false;
|
|
120651
|
+
const next = elements.map((el) => {
|
|
120652
|
+
let updated = el;
|
|
120653
|
+
const patch = elementPatches.get(el.id);
|
|
120654
|
+
if (patch) {
|
|
120655
|
+
updated = { ...el, ...patch };
|
|
120656
|
+
}
|
|
120657
|
+
if (updated.type === "group" && updated.children?.length) {
|
|
120658
|
+
const newChildren = patchElements(updated.children);
|
|
120659
|
+
if (newChildren !== updated.children) {
|
|
120660
|
+
updated = { ...updated, children: newChildren };
|
|
120661
|
+
}
|
|
120662
|
+
}
|
|
120663
|
+
if (updated !== el) {
|
|
120664
|
+
mutated = true;
|
|
120665
|
+
}
|
|
120666
|
+
return updated;
|
|
120667
|
+
});
|
|
120668
|
+
return mutated ? next : elements;
|
|
120669
|
+
};
|
|
120670
|
+
nextSlides = parsed.slides.map((s) => {
|
|
120671
|
+
const newElements = patchElements(s.elements);
|
|
120672
|
+
return newElements === s.elements ? s : { ...s, elements: newElements };
|
|
120673
|
+
});
|
|
120268
120674
|
}
|
|
120269
120675
|
}
|
|
120270
120676
|
handlerRef.current = handler;
|
|
120271
|
-
setSlides(
|
|
120677
|
+
setSlides(nextSlides);
|
|
120272
120678
|
setTemplateElementsBySlideId({});
|
|
120273
120679
|
setCanvasSize({
|
|
120274
120680
|
width: parsed.width ?? DEFAULT_CANVAS_WIDTH,
|
|
@@ -121442,7 +121848,19 @@ function injectFontFaces(svg, fontFaces) {
|
|
|
121442
121848
|
if (!fontFaces.length) {
|
|
121443
121849
|
return svg;
|
|
121444
121850
|
}
|
|
121445
|
-
const
|
|
121851
|
+
const safeFontFaces = fontFaces.filter((f) => {
|
|
121852
|
+
if (f.css.toLowerCase().includes("</style")) {
|
|
121853
|
+
console.warn(
|
|
121854
|
+
`[export-svg] Dropping @font-face entry for "${f.family}" containing "</style" \u2014 would break out of the <style> block.`
|
|
121855
|
+
);
|
|
121856
|
+
return false;
|
|
121857
|
+
}
|
|
121858
|
+
return true;
|
|
121859
|
+
});
|
|
121860
|
+
if (!safeFontFaces.length) {
|
|
121861
|
+
return svg;
|
|
121862
|
+
}
|
|
121863
|
+
const styleBlock = `<style type="text/css">${safeFontFaces.map((f) => f.css).join("\n")}</style>`;
|
|
121446
121864
|
if (svg.includes("<defs>")) {
|
|
121447
121865
|
return svg.replace("<defs>", `<defs>${styleBlock}`);
|
|
121448
121866
|
}
|
|
@@ -121768,7 +122186,7 @@ function useExportHandlers(input) {
|
|
|
121768
122186
|
activeSlideIndexForGuides,
|
|
121769
122187
|
modalControls
|
|
121770
122188
|
});
|
|
121771
|
-
const handleExportPng = async () => {
|
|
122189
|
+
const handleExportPng = useCallback(async () => {
|
|
121772
122190
|
const stageEl = canvasStageRef.current;
|
|
121773
122191
|
if (!stageEl) {
|
|
121774
122192
|
return;
|
|
@@ -121780,8 +122198,8 @@ function useExportHandlers(input) {
|
|
|
121780
122198
|
} catch (err) {
|
|
121781
122199
|
console.error("[PowerPointViewer] PNG export failed:", err);
|
|
121782
122200
|
}
|
|
121783
|
-
};
|
|
121784
|
-
const handleExportPdf = async () => {
|
|
122201
|
+
}, [canvasStageRef, activeSlideIndex, activeSlide?.backgroundColor]);
|
|
122202
|
+
const handleExportPdf = useCallback(async () => {
|
|
121785
122203
|
if (!canvasStageRef.current) {
|
|
121786
122204
|
return;
|
|
121787
122205
|
}
|
|
@@ -121822,8 +122240,8 @@ function useExportHandlers(input) {
|
|
|
121822
122240
|
exportAbortRef.current = null;
|
|
121823
122241
|
setExportModalOpen(false);
|
|
121824
122242
|
}
|
|
121825
|
-
};
|
|
121826
|
-
const handleExportNotesPdf = async () => {
|
|
122243
|
+
}, [canvasStageRef, slides.length, setActiveSlideIndex, activeSlideIndex]);
|
|
122244
|
+
const handleExportNotesPdf = useCallback(async () => {
|
|
121827
122245
|
if (!canvasStageRef.current) {
|
|
121828
122246
|
return;
|
|
121829
122247
|
}
|
|
@@ -121866,8 +122284,8 @@ function useExportHandlers(input) {
|
|
|
121866
122284
|
exportAbortRef.current = null;
|
|
121867
122285
|
setExportModalOpen(false);
|
|
121868
122286
|
}
|
|
121869
|
-
};
|
|
121870
|
-
const handleCopySlideAsImage = async () => {
|
|
122287
|
+
}, [canvasStageRef, slides, setActiveSlideIndex, activeSlideIndex]);
|
|
122288
|
+
const handleCopySlideAsImage = useCallback(async () => {
|
|
121871
122289
|
const stageEl = canvasStageRef.current;
|
|
121872
122290
|
if (!stageEl) {
|
|
121873
122291
|
return;
|
|
@@ -121879,8 +122297,8 @@ function useExportHandlers(input) {
|
|
|
121879
122297
|
} catch (err) {
|
|
121880
122298
|
console.error("[PowerPointViewer] Copy slide as image failed:", err);
|
|
121881
122299
|
}
|
|
121882
|
-
};
|
|
121883
|
-
const handleExportVideo = async () => {
|
|
122300
|
+
}, [canvasStageRef, activeSlide?.backgroundColor]);
|
|
122301
|
+
const handleExportVideo = useCallback(async () => {
|
|
121884
122302
|
if (!canvasStageRef.current) {
|
|
121885
122303
|
return;
|
|
121886
122304
|
}
|
|
@@ -121922,8 +122340,8 @@ function useExportHandlers(input) {
|
|
|
121922
122340
|
exportAbortRef.current = null;
|
|
121923
122341
|
setExportModalOpen(false);
|
|
121924
122342
|
}
|
|
121925
|
-
};
|
|
121926
|
-
const handleExportGif = async () => {
|
|
122343
|
+
}, [canvasStageRef, slides.length, setActiveSlideIndex, activeSlideIndex]);
|
|
122344
|
+
const handleExportGif = useCallback(async () => {
|
|
121927
122345
|
if (!canvasStageRef.current) {
|
|
121928
122346
|
return;
|
|
121929
122347
|
}
|
|
@@ -121961,7 +122379,7 @@ function useExportHandlers(input) {
|
|
|
121961
122379
|
exportAbortRef.current = null;
|
|
121962
122380
|
setExportModalOpen(false);
|
|
121963
122381
|
}
|
|
121964
|
-
};
|
|
122382
|
+
}, [canvasStageRef, slides.length, setActiveSlideIndex, activeSlideIndex]);
|
|
121965
122383
|
const handleCancelExport = useCallback(() => {
|
|
121966
122384
|
exportAbortRef.current?.abort();
|
|
121967
122385
|
exportAbortRef.current = null;
|
|
@@ -121987,6 +122405,15 @@ function useExportHandlers(input) {
|
|
|
121987
122405
|
exportStatusMessage
|
|
121988
122406
|
};
|
|
121989
122407
|
}
|
|
122408
|
+
function escapeHtmlAttr(value) {
|
|
122409
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
122410
|
+
}
|
|
122411
|
+
function safeDataImageSrc(src) {
|
|
122412
|
+
if (typeof src !== "string" || !src.startsWith("data:image/")) {
|
|
122413
|
+
return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNgAAIAAAUAAen63NgAAAAASUVORK5CYII=";
|
|
122414
|
+
}
|
|
122415
|
+
return escapeHtmlAttr(src);
|
|
122416
|
+
}
|
|
121990
122417
|
function openPrintWindow(title, bodyHtml, orientation, colorFilter, frameSlides) {
|
|
121991
122418
|
const printWindow = window.open("", "_blank", "noopener,noreferrer");
|
|
121992
122419
|
if (!printWindow) {
|
|
@@ -122169,7 +122596,7 @@ function usePrintHandlers(input) {
|
|
|
122169
122596
|
const slideImages = slideIndices.map((idx) => allImages[idx]).filter(Boolean);
|
|
122170
122597
|
if (settings.printWhat === "slides") {
|
|
122171
122598
|
const bodyHtml = slideImages.map(
|
|
122172
|
-
(img, i3) => `<section class="page slide-page"><img class="slide-img" src="${img}" alt="Slide ${slideIndices[i3] + 1}" /></section>`
|
|
122599
|
+
(img, i3) => `<section class="page slide-page"><img class="slide-img" src="${safeDataImageSrc(img)}" alt="Slide ${slideIndices[i3] + 1}" /></section>`
|
|
122173
122600
|
).join("");
|
|
122174
122601
|
openPrintWindow(
|
|
122175
122602
|
"Slides",
|
|
@@ -122185,7 +122612,7 @@ function usePrintHandlers(input) {
|
|
|
122185
122612
|
const idx = slideIndices[i3];
|
|
122186
122613
|
const notes = slides[idx]?.notes?.trim() || "";
|
|
122187
122614
|
return `<section class="page notes-page">
|
|
122188
|
-
<img class="notes-slide" src="${img}" alt="Slide ${idx + 1}" />
|
|
122615
|
+
<img class="notes-slide" src="${safeDataImageSrc(img)}" alt="Slide ${idx + 1}" />
|
|
122189
122616
|
<div class="notes-text">${escapeHtml2(notes)}</div>
|
|
122190
122617
|
</section>`;
|
|
122191
122618
|
}).join("");
|
|
@@ -122217,14 +122644,14 @@ function usePrintHandlers(input) {
|
|
|
122217
122644
|
if (isThreePerPage) {
|
|
122218
122645
|
const rows = Array.from({ length: spp }, (_, cellIndex) => {
|
|
122219
122646
|
const img = pageImgs[cellIndex];
|
|
122220
|
-
const slideCell = img ? `<div class="handout-cell"><img src="${img}" alt="Slide ${slideIndices[i3 + cellIndex] + 1}" /></div>` : `<div class="handout-cell"></div>`;
|
|
122647
|
+
const slideCell = img ? `<div class="handout-cell"><img src="${safeDataImageSrc(img)}" alt="Slide ${slideIndices[i3 + cellIndex] + 1}" /></div>` : `<div class="handout-cell"></div>`;
|
|
122221
122648
|
return `<div class="handout-row-3">${slideCell}${buildNoteLines()}</div>`;
|
|
122222
122649
|
}).join("");
|
|
122223
122650
|
pages.push(`<section class="page"><div class="handout-grid-3">${rows}</div></section>`);
|
|
122224
122651
|
} else {
|
|
122225
122652
|
const cells = Array.from({ length: spp }, (_, cellIndex) => {
|
|
122226
122653
|
const img = pageImgs[cellIndex];
|
|
122227
|
-
return img ? `<div class="handout-cell"><img src="${img}" alt="Slide ${slideIndices[i3 + cellIndex] + 1}" /></div>` : `<div class="handout-cell"></div>`;
|
|
122654
|
+
return img ? `<div class="handout-cell"><img src="${safeDataImageSrc(img)}" alt="Slide ${slideIndices[i3 + cellIndex] + 1}" /></div>` : `<div class="handout-cell"></div>`;
|
|
122228
122655
|
}).join("");
|
|
122229
122656
|
pages.push(
|
|
122230
122657
|
`<section class="page"><div class="handout-grid" style="grid-template-columns: repeat(${grid.columns}, minmax(0, 1fr)); grid-template-rows: repeat(${grid.rows}, minmax(0, 1fr));">${cells}</div></section>`
|