pptx-react-viewer 1.1.1 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/{PowerPointViewer-DtLlYf0r.d.mts → PowerPointViewer-CX0a7wz_.d.mts} +2 -0
  2. package/dist/{PowerPointViewer-DtLlYf0r.d.ts → PowerPointViewer-CX0a7wz_.d.ts} +2 -0
  3. package/dist/index.d.mts +2 -2
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.js +373 -64
  6. package/dist/index.mjs +373 -64
  7. package/dist/pptx-viewer.css +1 -1
  8. package/dist/viewer/index.d.mts +11 -3
  9. package/dist/viewer/index.d.ts +11 -3
  10. package/dist/viewer/index.js +373 -64
  11. package/dist/viewer/index.mjs +373 -64
  12. package/node_modules/emf-converter/package.json +1 -1
  13. package/node_modules/mtx-decompressor/dist/index.d.mts +2 -1
  14. package/node_modules/mtx-decompressor/dist/index.d.ts +2 -1
  15. package/node_modules/mtx-decompressor/dist/index.js +85 -93
  16. package/node_modules/mtx-decompressor/dist/index.mjs +85 -93
  17. package/node_modules/mtx-decompressor/package.json +1 -1
  18. package/node_modules/pptx-viewer-core/dist/{SvgExporter-CPr1npgo.d.ts → SvgExporter-BMjoxMDV.d.ts} +1 -1
  19. package/node_modules/pptx-viewer-core/dist/{SvgExporter-B4-1_Hjp.d.mts → SvgExporter-z6AbXRQg.d.mts} +1 -1
  20. package/node_modules/pptx-viewer-core/dist/cli/index.d.mts +2 -2
  21. package/node_modules/pptx-viewer-core/dist/cli/index.d.ts +2 -2
  22. package/node_modules/pptx-viewer-core/dist/cli/index.js +504 -253
  23. package/node_modules/pptx-viewer-core/dist/cli/index.mjs +504 -253
  24. package/node_modules/pptx-viewer-core/dist/converter/index.d.mts +3 -3
  25. package/node_modules/pptx-viewer-core/dist/converter/index.d.ts +3 -3
  26. package/node_modules/pptx-viewer-core/dist/index.d.mts +318 -6
  27. package/node_modules/pptx-viewer-core/dist/index.d.ts +318 -6
  28. package/node_modules/pptx-viewer-core/dist/index.js +1474 -253
  29. package/node_modules/pptx-viewer-core/dist/index.mjs +1450 -254
  30. package/node_modules/pptx-viewer-core/dist/{presentation-DgkIYhXo.d.mts → presentation-CchuDGfU.d.mts} +17 -1
  31. package/node_modules/pptx-viewer-core/dist/{presentation-DgkIYhXo.d.ts → presentation-CchuDGfU.d.ts} +17 -1
  32. package/node_modules/pptx-viewer-core/dist/{text-operations-dYKZp3zE.d.mts → text-operations-CeukUztU.d.mts} +1 -1
  33. package/node_modules/pptx-viewer-core/dist/{text-operations-B6U6XxWt.d.ts → text-operations-e7JxgI5l.d.ts} +1 -1
  34. package/node_modules/pptx-viewer-core/package.json +1 -1
  35. package/package.json +4 -4
@@ -1447,7 +1447,11 @@ function isoNow() {
1447
1447
  return (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d+Z$/, "Z");
1448
1448
  }
1449
1449
  var STANDARD_LAYOUTS = [
1450
- { name: "Title Slide", type: "ctrTitle" },
1450
+ // `type` is ST_SlideLayoutType per ECMA-376 §19.7.15. The Title Slide
1451
+ // layout uses `title`; `ctrTitle` is a placeholder type (ST_PlaceholderType)
1452
+ // and is not valid here — PowerPoint's OPC loader rejects the package
1453
+ // with ERROR_FILE_CORRUPT (0x80070570) when it sees it.
1454
+ { name: "Title Slide", type: "title" },
1451
1455
  { name: "Title and Content", type: "obj" },
1452
1456
  { name: "Section Header", type: "secHead" },
1453
1457
  { name: "Two Content", type: "twoObj" },
@@ -1481,7 +1485,7 @@ ${slideOverrides}
1481
1485
  <Override PartName="/ppt/viewProps.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml"/>
1482
1486
  <Override PartName="/ppt/tableStyles.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml"/>
1483
1487
  <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
1484
- <Override PartName="/docProps/app.xml" ContentType="application/vnd.ms-officedocument.extended-properties+xml"/>
1488
+ <Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
1485
1489
  </Types>`;
1486
1490
  }
1487
1491
  function rootRelsXml() {
@@ -2540,33 +2544,10 @@ var PptxPresentationSaveBuilder = class {
2540
2544
  init.presentationData["p:presentation"] = presentation;
2541
2545
  return init.presentationData;
2542
2546
  }
2543
- applyHeaderFooter(presentation, headerFooter) {
2544
- if (!headerFooter) {
2545
- return;
2546
- }
2547
- const hf = presentation["p:hf"] || {};
2548
- if (headerFooter.hasHeader !== void 0) {
2549
- hf["@_hdr"] = headerFooter.hasHeader ? "1" : "0";
2550
- }
2551
- if (headerFooter.hasFooter !== void 0) {
2552
- hf["@_ftr"] = headerFooter.hasFooter ? "1" : "0";
2553
- }
2554
- if (headerFooter.hasDateTime !== void 0) {
2555
- hf["@_dt"] = headerFooter.hasDateTime ? "1" : "0";
2556
- }
2557
- if (headerFooter.hasSlideNumber !== void 0) {
2558
- hf["@_sldNum"] = headerFooter.hasSlideNumber ? "1" : "0";
2547
+ applyHeaderFooter(presentation, _headerFooter) {
2548
+ if (presentation["p:hf"] !== void 0) {
2549
+ delete presentation["p:hf"];
2559
2550
  }
2560
- if (headerFooter.footerText !== void 0) {
2561
- hf["@_ftrText"] = headerFooter.footerText;
2562
- }
2563
- if (headerFooter.dateTimeText !== void 0) {
2564
- hf["@_dtText"] = headerFooter.dateTimeText;
2565
- }
2566
- if (headerFooter.dateFormat !== void 0) {
2567
- hf["@_dtFmt"] = headerFooter.dateFormat;
2568
- }
2569
- presentation["p:hf"] = hf;
2570
2551
  }
2571
2552
  applySlideDimensions(presentation, rawSlideWidthEmu, rawSlideHeightEmu, rawSlideSizeType) {
2572
2553
  const slideSize = presentation["p:sldSz"];
@@ -2830,9 +2811,40 @@ var PptxPresentationSlidesReconciler = class {
2830
2811
  "@_r:id": slide.rId
2831
2812
  };
2832
2813
  });
2833
- presentation["p:sldIdLst"] = slideIdList;
2834
- input.presentationData["p:presentation"] = presentation;
2814
+ input.presentationData["p:presentation"] = this.insertSlideIdListInOrder(
2815
+ presentation,
2816
+ slideIdList
2817
+ );
2818
+ }
2819
+ }
2820
+ /**
2821
+ * Return a new presentation XML object whose `p:sldIdLst` child sits in the
2822
+ * schema-mandated position (after `sldMasterIdLst` / `notesMasterIdLst` /
2823
+ * `handoutMasterIdLst`, before `sldSz`). Non-sldIdLst keys keep their
2824
+ * relative order; attribute keys (`@_...`) stay at the front.
2825
+ */
2826
+ insertSlideIdListInOrder(presentation, slideIdList) {
2827
+ const before = /* @__PURE__ */ new Set([
2828
+ "p:sldMasterIdLst",
2829
+ "p:notesMasterIdLst",
2830
+ "p:handoutMasterIdLst"
2831
+ ]);
2832
+ const rebuilt = {};
2833
+ let inserted = false;
2834
+ for (const key of Object.keys(presentation)) {
2835
+ if (key === "p:sldIdLst") {
2836
+ continue;
2837
+ }
2838
+ if (!inserted && !key.startsWith("@_") && !before.has(key)) {
2839
+ rebuilt["p:sldIdLst"] = slideIdList;
2840
+ inserted = true;
2841
+ }
2842
+ rebuilt[key] = presentation[key];
2835
2843
  }
2844
+ if (!inserted) {
2845
+ rebuilt["p:sldIdLst"] = slideIdList;
2846
+ }
2847
+ return rebuilt;
2836
2848
  }
2837
2849
  async attachNewSlide(init) {
2838
2850
  const sourceSlidePath = init.input.findSourceSlidePath(init.slide.sourceSlideId);
@@ -3242,7 +3254,9 @@ var PptxSlideNotesPartUpdater = class {
3242
3254
  var PptxSlideBackgroundBuilder = class {
3243
3255
  applyBackground(init) {
3244
3256
  const hasBackgroundColor = typeof init.slide.backgroundColor === "string" && init.slide.backgroundColor.length > 0 && init.slide.backgroundColor !== "transparent";
3245
- const hasBackgroundImage = typeof init.slide.backgroundImage === "string" && init.slide.backgroundImage.length > 0;
3257
+ const rawBackgroundImage = typeof init.slide.backgroundImage === "string" ? init.slide.backgroundImage : "";
3258
+ const hasBackgroundImage = rawBackgroundImage.length > 0;
3259
+ const hasDataUrlBackgroundImage = hasBackgroundImage && rawBackgroundImage.startsWith("data:");
3246
3260
  const hasBackgroundGradient = typeof init.slide.backgroundGradient === "string" && init.slide.backgroundGradient.length > 0;
3247
3261
  const cSld = init.slideNode["p:cSld"] || {};
3248
3262
  if (!(hasBackgroundColor || hasBackgroundImage || hasBackgroundGradient)) {
@@ -3250,9 +3264,17 @@ var PptxSlideBackgroundBuilder = class {
3250
3264
  init.slideNode["p:cSld"] = cSld;
3251
3265
  return;
3252
3266
  }
3267
+ const existingBg = cSld["p:bg"];
3268
+ const existingBgPr = existingBg?.["p:bgPr"];
3269
+ const existingHasBlipFill = existingBgPr?.["a:blipFill"] !== void 0;
3270
+ if (!hasDataUrlBackgroundImage && existingHasBlipFill) {
3271
+ this.reorderCSldBgFirst(cSld, existingBg);
3272
+ init.slideNode["p:cSld"] = cSld;
3273
+ return;
3274
+ }
3253
3275
  const backgroundProperties = {};
3254
- if (hasBackgroundImage && init.slide.backgroundImage) {
3255
- const parsedBackgroundImage = init.parseDataUrlToBytes(init.slide.backgroundImage);
3276
+ if (hasDataUrlBackgroundImage) {
3277
+ const parsedBackgroundImage = init.parseDataUrlToBytes(rawBackgroundImage);
3256
3278
  if (parsedBackgroundImage) {
3257
3279
  const backgroundImagePath = init.saveState.nextMediaPath(parsedBackgroundImage.extension);
3258
3280
  init.zip.file(backgroundImagePath, parsedBackgroundImage.bytes);
@@ -3275,9 +3297,42 @@ var PptxSlideBackgroundBuilder = class {
3275
3297
  }
3276
3298
  };
3277
3299
  }
3278
- backgroundProperties["a:effectLst"] = {};
3279
- cSld["p:bg"] = { "p:bgPr": backgroundProperties };
3280
- init.slideNode["p:cSld"] = cSld;
3300
+ const hasFillChild = backgroundProperties["a:blipFill"] !== void 0 || backgroundProperties["a:solidFill"] !== void 0 || backgroundProperties["a:gradFill"] !== void 0 || backgroundProperties["a:pattFill"] !== void 0 || backgroundProperties["a:noFill"] !== void 0 || backgroundProperties["a:grpFill"] !== void 0;
3301
+ if (hasFillChild) {
3302
+ backgroundProperties["a:effectLst"] = {};
3303
+ }
3304
+ if (!hasFillChild) {
3305
+ delete cSld["p:bg"];
3306
+ init.slideNode["p:cSld"] = cSld;
3307
+ return;
3308
+ }
3309
+ const rebuiltCSld = { "p:bg": { "p:bgPr": backgroundProperties } };
3310
+ for (const key of Object.keys(cSld)) {
3311
+ if (key === "p:bg") {
3312
+ continue;
3313
+ }
3314
+ rebuiltCSld[key] = cSld[key];
3315
+ }
3316
+ init.slideNode["p:cSld"] = rebuiltCSld;
3317
+ }
3318
+ reorderCSldBgFirst(cSld, bg) {
3319
+ const keys = Object.keys(cSld);
3320
+ if (keys.length > 0 && keys[0] === "p:bg") {
3321
+ return;
3322
+ }
3323
+ const reordered = { "p:bg": bg };
3324
+ for (const key of keys) {
3325
+ if (key === "p:bg") {
3326
+ continue;
3327
+ }
3328
+ reordered[key] = cSld[key];
3329
+ }
3330
+ for (const key of Object.keys(cSld)) {
3331
+ delete cSld[key];
3332
+ }
3333
+ for (const key of Object.keys(reordered)) {
3334
+ cSld[key] = reordered[key];
3335
+ }
3281
3336
  }
3282
3337
  };
3283
3338
 
@@ -6250,6 +6305,7 @@ var PptxConnectorParser = class {
6250
6305
  slideRelationships,
6251
6306
  this.context.getOrderedSlidePaths()
6252
6307
  );
6308
+ const connElementName = cNvPr?.["@_name"] ? String(cNvPr["@_name"]).trim() : void 0;
6253
6309
  const locks = this.context.parseShapeLocks(
6254
6310
  cNvConnectionShapeProperties?.["a:cxnSpLocks"] ?? cNvConnectionShapeProperties?.["a:spLocks"]
6255
6311
  );
@@ -6257,6 +6313,7 @@ var PptxConnectorParser = class {
6257
6313
  const textResult = this.context.parseConnectorTextBody?.(txBody, slidePath);
6258
6314
  return {
6259
6315
  id,
6316
+ name: connElementName || void 0,
6260
6317
  type: "connector",
6261
6318
  x: Math.round(parseInt(String(offset["@_x"] || "0"), 10) / this.context.emuPerPx),
6262
6319
  y: Math.round(parseInt(String(offset["@_y"] || "0"), 10) / this.context.emuPerPx),
@@ -9827,7 +9884,16 @@ var PptxRuntimeDependencyFactory = class {
9827
9884
  return new fastXmlParser.XMLParser({
9828
9885
  ignoreAttributes: false,
9829
9886
  attributeNamePrefix: "@_",
9830
- parseAttributeValue: false
9887
+ parseAttributeValue: false,
9888
+ // Keep element text as strings. When true (the fast-xml-parser
9889
+ // default), `<AppVersion>16.0000</AppVersion>` is coerced to the
9890
+ // JS number 16, losing the trailing zeros. On save we write back
9891
+ // "16", which fails PowerPoint's strict `[0-9]+\.[0-9]{4}` match
9892
+ // on AppVersion — the loader rejects the package with HRESULT
9893
+ // 0x80070570 (ERROR_FILE_CORRUPT) and shows the repair dialog.
9894
+ // More generally, OOXML element text is always an untyped string;
9895
+ // downstream callers coerce where needed.
9896
+ parseTagValue: false
9831
9897
  });
9832
9898
  }
9833
9899
  createBuilder() {
@@ -10695,7 +10761,7 @@ var TRIPLET_ENCODINGS = [
10695
10761
  { byteCount: 2, xBits: 4, yBits: 4, deltaX: 49, deltaY: 49, xSign: 1, ySign: -1 },
10696
10762
  { byteCount: 2, xBits: 4, yBits: 4, deltaX: 49, deltaY: 49, xSign: -1, ySign: 1 },
10697
10763
  { byteCount: 2, xBits: 4, yBits: 4, deltaX: 49, deltaY: 49, xSign: 1, ySign: 1 },
10698
- // Indices 84-107: 8-bit X + 8-bit Y (3 bytes total)
10764
+ // Indices 84-119: 8-bit X + 8-bit Y (3 bytes total)
10699
10765
  { byteCount: 3, xBits: 8, yBits: 8, deltaX: 1, deltaY: 1, xSign: -1, ySign: -1 },
10700
10766
  { byteCount: 3, xBits: 8, yBits: 8, deltaX: 1, deltaY: 1, xSign: 1, ySign: -1 },
10701
10767
  { byteCount: 3, xBits: 8, yBits: 8, deltaX: 1, deltaY: 1, xSign: -1, ySign: 1 },
@@ -10732,12 +10798,12 @@ var TRIPLET_ENCODINGS = [
10732
10798
  { byteCount: 3, xBits: 8, yBits: 8, deltaX: 513, deltaY: 513, xSign: 1, ySign: -1 },
10733
10799
  { byteCount: 3, xBits: 8, yBits: 8, deltaX: 513, deltaY: 513, xSign: -1, ySign: 1 },
10734
10800
  { byteCount: 3, xBits: 8, yBits: 8, deltaX: 513, deltaY: 513, xSign: 1, ySign: 1 },
10735
- // Indices 108-111: 12-bit X + 12-bit Y (4 bytes total)
10801
+ // Indices 120-123: 12-bit X + 12-bit Y (4 bytes total)
10736
10802
  { byteCount: 4, xBits: 12, yBits: 12, deltaX: 0, deltaY: 0, xSign: -1, ySign: -1 },
10737
10803
  { byteCount: 4, xBits: 12, yBits: 12, deltaX: 0, deltaY: 0, xSign: 1, ySign: -1 },
10738
10804
  { byteCount: 4, xBits: 12, yBits: 12, deltaX: 0, deltaY: 0, xSign: -1, ySign: 1 },
10739
10805
  { byteCount: 4, xBits: 12, yBits: 12, deltaX: 0, deltaY: 0, xSign: 1, ySign: 1 },
10740
- // Indices 112-115: 16-bit X + 16-bit Y (5 bytes total)
10806
+ // Indices 124-127: 16-bit X + 16-bit Y (5 bytes total)
10741
10807
  { byteCount: 5, xBits: 16, yBits: 16, deltaX: 0, deltaY: 0, xSign: -1, ySign: -1 },
10742
10808
  { byteCount: 5, xBits: 16, yBits: 16, deltaX: 0, deltaY: 0, xSign: 1, ySign: -1 },
10743
10809
  { byteCount: 5, xBits: 16, yBits: 16, deltaX: 0, deltaY: 0, xSign: -1, ySign: 1 },
@@ -10826,14 +10892,15 @@ function decodePushInstructions(sIn, sOut, pushCount) {
10826
10892
  if (pushCount === 0) {
10827
10893
  return;
10828
10894
  }
10829
- const values = [];
10830
- let isShort = false;
10895
+ const data = [];
10831
10896
  let remaining = pushCount;
10897
+ let isShort = false;
10898
+ const runValues = [];
10832
10899
  function flush() {
10833
- if (values.length === 0) {
10900
+ if (runValues.length === 0) {
10834
10901
  return;
10835
10902
  }
10836
- const count = values.length;
10903
+ const count = runValues.length;
10837
10904
  if (isShort) {
10838
10905
  if (count < 8) {
10839
10906
  sOut.writeU8(PUSHW + (count - 1));
@@ -10841,7 +10908,7 @@ function decodePushInstructions(sIn, sOut, pushCount) {
10841
10908
  sOut.writeU8(NPUSHW);
10842
10909
  sOut.writeU8(count);
10843
10910
  }
10844
- for (const v of values) {
10911
+ for (const v of runValues) {
10845
10912
  sOut.writeS16(v);
10846
10913
  }
10847
10914
  } else {
@@ -10851,54 +10918,50 @@ function decodePushInstructions(sIn, sOut, pushCount) {
10851
10918
  sOut.writeU8(NPUSHB);
10852
10919
  sOut.writeU8(count);
10853
10920
  }
10854
- for (const v of values) {
10921
+ for (const v of runValues) {
10855
10922
  sOut.writeU8(v & 255);
10856
10923
  }
10857
10924
  }
10858
- values.length = 0;
10925
+ runValues.length = 0;
10859
10926
  }
10860
- function addValue(v) {
10927
+ function put(v) {
10928
+ data.push(v);
10861
10929
  const needsShort = v < 0 || v > 255;
10862
- if (values.length > 0 && needsShort !== isShort) {
10930
+ if (runValues.length > 0 && needsShort !== isShort) {
10863
10931
  flush();
10864
10932
  }
10865
- if (values.length === 0) {
10933
+ if (runValues.length === 0) {
10866
10934
  isShort = needsShort;
10867
10935
  }
10868
- values.push(v);
10869
- if (values.length >= 255) {
10936
+ runValues.push(v);
10937
+ if (runValues.length >= 255) {
10870
10938
  flush();
10871
10939
  }
10872
10940
  }
10873
10941
  while (remaining > 0) {
10874
- const code = sIn.readU8();
10875
- if (code === 251 && remaining >= 4) {
10876
- const a = read255Short(sIn);
10877
- const b = read255Short(sIn);
10878
- const c = read255Short(sIn);
10879
- addValue(a);
10880
- addValue(b);
10881
- addValue(a);
10882
- addValue(c);
10883
- addValue(a);
10884
- remaining -= 5;
10885
- } else if (code === 252 && remaining >= 6) {
10886
- const a = read255Short(sIn);
10887
- const b = read255Short(sIn);
10942
+ const code = sIn.peekU8();
10943
+ if (code === 251 && remaining >= 3 && data.length >= 2) {
10944
+ sIn.readU8();
10945
+ const prev = data[data.length - 2];
10946
+ put(prev);
10947
+ const val = read255Short(sIn);
10948
+ put(val);
10949
+ put(prev);
10950
+ remaining -= 3;
10951
+ } else if (code === 252 && remaining >= 5 && data.length >= 2) {
10952
+ sIn.readU8();
10953
+ const prev = data[data.length - 2];
10954
+ put(prev);
10888
10955
  const c = read255Short(sIn);
10956
+ put(c);
10957
+ put(prev);
10889
10958
  const d = read255Short(sIn);
10890
- addValue(a);
10891
- addValue(b);
10892
- addValue(a);
10893
- addValue(c);
10894
- addValue(a);
10895
- addValue(d);
10896
- addValue(a);
10897
- remaining -= 7;
10959
+ put(d);
10960
+ put(prev);
10961
+ remaining -= 5;
10898
10962
  } else {
10899
- sIn.seekRelative(-1);
10900
10963
  const v = read255Short(sIn);
10901
- addValue(v);
10964
+ put(v);
10902
10965
  remaining -= 1;
10903
10966
  }
10904
10967
  }
@@ -10926,6 +10989,9 @@ function makeGlyphFlags(x, y, onCurve, firstTime) {
10926
10989
  return flags;
10927
10990
  }
10928
10991
  function decodeSimpleGlyph(numContours, streams, out, calcBBox, minX, minY, maxX, maxY) {
10992
+ if (numContours === 0) {
10993
+ return;
10994
+ }
10929
10995
  const sGlyph = streams[0];
10930
10996
  out.writeS16(numContours);
10931
10997
  const bboxPos = out.pos;
@@ -10946,13 +11012,12 @@ function decodeSimpleGlyph(numContours, streams, out, calcBBox, minX, minY, maxX
10946
11012
  }
10947
11013
  let totalPoints = 0;
10948
11014
  for (let c = 0; c < numContours; c++) {
10949
- const pointsInContour = read255UShort(sGlyph);
10950
- totalPoints += pointsInContour;
10951
11015
  if (c === 0) {
10952
- out.writeU16(pointsInContour - 1);
10953
- } else {
10954
- out.writeU16(totalPoints - 1);
11016
+ totalPoints = 1;
10955
11017
  }
11018
+ const pointsInContour = read255UShort(sGlyph);
11019
+ totalPoints += pointsInContour;
11020
+ out.writeU16(totalPoints - 1);
10956
11021
  }
10957
11022
  const flagBytes = new Uint8Array(totalPoints);
10958
11023
  for (let i = 0; i < totalPoints; i++) {
@@ -10965,7 +11030,7 @@ function decodeSimpleGlyph(numContours, streams, out, calcBBox, minX, minY, maxX
10965
11030
  let cumulativeY = 0;
10966
11031
  for (let i = 0; i < totalPoints; i++) {
10967
11032
  const flag = flagBytes[i];
10968
- onCurve[i] = flag >> 7;
11033
+ onCurve[i] = flag & 128 ? 0 : 1;
10969
11034
  const enc = TRIPLET_ENCODINGS[flag & 127];
10970
11035
  const extraBytes = enc.byteCount - 1;
10971
11036
  const subBuf = new Uint8Array(extraBytes);
@@ -11304,7 +11369,10 @@ var AHuff = class _AHuff {
11304
11369
  this.bio = bio;
11305
11370
  this.range = range;
11306
11371
  this.bitCount = bitsUsed(range - 1);
11307
- this.bitCount2 = this.bitCount > 8 ? this.bitCount - 8 : 0;
11372
+ this.bitCount2 = 0;
11373
+ if (range > 256 && range < 512) {
11374
+ this.bitCount2 = bitsUsed(range - 256 - 1) + 1;
11375
+ }
11308
11376
  const treeSize = 2 * range;
11309
11377
  this.tree = Array.from({ length: treeSize });
11310
11378
  for (let i = 0; i < treeSize; i++) {
@@ -11312,6 +11380,7 @@ var AHuff = class _AHuff {
11312
11380
  }
11313
11381
  for (let i = 2; i < treeSize; i++) {
11314
11382
  this.tree[i].up = i >> 1;
11383
+ this.tree[i].weight = 1;
11315
11384
  }
11316
11385
  for (let i = 1; i < range; i++) {
11317
11386
  this.tree[i].left = 2 * i;
@@ -11321,7 +11390,8 @@ var AHuff = class _AHuff {
11321
11390
  for (let i = 0; i < range; i++) {
11322
11391
  const leafIdx = range + i;
11323
11392
  this.tree[leafIdx].code = i;
11324
- this.tree[leafIdx].weight = 1;
11393
+ this.tree[leafIdx].left = -1;
11394
+ this.tree[leafIdx].right = -1;
11325
11395
  }
11326
11396
  this.symbolIndex = Array.from({ length: range });
11327
11397
  for (let i = 0; i < range; i++) {
@@ -11361,15 +11431,13 @@ var AHuff = class _AHuff {
11361
11431
  */
11362
11432
  readSymbol() {
11363
11433
  let a = _AHuff.ROOT;
11364
- while (this.tree[a].code < 0) {
11365
- if (this.bio.inputBit()) {
11366
- a = this.tree[a].right;
11367
- } else {
11368
- a = this.tree[a].left;
11369
- }
11370
- }
11434
+ let symbol;
11435
+ do {
11436
+ a = this.bio.inputBit() ? this.tree[a].right : this.tree[a].left;
11437
+ symbol = this.tree[a].code;
11438
+ } while (symbol < 0);
11371
11439
  this.updateWeight(a);
11372
- return this.tree[a].code;
11440
+ return symbol;
11373
11441
  }
11374
11442
  // --------------------------------------------------------------------
11375
11443
  // Private helpers
@@ -11393,17 +11461,19 @@ var AHuff = class _AHuff {
11393
11461
  updateWeight(a) {
11394
11462
  const tree = this.tree;
11395
11463
  for (; a !== _AHuff.ROOT; a = tree[a].up) {
11464
+ const weightA = tree[a].weight;
11396
11465
  let b = a - 1;
11397
- if (b > 0 && tree[b].weight === tree[a].weight) {
11398
- while (b > _AHuff.ROOT && tree[b - 1].weight === tree[a].weight) {
11466
+ if (tree[b].weight === weightA) {
11467
+ do {
11399
11468
  b--;
11400
- }
11401
- if (b > _AHuff.ROOT && b !== a) {
11469
+ } while (tree[b].weight === weightA);
11470
+ b++;
11471
+ if (b > _AHuff.ROOT) {
11402
11472
  this.swapNodes(a, b);
11403
11473
  a = b;
11404
11474
  }
11405
11475
  }
11406
- tree[a].weight++;
11476
+ tree[a].weight = weightA + 1;
11407
11477
  }
11408
11478
  tree[_AHuff.ROOT].weight++;
11409
11479
  }
@@ -11423,38 +11493,26 @@ var AHuff = class _AHuff {
11423
11493
  */
11424
11494
  swapNodes(a, b) {
11425
11495
  const tree = this.tree;
11426
- const na = tree[a];
11427
- const nb = tree[b];
11428
- let tmp;
11429
- tmp = na.left;
11430
- na.left = nb.left;
11431
- nb.left = tmp;
11432
- tmp = na.right;
11433
- na.right = nb.right;
11434
- nb.right = tmp;
11435
- tmp = na.code;
11436
- na.code = nb.code;
11437
- nb.code = tmp;
11438
- tmp = na.weight;
11439
- na.weight = nb.weight;
11440
- nb.weight = tmp;
11441
- if (na.left) {
11442
- tree[na.left].up = a;
11443
- }
11444
- if (na.right) {
11445
- tree[na.right].up = a;
11446
- }
11447
- if (nb.left) {
11448
- tree[nb.left].up = b;
11449
- }
11450
- if (nb.right) {
11451
- tree[nb.right].up = b;
11452
- }
11453
- if (na.code >= 0) {
11454
- this.symbolIndex[na.code] = a;
11496
+ const upa = tree[a].up;
11497
+ const upb = tree[b].up;
11498
+ const tmp = tree[a];
11499
+ tree[a] = tree[b];
11500
+ tree[b] = tmp;
11501
+ tree[a].up = upa;
11502
+ tree[b].up = upb;
11503
+ let code = tree[a].code;
11504
+ if (code < 0) {
11505
+ tree[tree[a].left].up = a;
11506
+ tree[tree[a].right].up = a;
11507
+ } else {
11508
+ this.symbolIndex[code] = a;
11455
11509
  }
11456
- if (nb.code >= 0) {
11457
- this.symbolIndex[nb.code] = b;
11510
+ code = tree[b].code;
11511
+ if (code < 0) {
11512
+ tree[tree[b].left].up = b;
11513
+ tree[tree[b].right].up = b;
11514
+ } else {
11515
+ this.symbolIndex[code] = b;
11458
11516
  }
11459
11517
  }
11460
11518
  /**
@@ -11833,12 +11891,12 @@ function unpackMtx(data, size) {
11833
11891
  const offset2 = data[4] << 16 | data[5] << 8 | data[6];
11834
11892
  const offset3 = data[7] << 16 | data[8] << 8 | data[9];
11835
11893
  const offsets = [10, offset2, offset3];
11836
- const sizes = [offset2 - 10, offset3 - offset2, size - offset3];
11894
+ const blockSizes = [offset2 - 10, offset3 - offset2, size - offset3];
11837
11895
  const streams = [];
11838
11896
  const decompressedSizes = [];
11839
11897
  for (let i = 0; i < 3; i++) {
11840
11898
  const block = data.subarray(offsets[i]);
11841
- const decompressed = lzcompDecompress(block, sizes[i], versionMagic);
11899
+ const decompressed = lzcompDecompress(block, blockSizes[i], versionMagic);
11842
11900
  streams.push(decompressed);
11843
11901
  decompressedSizes.push(decompressed.length);
11844
11902
  }
@@ -11930,6 +11988,15 @@ function parseEotHeader(data) {
11930
11988
  const fullName = readNameString();
11931
11989
  if (version >= 131074) {
11932
11990
  readNameString();
11991
+ offset += 8;
11992
+ if (offset + 4 <= data.length) {
11993
+ const signatureSize = readUint16LE(data, offset + 2);
11994
+ offset += 4 + signatureSize;
11995
+ }
11996
+ if (offset + 8 <= data.length) {
11997
+ const eudcFontSize = readUint32LE(data, offset + 4);
11998
+ offset += 8 + eudcFontSize;
11999
+ }
11933
12000
  }
11934
12001
  return {
11935
12002
  eotSize,
@@ -24484,6 +24551,943 @@ function applyThemeToData(data, newColorScheme, newFontScheme, themeName) {
24484
24551
  };
24485
24552
  }
24486
24553
 
24554
+ // src/core/utils/accessibility-checker.ts
24555
+ function parseHexColor(hex) {
24556
+ const cleaned = hex.replace(/^#/, "");
24557
+ if (!/^[\da-fA-F]+$/.test(cleaned)) {
24558
+ return null;
24559
+ }
24560
+ if (cleaned.length === 3) {
24561
+ const r = Number.parseInt(cleaned[0] + cleaned[0], 16);
24562
+ const g = Number.parseInt(cleaned[1] + cleaned[1], 16);
24563
+ const b = Number.parseInt(cleaned[2] + cleaned[2], 16);
24564
+ return [r, g, b];
24565
+ }
24566
+ if (cleaned.length === 6) {
24567
+ const r = Number.parseInt(cleaned.slice(0, 2), 16);
24568
+ const g = Number.parseInt(cleaned.slice(2, 4), 16);
24569
+ const b = Number.parseInt(cleaned.slice(4, 6), 16);
24570
+ return [r, g, b];
24571
+ }
24572
+ return null;
24573
+ }
24574
+ function relativeLuminance(r, g, b) {
24575
+ const [rs, gs, bs] = [r, g, b].map((c) => {
24576
+ const s = c / 255;
24577
+ return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
24578
+ });
24579
+ return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
24580
+ }
24581
+ function computeContrastRatio(fg, bg) {
24582
+ const fgRgb = parseHexColor(fg);
24583
+ const bgRgb = parseHexColor(bg);
24584
+ if (!fgRgb || !bgRgb) {
24585
+ return 21;
24586
+ }
24587
+ const l1 = relativeLuminance(...fgRgb);
24588
+ const l2 = relativeLuminance(...bgRgb);
24589
+ const lighter = Math.max(l1, l2);
24590
+ const darker = Math.min(l1, l2);
24591
+ return (lighter + 0.05) / (darker + 0.05);
24592
+ }
24593
+ var IMAGE_LIKE_TYPES = /* @__PURE__ */ new Set(["image", "picture"]);
24594
+ var VISUAL_CONTENT_TYPES = /* @__PURE__ */ new Set(["image", "picture", "chart", "smartArt", "media"]);
24595
+ function getElementText(el) {
24596
+ if ("text" in el && typeof el.text === "string") {
24597
+ return el.text;
24598
+ }
24599
+ if ("textSegments" in el && Array.isArray(el.textSegments)) {
24600
+ return el.textSegments.map((s) => s.text || "").join("");
24601
+ }
24602
+ return "";
24603
+ }
24604
+ function getAltText(el) {
24605
+ if ("altText" in el) {
24606
+ return el.altText;
24607
+ }
24608
+ return void 0;
24609
+ }
24610
+ function getTextColor(el) {
24611
+ if ("textStyle" in el && el.textStyle) {
24612
+ return el.textStyle.color;
24613
+ }
24614
+ if ("textSegments" in el && Array.isArray(el.textSegments) && el.textSegments.length > 0) {
24615
+ const firstStyle = el.textSegments[0]?.style;
24616
+ return firstStyle?.color;
24617
+ }
24618
+ return void 0;
24619
+ }
24620
+ function getBackgroundColor(el) {
24621
+ if ("shapeStyle" in el && el.shapeStyle) {
24622
+ return el.shapeStyle.fillColor;
24623
+ }
24624
+ return void 0;
24625
+ }
24626
+ function isTitleElement(el) {
24627
+ const id = el.id.toLowerCase();
24628
+ return id.includes("title") || id.startsWith("ctr") || id.includes("ctrtitle");
24629
+ }
24630
+ function isVisibleElement(el) {
24631
+ if ("hidden" in el && el.hidden) {
24632
+ return false;
24633
+ }
24634
+ if ("opacity" in el && typeof el.opacity === "number" && el.opacity <= 0) {
24635
+ return false;
24636
+ }
24637
+ return true;
24638
+ }
24639
+ function checkMissingAltText(slide, slideIndex) {
24640
+ const issues = [];
24641
+ for (const el of slide.elements) {
24642
+ if (!isVisibleElement(el)) {
24643
+ continue;
24644
+ }
24645
+ if (!VISUAL_CONTENT_TYPES.has(el.type)) {
24646
+ continue;
24647
+ }
24648
+ const alt = getAltText(el);
24649
+ if (!alt || alt.trim() === "") {
24650
+ const label = IMAGE_LIKE_TYPES.has(el.type) ? "Image" : el.type === "chart" ? "Chart" : el.type === "smartArt" ? "SmartArt" : "Media";
24651
+ issues.push({
24652
+ type: "missingAltText",
24653
+ severity: "error",
24654
+ slideIndex,
24655
+ elementId: el.id,
24656
+ message: `${label} is missing alternative text.`,
24657
+ suggestion: `Add a description to the ${label.toLowerCase()} so screen readers can describe it.`
24658
+ });
24659
+ }
24660
+ }
24661
+ return issues;
24662
+ }
24663
+ function checkMissingSlideTitle(slide, slideIndex) {
24664
+ const titleElement = slide.elements.find((el) => isTitleElement(el) && isVisibleElement(el));
24665
+ if (!titleElement) {
24666
+ return [
24667
+ {
24668
+ type: "missingSlideTitle",
24669
+ severity: "warning",
24670
+ slideIndex,
24671
+ message: "Slide is missing a title.",
24672
+ suggestion: "Add a title element so screen readers can navigate between slides."
24673
+ }
24674
+ ];
24675
+ }
24676
+ const text = getElementText(titleElement).trim();
24677
+ if (text === "") {
24678
+ return [
24679
+ {
24680
+ type: "missingSlideTitle",
24681
+ severity: "warning",
24682
+ slideIndex,
24683
+ elementId: titleElement.id,
24684
+ message: "Slide title is empty.",
24685
+ suggestion: "Add text to the title element."
24686
+ }
24687
+ ];
24688
+ }
24689
+ return [];
24690
+ }
24691
+ function checkLowContrast(slide, slideIndex, minRatio, slideBg) {
24692
+ const issues = [];
24693
+ const defaultBg = slideBg || "#FFFFFF";
24694
+ for (const el of slide.elements) {
24695
+ if (!isVisibleElement(el)) {
24696
+ continue;
24697
+ }
24698
+ const text = getElementText(el);
24699
+ if (!text.trim()) {
24700
+ continue;
24701
+ }
24702
+ const fg = getTextColor(el);
24703
+ if (!fg) {
24704
+ continue;
24705
+ }
24706
+ const bg = getBackgroundColor(el) || defaultBg;
24707
+ const ratio = computeContrastRatio(fg, bg);
24708
+ if (ratio < minRatio) {
24709
+ issues.push({
24710
+ type: "lowContrast",
24711
+ severity: "warning",
24712
+ slideIndex,
24713
+ elementId: el.id,
24714
+ message: `Text contrast ratio is ${ratio.toFixed(1)}:1 (minimum ${minRatio}:1).`,
24715
+ suggestion: "Increase contrast between text colour and background."
24716
+ });
24717
+ }
24718
+ }
24719
+ return issues;
24720
+ }
24721
+ function checkComplexTables(slide, slideIndex) {
24722
+ const issues = [];
24723
+ for (const el of slide.elements) {
24724
+ if (el.type !== "table") {
24725
+ continue;
24726
+ }
24727
+ const tableData = el.tableData;
24728
+ if (!tableData) {
24729
+ continue;
24730
+ }
24731
+ let mergeCount = 0;
24732
+ for (const row of tableData.rows) {
24733
+ for (const cell of row.cells) {
24734
+ if (cell.gridSpan && cell.gridSpan > 1 || cell.rowSpan && cell.rowSpan > 1) {
24735
+ mergeCount++;
24736
+ }
24737
+ }
24738
+ }
24739
+ if (mergeCount > 2) {
24740
+ issues.push({
24741
+ type: "complexTable",
24742
+ severity: "warning",
24743
+ slideIndex,
24744
+ elementId: el.id,
24745
+ message: `Table has ${mergeCount} merged cell regions, which can confuse screen readers.`,
24746
+ suggestion: "Simplify the table structure or split into multiple simpler tables."
24747
+ });
24748
+ }
24749
+ }
24750
+ return issues;
24751
+ }
24752
+ function checkDuplicateTitles(slides) {
24753
+ const issues = [];
24754
+ const titleMap = /* @__PURE__ */ new Map();
24755
+ for (let i = 0; i < slides.length; i++) {
24756
+ const slide = slides[i];
24757
+ const titleEl = slide.elements.find((el) => isTitleElement(el) && isVisibleElement(el));
24758
+ if (!titleEl) {
24759
+ continue;
24760
+ }
24761
+ const text = getElementText(titleEl).trim().toLowerCase();
24762
+ if (!text) {
24763
+ continue;
24764
+ }
24765
+ const existing = titleMap.get(text);
24766
+ if (existing) {
24767
+ existing.push(i);
24768
+ } else {
24769
+ titleMap.set(text, [i]);
24770
+ }
24771
+ }
24772
+ for (const [title, indices] of titleMap) {
24773
+ if (indices.length > 1) {
24774
+ for (const idx of indices) {
24775
+ issues.push({
24776
+ type: "duplicateTitle",
24777
+ severity: "tip",
24778
+ slideIndex: idx,
24779
+ message: `Slide title "${title}" is duplicated across ${indices.length} slides.`,
24780
+ suggestion: "Use unique titles to help screen reader users distinguish slides."
24781
+ });
24782
+ }
24783
+ }
24784
+ }
24785
+ return issues;
24786
+ }
24787
+ function checkBlankSlide(slide, slideIndex) {
24788
+ const hasVisibleContent = slide.elements.some((el) => {
24789
+ if (!isVisibleElement(el)) {
24790
+ return false;
24791
+ }
24792
+ if (el.type === "text" || el.type === "shape") {
24793
+ return getElementText(el).trim() !== "";
24794
+ }
24795
+ return true;
24796
+ });
24797
+ if (!hasVisibleContent) {
24798
+ return [
24799
+ {
24800
+ type: "blankSlide",
24801
+ severity: "tip",
24802
+ slideIndex,
24803
+ message: "Slide appears to have no visible content.",
24804
+ suggestion: "Add content or remove the blank slide."
24805
+ }
24806
+ ];
24807
+ }
24808
+ return [];
24809
+ }
24810
+ function checkPresentation(data, options = {}) {
24811
+ const { minContrastRatio = 4.5, skipContrast = false, skipBlankSlide = false } = options;
24812
+ const issues = [];
24813
+ for (let i = 0; i < data.slides.length; i++) {
24814
+ const slide = data.slides[i];
24815
+ issues.push(...checkMissingAltText(slide, i));
24816
+ issues.push(...checkMissingSlideTitle(slide, i));
24817
+ if (!skipContrast) {
24818
+ issues.push(...checkLowContrast(slide, i, minContrastRatio, slide.backgroundColor));
24819
+ }
24820
+ issues.push(...checkComplexTables(slide, i));
24821
+ if (!skipBlankSlide) {
24822
+ issues.push(...checkBlankSlide(slide, i));
24823
+ }
24824
+ }
24825
+ issues.push(...checkDuplicateTitles(data.slides));
24826
+ const severityOrder = { error: 0, warning: 1, tip: 2 };
24827
+ issues.sort(
24828
+ (a, b) => a.slideIndex - b.slideIndex || severityOrder[a.severity] - severityOrder[b.severity]
24829
+ );
24830
+ return issues;
24831
+ }
24832
+
24833
+ // src/core/utils/custom-show-utils.ts
24834
+ function findCustomShow(customShows, nameOrId) {
24835
+ if (!customShows || customShows.length === 0) {
24836
+ return void 0;
24837
+ }
24838
+ const lower = nameOrId.toLowerCase();
24839
+ return customShows.find((s) => s.id === nameOrId) || customShows.find((s) => s.name.toLowerCase() === lower);
24840
+ }
24841
+ function resolveCustomShowSlideIndices(customShow, slides) {
24842
+ const rIdToIndex = /* @__PURE__ */ new Map();
24843
+ for (let i = 0; i < slides.length; i++) {
24844
+ rIdToIndex.set(slides[i].rId, i);
24845
+ }
24846
+ const indices = [];
24847
+ for (const rId of customShow.slideRIds) {
24848
+ const idx = rIdToIndex.get(rId);
24849
+ if (idx !== void 0) {
24850
+ indices.push(idx);
24851
+ }
24852
+ }
24853
+ return indices;
24854
+ }
24855
+ function getCustomShowNames(customShows) {
24856
+ if (!customShows) {
24857
+ return [];
24858
+ }
24859
+ return customShows.map((s) => s.name);
24860
+ }
24861
+ function navigateCustomShow(currentSlideIndex, direction, filteredIndices, wrap = false) {
24862
+ if (filteredIndices.length === 0) {
24863
+ return currentSlideIndex;
24864
+ }
24865
+ const posInShow = filteredIndices.indexOf(currentSlideIndex);
24866
+ if (posInShow === -1) {
24867
+ return filteredIndices[0];
24868
+ }
24869
+ const nextPos = posInShow + direction;
24870
+ if (nextPos < 0) {
24871
+ return wrap ? filteredIndices[filteredIndices.length - 1] : currentSlideIndex;
24872
+ }
24873
+ if (nextPos >= filteredIndices.length) {
24874
+ return wrap ? filteredIndices[0] : currentSlideIndex;
24875
+ }
24876
+ return filteredIndices[nextPos];
24877
+ }
24878
+ function getCustomShowPositionLabel(currentSlideIndex, filteredIndices) {
24879
+ const pos2 = filteredIndices.indexOf(currentSlideIndex);
24880
+ if (pos2 === -1) {
24881
+ return "";
24882
+ }
24883
+ return `${pos2 + 1} of ${filteredIndices.length}`;
24884
+ }
24885
+
24886
+ // src/core/utils/table-style-resolver.ts
24887
+ function mergeBorder(base, override) {
24888
+ if (!base && !override) {
24889
+ return void 0;
24890
+ }
24891
+ if (!base) {
24892
+ return override;
24893
+ }
24894
+ if (!override) {
24895
+ return base;
24896
+ }
24897
+ return {
24898
+ width: override.width ?? base.width,
24899
+ color: override.color ?? base.color,
24900
+ dash: override.dash ?? base.dash
24901
+ };
24902
+ }
24903
+ function mergeStyleParts(base, override) {
24904
+ if (!base && !override) {
24905
+ return void 0;
24906
+ }
24907
+ if (!base) {
24908
+ return override;
24909
+ }
24910
+ if (!override) {
24911
+ return base;
24912
+ }
24913
+ const merged = {};
24914
+ if (override.fill || base.fill) {
24915
+ merged.fill = {
24916
+ color: override.fill?.color ?? base.fill?.color,
24917
+ gradient: override.fill?.gradient ?? base.fill?.gradient,
24918
+ pattern: override.fill?.pattern ?? base.fill?.pattern
24919
+ };
24920
+ }
24921
+ if (override.borders || base.borders) {
24922
+ merged.borders = {
24923
+ top: mergeBorder(base.borders?.top, override.borders?.top),
24924
+ bottom: mergeBorder(base.borders?.bottom, override.borders?.bottom),
24925
+ left: mergeBorder(base.borders?.left, override.borders?.left),
24926
+ right: mergeBorder(base.borders?.right, override.borders?.right)
24927
+ };
24928
+ }
24929
+ if (override.text || base.text) {
24930
+ merged.text = {
24931
+ bold: override.text?.bold ?? base.text?.bold,
24932
+ italic: override.text?.italic ?? base.text?.italic,
24933
+ color: override.text?.color ?? base.text?.color,
24934
+ fontSize: override.text?.fontSize ?? base.text?.fontSize
24935
+ };
24936
+ }
24937
+ return merged;
24938
+ }
24939
+ function resolveTableCellStyle(rowIndex, colIndex, totalRows, totalCols, flags, style) {
24940
+ let effective = style.wholeTbl ? { ...style.wholeTbl } : void 0;
24941
+ if (flags.bandedRows) {
24942
+ const cycle = flags.bandRowCycle ?? 1;
24943
+ const bandRow = flags.firstRow ? rowIndex - 1 : rowIndex;
24944
+ if (bandRow >= 0) {
24945
+ const bandIndex = Math.floor(bandRow / cycle) % 2;
24946
+ const bandPart = bandIndex === 0 ? style.band1H : style.band2H;
24947
+ if (bandPart) {
24948
+ effective = mergeStyleParts(effective, bandPart);
24949
+ }
24950
+ }
24951
+ }
24952
+ if (flags.bandedColumns) {
24953
+ const cycle = flags.bandColCycle ?? 1;
24954
+ const bandCol = flags.firstCol ? colIndex - 1 : colIndex;
24955
+ if (bandCol >= 0) {
24956
+ const bandIndex = Math.floor(bandCol / cycle) % 2;
24957
+ const bandPart = bandIndex === 0 ? style.band1V : style.band2V;
24958
+ if (bandPart) {
24959
+ effective = mergeStyleParts(effective, bandPart);
24960
+ }
24961
+ }
24962
+ }
24963
+ if (flags.lastRow && rowIndex === totalRows - 1 && style.lastRow) {
24964
+ effective = mergeStyleParts(effective, style.lastRow);
24965
+ }
24966
+ if (flags.firstRow && rowIndex === 0 && style.firstRow) {
24967
+ effective = mergeStyleParts(effective, style.firstRow);
24968
+ }
24969
+ if (flags.lastCol && colIndex === totalCols - 1 && style.lastCol) {
24970
+ effective = mergeStyleParts(effective, style.lastCol);
24971
+ }
24972
+ if (flags.firstCol && colIndex === 0 && style.firstCol) {
24973
+ effective = mergeStyleParts(effective, style.firstCol);
24974
+ }
24975
+ const isFirstRow = flags.firstRow && rowIndex === 0;
24976
+ const isLastRow = flags.lastRow && rowIndex === totalRows - 1;
24977
+ const isFirstCol = flags.firstCol && colIndex === 0;
24978
+ const isLastCol = flags.lastCol && colIndex === totalCols - 1;
24979
+ if (isLastRow && isLastCol && style.seCell) {
24980
+ effective = mergeStyleParts(effective, style.seCell);
24981
+ }
24982
+ if (isLastRow && isFirstCol && style.swCell) {
24983
+ effective = mergeStyleParts(effective, style.swCell);
24984
+ }
24985
+ if (isFirstRow && isLastCol && style.neCell) {
24986
+ effective = mergeStyleParts(effective, style.neCell);
24987
+ }
24988
+ if (isFirstRow && isFirstCol && style.nwCell) {
24989
+ effective = mergeStyleParts(effective, style.nwCell);
24990
+ }
24991
+ return partToCellStyle(effective);
24992
+ }
24993
+ function partToCellStyle(part) {
24994
+ if (!part) {
24995
+ return {};
24996
+ }
24997
+ const result = {};
24998
+ if (part.fill) {
24999
+ if (part.fill.color) {
25000
+ result.backgroundColor = part.fill.color;
25001
+ result.fillMode = "solid";
25002
+ }
25003
+ if (part.fill.gradient) {
25004
+ result.fillMode = "gradient";
25005
+ }
25006
+ if (part.fill.pattern) {
25007
+ result.fillMode = "pattern";
25008
+ }
25009
+ }
25010
+ if (part.borders) {
25011
+ if (part.borders.top) {
25012
+ if (part.borders.top.width !== void 0) {
25013
+ result.borderTopWidth = part.borders.top.width;
25014
+ }
25015
+ if (part.borders.top.color) {
25016
+ result.borderTopColor = part.borders.top.color;
25017
+ }
25018
+ if (part.borders.top.dash) {
25019
+ result.borderTopDash = part.borders.top.dash;
25020
+ }
25021
+ }
25022
+ if (part.borders.bottom) {
25023
+ if (part.borders.bottom.width !== void 0) {
25024
+ result.borderBottomWidth = part.borders.bottom.width;
25025
+ }
25026
+ if (part.borders.bottom.color) {
25027
+ result.borderBottomColor = part.borders.bottom.color;
25028
+ }
25029
+ if (part.borders.bottom.dash) {
25030
+ result.borderBottomDash = part.borders.bottom.dash;
25031
+ }
25032
+ }
25033
+ if (part.borders.left) {
25034
+ if (part.borders.left.width !== void 0) {
25035
+ result.borderLeftWidth = part.borders.left.width;
25036
+ }
25037
+ if (part.borders.left.color) {
25038
+ result.borderLeftColor = part.borders.left.color;
25039
+ }
25040
+ if (part.borders.left.dash) {
25041
+ result.borderLeftDash = part.borders.left.dash;
25042
+ }
25043
+ }
25044
+ if (part.borders.right) {
25045
+ if (part.borders.right.width !== void 0) {
25046
+ result.borderRightWidth = part.borders.right.width;
25047
+ }
25048
+ if (part.borders.right.color) {
25049
+ result.borderRightColor = part.borders.right.color;
25050
+ }
25051
+ if (part.borders.right.dash) {
25052
+ result.borderRightDash = part.borders.right.dash;
25053
+ }
25054
+ }
25055
+ }
25056
+ if (part.text) {
25057
+ if (part.text.bold !== void 0) {
25058
+ result.bold = part.text.bold;
25059
+ }
25060
+ if (part.text.italic !== void 0) {
25061
+ result.italic = part.text.italic;
25062
+ }
25063
+ if (part.text.color) {
25064
+ result.color = part.text.color;
25065
+ }
25066
+ if (part.text.fontSize !== void 0) {
25067
+ result.fontSize = part.text.fontSize;
25068
+ }
25069
+ }
25070
+ return result;
25071
+ }
25072
+
25073
+ // src/core/utils/animation-preset-catalog.ts
25074
+ var ENTRANCE_PRESETS = [
25075
+ {
25076
+ presetId: "entr.1",
25077
+ label: "Appear",
25078
+ category: "entrance",
25079
+ defaultDurationMs: 0,
25080
+ hasDirection: false,
25081
+ hasTextBuild: true
25082
+ },
25083
+ {
25084
+ presetId: "entr.10",
25085
+ label: "Fade",
25086
+ category: "entrance",
25087
+ defaultDurationMs: 500,
25088
+ hasDirection: false,
25089
+ hasTextBuild: true
25090
+ },
25091
+ {
25092
+ presetId: "entr.2",
25093
+ label: "Fly In",
25094
+ category: "entrance",
25095
+ defaultDurationMs: 500,
25096
+ hasDirection: true,
25097
+ directions: [
25098
+ "fromBottom",
25099
+ "fromLeft",
25100
+ "fromRight",
25101
+ "fromTop",
25102
+ "fromBottomLeft",
25103
+ "fromBottomRight",
25104
+ "fromTopLeft",
25105
+ "fromTopRight"
25106
+ ],
25107
+ hasTextBuild: true
25108
+ },
25109
+ {
25110
+ presetId: "entr.53",
25111
+ label: "Grow & Turn",
25112
+ category: "entrance",
25113
+ defaultDurationMs: 500,
25114
+ hasDirection: false,
25115
+ hasTextBuild: true
25116
+ },
25117
+ {
25118
+ presetId: "entr.23",
25119
+ label: "Zoom",
25120
+ category: "entrance",
25121
+ defaultDurationMs: 500,
25122
+ hasDirection: true,
25123
+ directions: ["inFromScreenCenter", "inSlightly", "objectCenter"],
25124
+ hasTextBuild: true
25125
+ },
25126
+ {
25127
+ presetId: "entr.14",
25128
+ label: "Bounce",
25129
+ category: "entrance",
25130
+ defaultDurationMs: 1e3,
25131
+ hasDirection: false,
25132
+ hasTextBuild: true
25133
+ },
25134
+ {
25135
+ presetId: "entr.22",
25136
+ label: "Wipe",
25137
+ category: "entrance",
25138
+ defaultDurationMs: 500,
25139
+ hasDirection: true,
25140
+ directions: ["fromBottom", "fromLeft", "fromRight", "fromTop"],
25141
+ hasTextBuild: true
25142
+ },
25143
+ {
25144
+ presetId: "entr.16",
25145
+ label: "Split",
25146
+ category: "entrance",
25147
+ defaultDurationMs: 500,
25148
+ hasDirection: true,
25149
+ directions: ["horizontalIn", "horizontalOut", "verticalIn", "verticalOut"],
25150
+ hasTextBuild: true
25151
+ },
25152
+ {
25153
+ presetId: "entr.9",
25154
+ label: "Dissolve In",
25155
+ category: "entrance",
25156
+ defaultDurationMs: 700,
25157
+ hasDirection: false,
25158
+ hasTextBuild: true
25159
+ },
25160
+ {
25161
+ presetId: "entr.21",
25162
+ label: "Wheel",
25163
+ category: "entrance",
25164
+ defaultDurationMs: 1e3,
25165
+ hasDirection: true,
25166
+ directions: ["1spoke", "2spoke", "3spoke", "4spoke", "8spoke"],
25167
+ hasTextBuild: true
25168
+ },
25169
+ {
25170
+ presetId: "entr.3",
25171
+ label: "Blinds",
25172
+ category: "entrance",
25173
+ defaultDurationMs: 500,
25174
+ hasDirection: true,
25175
+ directions: ["horizontal", "vertical"],
25176
+ hasTextBuild: true
25177
+ },
25178
+ {
25179
+ presetId: "entr.4",
25180
+ label: "Box",
25181
+ category: "entrance",
25182
+ defaultDurationMs: 500,
25183
+ hasDirection: true,
25184
+ directions: ["in", "out"],
25185
+ hasTextBuild: true
25186
+ },
25187
+ {
25188
+ presetId: "entr.12",
25189
+ label: "Float Up",
25190
+ category: "entrance",
25191
+ defaultDurationMs: 500,
25192
+ hasDirection: false,
25193
+ hasTextBuild: true
25194
+ },
25195
+ {
25196
+ presetId: "entr.42",
25197
+ label: "Rise Up",
25198
+ category: "entrance",
25199
+ defaultDurationMs: 500,
25200
+ hasDirection: false,
25201
+ hasTextBuild: true
25202
+ },
25203
+ {
25204
+ presetId: "entr.45",
25205
+ label: "Swivel",
25206
+ category: "entrance",
25207
+ defaultDurationMs: 500,
25208
+ hasDirection: true,
25209
+ directions: ["horizontal", "vertical"],
25210
+ hasTextBuild: true
25211
+ },
25212
+ {
25213
+ presetId: "entr.17",
25214
+ label: "Checkerboard",
25215
+ category: "entrance",
25216
+ defaultDurationMs: 500,
25217
+ hasDirection: true,
25218
+ directions: ["across", "down"],
25219
+ hasTextBuild: true
25220
+ },
25221
+ {
25222
+ presetId: "entr.18",
25223
+ label: "Flash Once",
25224
+ category: "entrance",
25225
+ defaultDurationMs: 300,
25226
+ hasDirection: false,
25227
+ hasTextBuild: false
25228
+ },
25229
+ {
25230
+ presetId: "entr.19",
25231
+ label: "Peek In",
25232
+ category: "entrance",
25233
+ defaultDurationMs: 500,
25234
+ hasDirection: true,
25235
+ directions: ["fromBottom", "fromLeft", "fromRight", "fromTop"],
25236
+ hasTextBuild: true
25237
+ },
25238
+ {
25239
+ presetId: "entr.20",
25240
+ label: "Random Bars",
25241
+ category: "entrance",
25242
+ defaultDurationMs: 500,
25243
+ hasDirection: true,
25244
+ directions: ["horizontal", "vertical"],
25245
+ hasTextBuild: true
25246
+ },
25247
+ {
25248
+ presetId: "entr.49",
25249
+ label: "Expand",
25250
+ category: "entrance",
25251
+ defaultDurationMs: 500,
25252
+ hasDirection: false,
25253
+ hasTextBuild: true
25254
+ }
25255
+ ];
25256
+ var EXIT_PRESETS = [
25257
+ {
25258
+ presetId: "exit.1",
25259
+ label: "Disappear",
25260
+ category: "exit",
25261
+ defaultDurationMs: 0,
25262
+ hasDirection: false,
25263
+ hasTextBuild: true
25264
+ },
25265
+ {
25266
+ presetId: "exit.10",
25267
+ label: "Fade",
25268
+ category: "exit",
25269
+ defaultDurationMs: 500,
25270
+ hasDirection: false,
25271
+ hasTextBuild: true
25272
+ },
25273
+ {
25274
+ presetId: "exit.2",
25275
+ label: "Fly Out",
25276
+ category: "exit",
25277
+ defaultDurationMs: 500,
25278
+ hasDirection: true,
25279
+ directions: ["toBottom", "toLeft", "toRight", "toTop"],
25280
+ hasTextBuild: true
25281
+ },
25282
+ {
25283
+ presetId: "exit.23",
25284
+ label: "Zoom",
25285
+ category: "exit",
25286
+ defaultDurationMs: 500,
25287
+ hasDirection: true,
25288
+ directions: ["outFromScreenCenter", "outSlightly", "objectCenter"],
25289
+ hasTextBuild: true
25290
+ },
25291
+ {
25292
+ presetId: "exit.14",
25293
+ label: "Bounce",
25294
+ category: "exit",
25295
+ defaultDurationMs: 1e3,
25296
+ hasDirection: false,
25297
+ hasTextBuild: true
25298
+ },
25299
+ {
25300
+ presetId: "exit.22",
25301
+ label: "Wipe",
25302
+ category: "exit",
25303
+ defaultDurationMs: 500,
25304
+ hasDirection: true,
25305
+ directions: ["fromBottom", "fromLeft", "fromRight", "fromTop"],
25306
+ hasTextBuild: true
25307
+ },
25308
+ {
25309
+ presetId: "exit.9",
25310
+ label: "Dissolve Out",
25311
+ category: "exit",
25312
+ defaultDurationMs: 700,
25313
+ hasDirection: false,
25314
+ hasTextBuild: true
25315
+ },
25316
+ {
25317
+ presetId: "exit.48",
25318
+ label: "Shrink & Turn",
25319
+ category: "exit",
25320
+ defaultDurationMs: 500,
25321
+ hasDirection: false,
25322
+ hasTextBuild: true
25323
+ }
25324
+ ];
25325
+ var EMPHASIS_PRESETS = [
25326
+ {
25327
+ presetId: "emph.32",
25328
+ label: "Pulse",
25329
+ category: "emphasis",
25330
+ defaultDurationMs: 1e3,
25331
+ hasDirection: false,
25332
+ hasTextBuild: false
25333
+ },
25334
+ {
25335
+ presetId: "emph.8",
25336
+ label: "Spin",
25337
+ category: "emphasis",
25338
+ defaultDurationMs: 1e3,
25339
+ hasDirection: true,
25340
+ directions: ["clockwise", "counterClockwise"],
25341
+ hasTextBuild: false
25342
+ },
25343
+ {
25344
+ presetId: "emph.6",
25345
+ label: "Grow/Shrink",
25346
+ category: "emphasis",
25347
+ defaultDurationMs: 500,
25348
+ hasDirection: false,
25349
+ hasTextBuild: false
25350
+ },
25351
+ {
25352
+ presetId: "emph.35",
25353
+ label: "Teeter",
25354
+ category: "emphasis",
25355
+ defaultDurationMs: 1e3,
25356
+ hasDirection: false,
25357
+ hasTextBuild: false
25358
+ },
25359
+ {
25360
+ presetId: "emph.9",
25361
+ label: "Transparency",
25362
+ category: "emphasis",
25363
+ defaultDurationMs: 500,
25364
+ hasDirection: false,
25365
+ hasTextBuild: false
25366
+ },
25367
+ {
25368
+ presetId: "emph.34",
25369
+ label: "Bold Flash",
25370
+ category: "emphasis",
25371
+ defaultDurationMs: 500,
25372
+ hasDirection: false,
25373
+ hasTextBuild: false
25374
+ },
25375
+ {
25376
+ presetId: "emph.36",
25377
+ label: "Wave",
25378
+ category: "emphasis",
25379
+ defaultDurationMs: 1e3,
25380
+ hasDirection: false,
25381
+ hasTextBuild: false
25382
+ }
25383
+ ];
25384
+ var MOTION_PATH_PRESETS = [
25385
+ {
25386
+ presetId: "path.line.down",
25387
+ label: "Lines: Down",
25388
+ category: "motionPath",
25389
+ defaultDurationMs: 2e3,
25390
+ hasDirection: false,
25391
+ hasTextBuild: false
25392
+ },
25393
+ {
25394
+ presetId: "path.line.left",
25395
+ label: "Lines: Left",
25396
+ category: "motionPath",
25397
+ defaultDurationMs: 2e3,
25398
+ hasDirection: false,
25399
+ hasTextBuild: false
25400
+ },
25401
+ {
25402
+ presetId: "path.line.right",
25403
+ label: "Lines: Right",
25404
+ category: "motionPath",
25405
+ defaultDurationMs: 2e3,
25406
+ hasDirection: false,
25407
+ hasTextBuild: false
25408
+ },
25409
+ {
25410
+ presetId: "path.line.up",
25411
+ label: "Lines: Up",
25412
+ category: "motionPath",
25413
+ defaultDurationMs: 2e3,
25414
+ hasDirection: false,
25415
+ hasTextBuild: false
25416
+ },
25417
+ {
25418
+ presetId: "path.arc.down",
25419
+ label: "Arcs: Down",
25420
+ category: "motionPath",
25421
+ defaultDurationMs: 2e3,
25422
+ hasDirection: false,
25423
+ hasTextBuild: false
25424
+ },
25425
+ {
25426
+ presetId: "path.circle",
25427
+ label: "Shapes: Circle",
25428
+ category: "motionPath",
25429
+ defaultDurationMs: 2e3,
25430
+ hasDirection: false,
25431
+ hasTextBuild: false
25432
+ },
25433
+ {
25434
+ presetId: "path.diamond",
25435
+ label: "Shapes: Diamond",
25436
+ category: "motionPath",
25437
+ defaultDurationMs: 2e3,
25438
+ hasDirection: false,
25439
+ hasTextBuild: false
25440
+ },
25441
+ {
25442
+ presetId: "path.custom",
25443
+ label: "Custom Path",
25444
+ category: "motionPath",
25445
+ defaultDurationMs: 2e3,
25446
+ hasDirection: false,
25447
+ hasTextBuild: false
25448
+ }
25449
+ ];
25450
+ var ALL_ANIMATION_PRESETS = [
25451
+ ...ENTRANCE_PRESETS,
25452
+ ...EXIT_PRESETS,
25453
+ ...EMPHASIS_PRESETS,
25454
+ ...MOTION_PATH_PRESETS
25455
+ ];
25456
+ function getAnimationPresetInfo(presetId) {
25457
+ return ALL_ANIMATION_PRESETS.find((p) => p.presetId === presetId);
25458
+ }
25459
+ function getPresetsByCategory(category) {
25460
+ switch (category) {
25461
+ case "entrance":
25462
+ return ENTRANCE_PRESETS;
25463
+ case "exit":
25464
+ return EXIT_PRESETS;
25465
+ case "emphasis":
25466
+ return EMPHASIS_PRESETS;
25467
+ case "motionPath":
25468
+ return MOTION_PATH_PRESETS;
25469
+ }
25470
+ }
25471
+
25472
+ // src/core/utils/smartart-relayout.ts
25473
+ function relayoutSmartArt(smartArtData, containerWidth, containerHeight) {
25474
+ if (!smartArtData.nodes || smartArtData.nodes.length === 0) {
25475
+ return [];
25476
+ }
25477
+ const bounds = {
25478
+ x: 0,
25479
+ y: 0,
25480
+ width: containerWidth,
25481
+ height: containerHeight
25482
+ };
25483
+ const engineShapes = computeSmartArtLayout(smartArtData, bounds);
25484
+ if (engineShapes && engineShapes.length > 0) {
25485
+ const layoutType = smartArtData.resolvedLayoutType ?? "list";
25486
+ return layoutEngineShapesToDrawingShapes(engineShapes, smartArtData.nodes, layoutType);
25487
+ }
25488
+ return smartArtData.drawingShapes ?? [];
25489
+ }
25490
+
24487
25491
  // src/core/core/runtime/PptxHandlerRuntimeSaveParagraphHelpers.ts
24488
25492
  var EMU_PER_PX5 = 9525;
24489
25493
  function buildParagraphPropertiesXml(textStyle, paragraphAlign, bulletInfo, spacing) {
@@ -24494,12 +25498,6 @@ function buildParagraphPropertiesXml(textStyle, paragraphAlign, bulletInfo, spac
24494
25498
  if (textStyle?.rtl !== void 0) {
24495
25499
  paragraphProps["@_rtl"] = textStyle.rtl ? "1" : "0";
24496
25500
  }
24497
- if (spacing.spacingBefore) {
24498
- paragraphProps["a:spcBef"] = spacing.spacingBefore;
24499
- }
24500
- if (spacing.spacingAfter) {
24501
- paragraphProps["a:spcAft"] = spacing.spacingAfter;
24502
- }
24503
25501
  if (spacing.lineSpacing) {
24504
25502
  paragraphProps["a:lnSpc"] = spacing.lineSpacing;
24505
25503
  } else if (typeof spacing.lineSpacingExactPt === "number" && Number.isFinite(spacing.lineSpacingExactPt)) {
@@ -24509,6 +25507,12 @@ function buildParagraphPropertiesXml(textStyle, paragraphAlign, bulletInfo, spac
24509
25507
  }
24510
25508
  };
24511
25509
  }
25510
+ if (spacing.spacingBefore) {
25511
+ paragraphProps["a:spcBef"] = spacing.spacingBefore;
25512
+ }
25513
+ if (spacing.spacingAfter) {
25514
+ paragraphProps["a:spcAft"] = spacing.spacingAfter;
25515
+ }
24512
25516
  if (typeof textStyle?.paragraphMarginLeft === "number" && Number.isFinite(textStyle.paragraphMarginLeft)) {
24513
25517
  paragraphProps["@_marL"] = String(Math.round(textStyle.paragraphMarginLeft * EMU_PER_PX5));
24514
25518
  }
@@ -24559,9 +25563,10 @@ function applyBulletProperties(paragraphProps, bulletInfo) {
24559
25563
  paragraphProps["a:buNone"] = {};
24560
25564
  return;
24561
25565
  }
24562
- if (bulletInfo.fontFamily) {
24563
- paragraphProps["a:buFont"] = {
24564
- "@_typeface": bulletInfo.fontFamily
25566
+ if (bulletInfo.color) {
25567
+ const colorHex = bulletInfo.color.replace("#", "");
25568
+ paragraphProps["a:buClr"] = {
25569
+ "a:srgbClr": { "@_val": colorHex }
24565
25570
  };
24566
25571
  }
24567
25572
  if (bulletInfo.sizePercent !== void 0) {
@@ -24574,10 +25579,9 @@ function applyBulletProperties(paragraphProps, bulletInfo) {
24574
25579
  "@_val": String(Math.round(bulletInfo.sizePts * 100))
24575
25580
  };
24576
25581
  }
24577
- if (bulletInfo.color) {
24578
- const colorHex = bulletInfo.color.replace("#", "");
24579
- paragraphProps["a:buClr"] = {
24580
- "a:srgbClr": { "@_val": colorHex }
25582
+ if (bulletInfo.fontFamily) {
25583
+ paragraphProps["a:buFont"] = {
25584
+ "@_typeface": bulletInfo.fontFamily
24581
25585
  };
24582
25586
  }
24583
25587
  if (bulletInfo.char) {
@@ -24600,9 +25604,8 @@ function applyBulletProperties(paragraphProps, bulletInfo) {
24600
25604
  }
24601
25605
  function assembleParagraphXml(runs, paragraphProps) {
24602
25606
  const paragraph = {
24603
- "a:endParaRPr": { "@_lang": "en-US" }
25607
+ "a:pPr": paragraphProps
24604
25608
  };
24605
- paragraph["a:pPr"] = paragraphProps;
24606
25609
  const regularRuns = runs.filter((r) => !r.__isField);
24607
25610
  const fieldRuns = runs.filter((r) => r.__isField).map((r) => {
24608
25611
  const { __isField, ...rest } = r;
@@ -24621,6 +25624,7 @@ function assembleParagraphXml(runs, paragraphProps) {
24621
25624
  if (cleanRegularRuns.length === 0 && fieldRuns.length === 0) {
24622
25625
  paragraph["a:r"] = runs.length > 1 ? runs : runs[0];
24623
25626
  }
25627
+ paragraph["a:endParaRPr"] = { "@_lang": "en-US" };
24624
25628
  return paragraph;
24625
25629
  }
24626
25630
  function computeUniformSegmentOverrides(textStyle, textSegments) {
@@ -27459,9 +28463,6 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
27459
28463
  if (style.textCaps && style.textCaps !== "none") {
27460
28464
  runProps["@_cap"] = style.textCaps;
27461
28465
  }
27462
- if (style.rtl !== void 0) {
27463
- runProps["@_rtl"] = style.rtl ? "1" : "0";
27464
- }
27465
28466
  if (style.kumimoji !== void 0) {
27466
28467
  runProps["@_kumimoji"] = style.kumimoji ? "1" : "0";
27467
28468
  }
@@ -27483,17 +28484,19 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
27483
28484
  if (style.bookmark) {
27484
28485
  runProps["@_bmk"] = style.bookmark;
27485
28486
  }
27486
- if (style.fontFamily) {
27487
- runProps["a:latin"] = { "@_typeface": style.fontFamily };
27488
- runProps["a:ea"] = {
27489
- "@_typeface": style.eastAsiaFont || style.fontFamily
27490
- };
27491
- runProps["a:cs"] = {
27492
- "@_typeface": style.complexScriptFont || style.fontFamily
27493
- };
27494
- }
27495
- if (style.symbolFont) {
27496
- runProps["a:sym"] = { "@_typeface": style.symbolFont };
28487
+ if (style.textOutlineWidth || style.textOutlineColor) {
28488
+ const lnObj = {};
28489
+ if (typeof style.textOutlineWidth === "number" && style.textOutlineWidth > 0) {
28490
+ lnObj["@_w"] = String(Math.round(style.textOutlineWidth * _PptxHandlerRuntime.EMU_PER_PX));
28491
+ }
28492
+ if (style.textOutlineColor) {
28493
+ lnObj["a:solidFill"] = {
28494
+ "a:srgbClr": {
28495
+ "@_val": style.textOutlineColor.replace("#", "")
28496
+ }
28497
+ };
28498
+ }
28499
+ runProps["a:ln"] = lnObj;
27497
28500
  }
27498
28501
  if (style.color) {
27499
28502
  runProps["a:solidFill"] = {
@@ -27501,15 +28504,7 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
27501
28504
  "@_val": style.color.replace("#", "")
27502
28505
  }
27503
28506
  };
27504
- }
27505
- if (style.highlightColor) {
27506
- runProps["a:highlight"] = {
27507
- "a:srgbClr": {
27508
- "@_val": style.highlightColor.replace("#", "")
27509
- }
27510
- };
27511
- }
27512
- if (style.textFillGradientStops && style.textFillGradientStops.length > 0) {
28507
+ } else if (style.textFillGradientStops && style.textFillGradientStops.length > 0) {
27513
28508
  const gradStops = style.textFillGradientStops.filter((stop) => Boolean(stop?.color)).map((stop) => {
27514
28509
  const rawPos = (stop.position ?? 0) / 100;
27515
28510
  const posVal = Math.round(Math.max(0, Math.min(1, rawPos)) * 1e5);
@@ -27542,8 +28537,7 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
27542
28537
  }
27543
28538
  runProps["a:gradFill"] = gradFillXml;
27544
28539
  }
27545
- }
27546
- if (style.textFillPattern) {
28540
+ } else if (style.textFillPattern) {
27547
28541
  const pattFill = { "@_prst": style.textFillPattern };
27548
28542
  if (style.textFillPatternForeground) {
27549
28543
  pattFill["a:fgClr"] = {
@@ -27561,6 +28555,17 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
27561
28555
  }
27562
28556
  runProps["a:pattFill"] = pattFill;
27563
28557
  }
28558
+ const textEffectLst = buildTextRunEffectListXml(style);
28559
+ if (textEffectLst) {
28560
+ runProps["a:effectLst"] = textEffectLst;
28561
+ }
28562
+ if (style.highlightColor) {
28563
+ runProps["a:highlight"] = {
28564
+ "a:srgbClr": {
28565
+ "@_val": style.highlightColor.replace("#", "")
28566
+ }
28567
+ };
28568
+ }
27564
28569
  if (style.underline && style.underlineColor) {
27565
28570
  runProps["a:uFill"] = {
27566
28571
  "a:solidFill": {
@@ -27570,23 +28575,17 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
27570
28575
  }
27571
28576
  };
27572
28577
  }
27573
- if (style.textOutlineWidth || style.textOutlineColor) {
27574
- const lnObj = {};
27575
- if (typeof style.textOutlineWidth === "number" && style.textOutlineWidth > 0) {
27576
- lnObj["@_w"] = String(Math.round(style.textOutlineWidth * _PptxHandlerRuntime.EMU_PER_PX));
27577
- }
27578
- if (style.textOutlineColor) {
27579
- lnObj["a:solidFill"] = {
27580
- "a:srgbClr": {
27581
- "@_val": style.textOutlineColor.replace("#", "")
27582
- }
27583
- };
27584
- }
27585
- runProps["a:ln"] = lnObj;
28578
+ if (style.fontFamily) {
28579
+ runProps["a:latin"] = { "@_typeface": style.fontFamily };
28580
+ runProps["a:ea"] = {
28581
+ "@_typeface": style.eastAsiaFont || style.fontFamily
28582
+ };
28583
+ runProps["a:cs"] = {
28584
+ "@_typeface": style.complexScriptFont || style.fontFamily
28585
+ };
27586
28586
  }
27587
- const textEffectLst = buildTextRunEffectListXml(style);
27588
- if (textEffectLst) {
27589
- runProps["a:effectLst"] = textEffectLst;
28587
+ if (style.symbolFont) {
28588
+ runProps["a:sym"] = { "@_typeface": style.symbolFont };
27590
28589
  }
27591
28590
  if (style.hyperlink && resolveHyperlinkRelationshipId) {
27592
28591
  const hyperlinkTarget = String(style.hyperlink).trim();
@@ -27834,6 +28833,55 @@ var PptxHandlerRuntime14 = class extends PptxHandlerRuntime13 {
27834
28833
 
27835
28834
  // src/core/core/runtime/PptxHandlerRuntimeSaveShapeXml.ts
27836
28835
  var PptxHandlerRuntime15 = class _PptxHandlerRuntime extends PptxHandlerRuntime14 {
28836
+ /**
28837
+ * Build a `p:graphicFrame` XML skeleton for an SDK-created table.
28838
+ *
28839
+ * Tables round-trip as `<p:graphicFrame>/<a:graphic>/<a:graphicData
28840
+ * uri=".../drawingml/2006/table">/<a:tbl>` inside `p:spTree`. When the
28841
+ * element was loaded from an existing file, `el.rawXml` already contains
28842
+ * this envelope and the downstream `serializeTableDataToXml` path
28843
+ * populates cells in place. When the element was created via the SDK
28844
+ * (`SlideBuilder.addTable`), there is no `rawXml`, so this method
28845
+ * fabricates a minimal envelope with an empty `a:tbl`. The element
28846
+ * writer then calls `serializeTableDataToXml`, which triggers
28847
+ * `rebuildTableXmlFromData` and fills in `a:tblGrid` / `a:tr` children.
28848
+ */
28849
+ createTableGraphicFrameXml(el) {
28850
+ const EMU = _PptxHandlerRuntime.EMU_PER_PX;
28851
+ const offX = String(Math.round(el.x * EMU));
28852
+ const offY = String(Math.round(el.y * EMU));
28853
+ const extCx = String(Math.round(Math.max(el.width, 1) * EMU));
28854
+ const extCy = String(Math.round(Math.max(el.height, 1) * EMU));
28855
+ const tblPr = {
28856
+ "@_firstRow": el.tableData?.firstRowHeader ? "1" : "0",
28857
+ "@_bandRow": el.tableData?.bandedRows ? "1" : "0"
28858
+ };
28859
+ if (el.tableData?.tableStyleId) {
28860
+ tblPr["a:tableStyleId"] = el.tableData.tableStyleId;
28861
+ }
28862
+ return {
28863
+ "p:nvGraphicFramePr": {
28864
+ "p:cNvPr": { "@_id": "0", "@_name": el.name || "Table" },
28865
+ "p:cNvGraphicFramePr": {
28866
+ "a:graphicFrameLocks": { "@_noGrp": "1" }
28867
+ },
28868
+ "p:nvPr": {}
28869
+ },
28870
+ "p:xfrm": {
28871
+ "a:off": { "@_x": offX, "@_y": offY },
28872
+ "a:ext": { "@_cx": extCx, "@_cy": extCy }
28873
+ },
28874
+ "a:graphic": {
28875
+ "a:graphicData": {
28876
+ "@_uri": "http://schemas.openxmlformats.org/drawingml/2006/table",
28877
+ "a:tbl": {
28878
+ "a:tblPr": tblPr,
28879
+ "a:tblGrid": {}
28880
+ }
28881
+ }
28882
+ }
28883
+ };
28884
+ }
27837
28885
  /**
27838
28886
  * Build a p:sp XML object for an ink annotation element.
27839
28887
  * Each ink path becomes a separate a:path within a:pathLst,
@@ -29315,14 +30363,15 @@ function writeCellTextFormatting(xmlCell, style, ensureArray6) {
29315
30363
  const paragraphs = ensureArray6(xmlCell["a:txBody"]?.["a:p"]);
29316
30364
  for (const paragraph of paragraphs) {
29317
30365
  const runs = ensureArray6(paragraph?.["a:r"]);
30366
+ const rebuiltRuns = [];
30367
+ let runsChanged = false;
29318
30368
  for (const run of runs) {
29319
30369
  if (!run) {
30370
+ rebuiltRuns.push(run);
29320
30371
  continue;
29321
30372
  }
29322
- if (!run["a:rPr"]) {
29323
- run["a:rPr"] = {};
29324
- }
29325
- const rPr = run["a:rPr"];
30373
+ const existingRPr = run["a:rPr"] ?? {};
30374
+ const rPr = { ...existingRPr };
29326
30375
  if (style.bold !== void 0) {
29327
30376
  rPr["@_b"] = style.bold ? "1" : "0";
29328
30377
  }
@@ -29342,6 +30391,18 @@ function writeCellTextFormatting(xmlCell, style, ensureArray6) {
29342
30391
  }
29343
30392
  };
29344
30393
  }
30394
+ const rebuilt = { "a:rPr": rPr };
30395
+ for (const key of Object.keys(run)) {
30396
+ if (key === "a:rPr") {
30397
+ continue;
30398
+ }
30399
+ rebuilt[key] = run[key];
30400
+ }
30401
+ rebuiltRuns.push(rebuilt);
30402
+ runsChanged = true;
30403
+ }
30404
+ if (runsChanged && rebuiltRuns.length > 0) {
30405
+ paragraph["a:r"] = rebuiltRuns.length === 1 ? rebuiltRuns[0] : rebuiltRuns;
29345
30406
  }
29346
30407
  }
29347
30408
  }
@@ -29363,6 +30424,9 @@ var PptxHandlerRuntime22 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
29363
30424
  const existingParagraphs = this.ensureArray(txBody["a:p"]);
29364
30425
  const firstRPr = this.ensureArray(existingParagraphs[0]?.["a:r"])[0]?.["a:rPr"];
29365
30426
  const firstPPr = existingParagraphs[0]?.["a:pPr"];
30427
+ const firstEndParaRPr = existingParagraphs[0]?.["a:endParaRPr"];
30428
+ const rPrForRun = firstRPr ? { ...firstRPr } : { "@_lang": "en-US", "@_dirty": "0" };
30429
+ const endParaRPr = firstEndParaRPr ? { ...firstEndParaRPr } : { "@_lang": "en-US", "@_dirty": "0" };
29366
30430
  const lines = text.split("\n");
29367
30431
  const paragraphs = lines.map((line) => {
29368
30432
  const paragraph = {};
@@ -29370,9 +30434,10 @@ var PptxHandlerRuntime22 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
29370
30434
  paragraph["a:pPr"] = firstPPr;
29371
30435
  }
29372
30436
  paragraph["a:r"] = {
29373
- ...firstRPr ? { "a:rPr": firstRPr } : {},
30437
+ "a:rPr": rPrForRun,
29374
30438
  "a:t": line
29375
30439
  };
30440
+ paragraph["a:endParaRPr"] = endParaRPr;
29376
30441
  return paragraph;
29377
30442
  });
29378
30443
  txBody["a:p"] = paragraphs.length === 1 ? paragraphs[0] : paragraphs;
@@ -29522,14 +30587,27 @@ function serializeCellMergeAttributes(xmlCell, cell) {
29522
30587
  delete xmlCell["@_vMerge"];
29523
30588
  }
29524
30589
  }
30590
+ var DEFAULT_POWERPOINT_TABLE_STYLE_ID = "{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}";
29525
30591
  function serializeTablePropertyFlags(tbl, tableData) {
29526
30592
  const tblPr = tbl["a:tblPr"] ?? {};
29527
- tblPr["@_bandRow"] = tableData.bandedRows ? "1" : "0";
29528
- tblPr["@_bandCol"] = tableData.bandedColumns ? "1" : "0";
29529
- tblPr["@_firstRow"] = tableData.firstRowHeader ? "1" : "0";
29530
- tblPr["@_lastRow"] = tableData.lastRow ? "1" : "0";
29531
- tblPr["@_firstCol"] = tableData.firstCol ? "1" : "0";
29532
- tblPr["@_lastCol"] = tableData.lastCol ? "1" : "0";
30593
+ const setOrDelete = (key, truthy) => {
30594
+ if (truthy) {
30595
+ tblPr[key] = "1";
30596
+ } else {
30597
+ delete tblPr[key];
30598
+ }
30599
+ };
30600
+ setOrDelete("@_bandRow", tableData.bandedRows);
30601
+ setOrDelete("@_bandCol", tableData.bandedColumns);
30602
+ setOrDelete("@_firstRow", tableData.firstRowHeader);
30603
+ setOrDelete("@_lastRow", tableData.lastRow);
30604
+ setOrDelete("@_firstCol", tableData.firstCol);
30605
+ setOrDelete("@_lastCol", tableData.lastCol);
30606
+ if (tableData.tableStyleId) {
30607
+ tblPr["a:tableStyleId"] = tableData.tableStyleId;
30608
+ } else if (!tblPr["a:tableStyleId"]) {
30609
+ tblPr["a:tableStyleId"] = DEFAULT_POWERPOINT_TABLE_STYLE_ID;
30610
+ }
29533
30611
  tbl["a:tblPr"] = tblPr;
29534
30612
  }
29535
30613
  function replaceFirstTextValueInTree(node, localName, newValue, getXmlLocalName) {
@@ -29574,7 +30652,9 @@ function createDefaultXmlCell() {
29574
30652
  "a:bodyPr": {},
29575
30653
  "a:lstStyle": {},
29576
30654
  "a:p": {
29577
- "a:endParaRPr": { "@_lang": "en-US" }
30655
+ // Match PowerPoint's "Insert Table" default: every paragraph-end
30656
+ // run carries `lang="en-US" dirty="0"`.
30657
+ "a:endParaRPr": { "@_lang": "en-US", "@_dirty": "0" }
29578
30658
  }
29579
30659
  },
29580
30660
  "a:tcPr": {}
@@ -29582,6 +30662,11 @@ function createDefaultXmlCell() {
29582
30662
  }
29583
30663
 
29584
30664
  // src/core/core/runtime/table-xml-rebuild.ts
30665
+ var GRID_COL_ID_EXT_URI = "{9D8B030D-6E8A-4147-A177-3AD203B41FA5}";
30666
+ var A16_NAMESPACE = "http://schemas.microsoft.com/office/drawing/2014/main";
30667
+ function randomColumnId() {
30668
+ return String(Math.floor(Math.random() * 4294967295));
30669
+ }
29585
30670
  function rebuildTableXmlFromData(tbl, tableData, emuPerPx, ensureArrayFn) {
29586
30671
  const existingXmlRows = ensureArrayFn(tbl["a:tr"]);
29587
30672
  const existingGridCols = ensureArrayFn(
@@ -29590,8 +30675,31 @@ function rebuildTableXmlFromData(tbl, tableData, emuPerPx, ensureArrayFn) {
29590
30675
  const totalWidthEmu = existingGridCols.reduce((sum, col) => {
29591
30676
  return sum + (parseInt(String(col?.["@_w"] || "0"), 10) || 0);
29592
30677
  }, 0) || 9144e3;
29593
- const newGridCols = tableData.columnWidths.map((w) => ({
29594
- "@_w": String(Math.round(w * totalWidthEmu))
30678
+ const existingColIds = existingGridCols.map((col) => {
30679
+ const extList = col?.["a:extLst"];
30680
+ const exts = Array.isArray(extList?.["a:ext"]) ? extList["a:ext"] : extList?.["a:ext"] ? [extList["a:ext"]] : [];
30681
+ for (const ext of exts) {
30682
+ if (ext?.["@_uri"] === GRID_COL_ID_EXT_URI) {
30683
+ const colId = ext["a16:colId"];
30684
+ const val = colId?.["@_val"];
30685
+ if (typeof val === "string" && val.length > 0) {
30686
+ return val;
30687
+ }
30688
+ }
30689
+ }
30690
+ return "";
30691
+ });
30692
+ const newGridCols = tableData.columnWidths.map((w, i) => ({
30693
+ "@_w": String(Math.round(w * totalWidthEmu)),
30694
+ "a:extLst": {
30695
+ "a:ext": {
30696
+ "@_uri": GRID_COL_ID_EXT_URI,
30697
+ "a16:colId": {
30698
+ "@_xmlns:a16": A16_NAMESPACE,
30699
+ "@_val": existingColIds[i] || randomColumnId()
30700
+ }
30701
+ }
30702
+ }
29595
30703
  }));
29596
30704
  if (!tbl["a:tblGrid"]) {
29597
30705
  tbl["a:tblGrid"] = {};
@@ -30507,32 +31615,58 @@ var PptxHandlerRuntime24 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
30507
31615
  };
30508
31616
  for (const variant of variants) {
30509
31617
  const fontData = variant.rawFontData;
30510
- const guid = variant.fontGuid ?? generateFontGuid();
30511
- const fileName = `{${guid}}.fntdata`;
30512
- const fontPartPath = `ppt/fonts/${fileName}`;
30513
- const relativeTarget = `fonts/${fileName}`;
30514
- const obfuscated = obfuscateFont(fontData, guid);
30515
- this.zip.file(fontPartPath, obfuscated);
31618
+ const hasOriginal = Boolean(variant.originalRId && variant.partPath);
31619
+ const reuseObfuscation = hasOriginal && Boolean(variant.fontGuid);
31620
+ const reuseVerbatim = hasOriginal && !variant.fontGuid && Boolean(variant.originalPartBytes);
31621
+ let guid;
31622
+ let fontPartPath;
31623
+ let relativeTarget;
30516
31624
  let rId;
30517
- const existingRel = relationships.find(
30518
- (r) => String(r?.["@_Target"] || "") === relativeTarget
30519
- );
30520
- if (existingRel) {
30521
- rId = String(existingRel["@_Id"]);
31625
+ let bytesToWrite;
31626
+ let fontKeyForXml;
31627
+ if (reuseObfuscation) {
31628
+ guid = variant.fontGuid;
31629
+ fontPartPath = variant.partPath;
31630
+ relativeTarget = fontPartPath.startsWith("ppt/") ? fontPartPath.substring(4) : fontPartPath;
31631
+ rId = variant.originalRId;
31632
+ bytesToWrite = obfuscateFont(fontData, guid);
31633
+ fontKeyForXml = `{${guid}}`;
31634
+ } else if (reuseVerbatim) {
31635
+ guid = "";
31636
+ fontPartPath = variant.partPath;
31637
+ relativeTarget = fontPartPath.startsWith("ppt/") ? fontPartPath.substring(4) : fontPartPath;
31638
+ rId = variant.originalRId;
31639
+ bytesToWrite = variant.originalPartBytes;
31640
+ fontKeyForXml = void 0;
30522
31641
  } else {
30523
- maxId++;
30524
- rId = `rId${maxId}`;
30525
- relationships.push({
30526
- "@_Id": rId,
30527
- "@_Type": _PptxHandlerRuntime.FONT_REL_TYPE,
30528
- "@_Target": relativeTarget
30529
- });
31642
+ guid = variant.fontGuid ?? generateFontGuid();
31643
+ const fileName = `{${guid}}.fntdata`;
31644
+ fontPartPath = `ppt/fonts/${fileName}`;
31645
+ relativeTarget = `fonts/${fileName}`;
31646
+ bytesToWrite = obfuscateFont(fontData, guid);
31647
+ fontKeyForXml = `{${guid}}`;
31648
+ const existingRel = relationships.find(
31649
+ (r) => String(r?.["@_Target"] || "") === relativeTarget
31650
+ );
31651
+ if (existingRel) {
31652
+ rId = String(existingRel["@_Id"]);
31653
+ } else {
31654
+ maxId++;
31655
+ rId = `rId${maxId}`;
31656
+ relationships.push({
31657
+ "@_Id": rId,
31658
+ "@_Type": _PptxHandlerRuntime.FONT_REL_TYPE,
31659
+ "@_Target": relativeTarget
31660
+ });
31661
+ }
30530
31662
  }
31663
+ this.zip.file(fontPartPath, bytesToWrite);
30531
31664
  const variantKey = variant.bold && variant.italic ? "p:boldItalic" : variant.bold ? "p:bold" : variant.italic ? "p:italic" : "p:regular";
30532
- entry[variantKey] = {
30533
- "@_r:id": rId,
30534
- "@_fontKey": `{${guid}}`
30535
- };
31665
+ const variantEntry = { "@_r:id": rId };
31666
+ if (fontKeyForXml) {
31667
+ variantEntry["@_fontKey"] = fontKeyForXml;
31668
+ }
31669
+ entry[variantKey] = variantEntry;
30536
31670
  }
30537
31671
  embeddedFontEntries.push(entry);
30538
31672
  }
@@ -30676,54 +31810,59 @@ var PptxHandlerRuntime25 = class extends PptxHandlerRuntime24 {
30676
31810
  }
30677
31811
  };
30678
31812
  const root = propsData["p:presentationPr"] || {};
30679
- const showPr = root["p:showPr"] || {};
30680
- delete showPr["p:present"];
30681
- delete showPr["p:browse"];
30682
- delete showPr["p:kiosk"];
30683
- if (properties.showType === "browsed") {
30684
- showPr["p:browse"] = {};
30685
- } else if (properties.showType === "kiosk") {
30686
- const kioskNode = {};
30687
- if (properties.kioskRestartTime !== void 0 && properties.kioskRestartTime > 0) {
30688
- kioskNode["@_restart"] = String(properties.kioskRestartTime);
31813
+ const existingShowPr = root["p:showPr"] || {};
31814
+ const rebuiltShowPr = {};
31815
+ for (const key of Object.keys(existingShowPr)) {
31816
+ if (key.startsWith("@_")) {
31817
+ rebuiltShowPr[key] = existingShowPr[key];
30689
31818
  }
30690
- showPr["p:kiosk"] = kioskNode;
30691
- } else {
30692
- showPr["p:present"] = {};
30693
31819
  }
30694
31820
  if (properties.loopContinuously !== void 0) {
30695
- showPr["@_loop"] = properties.loopContinuously ? "1" : "0";
31821
+ rebuiltShowPr["@_loop"] = properties.loopContinuously ? "1" : "0";
30696
31822
  }
30697
31823
  if (properties.showWithNarration !== void 0) {
30698
- showPr["@_showNarration"] = properties.showWithNarration ? "1" : "0";
31824
+ rebuiltShowPr["@_showNarration"] = properties.showWithNarration ? "1" : "0";
30699
31825
  }
30700
31826
  if (properties.showWithAnimation !== void 0) {
30701
- showPr["@_showAnimation"] = properties.showWithAnimation ? "1" : "0";
31827
+ rebuiltShowPr["@_showAnimation"] = properties.showWithAnimation ? "1" : "0";
30702
31828
  }
30703
31829
  if (properties.advanceMode !== void 0) {
30704
- showPr["@_useTimings"] = properties.advanceMode === "useTimings" ? "1" : "0";
31830
+ rebuiltShowPr["@_useTimings"] = properties.advanceMode === "useTimings" ? "1" : "0";
30705
31831
  }
30706
- if (properties.penColor) {
30707
- showPr["p:penClr"] = {
30708
- "a:srgbClr": { "@_val": properties.penColor.replace("#", "") }
30709
- };
31832
+ if (properties.showType === "browsed") {
31833
+ rebuiltShowPr["p:browse"] = {};
31834
+ } else if (properties.showType === "kiosk") {
31835
+ const kioskNode = {};
31836
+ if (properties.kioskRestartTime !== void 0 && properties.kioskRestartTime > 0) {
31837
+ kioskNode["@_restart"] = String(properties.kioskRestartTime);
31838
+ }
31839
+ rebuiltShowPr["p:kiosk"] = kioskNode;
31840
+ } else {
31841
+ rebuiltShowPr["p:present"] = {};
30710
31842
  }
30711
- delete showPr["p:sldAll"];
30712
- delete showPr["p:sldRg"];
30713
- delete showPr["p:custShow"];
30714
31843
  if (properties.showSlidesMode === "range") {
30715
- showPr["p:sldRg"] = {
31844
+ rebuiltShowPr["p:sldRg"] = {
30716
31845
  "@_st": String(properties.showSlidesFrom ?? 1),
30717
31846
  "@_end": String(properties.showSlidesTo ?? 1)
30718
31847
  };
30719
31848
  } else if (properties.showSlidesMode === "customShow" && properties.showSlidesCustomShowId) {
30720
- showPr["p:custShow"] = {
31849
+ rebuiltShowPr["p:custShow"] = {
30721
31850
  "@_id": properties.showSlidesCustomShowId
30722
31851
  };
30723
31852
  } else {
30724
- showPr["p:sldAll"] = {};
31853
+ rebuiltShowPr["p:sldAll"] = {};
31854
+ }
31855
+ if (properties.penColor) {
31856
+ rebuiltShowPr["p:penClr"] = {
31857
+ "a:srgbClr": { "@_val": properties.penColor.replace("#", "") }
31858
+ };
31859
+ } else if (existingShowPr["p:penClr"] !== void 0) {
31860
+ rebuiltShowPr["p:penClr"] = existingShowPr["p:penClr"];
30725
31861
  }
30726
- root["p:showPr"] = showPr;
31862
+ if (existingShowPr["p:extLst"] !== void 0) {
31863
+ rebuiltShowPr["p:extLst"] = existingShowPr["p:extLst"];
31864
+ }
31865
+ root["p:showPr"] = rebuiltShowPr;
30727
31866
  if (properties.printFrameSlides !== void 0 || properties.printSlidesPerPage !== void 0 || properties.printColorMode !== void 0) {
30728
31867
  const prnPr = root["p:prnPr"] || {};
30729
31868
  if (properties.printFrameSlides !== void 0) {
@@ -31854,7 +32993,12 @@ var PptxHandlerRuntime31 = class extends PptxHandlerRuntime30 {
31854
32993
  shape = this.createPictureXml(el, relationshipId);
31855
32994
  }
31856
32995
  if (targetImagePath) {
31857
- this.zip.file(targetImagePath, parsedImage.bytes);
32996
+ const targetExt = targetImagePath.toLowerCase().match(/\.([^./\\]+)$/)?.[1];
32997
+ const parsedExt = parsedImage.extension.toLowerCase();
32998
+ const extensionMismatch = targetExt !== void 0 && targetExt !== parsedExt && !(targetExt === "jpg" && parsedExt === "jpeg") && !(targetExt === "jpeg" && parsedExt === "jpg");
32999
+ if (!extensionMismatch) {
33000
+ this.zip.file(targetImagePath, parsedImage.bytes);
33001
+ }
31858
33002
  }
31859
33003
  } else {
31860
33004
  this.compatibilityService.reportWarning({
@@ -31965,6 +33109,9 @@ var PptxHandlerRuntime32 = class _PptxHandlerRuntime extends PptxHandlerRuntime3
31965
33109
  if (!shape && el.type === "ink") {
31966
33110
  shape = this.createInkShapeXml(el);
31967
33111
  }
33112
+ if (!shape && el.type === "table") {
33113
+ shape = this.createTableGraphicFrameXml(el);
33114
+ }
31968
33115
  if (!shape) {
31969
33116
  this.compatibilityService.reportWarning({
31970
33117
  code: "SAVE_ELEMENT_SKIPPED",
@@ -32259,6 +33406,7 @@ var PptxHandlerRuntime34 = class _PptxHandlerRuntime extends PptxHandlerRuntime3
32259
33406
  );
32260
33407
  } else {
32261
33408
  this.zip.remove("ppt/commentAuthors.xml");
33409
+ await this.stripPresentationCommentAuthorsRelationship();
32262
33410
  }
32263
33411
  const contentTypesXmlAfterComments = await this.zip.file("[Content_Types].xml")?.async("string");
32264
33412
  if (contentTypesXmlAfterComments) {
@@ -32332,8 +33480,39 @@ var PptxHandlerRuntime34 = class _PptxHandlerRuntime extends PptxHandlerRuntime3
32332
33480
  if (effectiveConformance === "strict") {
32333
33481
  await this.convertZipToStrictConformance();
32334
33482
  }
33483
+ for (const name of Object.keys(this.zip.files)) {
33484
+ if (this.zip.files[name].dir) {
33485
+ delete this.zip.files[name];
33486
+ }
33487
+ }
32335
33488
  return await this.zip.generateAsync({ type: "uint8array" });
32336
33489
  }
33490
+ /**
33491
+ * Remove any Relationship in presentation.xml.rels whose Type matches either
33492
+ * the Transitional or Strict commentAuthors relationship URI.
33493
+ */
33494
+ async stripPresentationCommentAuthorsRelationship() {
33495
+ const relsPath = "ppt/_rels/presentation.xml.rels";
33496
+ const relsXml = await this.zip.file(relsPath)?.async("string");
33497
+ if (!relsXml) {
33498
+ return;
33499
+ }
33500
+ const relsData = this.parser.parse(relsXml);
33501
+ const root = relsData["Relationships"];
33502
+ if (!root) {
33503
+ return;
33504
+ }
33505
+ const relationships = this.ensureArray(root["Relationship"]);
33506
+ const filtered = relationships.filter((relationship) => {
33507
+ const type = String(relationship?.["@_Type"] ?? "");
33508
+ return type !== "http://schemas.openxmlformats.org/officeDocument/2006/relationships/commentAuthors" && type !== "http://purl.oclc.org/ooxml/officeDocument/relationships/commentAuthors";
33509
+ });
33510
+ if (filtered.length === relationships.length) {
33511
+ return;
33512
+ }
33513
+ root["Relationship"] = filtered;
33514
+ this.zip.file(relsPath, this.builder.build(relsData));
33515
+ }
32337
33516
  };
32338
33517
 
32339
33518
  // src/core/core/runtime/PptxHandlerRuntimeElementParsing.ts
@@ -34318,7 +35497,7 @@ var PptxHandlerRuntime44 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
34318
35497
  }
34319
35498
  const shapeStyle = this.extractShapeStyle(effectiveSpPr, styleNode);
34320
35499
  const hasText = text.trim().length > 0;
34321
- const isPlainRect = !prstGeom || prstGeom === "rect";
35500
+ const isPlainRect = (!prstGeom || prstGeom === "rect") && !custGeom;
34322
35501
  const hasVisibleStyle = shapeStyle.fillColor && shapeStyle.fillColor !== "transparent" || (shapeStyle.strokeWidth || 0) > 0;
34323
35502
  let type = "shape";
34324
35503
  if (hasText && isPlainRect && !hasVisibleStyle) {
@@ -34330,6 +35509,7 @@ var PptxHandlerRuntime44 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
34330
35509
  slideRelationshipMap,
34331
35510
  this.orderedSlidePaths
34332
35511
  );
35512
+ const elementName = cNvPrForActions?.["@_name"] ? String(cNvPrForActions["@_name"]).trim() : void 0;
34333
35513
  const cNvSpPr = shape?.["p:nvSpPr"]?.["p:cNvSpPr"];
34334
35514
  const spLocksNode = cNvSpPr?.["a:spLocks"];
34335
35515
  const slideLocks = this.parseShapeLocks(spLocksNode);
@@ -34340,6 +35520,7 @@ var PptxHandlerRuntime44 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
34340
35520
  const promptText = !hasText && phDefaults?.promptText ? phDefaults.promptText : void 0;
34341
35521
  const commonProps = {
34342
35522
  id,
35523
+ name: elementName || void 0,
34343
35524
  x,
34344
35525
  y,
34345
35526
  width,
@@ -34576,12 +35757,14 @@ var PptxHandlerRuntime45 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
34576
35757
  picSlideRels,
34577
35758
  this.orderedSlidePaths
34578
35759
  );
35760
+ const picElementName = picCNvPr?.["@_name"] ? String(picCNvPr["@_name"]).trim() : void 0;
34579
35761
  const picCNvPicPr = pic?.["p:nvPicPr"]?.["p:cNvPicPr"];
34580
35762
  const picLocks = this.parseShapeLocks(
34581
35763
  picCNvPicPr?.["a:picLocks"] ?? picCNvPicPr?.["a:spLocks"]
34582
35764
  );
34583
35765
  return {
34584
35766
  id,
35767
+ name: picElementName || void 0,
34585
35768
  type: "picture",
34586
35769
  x,
34587
35770
  y,
@@ -35128,9 +36311,11 @@ var PptxHandlerRuntime47 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
35128
36311
  grpSlideRels,
35129
36312
  this.orderedSlidePaths
35130
36313
  );
36314
+ const grpElementName = grpCNvPr?.["@_name"] ? String(grpCNvPr["@_name"]).trim() : void 0;
35131
36315
  const groupElement = {
35132
36316
  type: "group",
35133
36317
  id: baseId,
36318
+ name: grpElementName || void 0,
35134
36319
  x: parentX,
35135
36320
  y: parentY,
35136
36321
  width: parentW || Math.max(...children.map((c) => c.x + c.width)),
@@ -39010,6 +40195,7 @@ var PptxHandlerRuntime71 = class extends PptxHandlerRuntime70 {
39010
40195
  if (!fontBinary || fontBinary.length === 0) {
39011
40196
  return null;
39012
40197
  }
40198
+ const originalPartBytes = new Uint8Array(fontBinary);
39013
40199
  let fontData;
39014
40200
  let resolvedGuid;
39015
40201
  if (isEotFormat(fontBinary)) {
@@ -39063,7 +40249,9 @@ var PptxHandlerRuntime71 = class extends PptxHandlerRuntime70 {
39063
40249
  format,
39064
40250
  rawFontData: fontData,
39065
40251
  partPath: fontPath,
39066
- fontGuid: resolvedGuid
40252
+ fontGuid: resolvedGuid,
40253
+ originalRId: rId,
40254
+ originalPartBytes
39067
40255
  };
39068
40256
  } catch {
39069
40257
  return null;
@@ -40674,6 +41862,14 @@ var EXTENDED_SHAPE_DEFINITIONS = [
40674
41862
  { name: "line", label: "Line", category: "other" },
40675
41863
  { name: "lineInv", label: "Line Inverse", category: "other" },
40676
41864
  { name: "straightConnector1", label: "Straight Connector", category: "other" },
41865
+ { name: "bentConnector2", label: "Elbow Connector (L)", category: "other" },
41866
+ { name: "bentConnector3", label: "Elbow Connector (Z)", category: "other" },
41867
+ { name: "bentConnector4", label: "Elbow Connector (3-Segment)", category: "other" },
41868
+ { name: "bentConnector5", label: "Elbow Connector (4-Segment)", category: "other" },
41869
+ { name: "curvedConnector2", label: "Curved Connector (L)", category: "other" },
41870
+ { name: "curvedConnector3", label: "Curved Connector (2-Segment)", category: "other" },
41871
+ { name: "curvedConnector4", label: "Curved Connector (3-Segment)", category: "other" },
41872
+ { name: "curvedConnector5", label: "Curved Connector (4-Segment)", category: "other" },
40677
41873
  // ── Arrows ────────────────────────────────────────────────────────────
40678
41874
  { name: "rightArrow", label: "Right Arrow", category: "arrows" },
40679
41875
  { name: "leftArrow", label: "Left Arrow", category: "arrows" },
@@ -49431,6 +50627,7 @@ var SvgExporter = class _SvgExporter {
49431
50627
  }
49432
50628
  };
49433
50629
 
50630
+ exports.ALL_ANIMATION_PRESETS = ALL_ANIMATION_PRESETS;
49434
50631
  exports.COLOR_MAP_ALIAS_KEYS = COLOR_MAP_ALIAS_KEYS;
49435
50632
  exports.CONNECTOR_ARROW_OPTIONS = CONNECTOR_ARROW_OPTIONS;
49436
50633
  exports.CONNECTOR_GEOMETRY_OPTIONS = CONNECTOR_GEOMETRY_OPTIONS;
@@ -49452,6 +50649,7 @@ exports.DIGITAL_SIGNATURE_ORIGIN_REL_TYPE = DIGITAL_SIGNATURE_ORIGIN_REL_TYPE;
49452
50649
  exports.DIGITAL_SIGNATURE_REL_TYPE = DIGITAL_SIGNATURE_REL_TYPE;
49453
50650
  exports.DataIntegrityError = DataIntegrityError;
49454
50651
  exports.DocumentConverter = DocumentConverter;
50652
+ exports.EMPHASIS_PRESETS = EMPHASIS_PRESETS;
49455
50653
  exports.EMU_PER_INCH = EMU_PER_INCH;
49456
50654
  exports.EMU_PER_PIXEL = EMU_PER_PIXEL2;
49457
50655
  exports.EMU_PER_POINT = EMU_PER_POINT;
@@ -49461,6 +50659,8 @@ exports.ENTERPRISE_REQUIRE_REVOCATION_ENV = ENTERPRISE_REQUIRE_REVOCATION_ENV;
49461
50659
  exports.ENTERPRISE_REQUIRE_TIMESTAMP_ENV = ENTERPRISE_REQUIRE_TIMESTAMP_ENV;
49462
50660
  exports.ENTERPRISE_TRUST_ROOTS_FILE_ENV = ENTERPRISE_TRUST_ROOTS_FILE_ENV;
49463
50661
  exports.ENTERPRISE_TRUST_ROOTS_PEM_ENV = ENTERPRISE_TRUST_ROOTS_PEM_ENV;
50662
+ exports.ENTRANCE_PRESETS = ENTRANCE_PRESETS;
50663
+ exports.EXIT_PRESETS = EXIT_PRESETS;
49464
50664
  exports.EncryptedFileError = EncryptedFileError;
49465
50665
  exports.FONT_SUBSTITUTION_MAP = FONT_SUBSTITUTION_MAP;
49466
50666
  exports.FreeformPathBuilder = FreeformPathBuilder;
@@ -49468,6 +50668,7 @@ exports.GroupBuilder = GroupBuilder;
49468
50668
  exports.ImageBuilder = ImageBuilder;
49469
50669
  exports.IncorrectPasswordError = IncorrectPasswordError;
49470
50670
  exports.MIN_ELEMENT_SIZE = MIN_ELEMENT_SIZE;
50671
+ exports.MOTION_PATH_PRESETS = MOTION_PATH_PRESETS;
49471
50672
  exports.MediaBuilder = MediaBuilder;
49472
50673
  exports.MediaContext = MediaContext;
49473
50674
  exports.MediaGraphicFrameXmlFactory = MediaGraphicFrameXmlFactory;
@@ -49579,6 +50780,13 @@ exports.chartDataChangeType = chartDataChangeType;
49579
50780
  exports.chartDataRemoveCategory = chartDataRemoveCategory;
49580
50781
  exports.chartDataRemoveSeries = chartDataRemoveSeries;
49581
50782
  exports.chartDataUpdatePoint = chartDataUpdatePoint;
50783
+ exports.checkBlankSlide = checkBlankSlide;
50784
+ exports.checkComplexTables = checkComplexTables;
50785
+ exports.checkDuplicateTitles = checkDuplicateTitles;
50786
+ exports.checkLowContrast = checkLowContrast;
50787
+ exports.checkMissingAltText = checkMissingAltText;
50788
+ exports.checkMissingSlideTitle = checkMissingSlideTitle;
50789
+ exports.checkPresentation = checkPresentation;
49582
50790
  exports.clampUnitInterval = clampUnitInterval;
49583
50791
  exports.classifyPanose = classifyPanose;
49584
50792
  exports.cloneElement = cloneElement;
@@ -49591,6 +50799,7 @@ exports.cm = cm;
49591
50799
  exports.cmToEmu = cmToEmu;
49592
50800
  exports.colorWithOpacity = colorWithOpacity;
49593
50801
  exports.combineShapes = combineShapes;
50802
+ exports.computeContrastRatio = computeContrastRatio;
49594
50803
  exports.computeCycleLayout = computeCycleLayout;
49595
50804
  exports.computeDetailStatus = computeDetailStatus;
49596
50805
  exports.computeDigestBase64WebCrypto = computeDigestBase64;
@@ -49656,6 +50865,7 @@ exports.extractGuidFromPartName = extractGuidFromPartName;
49656
50865
  exports.extractModel3DTransform = extractModel3DTransform;
49657
50866
  exports.extractTagAttribute = extractTagAttribute;
49658
50867
  exports.fetchUrlToBytes = fetchUrlToBytes;
50868
+ exports.findCustomShow = findCustomShow;
49659
50869
  exports.findLayoutByName = findLayoutByName;
49660
50870
  exports.findLayoutByType = findLayoutByType;
49661
50871
  exports.findPlaceholders = findPlaceholders;
@@ -49665,6 +50875,7 @@ exports.fragmentShapes = fragmentShapes;
49665
50875
  exports.generateFontGuid = generateFontGuid;
49666
50876
  exports.generateLayoutXml = generateLayoutXml;
49667
50877
  exports.generateMediaFilename = generateMediaFilename;
50878
+ exports.getAnimationPresetInfo = getAnimationPresetInfo;
49668
50879
  exports.getCalloutLeaderLineGeometry = getCalloutLeaderLineGeometry;
49669
50880
  exports.getCalloutTier = getCalloutTier;
49670
50881
  exports.getCalloutViewBoxBounds = getCalloutViewBoxBounds;
@@ -49672,6 +50883,8 @@ exports.getCommentMarkerPosition = getCommentMarkerPosition;
49672
50883
  exports.getConnectorAdjustment = getConnectorAdjustment;
49673
50884
  exports.getConnectorPathGeometry = getConnectorPathGeometry;
49674
50885
  exports.getCssBorderDashStyle = getCssBorderDashStyle;
50886
+ exports.getCustomShowNames = getCustomShowNames;
50887
+ exports.getCustomShowPositionLabel = getCustomShowPositionLabel;
49675
50888
  exports.getDirectory = getDirectory;
49676
50889
  exports.getElementLabel = getElementLabel;
49677
50890
  exports.getElementTextContent = getElementTextContent;
@@ -49681,6 +50894,7 @@ exports.getLinkedTextBoxSegments = getLinkedTextBoxSegments;
49681
50894
  exports.getOleObjectTypeLabel = getOleObjectTypeLabel;
49682
50895
  exports.getPanoseWeight = getPanoseWeight;
49683
50896
  exports.getPresetShapeClipPath = getPresetShapeClipPath;
50897
+ exports.getPresetsByCategory = getPresetsByCategory;
49684
50898
  exports.getRoundRectRadiusPx = getRoundRectRadiusPx;
49685
50899
  exports.getSectionForSlide = getSectionForSlide;
49686
50900
  exports.getSectionSlideRange = getSectionSlideRange;
@@ -49730,9 +50944,11 @@ exports.layoutEngineShapesToDrawingShapes = layoutEngineShapesToDrawingShapes;
49730
50944
  exports.mailMerge = mailMerge;
49731
50945
  exports.mergePresentation = mergePresentation;
49732
50946
  exports.mergeShapes = mergeShapes;
50947
+ exports.mergeStyleParts = mergeStyleParts;
49733
50948
  exports.mergeThemeColorOverride = mergeThemeColorOverride;
49734
50949
  exports.mm = mm;
49735
50950
  exports.moveSlidesToSection = moveSlidesToSection;
50951
+ exports.navigateCustomShow = navigateCustomShow;
49736
50952
  exports.normalizeHexColor = normalizeHexColor;
49737
50953
  exports.normalizeNamespaceUri = normalizeNamespaceUri;
49738
50954
  exports.normalizePartPath = normalizePartPath;
@@ -49759,6 +50975,7 @@ exports.parseDrawingHueDegrees = parseDrawingHueDegrees;
49759
50975
  exports.parseDrawingPercent = parseDrawingPercent;
49760
50976
  exports.parseEmbeddedXlsx = parseEmbeddedXlsx;
49761
50977
  exports.parseGuideDefinitions = parseGuideDefinitions;
50978
+ exports.parseHexColor = parseHexColor;
49762
50979
  exports.parseKinsoku = parseKinsoku;
49763
50980
  exports.parseLayoutDefinition = parseLayoutDefinition;
49764
50981
  exports.parseLineStyle = parseLineStyle;
@@ -49786,6 +51003,8 @@ exports.pt = pt;
49786
51003
  exports.reResolveSlideColors = reResolveSlideColors;
49787
51004
  exports.readFileAsDataUrl = readFileAsDataUrl;
49788
51005
  exports.reflowSmartArtLayout = reflowSmartArtLayout;
51006
+ exports.relativeLuminance = relativeLuminance;
51007
+ exports.relayoutSmartArt = relayoutSmartArt;
49789
51008
  exports.removeChartCategory = removeChartCategory;
49790
51009
  exports.removeChartSeries = removeChartSeries;
49791
51010
  exports.removeSection = removeSection;
@@ -49804,8 +51023,10 @@ exports.resetIdCounter = resetIdCounter;
49804
51023
  exports.resetSectionIdCounter = resetSectionIdCounter;
49805
51024
  exports.resetSmartArtEditCounter = resetSmartArtEditCounter;
49806
51025
  exports.resolveCoordinate = resolveCoordinate;
51026
+ exports.resolveCustomShowSlideIndices = resolveCustomShowSlideIndices;
49807
51027
  exports.resolveModel3DMimeType = resolveModel3DMimeType;
49808
51028
  exports.resolveReferenceUriToPart = resolveReferenceUriToPart;
51029
+ exports.resolveTableCellStyle = resolveTableCellStyle;
49809
51030
  exports.rgbToHsl = rgbToHsl;
49810
51031
  exports.selectAlternateContentBranch = selectAlternateContentBranch;
49811
51032
  exports.serializeCondition = serializeCondition;