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.
Files changed (28) hide show
  1. package/dist/index.js +512 -96
  2. package/dist/index.mjs +512 -97
  3. package/dist/viewer/index.js +530 -102
  4. package/dist/viewer/index.mjs +530 -103
  5. package/node_modules/emf-converter/dist/index.d.mts +2 -2
  6. package/node_modules/emf-converter/dist/index.d.ts +2 -2
  7. package/node_modules/emf-converter/dist/index.js +91 -33
  8. package/node_modules/emf-converter/dist/index.mjs +91 -33
  9. package/node_modules/emf-converter/package.json +1 -1
  10. package/node_modules/mtx-decompressor/dist/index.js +39 -9
  11. package/node_modules/mtx-decompressor/dist/index.mjs +39 -9
  12. package/node_modules/mtx-decompressor/package.json +1 -1
  13. package/node_modules/pptx-viewer-core/dist/cli/index.js +0 -0
  14. package/node_modules/pptx-viewer-core/dist/cli/index.mjs +0 -0
  15. package/node_modules/pptx-viewer-core/dist/converter/index.js +0 -0
  16. package/node_modules/pptx-viewer-core/dist/converter/index.mjs +0 -0
  17. package/node_modules/pptx-viewer-core/dist/index.d.mts +95 -11
  18. package/node_modules/pptx-viewer-core/dist/index.d.ts +95 -11
  19. package/node_modules/pptx-viewer-core/dist/index.js +795 -257
  20. package/node_modules/pptx-viewer-core/dist/index.mjs +791 -258
  21. package/node_modules/pptx-viewer-core/dist/{signature-inspection-status-BcJSdOvb.d.mts → signature-inspection-status-BCUpfCQh.d.mts} +13 -2
  22. package/node_modules/pptx-viewer-core/dist/{signature-inspection-status-BcJSdOvb.d.ts → signature-inspection-status-BCUpfCQh.d.ts} +13 -2
  23. package/node_modules/pptx-viewer-core/dist/signature-node/index.d.mts +2 -2
  24. package/node_modules/pptx-viewer-core/dist/signature-node/index.d.ts +2 -2
  25. package/node_modules/pptx-viewer-core/dist/signature-node/index.js +17 -3
  26. package/node_modules/pptx-viewer-core/dist/signature-node/index.mjs +16 -4
  27. package/node_modules/pptx-viewer-core/package.json +1 -1
  28. package/package.json +6 -4
@@ -10321,7 +10321,7 @@ var PptxAnimationWriteService = class {
10321
10321
  return existingRawTiming;
10322
10322
  }
10323
10323
  if (existingRawTiming) {
10324
- const cloned = JSON.parse(JSON.stringify(existingRawTiming));
10324
+ const cloned = typeof structuredClone === "function" ? structuredClone(existingRawTiming) : JSON.parse(JSON.stringify(existingRawTiming));
10325
10325
  return surgicallyUpdateTimingTree(cloned, validAnimations);
10326
10326
  }
10327
10327
  this.nextId = 1;
@@ -10461,7 +10461,14 @@ var PptxRuntimeDependencyFactory = class {
10461
10461
  // 0x80070570 (ERROR_FILE_CORRUPT) and shows the repair dialog.
10462
10462
  // More generally, OOXML element text is always an untyped string;
10463
10463
  // downstream callers coerce where needed.
10464
- parseTagValue: false
10464
+ parseTagValue: false,
10465
+ // Security hardening (Load M3): explicitly disable XML entity
10466
+ // processing. PPTX XML never uses DOCTYPE / DTDs, so allowing
10467
+ // entity expansion serves only as an attack surface
10468
+ // (billion-laughs / external-entity / future fast-xml-parser
10469
+ // regressions). v5.5.5 currently defaults to safe behaviour but
10470
+ // pinning this makes the guarantee explicit and forward-stable.
10471
+ processEntities: false
10465
10472
  });
10466
10473
  }
10467
10474
  createBuilder() {
@@ -11011,6 +11018,23 @@ function arrayBufferToBase64(buffer) {
11011
11018
  return btoa(binary);
11012
11019
  }
11013
11020
 
11021
+ // src/core/core/types.ts
11022
+ var DEFAULT_MAX_UNCOMPRESSED_BYTES = 500 * 1024 * 1024;
11023
+ var MAX_ZIP_ENTRY_COUNT = 65536;
11024
+ var ZipBombError = class extends Error {
11025
+ code = "ZIP_BOMB";
11026
+ uncompressedBytes;
11027
+ limit;
11028
+ entryCount;
11029
+ constructor(message, details) {
11030
+ super(message);
11031
+ this.name = "ZipBombError";
11032
+ this.uncompressedBytes = details.uncompressedBytes;
11033
+ this.limit = details.limit;
11034
+ this.entryCount = details.entryCount;
11035
+ }
11036
+ };
11037
+
11014
11038
  // ../mtx-decompressor/dist/index.mjs
11015
11039
  var Stream = class _Stream {
11016
11040
  buf;
@@ -11600,14 +11624,8 @@ function decodeSimpleGlyph(numContours, streams, out, calcBBox, minX, minY, maxX
11600
11624
  const flag = flagBytes[i];
11601
11625
  onCurve[i] = flag & 128 ? 0 : 1;
11602
11626
  const enc = TRIPLET_ENCODINGS[flag & 127];
11603
- const extraBytes = enc.byteCount - 1;
11604
- const subBuf = new Uint8Array(extraBytes);
11605
- for (let b = 0; b < extraBytes; b++) {
11606
- subBuf[b] = sGlyph.readU8();
11607
- }
11608
- const sub = new Stream(subBuf, extraBytes);
11609
- let dx = sub.readNBits(enc.xBits) + enc.deltaX;
11610
- let dy = sub.readNBits(enc.yBits) + enc.deltaY;
11627
+ let dx = sGlyph.readNBits(enc.xBits) + enc.deltaX;
11628
+ let dy = sGlyph.readNBits(enc.yBits) + enc.deltaY;
11611
11629
  if (enc.xSign !== 0) {
11612
11630
  dx *= enc.xSign;
11613
11631
  }
@@ -12159,6 +12177,8 @@ var MAX_2BYTE_DIST = 512;
12159
12177
  var PRELOAD_SIZE = 2 * 32 * 96 + 4 * 256;
12160
12178
  var LEN_MIN = 2;
12161
12179
  var DIST_MIN = 1;
12180
+ var MAX_OUT_LEN = 4 * 1024 * 1024;
12181
+ var MAX_OUT = 16 * 1024 * 1024;
12162
12182
  var RLE_INITIAL = 0;
12163
12183
  var RLE_NORMAL = 1;
12164
12184
  var RLE_SEEN_ESCAPE = 2;
@@ -12168,6 +12188,9 @@ function setDistRange(length) {
12168
12188
  let distMax = DIST_MIN + ((1 << DIST_WIDTH * numDistRanges) - 1);
12169
12189
  while (distMax < length) {
12170
12190
  numDistRanges++;
12191
+ if (numDistRanges > 8) {
12192
+ throw new Error("LZCOMP setDistRange: numDistRanges exceeds bound (8)");
12193
+ }
12171
12194
  distMax = DIST_MIN + ((1 << DIST_WIDTH * numDistRanges) - 1);
12172
12195
  }
12173
12196
  const DUP2 = 256 + (1 << LEN_WIDTH) * numDistRanges;
@@ -12198,7 +12221,11 @@ function decodeLength(lenEcoder, symbol, numDistRangesOut) {
12198
12221
  let firstTime = true;
12199
12222
  let value = 0;
12200
12223
  let done;
12224
+ let iters = 0;
12201
12225
  do {
12226
+ if (++iters > 16) {
12227
+ throw new Error("LZCOMP decodeLength: iteration cap exceeded");
12228
+ }
12202
12229
  let bits;
12203
12230
  if (firstTime) {
12204
12231
  bits = symbol - 256;
@@ -12237,6 +12264,9 @@ function lzcompDecompress(data, size, version) {
12237
12264
  const distEcoder = new AHuff(bio, 1 << DIST_WIDTH);
12238
12265
  const lenEcoder = new AHuff(bio, 1 << LEN_WIDTH);
12239
12266
  const outLen = bio.readValue(24);
12267
+ if (outLen > MAX_OUT_LEN) {
12268
+ throw new Error(`LZCOMP outLen ${outLen} exceeds maximum (${MAX_OUT_LEN})`);
12269
+ }
12240
12270
  const { DUP2, DUP4, DUP6, NUM_SYMS } = setDistRange(outLen);
12241
12271
  const symEcoder = new AHuff(bio, NUM_SYMS);
12242
12272
  const windowSize = PRELOAD_SIZE + outLen;
@@ -12253,6 +12283,9 @@ function lzcompDecompress(data, size, version) {
12253
12283
  if (!usingRunLength) {
12254
12284
  if (outIdx >= outBufSize) {
12255
12285
  outBufSize += outBufSize >>> 1;
12286
+ if (outBufSize > MAX_OUT) {
12287
+ throw new Error("LZCOMP output exceeds maximum size budget");
12288
+ }
12256
12289
  const tmp = new Uint8Array(outBufSize);
12257
12290
  tmp.set(outBuf);
12258
12291
  outBuf = tmp;
@@ -12271,6 +12304,9 @@ function lzcompDecompress(data, size, version) {
12271
12304
  } else {
12272
12305
  if (outIdx >= outBufSize) {
12273
12306
  outBufSize += outBufSize >>> 1;
12307
+ if (outBufSize > MAX_OUT) {
12308
+ throw new Error("LZCOMP output exceeds maximum size budget");
12309
+ }
12274
12310
  const tmp = new Uint8Array(outBufSize);
12275
12311
  tmp.set(outBuf);
12276
12312
  outBuf = tmp;
@@ -12283,6 +12319,9 @@ function lzcompDecompress(data, size, version) {
12283
12319
  if (rleCount === 0) {
12284
12320
  if (outIdx >= outBufSize) {
12285
12321
  outBufSize += outBufSize >>> 1;
12322
+ if (outBufSize > MAX_OUT) {
12323
+ throw new Error("LZCOMP output exceeds maximum size budget");
12324
+ }
12286
12325
  const tmp = new Uint8Array(outBufSize);
12287
12326
  tmp.set(outBuf);
12288
12327
  outBuf = tmp;
@@ -12296,6 +12335,9 @@ function lzcompDecompress(data, size, version) {
12296
12335
  case RLE_NEED_BYTE: {
12297
12336
  if (outIdx + rleCount > outBufSize) {
12298
12337
  outBufSize = outIdx + rleCount + (outBufSize >>> 1);
12338
+ if (outBufSize > MAX_OUT) {
12339
+ throw new Error("LZCOMP output exceeds maximum size budget");
12340
+ }
12299
12341
  const tmp = new Uint8Array(outBufSize);
12300
12342
  tmp.set(outBuf);
12301
12343
  outBuf = tmp;
@@ -12455,11 +12497,23 @@ function dumpContainer(ctr) {
12455
12497
  }
12456
12498
  var ENCRYPTION_KEY = 80;
12457
12499
  function unpackMtx(data, size) {
12500
+ if (size < 10 || data.length < 10) {
12501
+ throw new Error("MTX data too small: header requires at least 10 bytes");
12502
+ }
12458
12503
  const versionMagic = data[0];
12459
12504
  const offset2 = data[4] << 16 | data[5] << 8 | data[6];
12460
12505
  const offset3 = data[7] << 16 | data[8] << 8 | data[9];
12506
+ if (offset2 < 10 || offset3 < offset2 || offset3 > size) {
12507
+ throw new Error(
12508
+ `MTX header offsets out of bounds: offset2=${offset2}, offset3=${offset3}, size=${size}`
12509
+ );
12510
+ }
12461
12511
  const offsets = [10, offset2, offset3];
12462
- const blockSizes = [offset2 - 10, offset3 - offset2, size - offset3];
12512
+ const blockSizes = [
12513
+ Math.max(0, offset2 - 10),
12514
+ Math.max(0, offset3 - offset2),
12515
+ Math.max(0, size - offset3)
12516
+ ];
12463
12517
  const streams = [];
12464
12518
  const decompressedSizes = [];
12465
12519
  for (let i = 0; i < 3; i++) {
@@ -14706,6 +14760,9 @@ function cloneXmlObject(value) {
14706
14760
  return void 0;
14707
14761
  }
14708
14762
  try {
14763
+ if (typeof structuredClone === "function") {
14764
+ return structuredClone(value);
14765
+ }
14709
14766
  return JSON.parse(JSON.stringify(value));
14710
14767
  } catch (error) {
14711
14768
  console.warn("Failed to clone XML object, returning undefined.", value, error);
@@ -15167,7 +15224,23 @@ var extensionByResponseMime = {
15167
15224
  "image/svg+xml": "svg",
15168
15225
  "application/octet-stream": "bin"
15169
15226
  };
15170
- async function fetchUrlToBytes(url) {
15227
+ var DEFAULT_SAFE_SCHEMES = /* @__PURE__ */ new Set(["pptx-resource:", "blob:", "data:"]);
15228
+ async function fetchUrlToBytes(url, options = {}) {
15229
+ let scheme;
15230
+ try {
15231
+ scheme = new URL(url).protocol;
15232
+ } catch {
15233
+ return null;
15234
+ }
15235
+ const allowedSchemes = options.allowedSchemes ?? DEFAULT_SAFE_SCHEMES;
15236
+ const isHttp = scheme === "http:" || scheme === "https:";
15237
+ if (isHttp) {
15238
+ if (options.allowExternalFetch !== true) {
15239
+ return null;
15240
+ }
15241
+ } else if (!allowedSchemes.has(scheme)) {
15242
+ return null;
15243
+ }
15171
15244
  try {
15172
15245
  const response = await fetch(url);
15173
15246
  if (!response.ok) {
@@ -15297,17 +15370,35 @@ function buildForest(nodes) {
15297
15370
  }
15298
15371
  return roots;
15299
15372
  }
15300
- function treeWidth(t) {
15373
+ var MAX_TREE_DEPTH = 256;
15374
+ function treeWidth(t, depth = 0) {
15375
+ if (depth >= MAX_TREE_DEPTH) {
15376
+ return 1;
15377
+ }
15301
15378
  if (t.children.length === 0) {
15302
15379
  return 1;
15303
15380
  }
15304
- return t.children.reduce((s, c) => s + treeWidth(c), 0);
15381
+ let sum = 0;
15382
+ for (const c of t.children) {
15383
+ sum += treeWidth(c, depth + 1);
15384
+ }
15385
+ return sum;
15305
15386
  }
15306
- function treeDepth(t) {
15387
+ function treeDepth(t, depth = 0) {
15388
+ if (depth >= MAX_TREE_DEPTH) {
15389
+ return 0;
15390
+ }
15307
15391
  if (t.children.length === 0) {
15308
15392
  return 1;
15309
15393
  }
15310
- return 1 + Math.max(...t.children.map(treeDepth));
15394
+ let max = 0;
15395
+ for (const c of t.children) {
15396
+ const d = treeDepth(c, depth + 1);
15397
+ if (d > max) {
15398
+ max = d;
15399
+ }
15400
+ }
15401
+ return 1 + max;
15311
15402
  }
15312
15403
  function getContentNodes(nodes) {
15313
15404
  return nodes.filter((n) => n.text.length > 0);
@@ -15412,7 +15503,11 @@ function computeHierarchyLayout(nodes, constraints, bounds) {
15412
15503
  const nodeW = constraints.w ? constraints.w * bounds.width : Math.min(cellW * 0.8, 140);
15413
15504
  const nodeH = constraints.h ? constraints.h * bounds.height : Math.min(cellH * 0.35, 50);
15414
15505
  const shapes = [];
15506
+ const MAX_WALK_DEPTH = 256;
15415
15507
  function walk(t, xOffset, level) {
15508
+ if (level >= MAX_WALK_DEPTH) {
15509
+ return 1;
15510
+ }
15416
15511
  const w = treeWidth(t);
15417
15512
  const cx = bounds.x + begPad + (xOffset + w / 2) * cellW;
15418
15513
  const cy = bounds.y + begPad + level * cellH + cellH / 2;
@@ -17594,7 +17689,11 @@ function reflowHierarchy(nodes, bounds) {
17594
17689
  const boxW = Math.min(cellW * 0.8, 140);
17595
17690
  const boxH = Math.min(cellH * 0.35, 28);
17596
17691
  const shapes = [];
17692
+ const MAX_WALK_DEPTH = 256;
17597
17693
  function walkTree(t, xOffset, level) {
17694
+ if (level >= MAX_WALK_DEPTH) {
17695
+ return 1;
17696
+ }
17598
17697
  const w = treeWidth(t);
17599
17698
  const cx = bounds.x + padding + (xOffset + w / 2) * cellW;
17600
17699
  const cy = bounds.y + padding + level * cellH + cellH / 2;
@@ -19174,7 +19273,13 @@ async function createModifyVerifier(password, options) {
19174
19273
 
19175
19274
  // src/core/utils/signature-xml-utils.ts
19176
19275
  function escapeXmlAttr(value) {
19177
- return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
19276
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
19277
+ }
19278
+ function escapeXmlText(value) {
19279
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
19280
+ }
19281
+ function isValidBase64(value) {
19282
+ return typeof value === "string" && value.length > 0 && /^[A-Za-z0-9+/=\s]+$/.test(value);
19178
19283
  }
19179
19284
  function extractTagAttribute(xml, tagName, attributeName) {
19180
19285
  const pattern = new RegExp(
@@ -19475,6 +19580,8 @@ function createTempCanvas(width, height) {
19475
19580
  if (width <= 0 || height <= 0) {
19476
19581
  return null;
19477
19582
  }
19583
+ width = Math.max(1, Math.min(Math.floor(width), 8192));
19584
+ height = Math.max(1, Math.min(Math.floor(height), 8192));
19478
19585
  if (typeof OffscreenCanvas !== "undefined") {
19479
19586
  const canvas = new OffscreenCanvas(width, height);
19480
19587
  const ctx = canvas.getContext("2d");
@@ -19535,18 +19642,34 @@ function applyFont(ctx, state) {
19535
19642
  ctx.font = `${italic}${weight}${size}px ${state.fontFamily}`;
19536
19643
  }
19537
19644
  function readUtf16LE2(view, offset, charCount) {
19538
- const chars = [];
19539
- for (let i = 0; i < charCount; i++) {
19540
- if (offset + i * 2 + 1 >= view.byteLength) {
19541
- break;
19542
- }
19543
- const code = view.getUint16(offset + i * 2, true);
19544
- if (code === 0) {
19545
- break;
19645
+ if (charCount <= 0) {
19646
+ return "";
19647
+ }
19648
+ const maxBytes = view.byteLength - offset;
19649
+ if (maxBytes <= 0) {
19650
+ return "";
19651
+ }
19652
+ const usableChars = Math.min(charCount, Math.floor(maxBytes / 2));
19653
+ if (usableChars <= 0) {
19654
+ return "";
19655
+ }
19656
+ let decoded;
19657
+ try {
19658
+ const bytes = new Uint8Array(view.buffer, view.byteOffset + offset, usableChars * 2);
19659
+ decoded = new TextDecoder("utf-16le").decode(bytes);
19660
+ } catch {
19661
+ const chars = [];
19662
+ for (let i = 0; i < usableChars; i++) {
19663
+ const code = view.getUint16(offset + i * 2, true);
19664
+ if (code === 0) {
19665
+ return chars.join("");
19666
+ }
19667
+ chars.push(String.fromCharCode(code));
19546
19668
  }
19547
- chars.push(String.fromCharCode(code));
19669
+ return chars.join("");
19548
19670
  }
19549
- return chars.join("");
19671
+ const nul = decoded.indexOf(String.fromCharCode(0));
19672
+ return nul === -1 ? decoded : decoded.slice(0, nul);
19550
19673
  }
19551
19674
  function getStockObject(index) {
19552
19675
  switch (index) {
@@ -21498,7 +21621,12 @@ function applyClipCombineMode(rCtx, combineMode, opName, clipFn) {
21498
21621
  return true;
21499
21622
  }
21500
21623
  }
21501
- function traceRegionNodePath(ctx, node) {
21624
+ var MAX_REGION_TRACE_DEPTH = 64;
21625
+ function traceRegionNodePath(ctx, node, depth = 0) {
21626
+ if (depth > MAX_REGION_TRACE_DEPTH) {
21627
+ ctx.rect(0, 0, 0, 0);
21628
+ return;
21629
+ }
21502
21630
  switch (node.type) {
21503
21631
  case "rect":
21504
21632
  ctx.rect(node.x, node.y, node.width, node.height);
@@ -21513,7 +21641,7 @@ function traceRegionNodePath(ctx, node) {
21513
21641
  ctx.rect(0, 0, 0, 0);
21514
21642
  break;
21515
21643
  case "combine":
21516
- traceRegionNodePath(ctx, node.left);
21644
+ traceRegionNodePath(ctx, node.left, depth + 1);
21517
21645
  if (node.combineMode !== 0) {
21518
21646
  emfWarn(
21519
21647
  `traceRegionNodePath: combine mode ${node.combineMode} not fully supported, using left subtree only`
@@ -21524,7 +21652,7 @@ function traceRegionNodePath(ctx, node) {
21524
21652
  } catch {
21525
21653
  }
21526
21654
  ctx.beginPath();
21527
- traceRegionNodePath(ctx, node.right);
21655
+ traceRegionNodePath(ctx, node.right, depth + 1);
21528
21656
  }
21529
21657
  break;
21530
21658
  }
@@ -22314,19 +22442,23 @@ function handleEmfPlusObjectRecord(rCtx, recFlags, dataOff, recDataSize) {
22314
22442
  }
22315
22443
  }
22316
22444
  }
22317
- function parseRegionNode(view, off, endOff) {
22445
+ var MAX_REGION_NODE_DEPTH = 64;
22446
+ function parseRegionNode(view, off, endOff, depth = 0) {
22318
22447
  if (off + 4 > endOff) {
22319
22448
  return null;
22320
22449
  }
22450
+ if (depth > MAX_REGION_NODE_DEPTH) {
22451
+ return null;
22452
+ }
22321
22453
  const nodeType = view.getUint32(off, true);
22322
22454
  let cursor = off + 4;
22323
22455
  if (nodeType <= 4) {
22324
- const leftResult = parseRegionNode(view, cursor, endOff);
22456
+ const leftResult = parseRegionNode(view, cursor, endOff, depth + 1);
22325
22457
  if (!leftResult) {
22326
22458
  return null;
22327
22459
  }
22328
22460
  cursor += leftResult.bytesRead;
22329
- const rightResult = parseRegionNode(view, cursor, endOff);
22461
+ const rightResult = parseRegionNode(view, cursor, endOff, depth + 1);
22330
22462
  if (!rightResult) {
22331
22463
  return null;
22332
22464
  }
@@ -22712,18 +22844,23 @@ function replayEmfPlusRecords(view, offset, length, ctx, _canvasW, _canvasH, sta
22712
22844
  if (recDataSize >= 4) {
22713
22845
  const totalSize = view.getUint32(dataOff, true);
22714
22846
  const objectType = recFlags >> 8 & 127;
22715
- rCtx.continuationTotalSize = totalSize;
22716
- rCtx.continuationObjectId = objectId;
22717
- rCtx.continuationObjectType = objectType;
22718
- rCtx.continuationBuffer = new Uint8Array(totalSize);
22719
- const chunkSize = recDataSize - 4;
22720
- const chunk = new Uint8Array(
22721
- view.buffer,
22722
- view.byteOffset + dataOff + 4,
22723
- Math.min(chunkSize, totalSize)
22724
- );
22725
- rCtx.continuationBuffer.set(chunk, 0);
22726
- rCtx.continuationOffset = chunk.length;
22847
+ const MAX_CONTINUATION_BYTES = 64 * 1024 * 1024;
22848
+ const remainingEmfPlusBytes = view.byteLength - dataOff;
22849
+ if (!Number.isFinite(totalSize) || totalSize <= 0 || totalSize > MAX_CONTINUATION_BYTES || totalSize > remainingEmfPlusBytes || recDataSize - 4 < 0) ;
22850
+ else {
22851
+ rCtx.continuationTotalSize = totalSize;
22852
+ rCtx.continuationObjectId = objectId;
22853
+ rCtx.continuationObjectType = objectType;
22854
+ rCtx.continuationBuffer = new Uint8Array(totalSize);
22855
+ const chunkSize = recDataSize - 4;
22856
+ const chunk = new Uint8Array(
22857
+ view.buffer,
22858
+ view.byteOffset + dataOff + 4,
22859
+ Math.min(chunkSize, totalSize)
22860
+ );
22861
+ rCtx.continuationBuffer.set(chunk, 0);
22862
+ rCtx.continuationOffset = chunk.length;
22863
+ }
22727
22864
  }
22728
22865
  } else {
22729
22866
  const remaining = rCtx.continuationTotalSize - rCtx.continuationOffset;
@@ -23360,8 +23497,11 @@ function replayWmfRecords(view, ctx, header, canvasW, canvasH) {
23360
23497
  );
23361
23498
  }
23362
23499
  }
23363
- async function processDeferredImages(ctx, deferredImages) {
23364
- emfLog(`processDeferredImages: processing ${deferredImages.length} deferred images...`);
23500
+ var MAX_METAFILE_RECURSION = 3;
23501
+ async function processDeferredImages(ctx, deferredImages, recursionDepth = 0) {
23502
+ emfLog(
23503
+ `processDeferredImages: processing ${deferredImages.length} deferred images (recursionDepth=${recursionDepth})...`
23504
+ );
23365
23505
  for (let idx = 0; idx < deferredImages.length; idx++) {
23366
23506
  const img = deferredImages[idx];
23367
23507
  emfLog(
@@ -23380,8 +23520,26 @@ async function processDeferredImages(ctx, deferredImages) {
23380
23520
  img.transform[5]
23381
23521
  );
23382
23522
  if (img.isMetafile) {
23523
+ if (recursionDepth >= MAX_METAFILE_RECURSION) {
23524
+ emfWarn(
23525
+ ` Deferred image [${idx}]: skipping embedded metafile \u2014 recursion depth ${recursionDepth} >= ${MAX_METAFILE_RECURSION}`
23526
+ );
23527
+ continue;
23528
+ }
23383
23529
  emfLog(` Deferred image [${idx}]: recursively converting embedded metafile...`);
23384
- const metafileDataUrl = await convertEmfToDataUrl(plainBuffer) ?? await convertWmfToDataUrl(plainBuffer);
23530
+ const metafileDataUrl = await convertEmfToDataUrl(
23531
+ plainBuffer,
23532
+ void 0,
23533
+ void 0,
23534
+ void 0,
23535
+ recursionDepth + 1
23536
+ ) ?? await convertWmfToDataUrl(
23537
+ plainBuffer,
23538
+ void 0,
23539
+ void 0,
23540
+ void 0,
23541
+ recursionDepth + 1
23542
+ );
23385
23543
  if (metafileDataUrl) {
23386
23544
  emfLog(
23387
23545
  ` Deferred image [${idx}]: metafile converted, dataUrl length=${metafileDataUrl.length}`
@@ -23426,7 +23584,10 @@ async function processDeferredImages(ctx, deferredImages) {
23426
23584
  }
23427
23585
  ctx.setTransform(1, 0, 0, 1, 0, 0);
23428
23586
  }
23429
- async function convertEmfToDataUrl(buffer, maxWidth, maxHeight, optionsOrDpiScale) {
23587
+ async function convertEmfToDataUrl(buffer, maxWidth, maxHeight, optionsOrDpiScale, recursionDepth = 0) {
23588
+ if (recursionDepth > MAX_METAFILE_RECURSION) {
23589
+ return null;
23590
+ }
23430
23591
  const opts = typeof optionsOrDpiScale === "number" ? { dpiScale: optionsOrDpiScale } : optionsOrDpiScale ?? {};
23431
23592
  const dpiScale = opts.dpiScale ?? DEFAULT_DPI_SCALE;
23432
23593
  const effectiveMaxWidth = maxWidth ?? opts.maxWidth;
@@ -23495,7 +23656,10 @@ async function convertEmfToDataUrl(buffer, maxWidth, maxHeight, optionsOrDpiScal
23495
23656
  return null;
23496
23657
  }
23497
23658
  }
23498
- async function convertWmfToDataUrl(buffer, maxWidth, maxHeight, optionsOrDpiScale) {
23659
+ async function convertWmfToDataUrl(buffer, maxWidth, maxHeight, optionsOrDpiScale, recursionDepth = 0) {
23660
+ if (recursionDepth > MAX_METAFILE_RECURSION) {
23661
+ return null;
23662
+ }
23499
23663
  const opts = typeof optionsOrDpiScale === "number" ? { dpiScale: optionsOrDpiScale } : optionsOrDpiScale ?? {};
23500
23664
  const dpiScale = opts.dpiScale ?? DEFAULT_DPI_SCALE;
23501
23665
  const effectiveMaxWidth = maxWidth ?? opts.maxWidth;
@@ -26123,6 +26287,55 @@ function relayoutSmartArt(smartArtData, containerWidth, containerHeight) {
26123
26287
  return smartArtData.drawingShapes ?? [];
26124
26288
  }
26125
26289
 
26290
+ // src/core/utils/safe-path.ts
26291
+ function safeResolveZipPath(basePath, target) {
26292
+ if (typeof basePath !== "string" || typeof target !== "string") {
26293
+ return null;
26294
+ }
26295
+ const trimmedTarget = target.trim();
26296
+ if (trimmedTarget.length === 0) {
26297
+ return null;
26298
+ }
26299
+ if (trimmedTarget.startsWith("/")) {
26300
+ return normaliseSegments(trimmedTarget.slice(1).replace(/\\/g, "/"));
26301
+ }
26302
+ const baseParts = basePath.replace(/\\/g, "/").split("/").filter((p) => p.length > 0);
26303
+ const targetParts = trimmedTarget.replace(/\\/g, "/").split("/");
26304
+ const stack = [...baseParts];
26305
+ for (const part of targetParts) {
26306
+ if (part === "" || part === ".") {
26307
+ continue;
26308
+ }
26309
+ if (part === "..") {
26310
+ if (stack.length === 0) {
26311
+ return null;
26312
+ }
26313
+ stack.pop();
26314
+ continue;
26315
+ }
26316
+ stack.push(part);
26317
+ }
26318
+ return stack.join("/");
26319
+ }
26320
+ function normaliseSegments(input) {
26321
+ const parts = input.split("/");
26322
+ const stack = [];
26323
+ for (const part of parts) {
26324
+ if (part === "" || part === ".") {
26325
+ continue;
26326
+ }
26327
+ if (part === "..") {
26328
+ if (stack.length === 0) {
26329
+ return null;
26330
+ }
26331
+ stack.pop();
26332
+ continue;
26333
+ }
26334
+ stack.push(part);
26335
+ }
26336
+ return stack.join("/");
26337
+ }
26338
+
26126
26339
  // src/core/core/runtime/PptxHandlerRuntimeSaveParagraphHelpers.ts
26127
26340
  var EMU_PER_PX5 = 9525;
26128
26341
  function buildParagraphPropertiesXml(textStyle, paragraphAlign, bulletInfo, spacing, level) {
@@ -26559,6 +26772,12 @@ var PptxHandlerRuntime = class {
26559
26772
  * images are decoded lazily on first access via {@link getImageData}.
26560
26773
  */
26561
26774
  eagerDecodeImages = false;
26775
+ /**
26776
+ * When true, relationship targets pointing at `http://` / `https://`
26777
+ * URLs are passed through to `<img src>`. Default `false`. Mirrors the
26778
+ * `allowExternalImages` load option.
26779
+ */
26780
+ allowExternalImages = false;
26562
26781
  /** Ordered slide file paths (populated during load for action target resolution). */
26563
26782
  orderedSlidePaths = [];
26564
26783
  /** Theme colour scheme map: scheme key (e.g. "dk1", "accent1") -> hex colour value. */
@@ -27906,7 +28125,13 @@ var PptxHandlerRuntime7 = class extends PptxHandlerRuntime6 {
27906
28125
  return void 0;
27907
28126
  }
27908
28127
  const ext = this.getPathExtension(imagePath);
27909
- if (imagePath.startsWith("http://") || imagePath.startsWith("https://") || imagePath.startsWith("data:")) {
28128
+ if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
28129
+ if (this.allowExternalImages !== true) {
28130
+ return void 0;
28131
+ }
28132
+ return imagePath;
28133
+ }
28134
+ if (imagePath.startsWith("data:")) {
27910
28135
  return imagePath;
27911
28136
  }
27912
28137
  if (this.imageDataCache.has(imagePath)) {
@@ -27955,7 +28180,11 @@ var PptxHandlerRuntime7 = class extends PptxHandlerRuntime6 {
27955
28180
  * Enrich parsed media elements with timing data from the slide's
27956
28181
  * `p:timing` tree (trim, loop, poster frame, fullScreen).
27957
28182
  */
27958
- async enrichMediaElementsWithTiming(elements, timingMap) {
28183
+ async enrichMediaElementsWithTiming(elements, timingMap, depth = 0) {
28184
+ const MAX_TIMING_DEPTH = 32;
28185
+ if (depth > MAX_TIMING_DEPTH) {
28186
+ return;
28187
+ }
27959
28188
  for (const el of elements) {
27960
28189
  if (el.type !== "media") {
27961
28190
  continue;
@@ -28017,7 +28246,7 @@ var PptxHandlerRuntime7 = class extends PptxHandlerRuntime6 {
28017
28246
  }
28018
28247
  for (const el of elements) {
28019
28248
  if (el.type === "group" && el.children) {
28020
- await this.enrichMediaElementsWithTiming(el.children, timingMap);
28249
+ await this.enrichMediaElementsWithTiming(el.children, timingMap, depth + 1);
28021
28250
  }
28022
28251
  }
28023
28252
  }
@@ -28390,7 +28619,7 @@ var PptxHandlerRuntime8 = class extends PptxHandlerRuntime7 {
28390
28619
  };
28391
28620
 
28392
28621
  // src/core/core/runtime/PptxHandlerRuntimeSlideMasters.ts
28393
- var PptxHandlerRuntime9 = class extends PptxHandlerRuntime8 {
28622
+ var PptxHandlerRuntime9 = class _PptxHandlerRuntime extends PptxHandlerRuntime8 {
28394
28623
  /**
28395
28624
  * Parse background colour from a `p:bg` node.
28396
28625
  */
@@ -28429,6 +28658,18 @@ var PptxHandlerRuntime9 = class extends PptxHandlerRuntime8 {
28429
28658
  }
28430
28659
  return result;
28431
28660
  }
28661
+ /**
28662
+ * Allowed top-level OPC archive directories (Load M1).
28663
+ * After path resolution, the first segment must be one of these or the
28664
+ * path is rejected as a traversal attempt. PPTX archives only ever
28665
+ * legitimately reference parts under these roots.
28666
+ */
28667
+ static ALLOWED_PATH_ROOTS = /* @__PURE__ */ new Set([
28668
+ "ppt",
28669
+ "customXml",
28670
+ "docProps",
28671
+ "_rels"
28672
+ ]);
28432
28673
  resolvePath(base, relative) {
28433
28674
  const baseParts = base.split("/").filter(Boolean);
28434
28675
  const relParts = relative.split("/");
@@ -28437,16 +28678,36 @@ var PptxHandlerRuntime9 = class extends PptxHandlerRuntime8 {
28437
28678
  }
28438
28679
  for (const part of relParts) {
28439
28680
  if (part === "..") {
28681
+ if (baseParts.length === 0) {
28682
+ return "";
28683
+ }
28440
28684
  baseParts.pop();
28441
28685
  } else if (part !== ".") {
28442
28686
  baseParts.push(part);
28443
28687
  }
28444
28688
  }
28445
- return baseParts.join("/");
28689
+ const resolved = baseParts.join("/");
28690
+ if (resolved.length === 0) {
28691
+ return "";
28692
+ }
28693
+ const firstSegment = baseParts[0];
28694
+ if (!_PptxHandlerRuntime.ALLOWED_PATH_ROOTS.has(firstSegment)) {
28695
+ return "";
28696
+ }
28697
+ return resolved;
28446
28698
  }
28447
28699
  resolveImagePath(slidePath, target) {
28448
28700
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
28449
- return target.startsWith("..") ? this.resolvePath(slideDir, target) : target.startsWith("/") ? target.substring(1) : slideDir + target;
28701
+ const resolved = target.startsWith("..") ? this.resolvePath(slideDir, target) : target.startsWith("/") ? target.substring(1) : slideDir + target;
28702
+ if (resolved.length === 0) {
28703
+ return "";
28704
+ }
28705
+ const firstSlash = resolved.indexOf("/");
28706
+ const firstSegment = firstSlash === -1 ? resolved : resolved.substring(0, firstSlash);
28707
+ if (!_PptxHandlerRuntime.ALLOWED_PATH_ROOTS.has(firstSegment)) {
28708
+ return "";
28709
+ }
28710
+ return resolved;
28450
28711
  }
28451
28712
  /**
28452
28713
  * Parse all slide masters into structured PptxSlideMaster objects.
@@ -28925,6 +29186,9 @@ var PptxHandlerRuntime11 = class extends PptxHandlerRuntime10 {
28925
29186
  return void 0;
28926
29187
  }
28927
29188
  try {
29189
+ if (typeof structuredClone === "function") {
29190
+ return structuredClone(value);
29191
+ }
28928
29192
  return JSON.parse(JSON.stringify(value));
28929
29193
  } catch {
28930
29194
  return void 0;
@@ -32663,13 +32927,17 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
32663
32927
  if (this.customXmlParts.length === 0) {
32664
32928
  return;
32665
32929
  }
32930
+ const SAFE_ID = /^[A-Za-z0-9_-]+$/;
32931
+ let fallbackIndex = 1;
32666
32932
  for (const part of this.customXmlParts) {
32667
- this.zip.file(`customXml/item${part.id}.xml`, part.data);
32933
+ const rawId = String(part.id);
32934
+ const safeId = SAFE_ID.test(rawId) ? rawId : String(fallbackIndex++);
32935
+ this.zip.file(`customXml/item${safeId}.xml`, part.data);
32668
32936
  if (part.properties) {
32669
- this.zip.file(`customXml/itemProps${part.id}.xml`, part.properties);
32937
+ this.zip.file(`customXml/itemProps${safeId}.xml`, part.properties);
32670
32938
  }
32671
32939
  if (part.rels) {
32672
- this.zip.file(`customXml/_rels/item${part.id}.xml.rels`, part.rels);
32940
+ this.zip.file(`customXml/_rels/item${safeId}.xml.rels`, part.rels);
32673
32941
  }
32674
32942
  }
32675
32943
  }
@@ -32970,7 +33238,10 @@ var PptxHandlerRuntime25 = class extends PptxHandlerRuntime24 {
32970
33238
  if (relNode) {
32971
33239
  const target = String(relNode["@_Target"] || "").trim();
32972
33240
  if (target.length > 0) {
32973
- propsPath = target.startsWith("/") ? target.slice(1) : `ppt/${target}`;
33241
+ const resolved = safeResolveZipPath("ppt", target);
33242
+ if (resolved !== null) {
33243
+ propsPath = resolved;
33244
+ }
32974
33245
  }
32975
33246
  }
32976
33247
  } catch {
@@ -33414,7 +33685,10 @@ var PptxHandlerRuntime27 = class extends PptxHandlerRuntime26 {
33414
33685
  continue;
33415
33686
  }
33416
33687
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
33417
- return target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${target.replace("../", "")}`;
33688
+ const resolved = safeResolveZipPath(slideDir, target);
33689
+ if (resolved !== null) {
33690
+ return resolved;
33691
+ }
33418
33692
  }
33419
33693
  return void 0;
33420
33694
  }
@@ -33428,7 +33702,10 @@ var PptxHandlerRuntime27 = class extends PptxHandlerRuntime26 {
33428
33702
  continue;
33429
33703
  }
33430
33704
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
33431
- return target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
33705
+ const resolved = safeResolveZipPath(layoutDir, target);
33706
+ if (resolved !== null) {
33707
+ return resolved;
33708
+ }
33432
33709
  }
33433
33710
  return void 0;
33434
33711
  }
@@ -35540,7 +35817,20 @@ var PptxHandlerRuntime37 = class extends PptxHandlerRuntime36 {
35540
35817
  expected
35541
35818
  );
35542
35819
  }
35543
- mergeXmlObjects(base, override) {
35820
+ mergeXmlObjects(base, override, depth = 0) {
35821
+ const MAX_MERGE_DEPTH = 64;
35822
+ if (depth > MAX_MERGE_DEPTH) {
35823
+ if (!base && !override) {
35824
+ return void 0;
35825
+ }
35826
+ if (!base) {
35827
+ return override ? { ...override } : void 0;
35828
+ }
35829
+ if (!override) {
35830
+ return { ...base };
35831
+ }
35832
+ return { ...base, ...override };
35833
+ }
35544
35834
  if (!base && !override) {
35545
35835
  return void 0;
35546
35836
  }
@@ -35554,7 +35844,7 @@ var PptxHandlerRuntime37 = class extends PptxHandlerRuntime36 {
35554
35844
  for (const [key, value] of Object.entries(override)) {
35555
35845
  const existing = merged[key];
35556
35846
  if (value && typeof value === "object" && !Array.isArray(value) && existing && typeof existing === "object" && !Array.isArray(existing)) {
35557
- merged[key] = this.mergeXmlObjects(existing, value);
35847
+ merged[key] = this.mergeXmlObjects(existing, value, depth + 1);
35558
35848
  } else {
35559
35849
  merged[key] = value;
35560
35850
  }
@@ -37443,6 +37733,21 @@ var PptxHandlerRuntime45 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
37443
37733
  };
37444
37734
 
37445
37735
  // src/core/core/runtime/PptxHandlerRuntimePictureParsing.ts
37736
+ var INT32_MIN = -2147483648;
37737
+ var INT32_MAX = 2147483647;
37738
+ function parseEmuInt(value) {
37739
+ const parsed = parseInt(String(value ?? ""), 10);
37740
+ if (!Number.isFinite(parsed)) {
37741
+ return 0;
37742
+ }
37743
+ if (parsed < INT32_MIN) {
37744
+ return INT32_MIN;
37745
+ }
37746
+ if (parsed > INT32_MAX) {
37747
+ return INT32_MAX;
37748
+ }
37749
+ return parsed;
37750
+ }
37446
37751
  var PptxHandlerRuntime46 = class _PptxHandlerRuntime extends PptxHandlerRuntime45 {
37447
37752
  async parsePicture(pic, id, slidePath) {
37448
37753
  try {
@@ -37462,13 +37767,13 @@ var PptxHandlerRuntime46 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
37462
37767
  if (!off || !ext) {
37463
37768
  return null;
37464
37769
  }
37465
- const x = Math.round(parseInt(off["@_x"] || "0") / _PptxHandlerRuntime.EMU_PER_PX);
37466
- const y = Math.round(parseInt(off["@_y"] || "0") / _PptxHandlerRuntime.EMU_PER_PX);
37467
- const width = Math.round(parseInt(ext["@_cx"] || "0") / _PptxHandlerRuntime.EMU_PER_PX);
37468
- const height = Math.round(parseInt(ext["@_cy"] || "0") / _PptxHandlerRuntime.EMU_PER_PX);
37469
- const rotation = xfrm["@_rot"] ? parseInt(xfrm["@_rot"]) / 6e4 : void 0;
37470
- const skewX = xfrm["@_skewX"] ? parseInt(String(xfrm["@_skewX"]), 10) / 6e4 : void 0;
37471
- const skewY = xfrm["@_skewY"] ? parseInt(String(xfrm["@_skewY"]), 10) / 6e4 : void 0;
37770
+ const x = Math.round(parseEmuInt(off["@_x"]) / _PptxHandlerRuntime.EMU_PER_PX);
37771
+ const y = Math.round(parseEmuInt(off["@_y"]) / _PptxHandlerRuntime.EMU_PER_PX);
37772
+ const width = Math.round(parseEmuInt(ext["@_cx"]) / _PptxHandlerRuntime.EMU_PER_PX);
37773
+ const height = Math.round(parseEmuInt(ext["@_cy"]) / _PptxHandlerRuntime.EMU_PER_PX);
37774
+ const rotation = xfrm["@_rot"] ? parseEmuInt(xfrm["@_rot"]) / 6e4 : void 0;
37775
+ const skewX = xfrm["@_skewX"] ? parseEmuInt(xfrm["@_skewX"]) / 6e4 : void 0;
37776
+ const skewY = xfrm["@_skewY"] ? parseEmuInt(xfrm["@_skewY"]) / 6e4 : void 0;
37472
37777
  const { flipHorizontal, flipVertical } = this.readFlipState(xfrm);
37473
37778
  const nvPr = pic?.["p:nvPicPr"]?.["p:nvPr"];
37474
37779
  const videoFileNode = nvPr?.["a:videoFile"];
@@ -37495,7 +37800,13 @@ var PptxHandlerRuntime46 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
37495
37800
  const slideRels = this.slideRelsMap.get(slidePath);
37496
37801
  const posterTarget = slideRels?.get(posterREmbed || posterRLink);
37497
37802
  if (posterTarget) {
37498
- if (posterTarget.startsWith("http://") || posterTarget.startsWith("https://") || posterTarget.startsWith("data:")) {
37803
+ const isExternal = posterTarget.startsWith("http://") || posterTarget.startsWith("https://");
37804
+ if (isExternal) {
37805
+ if (this.allowExternalImages === true) {
37806
+ posterFramePath = posterTarget;
37807
+ posterFrameData = posterTarget;
37808
+ }
37809
+ } else if (posterTarget.startsWith("data:")) {
37499
37810
  posterFramePath = posterTarget;
37500
37811
  posterFrameData = posterTarget;
37501
37812
  } else {
@@ -37615,7 +37926,13 @@ var PptxHandlerRuntime46 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
37615
37926
  const slideRels = this.slideRelsMap.get(slidePath);
37616
37927
  const target = slideRels?.get(rEmbed || rLink);
37617
37928
  if (target) {
37618
- if (target.startsWith("http://") || target.startsWith("https://") || target.startsWith("data:")) {
37929
+ const isExternal = target.startsWith("http://") || target.startsWith("https://");
37930
+ if (isExternal) {
37931
+ if (this.allowExternalImages === true) {
37932
+ imagePath = target;
37933
+ imageData = target;
37934
+ }
37935
+ } else if (target.startsWith("data:")) {
37619
37936
  imagePath = target;
37620
37937
  imageData = target;
37621
37938
  } else {
@@ -38049,32 +38366,55 @@ var PptxHandlerRuntime47 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
38049
38366
  };
38050
38367
 
38051
38368
  // src/core/core/runtime/PptxHandlerRuntimeGroupParsing.ts
38369
+ var MAX_GROUP_DEPTH = 64;
38370
+ var INT32_MIN2 = -2147483648;
38371
+ var INT32_MAX2 = 2147483647;
38372
+ function parseEmuInt2(value) {
38373
+ const parsed = parseInt(String(value ?? ""), 10);
38374
+ if (!Number.isFinite(parsed)) {
38375
+ return 0;
38376
+ }
38377
+ if (parsed < INT32_MIN2) {
38378
+ return INT32_MIN2;
38379
+ }
38380
+ if (parsed > INT32_MAX2) {
38381
+ return INT32_MAX2;
38382
+ }
38383
+ return parsed;
38384
+ }
38052
38385
  var PptxHandlerRuntime48 = class _PptxHandlerRuntime extends PptxHandlerRuntime47 {
38053
- async parseGroupShape(group, baseId, slidePath, rawXmlStr) {
38386
+ async parseGroupShape(group, baseId, slidePath, rawXmlStr, depth = 0) {
38387
+ if (depth > MAX_GROUP_DEPTH) {
38388
+ this.compatibilityService.reportWarning({
38389
+ code: "group-depth-exceeded",
38390
+ severity: "warning",
38391
+ scope: "element",
38392
+ message: `Group nesting exceeded ${MAX_GROUP_DEPTH} levels; truncating subtree (baseId=${baseId})`,
38393
+ slideId: slidePath,
38394
+ elementId: baseId
38395
+ });
38396
+ return [];
38397
+ }
38054
38398
  const grpSpPr = group["p:grpSpPr"];
38055
38399
  const xfrm = grpSpPr?.["a:xfrm"];
38056
38400
  let parentX = 0, parentY = 0, parentW = 0, parentH = 0;
38057
38401
  let chX = 0, chY = 0, chW = 0, chH = 0;
38058
38402
  if (xfrm) {
38059
38403
  if (xfrm["a:off"]) {
38060
- parentX = Math.round(parseInt(xfrm["a:off"]["@_x"] || "0") / _PptxHandlerRuntime.EMU_PER_PX);
38061
- parentY = Math.round(parseInt(xfrm["a:off"]["@_y"] || "0") / _PptxHandlerRuntime.EMU_PER_PX);
38404
+ parentX = Math.round(parseEmuInt2(xfrm["a:off"]["@_x"]) / _PptxHandlerRuntime.EMU_PER_PX);
38405
+ parentY = Math.round(parseEmuInt2(xfrm["a:off"]["@_y"]) / _PptxHandlerRuntime.EMU_PER_PX);
38062
38406
  }
38063
38407
  if (xfrm["a:ext"]) {
38064
- parentW = Math.round(
38065
- parseInt(xfrm["a:ext"]["@_cx"] || "0") / _PptxHandlerRuntime.EMU_PER_PX
38066
- );
38067
- parentH = Math.round(
38068
- parseInt(xfrm["a:ext"]["@_cy"] || "0") / _PptxHandlerRuntime.EMU_PER_PX
38069
- );
38408
+ parentW = Math.round(parseEmuInt2(xfrm["a:ext"]["@_cx"]) / _PptxHandlerRuntime.EMU_PER_PX);
38409
+ parentH = Math.round(parseEmuInt2(xfrm["a:ext"]["@_cy"]) / _PptxHandlerRuntime.EMU_PER_PX);
38070
38410
  }
38071
38411
  if (xfrm["a:chOff"]) {
38072
- chX = Math.round(parseInt(xfrm["a:chOff"]["@_x"] || "0") / _PptxHandlerRuntime.EMU_PER_PX);
38073
- chY = Math.round(parseInt(xfrm["a:chOff"]["@_y"] || "0") / _PptxHandlerRuntime.EMU_PER_PX);
38412
+ chX = Math.round(parseEmuInt2(xfrm["a:chOff"]["@_x"]) / _PptxHandlerRuntime.EMU_PER_PX);
38413
+ chY = Math.round(parseEmuInt2(xfrm["a:chOff"]["@_y"]) / _PptxHandlerRuntime.EMU_PER_PX);
38074
38414
  }
38075
38415
  if (xfrm["a:chExt"]) {
38076
- chW = Math.round(parseInt(xfrm["a:chExt"]["@_cx"] || "0") / _PptxHandlerRuntime.EMU_PER_PX);
38077
- chH = Math.round(parseInt(xfrm["a:chExt"]["@_cy"] || "0") / _PptxHandlerRuntime.EMU_PER_PX);
38416
+ chW = Math.round(parseEmuInt2(xfrm["a:chExt"]["@_cx"]) / _PptxHandlerRuntime.EMU_PER_PX);
38417
+ chH = Math.round(parseEmuInt2(xfrm["a:chExt"]["@_cy"]) / _PptxHandlerRuntime.EMU_PER_PX);
38078
38418
  }
38079
38419
  }
38080
38420
  const scaleX = chW > 0 ? parentW / chW : 1;
@@ -38122,7 +38462,8 @@ var PptxHandlerRuntime48 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
38122
38462
  subGroup,
38123
38463
  `${baseId}-group-${entry.indexInType}`,
38124
38464
  slidePath,
38125
- rawXmlStr
38465
+ rawXmlStr,
38466
+ depth + 1
38126
38467
  );
38127
38468
  subElements.forEach((el) => transformElement(el));
38128
38469
  elements.push(...subElements);
@@ -38152,16 +38493,12 @@ var PptxHandlerRuntime48 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
38152
38493
  let parentX = 0, parentY = 0, parentW = 0, parentH = 0;
38153
38494
  if (xfrm) {
38154
38495
  if (xfrm["a:off"]) {
38155
- parentX = Math.round(parseInt(xfrm["a:off"]["@_x"] || "0") / _PptxHandlerRuntime.EMU_PER_PX);
38156
- parentY = Math.round(parseInt(xfrm["a:off"]["@_y"] || "0") / _PptxHandlerRuntime.EMU_PER_PX);
38496
+ parentX = Math.round(parseEmuInt2(xfrm["a:off"]["@_x"]) / _PptxHandlerRuntime.EMU_PER_PX);
38497
+ parentY = Math.round(parseEmuInt2(xfrm["a:off"]["@_y"]) / _PptxHandlerRuntime.EMU_PER_PX);
38157
38498
  }
38158
38499
  if (xfrm["a:ext"]) {
38159
- parentW = Math.round(
38160
- parseInt(xfrm["a:ext"]["@_cx"] || "0") / _PptxHandlerRuntime.EMU_PER_PX
38161
- );
38162
- parentH = Math.round(
38163
- parseInt(xfrm["a:ext"]["@_cy"] || "0") / _PptxHandlerRuntime.EMU_PER_PX
38164
- );
38500
+ parentW = Math.round(parseEmuInt2(xfrm["a:ext"]["@_cx"]) / _PptxHandlerRuntime.EMU_PER_PX);
38501
+ parentH = Math.round(parseEmuInt2(xfrm["a:ext"]["@_cy"]) / _PptxHandlerRuntime.EMU_PER_PX);
38165
38502
  }
38166
38503
  }
38167
38504
  const grpFillStyle = grpSpPr ? this.extractShapeStyle(grpSpPr) : void 0;
@@ -38475,6 +38812,12 @@ var PptxHandlerRuntime51 = class extends PptxHandlerRuntime50 {
38475
38812
  const slideRels = this.slideRelsMap.get(slidePath);
38476
38813
  const target = slideRels?.get(rEmbed);
38477
38814
  if (target) {
38815
+ if (target.startsWith("http://") || target.startsWith("https://")) {
38816
+ if (this.allowExternalImages !== true) {
38817
+ return void 0;
38818
+ }
38819
+ return target;
38820
+ }
38478
38821
  const imagePath = this.resolveImagePath(slidePath, target);
38479
38822
  return this.getImageData(imagePath);
38480
38823
  }
@@ -41131,30 +41474,41 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
41131
41474
  };
41132
41475
  }
41133
41476
  collectLocalTextValues(node, localName, output) {
41134
- if (node === null || node === void 0) {
41135
- return;
41136
- }
41137
- if (Array.isArray(node)) {
41138
- node.forEach((entry) => {
41139
- this.collectLocalTextValues(entry, localName, output);
41140
- });
41141
- return;
41142
- }
41143
- if (typeof node !== "object") {
41144
- return;
41145
- }
41146
- const objectNode = node;
41147
- for (const [key, value] of Object.entries(objectNode)) {
41148
- if (this.compatibilityService.getXmlLocalName(key) === localName) {
41149
- if (typeof value === "string" || typeof value === "number") {
41150
- const textValue = String(value).trim();
41151
- if (textValue.length > 0) {
41152
- output.push(textValue);
41477
+ const MAX_NODES = 1e6;
41478
+ const stack = [node];
41479
+ let visited = 0;
41480
+ while (stack.length > 0) {
41481
+ if (visited++ > MAX_NODES) {
41482
+ break;
41483
+ }
41484
+ const current = stack.pop();
41485
+ if (current === null || current === void 0) {
41486
+ continue;
41487
+ }
41488
+ if (Array.isArray(current)) {
41489
+ for (const entry of current) {
41490
+ stack.push(entry);
41491
+ }
41492
+ continue;
41493
+ }
41494
+ if (typeof current !== "object") {
41495
+ continue;
41496
+ }
41497
+ const objectNode = current;
41498
+ for (const [key, value] of Object.entries(objectNode)) {
41499
+ if (this.compatibilityService.getXmlLocalName(key) === localName) {
41500
+ if (typeof value === "string" || typeof value === "number") {
41501
+ const textValue = String(value).trim();
41502
+ if (textValue.length > 0) {
41503
+ output.push(textValue);
41504
+ }
41505
+ continue;
41153
41506
  }
41154
- continue;
41507
+ }
41508
+ if (value !== null && value !== void 0) {
41509
+ stack.push(value);
41155
41510
  }
41156
41511
  }
41157
- this.collectLocalTextValues(value, localName, output);
41158
41512
  }
41159
41513
  }
41160
41514
  /**
@@ -42671,6 +43025,7 @@ var PptxHandlerRuntime73 = class _PptxHandlerRuntime extends PptxHandlerRuntime7
42671
43025
  }
42672
43026
  async initializeLoadSession(data, options) {
42673
43027
  this.eagerDecodeImages = options.eagerDecodeImages ?? false;
43028
+ this.allowExternalImages = options.allowExternalImages === true;
42674
43029
  if (data.byteLength < 4) {
42675
43030
  throw new Error("Invalid PPTX binary: file is empty or truncated.");
42676
43031
  }
@@ -42688,6 +43043,29 @@ var PptxHandlerRuntime73 = class _PptxHandlerRuntime extends PptxHandlerRuntime7
42688
43043
  const message = error instanceof Error ? error.message : "Unable to read zip container.";
42689
43044
  throw new Error(`Invalid PPTX package: ${message}`, { cause: error });
42690
43045
  }
43046
+ const maxBytes = typeof options.maxUncompressedBytes === "number" && options.maxUncompressedBytes > 0 ? options.maxUncompressedBytes : DEFAULT_MAX_UNCOMPRESSED_BYTES;
43047
+ let totalUncompressed = 0;
43048
+ let entryCount = 0;
43049
+ for (const filename of Object.keys(this.zip.files)) {
43050
+ entryCount += 1;
43051
+ if (entryCount > MAX_ZIP_ENTRY_COUNT) {
43052
+ throw new ZipBombError(
43053
+ `PPTX archive contains more than ${MAX_ZIP_ENTRY_COUNT} entries \u2014 refusing to load.`,
43054
+ { limit: MAX_ZIP_ENTRY_COUNT, entryCount }
43055
+ );
43056
+ }
43057
+ const file = this.zip.files[filename];
43058
+ const size = Number(file?._data?.uncompressedSize ?? 0);
43059
+ if (Number.isFinite(size) && size > 0) {
43060
+ totalUncompressed += size;
43061
+ if (totalUncompressed > maxBytes) {
43062
+ throw new ZipBombError(
43063
+ `PPTX archive uncompressed size exceeds ${maxBytes} bytes (zip-bomb guard).`,
43064
+ { uncompressedBytes: totalUncompressed, limit: maxBytes }
43065
+ );
43066
+ }
43067
+ }
43068
+ }
42691
43069
  this.slideRelsMap.clear();
42692
43070
  this.externalRelsMap.clear();
42693
43071
  this.slideMap.clear();
@@ -42947,12 +43325,35 @@ var PptxHandlerRuntime74 = class extends PptxHandlerRuntime73 {
42947
43325
  * attribute on `p:cNvPr` / `p:cNvCxnSpPr` / `p:cNvPicPr` nodes.
42948
43326
  * This is used to seed the element builder's ID counter so that
42949
43327
  * new elements never collide with existing ones.
43328
+ *
43329
+ * Implementation note (Load H1): uses an explicit-stack iterative walk
43330
+ * instead of recursion to bound stack usage on attacker-supplied XML
43331
+ * with deeply nested nodes. Also caps total visited nodes at
43332
+ * MAX_NODES to bound CPU on pathological trees.
42950
43333
  */
42951
43334
  findMaxElementId(slides) {
43335
+ const MAX_NODES = 1e6;
42952
43336
  let max = 0;
42953
- const visit = (node) => {
43337
+ const stack = [];
43338
+ for (const slide of slides) {
43339
+ stack.push(slide.rawXml);
43340
+ }
43341
+ let visited = 0;
43342
+ while (stack.length > 0) {
43343
+ if (visited++ > MAX_NODES) {
43344
+ break;
43345
+ }
43346
+ const node = stack.pop();
42954
43347
  if (node === null || node === void 0 || typeof node !== "object") {
42955
- return;
43348
+ continue;
43349
+ }
43350
+ if (Array.isArray(node)) {
43351
+ for (const item of node) {
43352
+ if (item !== null && item !== void 0 && typeof item === "object") {
43353
+ stack.push(item);
43354
+ }
43355
+ }
43356
+ continue;
42956
43357
  }
42957
43358
  const obj = node;
42958
43359
  if ("@_id" in obj) {
@@ -42962,17 +43363,13 @@ var PptxHandlerRuntime74 = class extends PptxHandlerRuntime73 {
42962
43363
  }
42963
43364
  }
42964
43365
  for (const value of Object.values(obj)) {
42965
- if (Array.isArray(value)) {
42966
- for (const item of value) {
42967
- visit(item);
42968
- }
42969
- } else if (typeof value === "object" && value !== null) {
42970
- visit(value);
43366
+ if (value === null || value === void 0) {
43367
+ continue;
43368
+ }
43369
+ if (Array.isArray(value) || typeof value === "object") {
43370
+ stack.push(value);
42971
43371
  }
42972
43372
  }
42973
- };
42974
- for (const slide of slides) {
42975
- visit(slide.rawXml);
42976
43373
  }
42977
43374
  return max;
42978
43375
  }
@@ -45630,27 +46027,52 @@ function perpendicularDistance(p, start, end) {
45630
46027
  const distY = p.y - projY;
45631
46028
  return Math.sqrt(distX * distX + distY * distY);
45632
46029
  }
46030
+ var MAX_DOUGLAS_PEUCKER_POINTS = 1e5;
45633
46031
  function douglasPeucker(points, tolerance) {
45634
- if (points.length <= 2) {
46032
+ const n = points.length;
46033
+ if (n <= 2) {
45635
46034
  return [...points];
45636
46035
  }
45637
- let maxDist = 0;
45638
- let maxIdx = 0;
45639
- const first = points[0];
45640
- const last = points[points.length - 1];
45641
- for (let i = 1; i < points.length - 1; i++) {
45642
- const dist = perpendicularDistance(points[i], first, last);
45643
- if (dist > maxDist) {
45644
- maxDist = dist;
45645
- maxIdx = i;
46036
+ if (n > MAX_DOUGLAS_PEUCKER_POINTS) {
46037
+ return [points[0], points[n - 1]];
46038
+ }
46039
+ const keep = new Uint8Array(n);
46040
+ keep[0] = 1;
46041
+ keep[n - 1] = 1;
46042
+ const stack = [[0, n - 1]];
46043
+ while (stack.length > 0) {
46044
+ const range = stack.pop();
46045
+ if (!range) {
46046
+ break;
46047
+ }
46048
+ const [lo, hi] = range;
46049
+ if (hi - lo < 2) {
46050
+ continue;
46051
+ }
46052
+ const first = points[lo];
46053
+ const last = points[hi];
46054
+ let maxDist = 0;
46055
+ let maxIdx = -1;
46056
+ for (let i = lo + 1; i < hi; i++) {
46057
+ const dist = perpendicularDistance(points[i], first, last);
46058
+ if (dist > maxDist) {
46059
+ maxDist = dist;
46060
+ maxIdx = i;
46061
+ }
46062
+ }
46063
+ if (maxIdx !== -1 && maxDist > tolerance) {
46064
+ keep[maxIdx] = 1;
46065
+ stack.push([lo, maxIdx]);
46066
+ stack.push([maxIdx, hi]);
45646
46067
  }
45647
46068
  }
45648
- if (maxDist > tolerance) {
45649
- const left = douglasPeucker(points.slice(0, maxIdx + 1), tolerance);
45650
- const right = douglasPeucker(points.slice(maxIdx), tolerance);
45651
- return [...left.slice(0, -1), ...right];
46069
+ const result = [];
46070
+ for (let i = 0; i < n; i++) {
46071
+ if (keep[i]) {
46072
+ result.push(points[i]);
46073
+ }
45652
46074
  }
45653
- return [first, last];
46075
+ return result;
45654
46076
  }
45655
46077
  function catmullRomToBezier(points, factor = 6) {
45656
46078
  if (points.length < 2) {
@@ -46508,7 +46930,7 @@ function mergePresentation(targetData, sourceData, options) {
46508
46930
  if (options?.keepSourceTheme && sourceData.themeColorMap) {
46509
46931
  targetData.themeColorMap = { ...sourceData.themeColorMap };
46510
46932
  if (sourceData.theme) {
46511
- targetData.theme = JSON.parse(JSON.stringify(sourceData.theme));
46933
+ targetData.theme = typeof structuredClone === "function" ? structuredClone(sourceData.theme) : JSON.parse(JSON.stringify(sourceData.theme));
46512
46934
  }
46513
46935
  }
46514
46936
  return clonedSlides.length;
@@ -49607,6 +50029,29 @@ var MediaContext = class {
49607
50029
  };
49608
50030
 
49609
50031
  // src/converter/base.ts
50032
+ function escapeHtml(value) {
50033
+ if (value === void 0 || value === null) {
50034
+ return "";
50035
+ }
50036
+ return String(value).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
50037
+ }
50038
+ var SAFE_LINK_PREFIXES = ["http://", "https://", "mailto:", "tel:", "#"];
50039
+ function safeHrefOrHash(value) {
50040
+ if (typeof value !== "string") {
50041
+ return "#";
50042
+ }
50043
+ const trimmed = value.trim();
50044
+ if (trimmed.length === 0) {
50045
+ return "#";
50046
+ }
50047
+ const lower = trimmed.toLowerCase();
50048
+ for (const prefix of SAFE_LINK_PREFIXES) {
50049
+ if (lower.startsWith(prefix)) {
50050
+ return trimmed;
50051
+ }
50052
+ }
50053
+ return "#";
50054
+ }
49610
50055
  function normalizePath(pathValue) {
49611
50056
  return pathValue.trim().replace(/\\/g, "/");
49612
50057
  }
@@ -49660,7 +50105,8 @@ var DocumentConverter = class {
49660
50105
  const lines = ["---"];
49661
50106
  for (const [key, value] of Object.entries(metadata)) {
49662
50107
  if (typeof value === "string") {
49663
- lines.push(`${key}: "${value}"`);
50108
+ const safe = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/[-]/g, " ");
50109
+ lines.push(`${key}: "${safe}"`);
49664
50110
  } else {
49665
50111
  lines.push(`${key}: ${value}`);
49666
50112
  }
@@ -50054,14 +50500,16 @@ var ImageElementProcessor = class {
50054
50500
  console.error(`[image-processor] ${msg}`);
50055
50501
  return `> **[Image extraction failed]** ${imageElement.id} (slide ${ctx.slideNumber})`;
50056
50502
  }
50503
+ const safeAlt = escapeHtml(altText);
50504
+ const safeSrc = escapeHtml(imagePath);
50057
50505
  if (ctx.semanticMode) {
50058
- return `![${altText}](${imagePath})`;
50506
+ return `![${safeAlt}](${imagePath})`;
50059
50507
  }
50060
50508
  if (ctx.layoutScale) {
50061
- return `<img src="${imagePath}" alt="${altText}" style="max-width:100%;height:auto">`;
50509
+ return `<img src="${safeSrc}" alt="${safeAlt}" style="max-width:100%;height:auto">`;
50062
50510
  }
50063
50511
  const dims = this.computeDisplaySize(element.width, element.height);
50064
- return `<img src="${imagePath}" alt="${altText}" width="${dims.w}" height="${dims.h}">`;
50512
+ return `<img src="${safeSrc}" alt="${safeAlt}" width="${dims.w}" height="${dims.h}">`;
50065
50513
  }
50066
50514
  /** Scale element dimensions to a sensible display size, capping width. */
50067
50515
  computeDisplaySize(origW, origH, maxW = 600) {
@@ -50335,6 +50783,59 @@ var SmartArtElementProcessor = class {
50335
50783
  };
50336
50784
 
50337
50785
  // src/converter/elements/TableElementProcessor.ts
50786
+ var SAFE_CSS_NAMED_COLORS = /* @__PURE__ */ new Set([
50787
+ "black",
50788
+ "silver",
50789
+ "gray",
50790
+ "white",
50791
+ "maroon",
50792
+ "red",
50793
+ "purple",
50794
+ "fuchsia",
50795
+ "green",
50796
+ "lime",
50797
+ "olive",
50798
+ "yellow",
50799
+ "navy",
50800
+ "blue",
50801
+ "teal",
50802
+ "aqua",
50803
+ "orange",
50804
+ "transparent",
50805
+ "currentcolor",
50806
+ "inherit",
50807
+ "initial",
50808
+ "unset"
50809
+ ]);
50810
+ function cssColorSafe(value) {
50811
+ if (typeof value !== "string") {
50812
+ return void 0;
50813
+ }
50814
+ const trimmed = value.trim();
50815
+ if (trimmed.length === 0) {
50816
+ return void 0;
50817
+ }
50818
+ if (/^#[0-9a-f]{3,8}$/i.test(trimmed)) {
50819
+ return trimmed;
50820
+ }
50821
+ if (SAFE_CSS_NAMED_COLORS.has(trimmed.toLowerCase())) {
50822
+ return trimmed;
50823
+ }
50824
+ return void 0;
50825
+ }
50826
+ function cssFontFamilySafe(value) {
50827
+ if (typeof value !== "string") {
50828
+ return void 0;
50829
+ }
50830
+ const trimmed = value.trim();
50831
+ if (trimmed.length === 0) {
50832
+ return void 0;
50833
+ }
50834
+ if (/^[a-zA-Z0-9 _\-,'"]{1,80}$/.test(trimmed)) {
50835
+ return trimmed;
50836
+ }
50837
+ return void 0;
50838
+ }
50338
50839
  var TableElementProcessor = class {
50339
50840
  supportedTypes = ["table"];
50340
50841
  async process(element, ctx) {
@@ -50401,27 +50902,29 @@ ${htmlRows.join("\n")}
50401
50902
  }
50402
50903
  const css = this.buildCellCss(cell.style, isHeader);
50403
50904
  if (css) {
50404
- parts.push(` style="${css}"`);
50905
+ parts.push(` style="${escapeHtml(css)}"`);
50405
50906
  }
50406
50907
  return parts.join("");
50407
50908
  }
50408
50909
  /** Converts PptxTableCellStyle to an inline CSS string. */
50409
50910
  buildCellCss(style, isHeader) {
50410
50911
  const rules = [];
50411
- if (style?.backgroundColor) {
50412
- rules.push(`background:${style.backgroundColor}`);
50912
+ const safeBackground = cssColorSafe(style?.backgroundColor);
50913
+ if (safeBackground) {
50914
+ rules.push(`background:${safeBackground}`);
50413
50915
  }
50414
- if (style?.align) {
50916
+ if (style?.align && /^[a-zA-Z]+$/.test(style.align)) {
50415
50917
  rules.push(`text-align:${style.align}`);
50416
50918
  }
50417
- if (style?.vAlign) {
50919
+ if (style?.vAlign && /^[a-zA-Z]+$/.test(style.vAlign)) {
50418
50920
  rules.push(`vertical-align:${style.vAlign}`);
50419
50921
  }
50420
50922
  if (style?.fontSize) {
50421
50923
  rules.push(`font-size:${Math.round(style.fontSize)}px`);
50422
50924
  }
50423
- if (style?.color) {
50424
- rules.push(`color:${style.color}`);
50925
+ const safeColor = cssColorSafe(style?.color);
50926
+ if (safeColor) {
50927
+ rules.push(`color:${safeColor}`);
50425
50928
  }
50426
50929
  if (style?.bold || isHeader) {
50427
50930
  rules.push("font-weight:bold");
@@ -50445,20 +50948,25 @@ ${htmlRows.join("\n")}
50445
50948
  return "";
50446
50949
  }
50447
50950
  const edges = [];
50448
- if (style.borderTopWidth && style.borderTopColor) {
50449
- edges.push(`border-top:${style.borderTopWidth}px solid ${style.borderTopColor}`);
50951
+ const topColor = cssColorSafe(style.borderTopColor);
50952
+ if (style.borderTopWidth && topColor) {
50953
+ edges.push(`border-top:${Math.round(style.borderTopWidth)}px solid ${topColor}`);
50450
50954
  }
50451
- if (style.borderBottomWidth && style.borderBottomColor) {
50452
- edges.push(`border-bottom:${style.borderBottomWidth}px solid ${style.borderBottomColor}`);
50955
+ const bottomColor = cssColorSafe(style.borderBottomColor);
50956
+ if (style.borderBottomWidth && bottomColor) {
50957
+ edges.push(`border-bottom:${Math.round(style.borderBottomWidth)}px solid ${bottomColor}`);
50453
50958
  }
50454
- if (style.borderLeftWidth && style.borderLeftColor) {
50455
- edges.push(`border-left:${style.borderLeftWidth}px solid ${style.borderLeftColor}`);
50959
+ const leftColor = cssColorSafe(style.borderLeftColor);
50960
+ if (style.borderLeftWidth && leftColor) {
50961
+ edges.push(`border-left:${Math.round(style.borderLeftWidth)}px solid ${leftColor}`);
50456
50962
  }
50457
- if (style.borderRightWidth && style.borderRightColor) {
50458
- edges.push(`border-right:${style.borderRightWidth}px solid ${style.borderRightColor}`);
50963
+ const rightColor = cssColorSafe(style.borderRightColor);
50964
+ if (style.borderRightWidth && rightColor) {
50965
+ edges.push(`border-right:${Math.round(style.borderRightWidth)}px solid ${rightColor}`);
50459
50966
  }
50460
- if (edges.length === 0 && style.borderColor) {
50461
- return `border:1px solid ${style.borderColor}`;
50967
+ const fallback = cssColorSafe(style.borderColor);
50968
+ if (edges.length === 0 && fallback) {
50969
+ return `border:1px solid ${fallback}`;
50462
50970
  }
50463
50971
  return edges.join(";");
50464
50972
  }
@@ -50497,7 +51005,7 @@ ${htmlRows.join("\n")}
50497
51005
  }
50498
51006
  const css = this.buildRunCss(seg, cell.style);
50499
51007
  if (css) {
50500
- parts.push(`<span style="${css}">${text}</span>`);
51008
+ parts.push(`<span style="${escapeHtml(css)}">${text}</span>`);
50501
51009
  } else {
50502
51010
  parts.push(text);
50503
51011
  }
@@ -50510,13 +51018,19 @@ ${htmlRows.join("\n")}
50510
51018
  const s = seg.style;
50511
51019
  const rules = [];
50512
51020
  if (s.fontFamily) {
50513
- rules.push(`font-family:${getSubstituteFontFamily(s.fontFamily)}`);
51021
+ const safeFamily = cssFontFamilySafe(getSubstituteFontFamily(s.fontFamily));
51022
+ if (safeFamily) {
51023
+ rules.push(`font-family:${safeFamily}`);
51024
+ }
50514
51025
  }
50515
51026
  if (s.fontSize && s.fontSize !== cellStyle?.fontSize) {
50516
51027
  rules.push(`font-size:${Math.round(s.fontSize)}px`);
50517
51028
  }
50518
51029
  if (s.color && s.color !== cellStyle?.color) {
50519
- rules.push(`color:${s.color}`);
51030
+ const safeColor = cssColorSafe(s.color);
51031
+ if (safeColor) {
51032
+ rules.push(`color:${safeColor}`);
51033
+ }
50520
51034
  }
50521
51035
  if (s.bold && !cellStyle?.bold) {
50522
51036
  rules.push("font-weight:bold");
@@ -50995,7 +51509,7 @@ var TextElementProcessor = class {
50995
51509
  if (fallbackText) {
50996
51510
  const align = textElement.textStyle?.align;
50997
51511
  if (align && align !== "left") {
50998
- parts.push(`<p align="${align}">${fallbackText}</p>`);
51512
+ parts.push(`<p align="${escapeHtml(align)}">${escapeHtml(fallbackText)}</p>`);
50999
51513
  } else {
51000
51514
  parts.push(fallbackText);
51001
51515
  }
@@ -51030,7 +51544,7 @@ var TextElementProcessor = class {
51030
51544
  seen.add(dataUrl);
51031
51545
  try {
51032
51546
  const path = await ctx.mediaContext.saveImage(dataUrl, `slide${ctx.slideNumber}-bullet`);
51033
- extracted.push(`<img src="${path}" alt="Bullet image">`);
51547
+ extracted.push(`<img src="${escapeHtml(path)}" alt="Bullet image">`);
51034
51548
  } catch {
51035
51549
  }
51036
51550
  }
@@ -51055,7 +51569,7 @@ var TextElementProcessor = class {
51055
51569
  if (ctx.semanticMode) {
51056
51570
  return `![Shape fill](${path})`;
51057
51571
  }
51058
- return `<img src="${path}" alt="Shape fill">`;
51572
+ return `<img src="${escapeHtml(path)}" alt="Shape fill">`;
51059
51573
  } catch {
51060
51574
  return null;
51061
51575
  }
@@ -51089,10 +51603,10 @@ var TextElementProcessor = class {
51089
51603
  return `![Shape](${imgPath})`;
51090
51604
  }
51091
51605
  if (ctx.layoutScale) {
51092
- return `<img src="${imgPath}" alt="Shape" style="max-width:100%;height:auto">`;
51606
+ return `<img src="${escapeHtml(imgPath)}" alt="Shape" style="max-width:100%;height:auto">`;
51093
51607
  }
51094
51608
  const dims = this.computeDisplaySize(shape.width, shape.height);
51095
- return `<img src="${imgPath}" alt="Shape" width="${dims.w}" height="${dims.h}">`;
51609
+ return `<img src="${escapeHtml(imgPath)}" alt="Shape" width="${dims.w}" height="${dims.h}">`;
51096
51610
  } catch {
51097
51611
  return null;
51098
51612
  }
@@ -51422,7 +51936,7 @@ var SlideProcessor = class {
51422
51936
  slide.backgroundImage,
51423
51937
  `slide${slide.slideNumber}-bg`
51424
51938
  );
51425
- return `<img src="${path}" alt="Slide background" style="width:100%;height:100%;object-fit:cover">`;
51939
+ return `<img src="${escapeHtml(path)}" alt="Slide background" style="width:100%;height:100%;object-fit:cover">`;
51426
51940
  } catch {
51427
51941
  return void 0;
51428
51942
  }
@@ -52217,10 +52731,11 @@ var TextSegmentRenderer = class {
52217
52731
  text = `<span style="font-variant:small-caps">${text}</span>`;
52218
52732
  }
52219
52733
  if (segment.style.hyperlink) {
52220
- const dest = this.renderLinkDestination(segment.style.hyperlink);
52221
52734
  if (useHtml) {
52222
- text = `<a href="${dest}">${text}</a>`;
52735
+ const safeDest = escapeHtml(safeHrefOrHash(segment.style.hyperlink));
52736
+ text = `<a href="${safeDest}">${text}</a>`;
52223
52737
  } else {
52738
+ const dest = this.renderLinkDestination(segment.style.hyperlink);
52224
52739
  const title = segment.style.hyperlinkTooltip ? ` "${this.escapeLinkTitle(segment.style.hyperlinkTooltip)}"` : "";
52225
52740
  text = `[${text}](${dest}${title})`;
52226
52741
  }
@@ -52600,11 +53115,20 @@ function resolveDefaults(opts) {
52600
53115
  defaultFontSize: opts?.defaultFontSize ?? 18
52601
53116
  };
52602
53117
  }
52603
- var _markerIdCounter = 0;
52604
- function arrowMarkerDef(color) {
52605
- const id = `arrow_${++_markerIdCounter}`;
53118
+ function createRenderContext() {
53119
+ return { defs: [], markerCache: /* @__PURE__ */ new Map(), markerIdCounter: 0 };
53120
+ }
53121
+ function getOrCreateArrowMarker(ctx, color) {
53122
+ const key = color;
53123
+ const cached = ctx.markerCache.get(key);
53124
+ if (cached) {
53125
+ return cached;
53126
+ }
53127
+ const id = `arrow_${++ctx.markerIdCounter}`;
52606
53128
  const svg = `<marker id="${id}" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto" markerUnits="strokeWidth"><polygon points="0 0, 10 3.5, 0 7" fill="${escXml(color)}" /></marker>`;
52607
- return { id, svg };
53129
+ ctx.defs.push(svg);
53130
+ ctx.markerCache.set(key, id);
53131
+ return id;
52608
53132
  }
52609
53133
  function renderTransform(el) {
52610
53134
  const parts = [];
@@ -52644,13 +53168,16 @@ function renderText(el, defaults) {
52644
53168
  textX = el.width - 4;
52645
53169
  }
52646
53170
  if (segments && segments.length > 0) {
52647
- let svg2 = `<text${attrs({
52648
- x: textX,
52649
- "text-anchor": textAnchor,
52650
- "font-family": fontFamily,
52651
- "font-size": fontSize,
52652
- fill: color
52653
- })}>`;
53171
+ const parts2 = [];
53172
+ parts2.push(
53173
+ `<text${attrs({
53174
+ x: textX,
53175
+ "text-anchor": textAnchor,
53176
+ "font-family": fontFamily,
53177
+ "font-size": fontSize,
53178
+ fill: color
53179
+ })}>`
53180
+ );
52654
53181
  let dy = fontSize * 1.2;
52655
53182
  let isFirstSegment = true;
52656
53183
  for (const seg of segments) {
@@ -52687,31 +53214,36 @@ function renderText(el, defaults) {
52687
53214
  if (segStyle.underline) {
52688
53215
  segAttrs["text-decoration"] = "underline";
52689
53216
  }
52690
- svg2 += `<tspan${attrs(segAttrs)}>${escXml(seg.text)}</tspan>`;
53217
+ parts2.push(`<tspan${attrs(segAttrs)}>${escXml(seg.text)}</tspan>`);
52691
53218
  }
52692
- svg2 += `</text>`;
52693
- return svg2;
53219
+ parts2.push(`</text>`);
53220
+ return parts2.join("");
52694
53221
  }
52695
53222
  const bold = style?.bold;
52696
53223
  const italic = style?.italic;
52697
53224
  const lines = text.split("\n");
52698
- let svg = `<text${attrs({
52699
- x: textX,
52700
- "text-anchor": textAnchor,
52701
- "font-family": fontFamily,
52702
- "font-size": fontSize,
52703
- fill: color,
52704
- "font-weight": bold ? "bold" : void 0,
52705
- "font-style": italic ? "italic" : void 0
52706
- })}>`;
52707
- for (let i = 0; i < lines.length; i++) {
52708
- svg += `<tspan${attrs({
53225
+ const parts = [];
53226
+ parts.push(
53227
+ `<text${attrs({
52709
53228
  x: textX,
52710
- dy: i === 0 ? fontSize * 1.2 : fontSize * 1.2
52711
- })}>${escXml(lines[i])}</tspan>`;
53229
+ "text-anchor": textAnchor,
53230
+ "font-family": fontFamily,
53231
+ "font-size": fontSize,
53232
+ fill: color,
53233
+ "font-weight": bold ? "bold" : void 0,
53234
+ "font-style": italic ? "italic" : void 0
53235
+ })}>`
53236
+ );
53237
+ for (let i = 0; i < lines.length; i++) {
53238
+ parts.push(
53239
+ `<tspan${attrs({
53240
+ x: textX,
53241
+ dy: i === 0 ? fontSize * 1.2 : fontSize * 1.2
53242
+ })}>${escXml(lines[i])}</tspan>`
53243
+ );
52712
53244
  }
52713
- svg += `</text>`;
52714
- return svg;
53245
+ parts.push(`</text>`);
53246
+ return parts.join("");
52715
53247
  }
52716
53248
  function renderShapeBody(el) {
52717
53249
  if (el.type !== "shape" && el.type !== "text") {
@@ -52786,7 +53318,7 @@ function renderImageElement(el) {
52786
53318
  preserveAspectRatio: "none"
52787
53319
  })} href="${escXml(imageData)}" />`;
52788
53320
  }
52789
- function renderConnector(el, defs) {
53321
+ function renderConnector(el, ctx) {
52790
53322
  if (el.type !== "connector") {
52791
53323
  return "";
52792
53324
  }
@@ -52796,14 +53328,12 @@ function renderConnector(el, defs) {
52796
53328
  let markerStart;
52797
53329
  let markerEnd;
52798
53330
  if (shapeStyle?.connectorStartArrow && shapeStyle.connectorStartArrow !== "none") {
52799
- const m = arrowMarkerDef(strokeColor);
52800
- defs.push(m.svg);
52801
- markerStart = `url(#${m.id})`;
53331
+ const id = getOrCreateArrowMarker(ctx, strokeColor);
53332
+ markerStart = `url(#${id})`;
52802
53333
  }
52803
53334
  if (shapeStyle?.connectorEndArrow && shapeStyle.connectorEndArrow !== "none") {
52804
- const m = arrowMarkerDef(strokeColor);
52805
- defs.push(m.svg);
52806
- markerEnd = `url(#${m.id})`;
53335
+ const id = getOrCreateArrowMarker(ctx, strokeColor);
53336
+ markerEnd = `url(#${id})`;
52807
53337
  }
52808
53338
  return `<line${attrs({
52809
53339
  x1: 0,
@@ -52827,7 +53357,7 @@ function renderTable(el, defaults) {
52827
53357
  const cols = tableData.columnWidths;
52828
53358
  const numRows = tableData.rows.length;
52829
53359
  const rowHeight = el.height / numRows;
52830
- let svg = "";
53360
+ const parts = [];
52831
53361
  let yOffset = 0;
52832
53362
  for (const row of tableData.rows) {
52833
53363
  const h = row.height ?? rowHeight;
@@ -52844,62 +53374,68 @@ function renderTable(el, defaults) {
52844
53374
  const textColor = cell.style?.color ?? "#000000";
52845
53375
  const fontSize = cell.style?.fontSize ?? defaults.defaultFontSize;
52846
53376
  const bold = cell.style?.bold;
52847
- svg += `<rect${attrs({
52848
- x: xOffset,
52849
- y: yOffset,
52850
- width: cellWidth,
52851
- height: h,
52852
- fill: bgColor,
52853
- stroke: borderColor,
52854
- "stroke-width": 0.5
52855
- })} />`;
53377
+ parts.push(
53378
+ `<rect${attrs({
53379
+ x: xOffset,
53380
+ y: yOffset,
53381
+ width: cellWidth,
53382
+ height: h,
53383
+ fill: bgColor,
53384
+ stroke: borderColor,
53385
+ "stroke-width": 0.5
53386
+ })} />`
53387
+ );
52856
53388
  if (cell.text) {
52857
- svg += `<text${attrs({
52858
- x: xOffset + 4,
52859
- y: yOffset + h / 2,
52860
- "dominant-baseline": "central",
52861
- "font-family": defaults.defaultFontFamily,
52862
- "font-size": fontSize,
52863
- fill: textColor,
52864
- "font-weight": bold ? "bold" : void 0
52865
- })}>${escXml(cell.text)}</text>`;
53389
+ parts.push(
53390
+ `<text${attrs({
53391
+ x: xOffset + 4,
53392
+ y: yOffset + h / 2,
53393
+ "dominant-baseline": "central",
53394
+ "font-family": defaults.defaultFontFamily,
53395
+ "font-size": fontSize,
53396
+ fill: textColor,
53397
+ "font-weight": bold ? "bold" : void 0
53398
+ })}>${escXml(cell.text)}</text>`
53399
+ );
52866
53400
  }
52867
53401
  xOffset += cellWidth;
52868
53402
  }
52869
53403
  yOffset += h;
52870
53404
  }
52871
- return svg;
53405
+ return parts.join("");
52872
53406
  }
52873
- function renderGroup(el, defaults, defs) {
53407
+ function renderGroup(el, defaults, ctx) {
52874
53408
  if (el.type !== "group") {
52875
53409
  return "";
52876
53410
  }
52877
- let inner = "";
53411
+ const parts = [];
52878
53412
  for (const child of el.children) {
52879
- inner += renderElement(child, defaults, defs);
53413
+ parts.push(renderElement(child, defaults, ctx));
52880
53414
  }
52881
- return inner;
53415
+ return parts.join("");
52882
53416
  }
52883
53417
  function renderInk(el) {
52884
53418
  if (el.type !== "ink") {
52885
53419
  return "";
52886
53420
  }
52887
- let svg = "";
53421
+ const parts = [];
52888
53422
  for (let i = 0; i < el.inkPaths.length; i++) {
52889
53423
  const path = el.inkPaths[i];
52890
53424
  const color = el.inkColors?.[i] ?? "#000000";
52891
53425
  const width = el.inkWidths?.[i] ?? 1;
52892
53426
  const opacity = el.inkOpacities?.[i];
52893
- svg += `<path${attrs({
52894
- d: path,
52895
- fill: "none",
52896
- stroke: color,
52897
- "stroke-width": width,
52898
- "stroke-opacity": opacity,
52899
- "stroke-linecap": "round"
52900
- })} />`;
53427
+ parts.push(
53428
+ `<path${attrs({
53429
+ d: path,
53430
+ fill: "none",
53431
+ stroke: color,
53432
+ "stroke-width": width,
53433
+ "stroke-opacity": opacity,
53434
+ "stroke-linecap": "round"
53435
+ })} />`
53436
+ );
52901
53437
  }
52902
- return svg;
53438
+ return parts.join("");
52903
53439
  }
52904
53440
  function renderPlaceholder(el) {
52905
53441
  return `<rect${attrs({
@@ -52919,7 +53455,7 @@ function renderPlaceholder(el) {
52919
53455
  fill: "#999999"
52920
53456
  })}>${escXml(el.type)}</text>`;
52921
53457
  }
52922
- function renderElement(el, defaults, defs) {
53458
+ function renderElement(el, defaults, ctx) {
52923
53459
  if (el.hidden) {
52924
53460
  return "";
52925
53461
  }
@@ -52934,7 +53470,7 @@ function renderElement(el, defaults, defs) {
52934
53470
  inner = renderShapeBody(el) + renderText(el, defaults);
52935
53471
  break;
52936
53472
  case "connector":
52937
- inner = renderConnector(el, defs);
53473
+ inner = renderConnector(el, ctx);
52938
53474
  break;
52939
53475
  case "image":
52940
53476
  case "picture":
@@ -52944,7 +53480,7 @@ function renderElement(el, defaults, defs) {
52944
53480
  inner = renderTable(el, defaults);
52945
53481
  break;
52946
53482
  case "group":
52947
- inner = renderGroup(el, defaults, defs);
53483
+ inner = renderGroup(el, defaults, ctx);
52948
53484
  break;
52949
53485
  case "ink":
52950
53486
  inner = renderInk(el);
@@ -52990,24 +53526,21 @@ var SvgExporter = class _SvgExporter {
52990
53526
  * @returns A complete SVG document as a string.
52991
53527
  */
52992
53528
  static exportSlide(slide, width, height, options) {
52993
- _markerIdCounter = 0;
52994
53529
  const defaults = resolveDefaults(options);
52995
- const defs = [];
52996
- let body = renderBackground(slide, width, height);
53530
+ const ctx = createRenderContext();
53531
+ const bodyParts = [];
53532
+ bodyParts.push(renderBackground(slide, width, height));
52997
53533
  for (const el of slide.elements) {
52998
- body += renderElement(el, defaults, defs);
52999
- }
53000
- let defsBlock = "";
53001
- if (defs.length) {
53002
- defsBlock = `<defs>${defs.join("")}</defs>`;
53534
+ bodyParts.push(renderElement(el, defaults, ctx));
53003
53535
  }
53536
+ const defsBlock = ctx.defs.length ? `<defs>${ctx.defs.join("")}</defs>` : "";
53004
53537
  return `<svg${attrs({
53005
53538
  xmlns: SVG_NS,
53006
53539
  "xmlns:xlink": XLINK_NS,
53007
53540
  viewBox: `0 0 ${width} ${height}`,
53008
53541
  width,
53009
53542
  height
53010
- })}>${defsBlock}${body}</svg>`;
53543
+ })}>${defsBlock}${bodyParts.join("")}</svg>`;
53011
53544
  }
53012
53545
  /**
53013
53546
  * Export all (or selected) slides to SVG XML strings.
@@ -53033,4 +53566,4 @@ var SvgExporter = class _SvgExporter {
53033
53566
  }
53034
53567
  };
53035
53568
 
53036
- export { ALL_ANIMATION_PRESETS, BLIP_FILL_ORDER, COLOR_MAP_ALIAS_KEYS, CONNECTOR_ARROW_OPTIONS, CONNECTOR_GEOMETRY_OPTIONS, ChartBuilder, ConnectorBuilder, ConnectorXmlFactory, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, DEFAULT_COLOR_MAP, DEFAULT_FILL_COLOR, DEFAULT_FONT_FAMILY, DEFAULT_SCHEME_COLOR_MAP, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_COLOR, DEFAULT_TEXT_FONT_SIZE, DIGEST_ALGORITHM_TO_HASH, DIGEST_ALGORITHM_TO_WEB_CRYPTO, DIGITAL_SIGNATURE_ORIGIN_REL_TYPE, DIGITAL_SIGNATURE_REL_TYPE, DataIntegrityError, DocumentConverter, EFFECT_LST_ORDER, EMPHASIS_PRESETS, EMU_PER_INCH, EMU_PER_PIXEL2 as EMU_PER_PIXEL, EMU_PER_POINT, EMU_PER_PX, ENTERPRISE_FAIL_ON_REVOCATION_UNKNOWN_ENV, ENTERPRISE_REQUIRE_REVOCATION_ENV, ENTERPRISE_REQUIRE_TIMESTAMP_ENV, ENTERPRISE_TRUST_ROOTS_FILE_ENV, ENTERPRISE_TRUST_ROOTS_PEM_ENV, ENTRANCE_PRESETS, EXIT_PRESETS, EncryptedFileError, FONT_SUBSTITUTION_MAP, FreeformPathBuilder, GroupBuilder, ImageBuilder, IncorrectPasswordError, MIN_ELEMENT_SIZE, MOTION_PATH_PRESETS, MediaBuilder, MediaContext, MediaGraphicFrameXmlFactory, OPC_RELATIONSHIP_TRANSFORM, Ole2ParseError, P14_GUIDE_URI, P15_GUIDE_URI, PANOSE_FAMILY_MAP, PANOSE_MONOSPACE_PROPORTION, PANOSE_SANS_SERIF_STYLES, PANOSE_WEIGHT_MAP, POWERPOINT_PRESENCE_KEY, PPTX_VIEWER_MANIFEST_NS, PRESET_COLOR_MAP, PRESET_SHAPE_CATEGORY_LABELS, PRESET_SHAPE_CLIP_PATHS, PRESET_SHAPE_DEFINITIONS, PRESET_TO_OOXML, PictureXmlFactory, PptxAnimationWriteService, PptxColorStyleCodec, PptxCommentAuthorsXmlFactory, PptxCommentXmlFactoryProvider, PptxCompatibilityService, PptxConnectorParser, PptxContentTypesBuilder, PptxDocumentPropertiesUpdater, PptxEditorAnimationService, PptxElementTransformUpdater, PptxElementXmlBuilder, PptxGraphicFrameParser, PptxHandler, PptxHandlerRuntime76 as PptxHandlerRuntime, PptxHandlerRuntimeFactory, PptxLoadDataBuilder, PptxMarkdownConverter, PptxMediaDataParser, PptxNativeAnimationService, PptxPresentationSaveBuilder, PptxPresentationSlidesReconciler, PptxRuntimeDependencyFactory, PptxSaveConstantsFactory, PptxSaveState as PptxSaveSession, PptxSaveStateBuilder as PptxSaveSessionBuilder, PptxSaveState, PptxSaveStateBuilder, PptxShapeIdValidator, PptxShapeStyleExtractor, PptxSlideBackgroundBuilder, PptxSlideBuilder, PptxSlideCommentPartWriter, PptxSlideCommentsXmlFactory, PptxSlideElementsBuilder, PptxSlideLoaderService, PptxSlideMediaRelationshipBuilder, PptxSlideNotesBuilder, PptxSlideNotesPartUpdater, PptxSlideRelationshipRegistry, PptxSlideTransitionService, PptxTableDataParser, PptxTemplateBackgroundService, PptxXmlBuilder, PptxXmlFactoryProvider, PptxXmlLookupService, Presentation, PresentationBuilder, SHAPE_TREE_ELEMENT_TAGS, SP_PR_ORDER, STROKE_DASH_OPTIONS, SUPPORTED_XML_CANON_TRANSFORMS, SWITCHABLE_LAYOUT_TYPES, SYSTEM_COLOR_MAP, ShapeBuilder, SlideBuilder, SlideProcessor, SlideSizes, SvgExporter, TC_PR_BORDERS_ORDER, THEME_COLOR_SCHEME_KEYS, THEME_PRESETS, TRANSITION_VALID_DIRECTIONS, TableBuilder, TextBuilder, TextShapeXmlFactory, ThemePresets, VML_SHAPE_TAGS, XMLDSIG_NS, XML_TRANSFORM_ENVELOPED_SIGNATURE, addChartCategory, addChartSeries, addSection, addSmartArtNode, addSmartArtNodeAsChild, applyDrawingColorTransforms, applyKinsokuToXml, applyTemplate, applyThemeToData, areNamespacesSupported, buildCalloutLeaderLineSvgPath, buildClrMapOverrideXml, buildFontFamilyString, buildGuideListExtension, buildLinkedTextBoxChains, buildOle2, buildSingleEffectNode, buildSrgbColorChoice, buildThemeColorMap, catmullRomToBezier, chartDataAddCategory, chartDataAddSeries, chartDataChangeType, chartDataRemoveCategory, chartDataRemoveSeries, chartDataUpdatePoint, checkBlankSlide, checkComplexTables, checkDuplicateTitles, checkLowContrast, checkMissingAltText, checkMissingSlideTitle, checkPresentation, clampUnitInterval, classifyPanose, cloneElement, cloneShapeStyle, cloneSlide, cloneTemplateElementsBySlideId, cloneTextStyle, cloneXmlObject, cm, cmToEmu, colorWithOpacity, colorsEqual, combineShapes, computeContrastRatio, computeCycleLayout, computeDetailStatus, computeDigestBase64 as computeDigestBase64WebCrypto, computeHierarchyLayout, computeLinearLayout, computeMatrixLayout, computePyramidLayout, computeSmartArtLayout, computeSnakeLayout, computeVerificationStatus, convertEmfToDataUrl, convertWmfToDataUrl, convertXmlToStrict, createArrayBufferCopy, createBuiltinVariables, createChartElement, createConnectorElement, createDefaultPptxHandlerRuntime, createEditorId, createFreeformElement, createGroupElement, createImageElement, createLayout, createLayouts, createMediaElement, createModifyVerifier, createPptxSaveConstants, createShapeElement, createTableElement, createTemplateConnectorRawXml, createTemplateShapeRawXml, createTextElement, createUniformTextSegments, dataUrlToMediaBytes, decomposeSmartArt, decryptPptx, demoteSmartArtNode, deobfuscateFont, deriveOutputPath, detectDigitalSignatures, detectFileFormat, detectFontFormat, detectOleObjectType, detectStrictConformance, diffPresentations, diffSlides, distributeSegmentsAcrossChain, douglasPeucker, duplicateElement, duplicateSlide, elementActionToPptxAction, elementHasAction, emuToPixels, encryptPptx, ensureArrayValue, escapeXmlAttr, estimateTextBoxCapacity, evaluateGeometryPaths, evaluateGuides, extractAllTagText, extractColorChoiceXml, extractFirstTagText, extractGuidFromPartName, extractModel3DTransform, extractTagAttribute, fetchUrlToBytes, findCustomShow, findLayoutByName, findLayoutByType, findPlaceholders, findText, formatCommentTimestamp, fragmentShapes, generateFontGuid, generateLayoutXml, generateMediaFilename, getAnimationPresetInfo, getCalloutLeaderLineGeometry, getCalloutTier, getCalloutViewBoxBounds, getCommentMarkerPosition, getConnectorAdjustment, getConnectorPathGeometry, getCssBorderDashStyle, getCustomShowNames, getCustomShowPositionLabel, getDirectory, getElementLabel, getElementTextContent, getElementTransform, getImageMaskStyle, getLinkedTextBoxSegments, getOleObjectTypeLabel, getPanoseWeight, getPresetShapeClipPath, getPresetsByCategory, getRoundRectRadiusPx, getSectionForSlide, getSectionSlideRange, getShapeClipPath, getShapeType, getSignaturePathsToStrip, getSubstituteFontFamily, getSubstituteFonts, getSupportedNamespaces, getSvgStrokeDasharray, getTextCompensationTransform, getThemePreset, getZoomElements, getZoomTargetSlideIndexes, guidToKey, guideEmuToPx, guidePxToEmu, hasDirectSubstitution, hasNonTrivialOverride, hasShapeProperties, hasTextProperties, hexToRgbChannels, hslToRgb, inches, inchesToEmu, inferOleExtensionFromTarget, interpolateShapeGeometry, intersectPolygons, intersectShapes, intersectSvgPaths, isCalloutShape, isConnectorElement, isEditableTextElement, isImageLikeElement, isInkElement, isNamespaceSupported, isShapeElement, isStrictNamespaceUri, isSummaryZoomSlide, isSwitchableLayoutType, isTemplateElement, isTextElement, isTransitionalNamespaceUri, isZoomElement, isZoomElement2 as isZoomElementUtil, layoutEngineShapesToDrawingShapes, mailMerge, mergePresentation, mergeShapes, mergeStyleParts, mergeThemeColorOverride, mm, moveSlidesToSection, navigateCustomShow, normalizeHexColor, normalizeNamespaceUri, normalizePartPath, normalizePath, normalizeStrictXml, normalizeStrokeDashType, obfuscateFont, ooxmlArcToSvg, parseActiveXControlsFromSlide, parseAdjustmentValues, parseBodyPrBooleanAttrs, parseChart3DSurfaces, parseChartAxes, parseCondition, parseConditionList, parseCxChartSeries, parseDataTable, parseDataUrlToBytes, parseDrawingColor, parseDrawingColorChoice, parseDrawingColorOpacity, parseDrawingFraction, parseDrawingHueDegrees, parseDrawingPercent, parseEmbeddedXlsx, parseGuideDefinitions, parseHexColor, parseKinsoku, parseLayoutDefinition, parseLineStyle, parseMarker, parseOle2, parsePanoseBytes, parsePanoseString, parsePresentationDrawingGuides, parseSeriesDataLabels, parseSeriesDataPoints, parseSeriesErrBars, parseSeriesExplosion, parseSeriesTrendlines, parseShapeProps, parseSignatureXml, parseSlideDrawingGuides, parseSvgPath, parseVmlElement, parseVmlElements, pixelsToEmu, polygonsToSvgPath, pptxActionToElementAction, promoteSmartArtNode, pt, reResolveSlideColors, readFileAsDataUrl, reflowSmartArtLayout, relativeLuminance, relayoutSmartArt, removeChartCategory, removeChartSeries, removeSection, removeSmartArtNode, reorderObjectKeys, reorderSections, reorderSmartArtNode, reorderSmartArtNodeToIndex, repairPptx, replaceShapeGeometry, replaceText, replaceTextInSlide, replaceWithCustomGeometry, resetCloneIdCounter, resetDecomposeCounter, resetIdCounter, resetSectionIdCounter, resetSmartArtEditCounter, resolveCoordinate, resolveCustomShowSlideIndices, resolveModel3DMimeType, resolveReferenceUriToPart, resolveTableCellStyle, rgbToHsl, selectAlternateContentBranch, serializeColorChoice, serializeCondition, serializeConditionList, serializeSvgPath, setChartCategories, setChartGrouping, setChartTitle, setChartType, shouldRenderFallbackLabel, shouldReturnToZoomSlide, subtractPolygons, subtractShapes, subtractSvgPaths, svgPathToPolygons, switchSmartArtLayout, toHex, toStrictNamespaceUri, unionPolygons, unionShapes, unionSvgPaths, unwrapAlternateContent, updateChartDataPoint, updateChartSeriesValues, updateSmartArtNodeText, validatePptx, verifyModifyPassword, verifyPassword, verifySignatureDigests, writeBodyPrBooleanAttrs };
53569
+ export { ALL_ANIMATION_PRESETS, BLIP_FILL_ORDER, COLOR_MAP_ALIAS_KEYS, CONNECTOR_ARROW_OPTIONS, CONNECTOR_GEOMETRY_OPTIONS, ChartBuilder, ConnectorBuilder, ConnectorXmlFactory, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, DEFAULT_COLOR_MAP, DEFAULT_FILL_COLOR, DEFAULT_FONT_FAMILY, DEFAULT_MAX_UNCOMPRESSED_BYTES, DEFAULT_SCHEME_COLOR_MAP, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_COLOR, DEFAULT_TEXT_FONT_SIZE, DIGEST_ALGORITHM_TO_HASH, DIGEST_ALGORITHM_TO_WEB_CRYPTO, DIGITAL_SIGNATURE_ORIGIN_REL_TYPE, DIGITAL_SIGNATURE_REL_TYPE, DataIntegrityError, DocumentConverter, EFFECT_LST_ORDER, EMPHASIS_PRESETS, EMU_PER_INCH, EMU_PER_PIXEL2 as EMU_PER_PIXEL, EMU_PER_POINT, EMU_PER_PX, ENTERPRISE_FAIL_ON_REVOCATION_UNKNOWN_ENV, ENTERPRISE_REQUIRE_REVOCATION_ENV, ENTERPRISE_REQUIRE_TIMESTAMP_ENV, ENTERPRISE_TRUST_ROOTS_FILE_ENV, ENTERPRISE_TRUST_ROOTS_PEM_ENV, ENTRANCE_PRESETS, EXIT_PRESETS, EncryptedFileError, FONT_SUBSTITUTION_MAP, FreeformPathBuilder, GroupBuilder, ImageBuilder, IncorrectPasswordError, MAX_ZIP_ENTRY_COUNT, MIN_ELEMENT_SIZE, MOTION_PATH_PRESETS, MediaBuilder, MediaContext, MediaGraphicFrameXmlFactory, OPC_RELATIONSHIP_TRANSFORM, Ole2ParseError, P14_GUIDE_URI, P15_GUIDE_URI, PANOSE_FAMILY_MAP, PANOSE_MONOSPACE_PROPORTION, PANOSE_SANS_SERIF_STYLES, PANOSE_WEIGHT_MAP, POWERPOINT_PRESENCE_KEY, PPTX_VIEWER_MANIFEST_NS, PRESET_COLOR_MAP, PRESET_SHAPE_CATEGORY_LABELS, PRESET_SHAPE_CLIP_PATHS, PRESET_SHAPE_DEFINITIONS, PRESET_TO_OOXML, PictureXmlFactory, PptxAnimationWriteService, PptxColorStyleCodec, PptxCommentAuthorsXmlFactory, PptxCommentXmlFactoryProvider, PptxCompatibilityService, PptxConnectorParser, PptxContentTypesBuilder, PptxDocumentPropertiesUpdater, PptxEditorAnimationService, PptxElementTransformUpdater, PptxElementXmlBuilder, PptxGraphicFrameParser, PptxHandler, PptxHandlerRuntime76 as PptxHandlerRuntime, PptxHandlerRuntimeFactory, PptxLoadDataBuilder, PptxMarkdownConverter, PptxMediaDataParser, PptxNativeAnimationService, PptxPresentationSaveBuilder, PptxPresentationSlidesReconciler, PptxRuntimeDependencyFactory, PptxSaveConstantsFactory, PptxSaveState as PptxSaveSession, PptxSaveStateBuilder as PptxSaveSessionBuilder, PptxSaveState, PptxSaveStateBuilder, PptxShapeIdValidator, PptxShapeStyleExtractor, PptxSlideBackgroundBuilder, PptxSlideBuilder, PptxSlideCommentPartWriter, PptxSlideCommentsXmlFactory, PptxSlideElementsBuilder, PptxSlideLoaderService, PptxSlideMediaRelationshipBuilder, PptxSlideNotesBuilder, PptxSlideNotesPartUpdater, PptxSlideRelationshipRegistry, PptxSlideTransitionService, PptxTableDataParser, PptxTemplateBackgroundService, PptxXmlBuilder, PptxXmlFactoryProvider, PptxXmlLookupService, Presentation, PresentationBuilder, SHAPE_TREE_ELEMENT_TAGS, SP_PR_ORDER, STROKE_DASH_OPTIONS, SUPPORTED_XML_CANON_TRANSFORMS, SWITCHABLE_LAYOUT_TYPES, SYSTEM_COLOR_MAP, ShapeBuilder, SlideBuilder, SlideProcessor, SlideSizes, SvgExporter, TC_PR_BORDERS_ORDER, THEME_COLOR_SCHEME_KEYS, THEME_PRESETS, TRANSITION_VALID_DIRECTIONS, TableBuilder, TextBuilder, TextShapeXmlFactory, ThemePresets, VML_SHAPE_TAGS, XMLDSIG_NS, XML_TRANSFORM_ENVELOPED_SIGNATURE, ZipBombError, addChartCategory, addChartSeries, addSection, addSmartArtNode, addSmartArtNodeAsChild, applyDrawingColorTransforms, applyKinsokuToXml, applyTemplate, applyThemeToData, areNamespacesSupported, buildCalloutLeaderLineSvgPath, buildClrMapOverrideXml, buildFontFamilyString, buildGuideListExtension, buildLinkedTextBoxChains, buildOle2, buildSingleEffectNode, buildSrgbColorChoice, buildThemeColorMap, catmullRomToBezier, chartDataAddCategory, chartDataAddSeries, chartDataChangeType, chartDataRemoveCategory, chartDataRemoveSeries, chartDataUpdatePoint, checkBlankSlide, checkComplexTables, checkDuplicateTitles, checkLowContrast, checkMissingAltText, checkMissingSlideTitle, checkPresentation, clampUnitInterval, classifyPanose, cloneElement, cloneShapeStyle, cloneSlide, cloneTemplateElementsBySlideId, cloneTextStyle, cloneXmlObject, cm, cmToEmu, colorWithOpacity, colorsEqual, combineShapes, computeContrastRatio, computeCycleLayout, computeDetailStatus, computeDigestBase64 as computeDigestBase64WebCrypto, computeHierarchyLayout, computeLinearLayout, computeMatrixLayout, computePyramidLayout, computeSmartArtLayout, computeSnakeLayout, computeVerificationStatus, convertEmfToDataUrl, convertWmfToDataUrl, convertXmlToStrict, createArrayBufferCopy, createBuiltinVariables, createChartElement, createConnectorElement, createDefaultPptxHandlerRuntime, createEditorId, createFreeformElement, createGroupElement, createImageElement, createLayout, createLayouts, createMediaElement, createModifyVerifier, createPptxSaveConstants, createShapeElement, createTableElement, createTemplateConnectorRawXml, createTemplateShapeRawXml, createTextElement, createUniformTextSegments, dataUrlToMediaBytes, decomposeSmartArt, decryptPptx, demoteSmartArtNode, deobfuscateFont, deriveOutputPath, detectDigitalSignatures, detectFileFormat, detectFontFormat, detectOleObjectType, detectStrictConformance, diffPresentations, diffSlides, distributeSegmentsAcrossChain, douglasPeucker, duplicateElement, duplicateSlide, elementActionToPptxAction, elementHasAction, emuToPixels, encryptPptx, ensureArrayValue, escapeXmlAttr, escapeXmlText, estimateTextBoxCapacity, evaluateGeometryPaths, evaluateGuides, extractAllTagText, extractColorChoiceXml, extractFirstTagText, extractGuidFromPartName, extractModel3DTransform, extractTagAttribute, fetchUrlToBytes, findCustomShow, findLayoutByName, findLayoutByType, findPlaceholders, findText, formatCommentTimestamp, fragmentShapes, generateFontGuid, generateLayoutXml, generateMediaFilename, getAnimationPresetInfo, getCalloutLeaderLineGeometry, getCalloutTier, getCalloutViewBoxBounds, getCommentMarkerPosition, getConnectorAdjustment, getConnectorPathGeometry, getCssBorderDashStyle, getCustomShowNames, getCustomShowPositionLabel, getDirectory, getElementLabel, getElementTextContent, getElementTransform, getImageMaskStyle, getLinkedTextBoxSegments, getOleObjectTypeLabel, getPanoseWeight, getPresetShapeClipPath, getPresetsByCategory, getRoundRectRadiusPx, getSectionForSlide, getSectionSlideRange, getShapeClipPath, getShapeType, getSignaturePathsToStrip, getSubstituteFontFamily, getSubstituteFonts, getSupportedNamespaces, getSvgStrokeDasharray, getTextCompensationTransform, getThemePreset, getZoomElements, getZoomTargetSlideIndexes, guidToKey, guideEmuToPx, guidePxToEmu, hasDirectSubstitution, hasNonTrivialOverride, hasShapeProperties, hasTextProperties, hexToRgbChannels, hslToRgb, inches, inchesToEmu, inferOleExtensionFromTarget, interpolateShapeGeometry, intersectPolygons, intersectShapes, intersectSvgPaths, isCalloutShape, isConnectorElement, isEditableTextElement, isImageLikeElement, isInkElement, isNamespaceSupported, isShapeElement, isStrictNamespaceUri, isSummaryZoomSlide, isSwitchableLayoutType, isTemplateElement, isTextElement, isTransitionalNamespaceUri, isValidBase64, isZoomElement, isZoomElement2 as isZoomElementUtil, layoutEngineShapesToDrawingShapes, mailMerge, mergePresentation, mergeShapes, mergeStyleParts, mergeThemeColorOverride, mm, moveSlidesToSection, navigateCustomShow, normalizeHexColor, normalizeNamespaceUri, normalizePartPath, normalizePath, normalizeStrictXml, normalizeStrokeDashType, obfuscateFont, ooxmlArcToSvg, parseActiveXControlsFromSlide, parseAdjustmentValues, parseBodyPrBooleanAttrs, parseChart3DSurfaces, parseChartAxes, parseCondition, parseConditionList, parseCxChartSeries, parseDataTable, parseDataUrlToBytes, parseDrawingColor, parseDrawingColorChoice, parseDrawingColorOpacity, parseDrawingFraction, parseDrawingHueDegrees, parseDrawingPercent, parseEmbeddedXlsx, parseGuideDefinitions, parseHexColor, parseKinsoku, parseLayoutDefinition, parseLineStyle, parseMarker, parseOle2, parsePanoseBytes, parsePanoseString, parsePresentationDrawingGuides, parseSeriesDataLabels, parseSeriesDataPoints, parseSeriesErrBars, parseSeriesExplosion, parseSeriesTrendlines, parseShapeProps, parseSignatureXml, parseSlideDrawingGuides, parseSvgPath, parseVmlElement, parseVmlElements, pixelsToEmu, polygonsToSvgPath, pptxActionToElementAction, promoteSmartArtNode, pt, reResolveSlideColors, readFileAsDataUrl, reflowSmartArtLayout, relativeLuminance, relayoutSmartArt, removeChartCategory, removeChartSeries, removeSection, removeSmartArtNode, reorderObjectKeys, reorderSections, reorderSmartArtNode, reorderSmartArtNodeToIndex, repairPptx, replaceShapeGeometry, replaceText, replaceTextInSlide, replaceWithCustomGeometry, resetCloneIdCounter, resetDecomposeCounter, resetIdCounter, resetSectionIdCounter, resetSmartArtEditCounter, resolveCoordinate, resolveCustomShowSlideIndices, resolveModel3DMimeType, resolveReferenceUriToPart, resolveTableCellStyle, rgbToHsl, selectAlternateContentBranch, serializeColorChoice, serializeCondition, serializeConditionList, serializeSvgPath, setChartCategories, setChartGrouping, setChartTitle, setChartType, shouldRenderFallbackLabel, shouldReturnToZoomSlide, subtractPolygons, subtractShapes, subtractSvgPaths, svgPathToPolygons, switchSmartArtLayout, toHex, toStrictNamespaceUri, unionPolygons, unionShapes, unionSvgPaths, unwrapAlternateContent, updateChartDataPoint, updateChartSeriesValues, updateSmartArtNodeText, validatePptx, verifyModifyPassword, verifyPassword, verifySignatureDigests, writeBodyPrBooleanAttrs };