pptx-react-viewer 1.1.3 → 1.1.4

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 (25) hide show
  1. package/dist/index.js +587 -288
  2. package/dist/index.mjs +587 -288
  3. package/dist/pptx-viewer.css +1 -1
  4. package/dist/viewer/index.js +587 -288
  5. package/dist/viewer/index.mjs +587 -288
  6. package/node_modules/emf-converter/package.json +2 -2
  7. package/node_modules/mtx-decompressor/package.json +2 -2
  8. package/node_modules/pptx-viewer-core/dist/{SvgExporter-BMjoxMDV.d.ts → SvgExporter-0TxiiorD.d.ts} +1 -1
  9. package/node_modules/pptx-viewer-core/dist/{SvgExporter-z6AbXRQg.d.mts → SvgExporter-BQ4KbRO9.d.mts} +1 -1
  10. package/node_modules/pptx-viewer-core/dist/cli/index.d.mts +2 -2
  11. package/node_modules/pptx-viewer-core/dist/cli/index.d.ts +2 -2
  12. package/node_modules/pptx-viewer-core/dist/cli/index.js +2711 -304
  13. package/node_modules/pptx-viewer-core/dist/cli/index.mjs +2711 -304
  14. package/node_modules/pptx-viewer-core/dist/converter/index.d.mts +3 -3
  15. package/node_modules/pptx-viewer-core/dist/converter/index.d.ts +3 -3
  16. package/node_modules/pptx-viewer-core/dist/index.d.mts +692 -44
  17. package/node_modules/pptx-viewer-core/dist/index.d.ts +692 -44
  18. package/node_modules/pptx-viewer-core/dist/index.js +2794 -373
  19. package/node_modules/pptx-viewer-core/dist/index.mjs +2785 -373
  20. package/node_modules/pptx-viewer-core/dist/{presentation-CchuDGfU.d.mts → presentation-ArhfImJ5.d.mts} +225 -8
  21. package/node_modules/pptx-viewer-core/dist/{presentation-CchuDGfU.d.ts → presentation-ArhfImJ5.d.ts} +225 -8
  22. package/node_modules/pptx-viewer-core/dist/{text-operations-CeukUztU.d.mts → text-operations-CLj-sJyk.d.mts} +1 -1
  23. package/node_modules/pptx-viewer-core/dist/{text-operations-e7JxgI5l.d.ts → text-operations-rhJV-A_W.d.ts} +1 -1
  24. package/node_modules/pptx-viewer-core/package.json +5 -5
  25. package/package.json +20 -20
@@ -676,12 +676,25 @@ function svgToCustomGeometryPaths(pathData, width, height) {
676
676
  function pointToXml(pt2) {
677
677
  return { "@_x": String(Math.round(pt2.x)), "@_y": String(Math.round(pt2.y)) };
678
678
  }
679
- function customGeometryPathsToXml(paths) {
679
+ function customGeometryPathsToXml(paths, rawData) {
680
680
  const xmlPaths = paths.map((path) => {
681
681
  const pathXml = {
682
682
  "@_w": String(Math.round(path.width)),
683
683
  "@_h": String(Math.round(path.height))
684
684
  };
685
+ if (path.fillMode) {
686
+ pathXml["@_fill"] = path.fillMode;
687
+ }
688
+ if (path.stroke === false) {
689
+ pathXml["@_stroke"] = "0";
690
+ } else if (path.stroke === true) {
691
+ pathXml["@_stroke"] = "1";
692
+ }
693
+ if (path.extrusionOk === true) {
694
+ pathXml["@_extrusionOk"] = "1";
695
+ } else if (path.extrusionOk === false) {
696
+ pathXml["@_extrusionOk"] = "0";
697
+ }
685
698
  const moveToList = [];
686
699
  const lnToList = [];
687
700
  const cubicBezToList = [];
@@ -739,12 +752,12 @@ function customGeometryPathsToXml(paths) {
739
752
  }
740
753
  return pathXml;
741
754
  });
742
- return {
755
+ const result = {
743
756
  "a:avLst": {},
744
- "a:gdLst": {},
745
- "a:ahLst": {},
746
- "a:cxnLst": {},
747
- "a:rect": {
757
+ "a:gdLst": rawData?.gdLstXml ?? {},
758
+ "a:ahLst": rawData?.ahLstXml ?? {},
759
+ "a:cxnLst": rawData?.cxnLstXml ?? {},
760
+ "a:rect": rawData?.rectXml ?? {
748
761
  "@_l": "l",
749
762
  "@_t": "t",
750
763
  "@_r": "r",
@@ -754,6 +767,7 @@ function customGeometryPathsToXml(paths) {
754
767
  "a:path": xmlPaths.length === 1 ? xmlPaths[0] : xmlPaths
755
768
  }
756
769
  };
770
+ return result;
757
771
  }
758
772
 
759
773
  // src/core/builders/sdk/ElementFactory.ts
@@ -1503,6 +1517,9 @@ ${Array.from(
1503
1517
  <p:presentation xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
1504
1518
  xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
1505
1519
  xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"
1520
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
1521
+ xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main"
1522
+ xmlns:p15="http://schemas.microsoft.com/office/powerpoint/2012/main"
1506
1523
  saveSubsetFonts="1">
1507
1524
  <p:sldMasterIdLst>
1508
1525
  <p:sldMasterId id="2147483648" r:id="rId1"/>
@@ -2924,6 +2941,22 @@ var PptxPresentationSlidesReconciler = class {
2924
2941
  };
2925
2942
 
2926
2943
  // src/core/core/builders/PptxSlideRelationshipRegistry.ts
2944
+ function isExternalTarget(target) {
2945
+ const normalized = target.trim();
2946
+ if (normalized.length === 0) {
2947
+ return false;
2948
+ }
2949
+ const colonIdx = normalized.indexOf(":");
2950
+ if (colonIdx <= 0) {
2951
+ return false;
2952
+ }
2953
+ const slashIdx = normalized.indexOf("/");
2954
+ if (slashIdx !== -1 && slashIdx < colonIdx) {
2955
+ return false;
2956
+ }
2957
+ const scheme = normalized.slice(0, colonIdx);
2958
+ return /^[A-Za-z][A-Za-z0-9+\-.]*$/.test(scheme);
2959
+ }
2927
2960
  var PptxSlideRelationshipRegistry = class {
2928
2961
  relationships;
2929
2962
  usedRelationshipIds = /* @__PURE__ */ new Set();
@@ -2994,7 +3027,7 @@ var PptxSlideRelationshipRegistry = class {
2994
3027
  return existingRelationshipId;
2995
3028
  }
2996
3029
  const relationshipId = this.nextRelationshipId();
2997
- const targetMode = /^(https?:|mailto:|ftp:|file:)/i.test(normalizedTarget) ? "External" : void 0;
3030
+ const targetMode = isExternalTarget(normalizedTarget) ? "External" : void 0;
2998
3031
  this.upsertRelationship(
2999
3032
  relationshipId,
3000
3033
  this.hyperlinkRelationshipType,
@@ -3244,6 +3277,82 @@ var PptxSlideNotesPartUpdater = class {
3244
3277
  }
3245
3278
  };
3246
3279
 
3280
+ // src/core/utils/xml-reorder.ts
3281
+ function reorderObjectKeys(obj, schemaOrder) {
3282
+ const result = {};
3283
+ const consumed = /* @__PURE__ */ new Set();
3284
+ for (const key of schemaOrder) {
3285
+ if (Object.hasOwn(obj, key)) {
3286
+ const value = obj[key];
3287
+ if (value !== void 0) {
3288
+ result[key] = value;
3289
+ }
3290
+ consumed.add(key);
3291
+ }
3292
+ }
3293
+ for (const key of Object.keys(obj)) {
3294
+ if (consumed.has(key)) {
3295
+ continue;
3296
+ }
3297
+ const value = obj[key];
3298
+ if (value !== void 0) {
3299
+ result[key] = value;
3300
+ }
3301
+ }
3302
+ return result;
3303
+ }
3304
+ var EFFECT_LST_ORDER = [
3305
+ "a:blur",
3306
+ "a:fillOverlay",
3307
+ "a:glow",
3308
+ "a:innerShdw",
3309
+ "a:outerShdw",
3310
+ "a:prstShdw",
3311
+ "a:reflection",
3312
+ "a:softEdge"
3313
+ ];
3314
+ var SP_PR_ORDER = [
3315
+ "a:xfrm",
3316
+ "a:custGeom",
3317
+ "a:prstGeom",
3318
+ "a:noFill",
3319
+ "a:solidFill",
3320
+ "a:gradFill",
3321
+ "a:blipFill",
3322
+ "a:pattFill",
3323
+ "a:grpFill",
3324
+ "a:ln",
3325
+ "a:effectLst",
3326
+ "a:effectDag",
3327
+ "a:scene3d",
3328
+ "a:sp3d",
3329
+ "a:extLst"
3330
+ ];
3331
+ var TC_PR_BORDERS_ORDER = [
3332
+ "a:lnL",
3333
+ "a:lnR",
3334
+ "a:lnT",
3335
+ "a:lnB",
3336
+ "a:lnTlToBr",
3337
+ "a:lnBlToTr",
3338
+ "a:cell3D",
3339
+ "a:noFill",
3340
+ "a:solidFill",
3341
+ "a:gradFill",
3342
+ "a:blipFill",
3343
+ "a:pattFill",
3344
+ "a:grpFill",
3345
+ "a:headers",
3346
+ "a:extLst"
3347
+ ];
3348
+ var BLIP_FILL_ORDER = ["a:blip", "a:srcRect", "a:tile", "a:stretch"];
3349
+ var SHAPE_STYLE_ORDER = [
3350
+ "a:lnRef",
3351
+ "a:fillRef",
3352
+ "a:effectRef",
3353
+ "a:fontRef"
3354
+ ];
3355
+
3247
3356
  // src/core/core/builders/PptxSlideBackgroundBuilder.ts
3248
3357
  var PptxSlideBackgroundBuilder = class {
3249
3358
  applyBackground(init) {
@@ -3279,10 +3388,13 @@ var PptxSlideBackgroundBuilder = class {
3279
3388
  init.slideImageRelationshipType,
3280
3389
  relativeBackgroundImagePath
3281
3390
  );
3282
- backgroundProperties["a:blipFill"] = {
3283
- "a:blip": { "@_r:embed": backgroundRelationshipId },
3284
- "a:stretch": { "a:fillRect": {} }
3285
- };
3391
+ backgroundProperties["a:blipFill"] = reorderObjectKeys(
3392
+ {
3393
+ "a:blip": { "@_r:embed": backgroundRelationshipId },
3394
+ "a:stretch": { "a:fillRect": {} }
3395
+ },
3396
+ BLIP_FILL_ORDER
3397
+ );
3286
3398
  }
3287
3399
  } else if (hasBackgroundColor && init.slide.backgroundColor) {
3288
3400
  backgroundProperties["a:solidFill"] = {
@@ -4104,6 +4216,45 @@ var PptxGradientStyleCodec = class {
4104
4216
  b: Number.isFinite(b) ? this.context.clampUnitInterval(b / 1e5) : 0
4105
4217
  };
4106
4218
  }
4219
+ extractGradientFlip(gradFill) {
4220
+ const flipRaw = String(gradFill["@_flip"] || "").trim().toLowerCase();
4221
+ if (flipRaw === "x" || flipRaw === "y" || flipRaw === "xy" || flipRaw === "none") {
4222
+ return flipRaw;
4223
+ }
4224
+ return void 0;
4225
+ }
4226
+ extractGradientRotWithShape(gradFill) {
4227
+ const rot = gradFill["@_rotWithShape"];
4228
+ if (rot === void 0 || rot === null) {
4229
+ return void 0;
4230
+ }
4231
+ const token = String(rot).trim().toLowerCase();
4232
+ if (token === "1" || token === "true") {
4233
+ return true;
4234
+ }
4235
+ if (token === "0" || token === "false") {
4236
+ return false;
4237
+ }
4238
+ return void 0;
4239
+ }
4240
+ extractGradientScaled(gradFill) {
4241
+ const lin = gradFill["a:lin"];
4242
+ if (!lin) {
4243
+ return void 0;
4244
+ }
4245
+ const scaled = lin["@_scaled"];
4246
+ if (scaled === void 0 || scaled === null) {
4247
+ return void 0;
4248
+ }
4249
+ const token = String(scaled).trim().toLowerCase();
4250
+ if (token === "1" || token === "true") {
4251
+ return true;
4252
+ }
4253
+ if (token === "0" || token === "false") {
4254
+ return false;
4255
+ }
4256
+ return void 0;
4257
+ }
4107
4258
  extractGradientAngle(gradFill) {
4108
4259
  const angleRaw = Number.parseInt(
4109
4260
  String(gradFill["a:lin"]?.["@_ang"] || ""),
@@ -4190,11 +4341,14 @@ var PptxGradientStyleCodec = class {
4190
4341
  return void 0;
4191
4342
  }
4192
4343
  const gradientType = shapeStyle.fillGradientType || "linear";
4193
- const gradientXml = {
4194
- "a:gsLst": {
4195
- "a:gs": stops
4196
- }
4197
- };
4344
+ const gradientXml = {};
4345
+ if (shapeStyle.fillGradientFlip && shapeStyle.fillGradientFlip !== "none") {
4346
+ gradientXml["@_flip"] = shapeStyle.fillGradientFlip;
4347
+ }
4348
+ if (shapeStyle.fillGradientRotWithShape !== void 0) {
4349
+ gradientXml["@_rotWithShape"] = shapeStyle.fillGradientRotWithShape ? "1" : "0";
4350
+ }
4351
+ gradientXml["a:gsLst"] = { "a:gs": stops };
4198
4352
  if (gradientType === "radial") {
4199
4353
  const pathType = shapeStyle.fillGradientPathType || "circle";
4200
4354
  const pathXml = {
@@ -4224,10 +4378,15 @@ var PptxGradientStyleCodec = class {
4224
4378
  gradientXml["a:path"] = pathXml;
4225
4379
  } else {
4226
4380
  const normalizedAngle = typeof shapeStyle.fillGradientAngle === "number" && Number.isFinite(shapeStyle.fillGradientAngle) ? shapeStyle.fillGradientAngle : 90;
4227
- gradientXml["a:lin"] = {
4228
- "@_ang": String(Math.round(normalizedAngle * 6e4)),
4229
- "@_scaled": "1"
4381
+ const linNode = {
4382
+ "@_ang": String(Math.round(normalizedAngle * 6e4))
4230
4383
  };
4384
+ if (shapeStyle.fillGradientScaled !== void 0) {
4385
+ linNode["@_scaled"] = shapeStyle.fillGradientScaled ? "1" : "0";
4386
+ } else {
4387
+ linNode["@_scaled"] = "1";
4388
+ }
4389
+ gradientXml["a:lin"] = linNode;
4231
4390
  }
4232
4391
  return gradientXml;
4233
4392
  }
@@ -4624,6 +4783,30 @@ var PRESET_SHADOW_OPACITY_MAP = {
4624
4783
  };
4625
4784
 
4626
4785
  // src/core/core/builders/PptxShapeEffectStyleExtractor.ts
4786
+ var VALID_ALIGNMENTS = /* @__PURE__ */ new Set(["tl", "t", "tr", "l", "ctr", "r", "bl", "b", "br"]);
4787
+ function parseIntAttr(value) {
4788
+ if (value === void 0 || value === null || value === "") {
4789
+ return void 0;
4790
+ }
4791
+ const parsed = Number.parseInt(String(value), 10);
4792
+ return Number.isFinite(parsed) ? parsed : void 0;
4793
+ }
4794
+ function parseAlignmentAttr(value) {
4795
+ const v = String(value ?? "").trim();
4796
+ return VALID_ALIGNMENTS.has(v) ? v : void 0;
4797
+ }
4798
+ function parseBoolAttr(value) {
4799
+ if (typeof value === "boolean") {
4800
+ return value;
4801
+ }
4802
+ if (value === "1" || value === "true") {
4803
+ return true;
4804
+ }
4805
+ if (value === "0" || value === "false") {
4806
+ return false;
4807
+ }
4808
+ return void 0;
4809
+ }
4627
4810
  var PptxShapeEffectStyleExtractor = class {
4628
4811
  context;
4629
4812
  constructor(context) {
@@ -4647,7 +4830,12 @@ var PptxShapeEffectStyleExtractor = class {
4647
4830
  const shadowOffsetX = distance !== void 0 ? Math.round(Math.cos(directionRadians) * distance * 100) / 100 : void 0;
4648
4831
  const shadowOffsetY = distance !== void 0 ? Math.round(Math.sin(directionRadians) * distance * 100) / 100 : void 0;
4649
4832
  const rotateWithShape = outerShadow["@_rotWithShape"];
4650
- const shadowRotateWithShape = typeof rotateWithShape === "boolean" ? rotateWithShape : rotateWithShape === "1" || rotateWithShape === "true" ? true : void 0;
4833
+ const shadowRotateWithShape = typeof rotateWithShape === "boolean" ? rotateWithShape : rotateWithShape === "1" || rotateWithShape === "true" ? true : rotateWithShape === "0" || rotateWithShape === "false" ? false : void 0;
4834
+ const shadowScaleX = parseIntAttr(outerShadow["@_sx"]);
4835
+ const shadowScaleY = parseIntAttr(outerShadow["@_sy"]);
4836
+ const shadowSkewX = parseIntAttr(outerShadow["@_kx"]);
4837
+ const shadowSkewY = parseIntAttr(outerShadow["@_ky"]);
4838
+ const shadowAlignment = parseAlignmentAttr(outerShadow["@_algn"]);
4651
4839
  return {
4652
4840
  shadowColor,
4653
4841
  shadowOpacity,
@@ -4656,7 +4844,12 @@ var PptxShapeEffectStyleExtractor = class {
4656
4844
  shadowOffsetY,
4657
4845
  shadowAngle: directionDegrees,
4658
4846
  shadowDistance: distance,
4659
- shadowRotateWithShape
4847
+ shadowRotateWithShape,
4848
+ shadowScaleX,
4849
+ shadowScaleY,
4850
+ shadowSkewX,
4851
+ shadowSkewY,
4852
+ shadowAlignment
4660
4853
  };
4661
4854
  }
4662
4855
  extractPresetShadowStyle(effectLstParent) {
@@ -4702,12 +4895,14 @@ var PptxShapeEffectStyleExtractor = class {
4702
4895
  const directionRadians = directionDegrees * Math.PI / 180;
4703
4896
  const innerShadowOffsetX = distance !== void 0 ? Math.round(Math.cos(directionRadians) * distance * 100) / 100 : void 0;
4704
4897
  const innerShadowOffsetY = distance !== void 0 ? Math.round(Math.sin(directionRadians) * distance * 100) / 100 : void 0;
4898
+ const innerShadowRotateWithShape = parseBoolAttr(innerShadow["@_rotWithShape"]);
4705
4899
  return {
4706
4900
  innerShadowColor,
4707
4901
  innerShadowOpacity,
4708
4902
  innerShadowBlur,
4709
4903
  innerShadowOffsetX,
4710
- innerShadowOffsetY
4904
+ innerShadowOffsetY,
4905
+ innerShadowRotateWithShape
4711
4906
  };
4712
4907
  }
4713
4908
  extractGlowStyle(shapeProps) {
@@ -4756,6 +4951,16 @@ var PptxShapeEffectStyleExtractor = class {
4756
4951
  const reflectionRotation = Number.isFinite(rotationRaw) ? rotationRaw / 6e4 : void 0;
4757
4952
  const distanceRaw = Number.parseInt(String(reflectionNode["@_dist"] || ""), 10);
4758
4953
  const reflectionDistance = Number.isFinite(distanceRaw) && distanceRaw >= 0 ? distanceRaw / this.context.emuPerPx : void 0;
4954
+ const fadeDirRaw = parseIntAttr(reflectionNode["@_fadeDir"]);
4955
+ const reflectionFadeDirection = fadeDirRaw !== void 0 ? fadeDirRaw / 6e4 : void 0;
4956
+ const reflectionScaleX = parseIntAttr(reflectionNode["@_sx"]);
4957
+ const reflectionScaleY = parseIntAttr(reflectionNode["@_sy"]);
4958
+ const reflectionSkewX = parseIntAttr(reflectionNode["@_kx"]);
4959
+ const reflectionSkewY = parseIntAttr(reflectionNode["@_ky"]);
4960
+ const reflectionAlignment = parseAlignmentAttr(reflectionNode["@_algn"]);
4961
+ const reflectionRotateWithShape = parseBoolAttr(reflectionNode["@_rotWithShape"]);
4962
+ const stPosRaw = parseIntAttr(reflectionNode["@_stPos"]);
4963
+ const reflectionStartPosition = stPosRaw !== void 0 ? stPosRaw / 1e5 : void 0;
4759
4964
  return {
4760
4965
  reflectionBlurRadius,
4761
4966
  reflectionStartOpacity,
@@ -4763,7 +4968,15 @@ var PptxShapeEffectStyleExtractor = class {
4763
4968
  reflectionEndPosition,
4764
4969
  reflectionDirection,
4765
4970
  reflectionRotation,
4766
- reflectionDistance
4971
+ reflectionDistance,
4972
+ reflectionFadeDirection,
4973
+ reflectionScaleX,
4974
+ reflectionScaleY,
4975
+ reflectionSkewX,
4976
+ reflectionSkewY,
4977
+ reflectionAlignment,
4978
+ reflectionRotateWithShape,
4979
+ reflectionStartPosition
4767
4980
  };
4768
4981
  }
4769
4982
  extractBlurStyle(shapeProps) {
@@ -4815,11 +5028,56 @@ var PptxShapeEffectXmlBuilder = class {
4815
5028
  }
4816
5029
  }
4817
5030
  };
5031
+ if (typeof shapeStyle.shadowScaleX === "number") {
5032
+ xmlObj["@_sx"] = String(Math.round(shapeStyle.shadowScaleX));
5033
+ }
5034
+ if (typeof shapeStyle.shadowScaleY === "number") {
5035
+ xmlObj["@_sy"] = String(Math.round(shapeStyle.shadowScaleY));
5036
+ }
5037
+ if (typeof shapeStyle.shadowSkewX === "number") {
5038
+ xmlObj["@_kx"] = String(Math.round(shapeStyle.shadowSkewX));
5039
+ }
5040
+ if (typeof shapeStyle.shadowSkewY === "number") {
5041
+ xmlObj["@_ky"] = String(Math.round(shapeStyle.shadowSkewY));
5042
+ }
5043
+ if (shapeStyle.shadowAlignment) {
5044
+ xmlObj["@_algn"] = shapeStyle.shadowAlignment;
5045
+ }
4818
5046
  if (typeof shapeStyle.shadowRotateWithShape === "boolean") {
4819
5047
  xmlObj["@_rotWithShape"] = shapeStyle.shadowRotateWithShape ? "1" : "0";
4820
5048
  }
4821
5049
  return xmlObj;
4822
5050
  }
5051
+ buildPresetShadowXml(shapeStyle) {
5052
+ const preset = shapeStyle.presetShadowName;
5053
+ if (!preset || preset.length === 0) {
5054
+ return void 0;
5055
+ }
5056
+ const shadowColor = String(shapeStyle.shadowColor || "#000000").trim();
5057
+ const shadowOpacity = typeof shapeStyle.shadowOpacity === "number" && Number.isFinite(shapeStyle.shadowOpacity) ? this.context.clampUnitInterval(shapeStyle.shadowOpacity) : 0.5;
5058
+ let distance;
5059
+ let directionDegrees;
5060
+ if (typeof shapeStyle.shadowAngle === "number" && typeof shapeStyle.shadowDistance === "number") {
5061
+ directionDegrees = shapeStyle.shadowAngle;
5062
+ distance = shapeStyle.shadowDistance;
5063
+ } else {
5064
+ const ox = typeof shapeStyle.shadowOffsetX === "number" ? shapeStyle.shadowOffsetX : 0;
5065
+ const oy = typeof shapeStyle.shadowOffsetY === "number" ? shapeStyle.shadowOffsetY : 0;
5066
+ distance = Math.sqrt(ox * ox + oy * oy);
5067
+ directionDegrees = (Math.atan2(oy, ox) * 180 / Math.PI + 360) % 360;
5068
+ }
5069
+ return {
5070
+ "@_prst": preset,
5071
+ "@_dist": String(Math.round(distance * this.context.emuPerPx)),
5072
+ "@_dir": String(Math.round(directionDegrees * 6e4)),
5073
+ "a:srgbClr": {
5074
+ "@_val": shadowColor.replace("#", ""),
5075
+ "a:alpha": {
5076
+ "@_val": String(Math.round(shadowOpacity * 1e5))
5077
+ }
5078
+ }
5079
+ };
5080
+ }
4823
5081
  buildInnerShadowXml(shapeStyle) {
4824
5082
  const innerColor = String(shapeStyle.innerShadowColor || "").trim();
4825
5083
  if (innerColor.length === 0 || innerColor === "transparent") {
@@ -4831,7 +5089,7 @@ var PptxShapeEffectXmlBuilder = class {
4831
5089
  const opacity = typeof shapeStyle.innerShadowOpacity === "number" && Number.isFinite(shapeStyle.innerShadowOpacity) ? this.context.clampUnitInterval(shapeStyle.innerShadowOpacity) : 0.5;
4832
5090
  const distance = Math.sqrt(offsetX * offsetX + offsetY * offsetY);
4833
5091
  const directionDegrees = (Math.atan2(offsetY, offsetX) * 180 / Math.PI + 360) % 360;
4834
- return {
5092
+ const xmlObj = {
4835
5093
  "@_blurRad": String(Math.round(blurValue * this.context.emuPerPx)),
4836
5094
  "@_dist": String(Math.round(distance * this.context.emuPerPx)),
4837
5095
  "@_dir": String(Math.round(directionDegrees * 6e4)),
@@ -4842,6 +5100,10 @@ var PptxShapeEffectXmlBuilder = class {
4842
5100
  }
4843
5101
  }
4844
5102
  };
5103
+ if (typeof shapeStyle.innerShadowRotateWithShape === "boolean") {
5104
+ xmlObj["@_rotWithShape"] = shapeStyle.innerShadowRotateWithShape ? "1" : "0";
5105
+ }
5106
+ return xmlObj;
4845
5107
  }
4846
5108
  buildGlowXml(shapeStyle) {
4847
5109
  const glowColor = String(shapeStyle.glowColor || "").trim();
@@ -4903,6 +5165,30 @@ var PptxShapeEffectXmlBuilder = class {
4903
5165
  Math.round(shapeStyle.reflectionDistance * this.context.emuPerPx)
4904
5166
  );
4905
5167
  }
5168
+ if (typeof shapeStyle.reflectionFadeDirection === "number") {
5169
+ reflectionXml["@_fadeDir"] = String(Math.round(shapeStyle.reflectionFadeDirection * 6e4));
5170
+ }
5171
+ if (typeof shapeStyle.reflectionScaleX === "number") {
5172
+ reflectionXml["@_sx"] = String(Math.round(shapeStyle.reflectionScaleX));
5173
+ }
5174
+ if (typeof shapeStyle.reflectionScaleY === "number") {
5175
+ reflectionXml["@_sy"] = String(Math.round(shapeStyle.reflectionScaleY));
5176
+ }
5177
+ if (typeof shapeStyle.reflectionSkewX === "number") {
5178
+ reflectionXml["@_kx"] = String(Math.round(shapeStyle.reflectionSkewX));
5179
+ }
5180
+ if (typeof shapeStyle.reflectionSkewY === "number") {
5181
+ reflectionXml["@_ky"] = String(Math.round(shapeStyle.reflectionSkewY));
5182
+ }
5183
+ if (shapeStyle.reflectionAlignment) {
5184
+ reflectionXml["@_algn"] = shapeStyle.reflectionAlignment;
5185
+ }
5186
+ if (typeof shapeStyle.reflectionRotateWithShape === "boolean") {
5187
+ reflectionXml["@_rotWithShape"] = shapeStyle.reflectionRotateWithShape ? "1" : "0";
5188
+ }
5189
+ if (typeof shapeStyle.reflectionStartPosition === "number") {
5190
+ reflectionXml["@_stPos"] = String(Math.round(shapeStyle.reflectionStartPosition * 1e5));
5191
+ }
4906
5192
  return reflectionXml;
4907
5193
  }
4908
5194
  buildBlurXml(shapeStyle) {
@@ -5010,6 +5296,9 @@ var PptxShapeEffectXmlCodec = class {
5010
5296
  buildOuterShadowXml(shapeStyle) {
5011
5297
  return this.builder.buildOuterShadowXml(shapeStyle);
5012
5298
  }
5299
+ buildPresetShadowXml(shapeStyle) {
5300
+ return this.builder.buildPresetShadowXml(shapeStyle);
5301
+ }
5013
5302
  buildInnerShadowXml(shapeStyle) {
5014
5303
  return this.builder.buildInnerShadowXml(shapeStyle);
5015
5304
  }
@@ -5170,6 +5459,9 @@ var PptxColorStyleCodec = class {
5170
5459
  buildOuterShadowXml(shapeStyle) {
5171
5460
  return this.shapeEffectXmlCodec.buildOuterShadowXml(shapeStyle);
5172
5461
  }
5462
+ buildPresetShadowXml(shapeStyle) {
5463
+ return this.shapeEffectXmlCodec.buildPresetShadowXml(shapeStyle);
5464
+ }
5173
5465
  buildInnerShadowXml(shapeStyle) {
5174
5466
  return this.shapeEffectXmlCodec.buildInnerShadowXml(shapeStyle);
5175
5467
  }
@@ -5191,6 +5483,15 @@ var PptxColorStyleCodec = class {
5191
5483
  extractGradientFillColor(gradFill) {
5192
5484
  return this.gradientStyleCodec.extractGradientFillColor(gradFill);
5193
5485
  }
5486
+ extractGradientFlip(gradFill) {
5487
+ return this.gradientStyleCodec.extractGradientFlip(gradFill);
5488
+ }
5489
+ extractGradientRotWithShape(gradFill) {
5490
+ return this.gradientStyleCodec.extractGradientRotWithShape(gradFill);
5491
+ }
5492
+ extractGradientScaled(gradFill) {
5493
+ return this.gradientStyleCodec.extractGradientScaled(gradFill);
5494
+ }
5194
5495
  extractGradientPathType(gradFill) {
5195
5496
  return this.gradientStyleCodec.extractGradientPathType(gradFill);
5196
5497
  }
@@ -5202,6 +5503,61 @@ var PptxColorStyleCodec = class {
5202
5503
  }
5203
5504
  };
5204
5505
 
5506
+ // src/core/utils/color-xml-preservation.ts
5507
+ var COLOR_CHOICE_KEYS = [
5508
+ "a:srgbClr",
5509
+ "a:schemeClr",
5510
+ "a:sysClr",
5511
+ "a:prstClr",
5512
+ "a:scrgbClr",
5513
+ "a:hslClr"
5514
+ ];
5515
+ function extractColorChoiceXml(parent) {
5516
+ if (!parent) {
5517
+ return void 0;
5518
+ }
5519
+ for (const key of COLOR_CHOICE_KEYS) {
5520
+ if (parent[key] !== void 0) {
5521
+ return { [key]: parent[key] };
5522
+ }
5523
+ }
5524
+ return void 0;
5525
+ }
5526
+ function normalizeHex(value) {
5527
+ const raw = String(value ?? "").trim();
5528
+ if (raw.length === 0) {
5529
+ return "";
5530
+ }
5531
+ const hex = raw.replace(/^#/, "");
5532
+ if (/^[0-9a-fA-F]{6}$/.test(hex)) {
5533
+ return hex.toUpperCase();
5534
+ }
5535
+ return raw.toLowerCase();
5536
+ }
5537
+ function colorsEqual(left, right) {
5538
+ if (left === void 0 || right === void 0) {
5539
+ return false;
5540
+ }
5541
+ return normalizeHex(left) === normalizeHex(right);
5542
+ }
5543
+ function buildSrgbColorChoice(hex, opacity) {
5544
+ const normalized = String(hex || "").replace(/^#/, "");
5545
+ const srgb = { "@_val": normalized };
5546
+ if (typeof opacity === "number" && Number.isFinite(opacity) && opacity >= 0 && opacity < 1) {
5547
+ const alphaPct = Math.round(Math.max(0, Math.min(1, opacity)) * 1e5);
5548
+ srgb["a:alpha"] = { "@_val": String(alphaPct) };
5549
+ }
5550
+ return { "a:srgbClr": srgb };
5551
+ }
5552
+ function serializeColorChoice(originalColorXml, currentResolvedHex, fallbackHex, opacity, options = {}) {
5553
+ if (originalColorXml && colorsEqual(currentResolvedHex, fallbackHex)) {
5554
+ if (options.preserveAlphaFromOriginal !== false) {
5555
+ return originalColorXml;
5556
+ }
5557
+ }
5558
+ return buildSrgbColorChoice(fallbackHex, opacity);
5559
+ }
5560
+
5205
5561
  // src/core/core/builders/shape-style-3d-helpers.ts
5206
5562
  function applyScene3dStyle(shapeProps, style) {
5207
5563
  const scene3dNode = shapeProps["a:scene3d"];
@@ -5287,6 +5643,10 @@ function applyStrokeColor(lineNode, style, context) {
5287
5643
  const lineFill = lineNode["a:solidFill"];
5288
5644
  style.strokeColor = context.parseColor(lineFill);
5289
5645
  style.strokeOpacity = context.extractColorOpacity(lineFill);
5646
+ const strokeColorXml = extractColorChoiceXml(lineFill);
5647
+ if (strokeColorXml) {
5648
+ style.strokeColorXml = strokeColorXml;
5649
+ }
5290
5650
  } else if (lineNode["a:gradFill"]) {
5291
5651
  style.strokeColor = context.extractGradientFillColor(lineNode["a:gradFill"]);
5292
5652
  style.strokeOpacity = context.extractGradientOpacity(lineNode["a:gradFill"]);
@@ -5354,6 +5714,14 @@ function applyJoinCapCompound(lineNode, style) {
5354
5714
  style.lineJoin = "bevel";
5355
5715
  } else if ("a:miter" in lineNode) {
5356
5716
  style.lineJoin = "miter";
5717
+ const miterNode = lineNode["a:miter"];
5718
+ const limRaw = miterNode?.["@_lim"];
5719
+ if (limRaw !== void 0 && limRaw !== "") {
5720
+ const parsed = parseInt(String(limRaw), 10);
5721
+ if (Number.isFinite(parsed)) {
5722
+ style.miterLimit = parsed;
5723
+ }
5724
+ }
5357
5725
  }
5358
5726
  const capValue = String(lineNode["@_cap"] || "").trim().toLowerCase();
5359
5727
  if (capValue === "rnd" || capValue === "sq" || capValue === "flat") {
@@ -5410,6 +5778,10 @@ var PptxShapeStyleExtractor = class {
5410
5778
  style.fillMode = "solid";
5411
5779
  style.fillColor = this.context.parseColor(solidFill);
5412
5780
  style.fillOpacity = this.context.extractColorOpacity(solidFill);
5781
+ const solidFillColorXml = extractColorChoiceXml(solidFill);
5782
+ if (solidFillColorXml) {
5783
+ style.fillColorXml = solidFillColorXml;
5784
+ }
5413
5785
  } else if (gradFill) {
5414
5786
  style.fillMode = "gradient";
5415
5787
  style.fillColor = this.context.extractGradientFillColor(gradFill);
@@ -5421,6 +5793,18 @@ var PptxShapeStyleExtractor = class {
5421
5793
  style.fillGradientPathType = this.context.extractGradientPathType(gradFill);
5422
5794
  style.fillGradientFocalPoint = this.context.extractGradientFocalPoint(gradFill);
5423
5795
  style.fillGradientFillToRect = this.context.extractGradientFillToRect(gradFill);
5796
+ const gradFlip = this.context.extractGradientFlip(gradFill);
5797
+ if (gradFlip) {
5798
+ style.fillGradientFlip = gradFlip;
5799
+ }
5800
+ const gradRot = this.context.extractGradientRotWithShape(gradFill);
5801
+ if (gradRot !== void 0) {
5802
+ style.fillGradientRotWithShape = gradRot;
5803
+ }
5804
+ const gradScaled = this.context.extractGradientScaled(gradFill);
5805
+ if (gradScaled !== void 0) {
5806
+ style.fillGradientScaled = gradScaled;
5807
+ }
5424
5808
  } else if (pattFill) {
5425
5809
  style.fillMode = "pattern";
5426
5810
  style.fillColor = this.context.parseColor(pattFill["a:fgClr"]) || this.context.parseColor(pattFill["a:bgClr"]);
@@ -5502,10 +5886,45 @@ var PptxShapeStyleExtractor = class {
5502
5886
  if (styleNode?.["a:effectRef"]) {
5503
5887
  this.context.resolveThemeEffectRef(styleNode["a:effectRef"], style);
5504
5888
  }
5889
+ const fontRef = styleNode?.["a:fontRef"];
5890
+ if (fontRef) {
5891
+ const idxAttr = String(fontRef["@_idx"] || "").trim();
5892
+ if (idxAttr.length > 0) {
5893
+ style.fontRefIdx = idxAttr;
5894
+ }
5895
+ const overrideColorXml = this.extractFontRefColorXml(fontRef);
5896
+ if (overrideColorXml) {
5897
+ style.fontRefColorXml = overrideColorXml;
5898
+ }
5899
+ }
5505
5900
  applyScene3dStyle(shapeProps, style);
5506
5901
  applyShape3dStyle(shapeProps, style, this.context);
5507
5902
  return style;
5508
5903
  }
5904
+ /**
5905
+ * Pull the verbatim colour-choice child out of an `a:fontRef` element,
5906
+ * preserving any contained colour transforms for round-trip.
5907
+ */
5908
+ extractFontRefColorXml(refNode) {
5909
+ if (!refNode) {
5910
+ return void 0;
5911
+ }
5912
+ const keys = [
5913
+ "a:scrgbClr",
5914
+ "a:srgbClr",
5915
+ "a:hslClr",
5916
+ "a:sysClr",
5917
+ "a:schemeClr",
5918
+ "a:prstClr"
5919
+ ];
5920
+ for (const key of keys) {
5921
+ const child = refNode[key];
5922
+ if (child !== void 0) {
5923
+ return { [key]: child };
5924
+ }
5925
+ }
5926
+ return void 0;
5927
+ }
5509
5928
  /**
5510
5929
  * Extract p14:hiddenFill from the shape properties extension list.
5511
5930
  * URI: {AF507438-7753-43E0-B8FC-AC1667EBCBE1}
@@ -5556,10 +5975,15 @@ var PptxShapeStyleExtractor = class {
5556
5975
  function applyCellFillStyle(cellProperties, style, context) {
5557
5976
  let hasStyle = false;
5558
5977
  if (cellProperties?.["a:solidFill"]) {
5559
- const fillColor = context.parseColor(cellProperties["a:solidFill"]);
5978
+ const solidFillNode = cellProperties["a:solidFill"];
5979
+ const fillColor = context.parseColor(solidFillNode);
5560
5980
  if (fillColor) {
5561
5981
  style.fillMode = "solid";
5562
5982
  style.backgroundColor = fillColor;
5983
+ const bgColorXml = extractColorChoiceXml(solidFillNode);
5984
+ if (bgColorXml) {
5985
+ style.backgroundColorXml = bgColorXml;
5986
+ }
5563
5987
  hasStyle = true;
5564
5988
  }
5565
5989
  }
@@ -5596,6 +6020,10 @@ function applyCellFillStyle(cellProperties, style, context) {
5596
6020
  }
5597
6021
  }
5598
6022
  }
6023
+ if (cellProperties?.["a:noFill"] !== void 0) {
6024
+ style.fillMode = "none";
6025
+ hasStyle = true;
6026
+ }
5599
6027
  if (cellProperties?.["a:pattFill"]) {
5600
6028
  const pattFill = cellProperties["a:pattFill"];
5601
6029
  const fgColor = context.parseColor(pattFill["a:fgClr"]);
@@ -5902,8 +6330,7 @@ var PptxTableDataParser = class {
5902
6330
  return width / totalWidthEmu;
5903
6331
  }) : gridColumns.map(() => 1 / Math.max(gridColumns.length, 1));
5904
6332
  const tableProperties = tableNode["a:tblPr"] || {};
5905
- const tableStyleNode = tableProperties["a:tblStyle"];
5906
- const tableStyleId = String(tableStyleNode?.["@_val"] || tableProperties["@_tblStyle"] || "").trim() || void 0;
6333
+ const tableStyleId = this.extractTableStyleId(tableProperties);
5907
6334
  const xmlRows = this.context.ensureArray(tableNode["a:tr"]);
5908
6335
  const rows = xmlRows.map((rowNode) => {
5909
6336
  const rowHeightEmu = parseInt(String(rowNode?.["@_h"] || "0"), 10) || 0;
@@ -5938,6 +6365,28 @@ var PptxTableDataParser = class {
5938
6365
  return void 0;
5939
6366
  }
5940
6367
  }
6368
+ /**
6369
+ * Read the table style ID from `a:tblPr`.
6370
+ *
6371
+ * ECMA-376 §21.1.3.13 defines `<a:tableStyleId>{GUID}</a:tableStyleId>` as
6372
+ * a child element of `a:tblPr` carrying the GUID as element text. Older
6373
+ * inputs (and earlier versions of this library) used the legacy
6374
+ * `<a:tblStyle val="{GUID}"/>` child element or a `@_tblStyle` attribute.
6375
+ * Accept all three; the spec form takes precedence.
6376
+ */
6377
+ extractTableStyleId(tableProperties) {
6378
+ const tableStyleIdNode = tableProperties["a:tableStyleId"];
6379
+ if (tableStyleIdNode !== void 0 && tableStyleIdNode !== null) {
6380
+ const direct = typeof tableStyleIdNode === "string" || typeof tableStyleIdNode === "number" ? String(tableStyleIdNode) : String(tableStyleIdNode["#text"] ?? "");
6381
+ const trimmed = direct.trim();
6382
+ if (trimmed.length > 0) {
6383
+ return trimmed;
6384
+ }
6385
+ }
6386
+ const tableStyleNode = tableProperties["a:tblStyle"];
6387
+ const legacy = String(tableStyleNode?.["@_val"] || tableProperties["@_tblStyle"] || "").trim();
6388
+ return legacy.length > 0 ? legacy : void 0;
6389
+ }
5941
6390
  extractTableCellText(tableCell) {
5942
6391
  const paragraphs = this.context.ensureArray(tableCell?.["a:txBody"]?.["a:p"]);
5943
6392
  const lines = [];
@@ -6234,6 +6683,19 @@ var PptxGraphicFrameParser = class {
6234
6683
  if (graphicData["a:videoFile"] || graphicData["a:audioFile"] || uri.includes("/drawingml/2006/media")) {
6235
6684
  return "media";
6236
6685
  }
6686
+ if (graphicData["aink:ink"] || uri.includes("/2010/ink") || uri.includes("drawing/2010/ink")) {
6687
+ return "ink";
6688
+ }
6689
+ const alternateContent = graphicData["mc:AlternateContent"];
6690
+ if (alternateContent) {
6691
+ const choices = Array.isArray(alternateContent["mc:Choice"]) ? alternateContent["mc:Choice"] : alternateContent["mc:Choice"] ? [alternateContent["mc:Choice"]] : [];
6692
+ for (const choice of choices) {
6693
+ const requires = String(choice?.["@_Requires"] || "").toLowerCase();
6694
+ if (requires.includes("aink") || choice?.["aink:ink"]) {
6695
+ return "ink";
6696
+ }
6697
+ }
6698
+ }
6237
6699
  return "unknown";
6238
6700
  }
6239
6701
  };
@@ -7135,6 +7597,7 @@ var PptxDocumentPropertiesUpdater = class {
7135
7597
  }));
7136
7598
  if (sanitized.length === 0) {
7137
7599
  this.context.zip.remove("docProps/custom.xml");
7600
+ await this.removeCustomPropertiesPackagingArtifacts();
7138
7601
  return;
7139
7602
  }
7140
7603
  const customXml = {
@@ -7154,6 +7617,116 @@ var PptxDocumentPropertiesUpdater = class {
7154
7617
  }
7155
7618
  };
7156
7619
  this.context.zip.file("docProps/custom.xml", this.context.builder.build(customXml));
7620
+ await this.ensureCustomPropertiesPackagingArtifacts();
7621
+ }
7622
+ /**
7623
+ * Ensure `[Content_Types].xml` has an `Override` for `docProps/custom.xml`
7624
+ * and the root `_rels/.rels` references it (ECMA-376 §15.2.12.2 +
7625
+ * Part 2 §10.1.2.5). Without these, the package fails OPC validation
7626
+ * and Office strips the custom properties on next save.
7627
+ */
7628
+ async ensureCustomPropertiesPackagingArtifacts() {
7629
+ const customContentType = "application/vnd.openxmlformats-officedocument.custom-properties+xml";
7630
+ const customRelType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties";
7631
+ const ctFile = this.context.zip.file("[Content_Types].xml");
7632
+ if (ctFile) {
7633
+ try {
7634
+ const ctXml = await ctFile.async("string");
7635
+ const ctData = this.context.parser.parse(ctXml);
7636
+ const types = ctData["Types"];
7637
+ if (types) {
7638
+ const overrides = Array.isArray(types["Override"]) ? types["Override"] : types["Override"] ? [types["Override"]] : [];
7639
+ const hasCustomOverride = overrides.some(
7640
+ (o) => String(o?.["@_PartName"] || "") === "/docProps/custom.xml"
7641
+ );
7642
+ if (!hasCustomOverride) {
7643
+ overrides.push({
7644
+ "@_PartName": "/docProps/custom.xml",
7645
+ "@_ContentType": customContentType
7646
+ });
7647
+ types["Override"] = overrides.length === 1 ? overrides[0] : overrides;
7648
+ this.context.zip.file("[Content_Types].xml", this.context.builder.build(ctData));
7649
+ }
7650
+ }
7651
+ } catch (error) {
7652
+ console.warn("Failed to update [Content_Types].xml for custom properties:", error);
7653
+ }
7654
+ }
7655
+ const relsFile = this.context.zip.file("_rels/.rels");
7656
+ if (relsFile) {
7657
+ try {
7658
+ const relsXml = await relsFile.async("string");
7659
+ const relsData = this.context.parser.parse(relsXml);
7660
+ const relationships = relsData["Relationships"];
7661
+ if (relationships) {
7662
+ const rels = Array.isArray(relationships["Relationship"]) ? relationships["Relationship"] : relationships["Relationship"] ? [relationships["Relationship"]] : [];
7663
+ const hasCustomRel = rels.some((r) => String(r?.["@_Type"] || "") === customRelType);
7664
+ if (!hasCustomRel) {
7665
+ let maxId = 0;
7666
+ for (const rel of rels) {
7667
+ const id = String(rel?.["@_Id"] || "");
7668
+ const num = Number.parseInt(id.replace(/^rId/, ""), 10);
7669
+ if (Number.isFinite(num) && num > maxId) {
7670
+ maxId = num;
7671
+ }
7672
+ }
7673
+ rels.push({
7674
+ "@_Id": `rId${maxId + 1}`,
7675
+ "@_Type": customRelType,
7676
+ "@_Target": "docProps/custom.xml"
7677
+ });
7678
+ relationships["Relationship"] = rels;
7679
+ this.context.zip.file("_rels/.rels", this.context.builder.build(relsData));
7680
+ }
7681
+ }
7682
+ } catch (error) {
7683
+ console.warn("Failed to update _rels/.rels for custom properties:", error);
7684
+ }
7685
+ }
7686
+ }
7687
+ /**
7688
+ * Remove the Override + root rel for `docProps/custom.xml` when the
7689
+ * caller has emptied custom properties so the package doesn't keep an
7690
+ * orphan content-type entry referencing a deleted part.
7691
+ */
7692
+ async removeCustomPropertiesPackagingArtifacts() {
7693
+ const customRelType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties";
7694
+ const ctFile = this.context.zip.file("[Content_Types].xml");
7695
+ if (ctFile) {
7696
+ try {
7697
+ const ctXml = await ctFile.async("string");
7698
+ const ctData = this.context.parser.parse(ctXml);
7699
+ const types = ctData["Types"];
7700
+ if (types) {
7701
+ const overrides = Array.isArray(types["Override"]) ? types["Override"] : types["Override"] ? [types["Override"]] : [];
7702
+ const filtered = overrides.filter(
7703
+ (o) => String(o?.["@_PartName"] || "") !== "/docProps/custom.xml"
7704
+ );
7705
+ if (filtered.length !== overrides.length) {
7706
+ types["Override"] = filtered.length === 1 ? filtered[0] : filtered;
7707
+ this.context.zip.file("[Content_Types].xml", this.context.builder.build(ctData));
7708
+ }
7709
+ }
7710
+ } catch {
7711
+ }
7712
+ }
7713
+ const relsFile = this.context.zip.file("_rels/.rels");
7714
+ if (relsFile) {
7715
+ try {
7716
+ const relsXml = await relsFile.async("string");
7717
+ const relsData = this.context.parser.parse(relsXml);
7718
+ const relationships = relsData["Relationships"];
7719
+ if (relationships) {
7720
+ const rels = Array.isArray(relationships["Relationship"]) ? relationships["Relationship"] : relationships["Relationship"] ? [relationships["Relationship"]] : [];
7721
+ const filtered = rels.filter((r) => String(r?.["@_Type"] || "") !== customRelType);
7722
+ if (filtered.length !== rels.length) {
7723
+ relationships["Relationship"] = filtered;
7724
+ this.context.zip.file("_rels/.rels", this.context.builder.build(relsData));
7725
+ }
7726
+ }
7727
+ } catch {
7728
+ }
7729
+ }
7157
7730
  }
7158
7731
  normalizeCustomPropertyType(type) {
7159
7732
  const supportedTypes = /* @__PURE__ */ new Set([
@@ -7506,6 +8079,7 @@ var PptxSlideLoaderService = class {
7506
8079
  await params.loadSlideRelationships(path, slideRelsPath);
7507
8080
  const clrMapOverride = params.parseSlideClrMapOverride(slideXmlObj);
7508
8081
  params.setCurrentSlideClrMapOverride(clrMapOverride);
8082
+ await params.setActiveMasterForSlide?.(path);
7509
8083
  let restoreThemeOverride;
7510
8084
  try {
7511
8085
  const layoutPathForOverride = params.findLayoutPathForSlide(path);
@@ -12481,6 +13055,20 @@ var AXIS_TYPE_MAP = {
12481
13055
  dateAx: "dateAx",
12482
13056
  serAx: "serAx"
12483
13057
  };
13058
+ function upsertChartAxisChild(parent, localName, value, getLocalName) {
13059
+ const existingKey = Object.keys(parent).find((k) => getLocalName(k) === localName);
13060
+ if (value === void 0) {
13061
+ if (existingKey) {
13062
+ delete parent[existingKey];
13063
+ }
13064
+ return;
13065
+ }
13066
+ if (existingKey) {
13067
+ parent[existingKey]["@_val"] = value;
13068
+ } else {
13069
+ parent[`c:${localName}`] = { "@_val": value };
13070
+ }
13071
+ }
12484
13072
  function parseChartAxes(plotArea, xmlLookup, colorParser, getLocalName) {
12485
13073
  const result = [];
12486
13074
  for (const key of Object.keys(plotArea)) {
@@ -12601,6 +13189,27 @@ function parseSingleAxis(axisNode, axisType, xmlLookup, colorParser) {
12601
13189
  if (dispUnitsNode) {
12602
13190
  parseDisplayUnits(dispUnitsNode, xmlLookup, result);
12603
13191
  }
13192
+ const majorUnitNode = xmlLookup.getChildByLocalName(axisNode, "majorUnit");
13193
+ if (majorUnitNode) {
13194
+ const majorVal = parseFloat(String(majorUnitNode["@_val"]));
13195
+ if (Number.isFinite(majorVal)) {
13196
+ result.majorUnit = majorVal;
13197
+ }
13198
+ }
13199
+ const minorUnitNode = xmlLookup.getChildByLocalName(axisNode, "minorUnit");
13200
+ if (minorUnitNode) {
13201
+ const minorVal = parseFloat(String(minorUnitNode["@_val"]));
13202
+ if (Number.isFinite(minorVal)) {
13203
+ result.minorUnit = minorVal;
13204
+ }
13205
+ }
13206
+ const tickLblPosNode = xmlLookup.getChildByLocalName(axisNode, "tickLblPos");
13207
+ if (tickLblPosNode) {
13208
+ const v = String(tickLblPosNode["@_val"] || "").trim();
13209
+ if (v === "high" || v === "low" || v === "nextTo" || v === "none") {
13210
+ result.tickLblPos = v;
13211
+ }
13212
+ }
12604
13213
  return result;
12605
13214
  }
12606
13215
  var VALID_DISPLAY_UNITS = /* @__PURE__ */ new Set([
@@ -13913,23 +14522,55 @@ var SHAPE_TREE_ELEMENT_TAGS = /* @__PURE__ */ new Set([
13913
14522
  "p16:model3D",
13914
14523
  ...VML_SHAPE_TAGS
13915
14524
  ]);
14525
+ function diagnoseSelection(ac) {
14526
+ const choices = ensureArray2(ac["mc:Choice"]);
14527
+ for (let i = 0; i < choices.length; i++) {
14528
+ const choice = choices[i];
14529
+ const requires = String(choice?.["@_Requires"] ?? "").trim();
14530
+ if (requires.length === 0 || areNamespacesSupported(requires)) {
14531
+ const resolved = resolveNestedAlternateContent(choice);
14532
+ return { branch: "choice", choiceIndex: i, resolved };
14533
+ }
14534
+ }
14535
+ const fallback = ac["mc:Fallback"];
14536
+ if (fallback) {
14537
+ return { branch: "fallback", resolved: resolveNestedAlternateContent(fallback) };
14538
+ }
14539
+ return void 0;
14540
+ }
13916
14541
  function unwrapAlternateContent(container) {
13917
14542
  const altContents = ensureArray2(container["mc:AlternateContent"]);
13918
14543
  if (altContents.length === 0) {
13919
- return;
14544
+ return [];
13920
14545
  }
14546
+ const blocks = [];
13921
14547
  for (const ac of altContents) {
13922
- const branch = selectAlternateContentBranch(ac);
13923
- if (!branch) {
14548
+ const diagnosis = diagnoseSelection(ac);
14549
+ if (!diagnosis) {
13924
14550
  continue;
13925
14551
  }
14552
+ const block = {
14553
+ rawAc: ac,
14554
+ selectedBranch: diagnosis.branch,
14555
+ choiceIndex: diagnosis.branch === "choice" ? diagnosis.choiceIndex : void 0,
14556
+ childRefs: []
14557
+ };
14558
+ const branch = diagnosis.resolved;
13926
14559
  for (const tag of SHAPE_TREE_ELEMENT_TAGS) {
13927
14560
  const children = ensureArray2(branch[tag]);
13928
14561
  if (children.length > 0) {
13929
14562
  container[tag] = [...ensureArray2(container[tag]), ...children];
14563
+ for (const child of children) {
14564
+ block.childRefs.push({ tag, node: child });
14565
+ }
13930
14566
  }
13931
14567
  }
14568
+ if (block.childRefs.length > 0) {
14569
+ blocks.push(block);
14570
+ }
13932
14571
  }
14572
+ delete container["mc:AlternateContent"];
14573
+ return blocks;
13933
14574
  }
13934
14575
  function isNamespaceSupported(ns) {
13935
14576
  return SUPPORTED_MC_NAMESPACES.has(ns);
@@ -13947,7 +14588,7 @@ function ensureArray2(val) {
13947
14588
 
13948
14589
  // src/core/utils/body-properties-parser.ts
13949
14590
  function parseBodyPrBooleanAttrs(bodyPr, textStyle) {
13950
- const parseBoolAttr = (attr) => {
14591
+ const parseBoolAttr2 = (attr) => {
13951
14592
  const raw = bodyPr[attr];
13952
14593
  if (raw === void 0) {
13953
14594
  return void 0;
@@ -13955,19 +14596,19 @@ function parseBodyPrBooleanAttrs(bodyPr, textStyle) {
13955
14596
  const val = String(raw).trim().toLowerCase();
13956
14597
  return val === "1" || val === "true";
13957
14598
  };
13958
- const compatLnSpc = parseBoolAttr("@_compatLnSpc");
14599
+ const compatLnSpc = parseBoolAttr2("@_compatLnSpc");
13959
14600
  if (compatLnSpc !== void 0) {
13960
14601
  textStyle.compatibleLineSpacing = compatLnSpc;
13961
14602
  }
13962
- const forceAA = parseBoolAttr("@_forceAA");
14603
+ const forceAA = parseBoolAttr2("@_forceAA");
13963
14604
  if (forceAA !== void 0) {
13964
14605
  textStyle.forceAntiAlias = forceAA;
13965
14606
  }
13966
- const upright = parseBoolAttr("@_upright");
14607
+ const upright = parseBoolAttr2("@_upright");
13967
14608
  if (upright !== void 0) {
13968
14609
  textStyle.upright = upright;
13969
14610
  }
13970
- const fromWordArt = parseBoolAttr("@_fromWordArt");
14611
+ const fromWordArt = parseBoolAttr2("@_fromWordArt");
13971
14612
  if (fromWordArt !== void 0) {
13972
14613
  textStyle.fromWordArt = fromWordArt;
13973
14614
  }
@@ -13990,100 +14631,6 @@ function writeBodyPrBooleanAttrs(bodyPr, textStyle) {
13990
14631
  }
13991
14632
  }
13992
14633
 
13993
- // src/core/utils/theme-override-utils.ts
13994
- var COLOR_MAP_ALIAS_KEYS = [
13995
- "bg1",
13996
- "tx1",
13997
- "bg2",
13998
- "tx2",
13999
- "accent1",
14000
- "accent2",
14001
- "accent3",
14002
- "accent4",
14003
- "accent5",
14004
- "accent6",
14005
- "hlink",
14006
- "folHlink"
14007
- ];
14008
- var DEFAULT_COLOR_MAP = {
14009
- bg1: "lt1",
14010
- tx1: "dk1",
14011
- bg2: "lt2",
14012
- tx2: "dk2",
14013
- accent1: "accent1",
14014
- accent2: "accent2",
14015
- accent3: "accent3",
14016
- accent4: "accent4",
14017
- accent5: "accent5",
14018
- accent6: "accent6",
14019
- hlink: "hlink",
14020
- folHlink: "folHlink"
14021
- };
14022
- function buildClrMapOverrideXml(override) {
14023
- if (!override || Object.keys(override).length === 0) {
14024
- return { "a:masterClrMapping": {} };
14025
- }
14026
- const attrs2 = {};
14027
- for (const key of COLOR_MAP_ALIAS_KEYS) {
14028
- attrs2[`@_${key}`] = override[key] ?? DEFAULT_COLOR_MAP[key];
14029
- }
14030
- return { "a:overrideClrMapping": attrs2 };
14031
- }
14032
- function mergeThemeColorOverride(base, override) {
14033
- if (!override || Object.keys(override).length === 0) {
14034
- return { ...base };
14035
- }
14036
- const slotLookup = {};
14037
- for (const key of THEME_COLOR_SCHEME_KEYS) {
14038
- slotLookup[key] = base[key];
14039
- }
14040
- slotLookup["bg1"] = base.lt1;
14041
- slotLookup["tx1"] = base.dk1;
14042
- slotLookup["bg2"] = base.lt2;
14043
- slotLookup["tx2"] = base.dk2;
14044
- const result = { ...base };
14045
- for (const [alias, targetSlot] of Object.entries(override)) {
14046
- const resolvedColor = slotLookup[targetSlot] ?? base[targetSlot];
14047
- if (!resolvedColor) {
14048
- continue;
14049
- }
14050
- switch (alias) {
14051
- case "bg1":
14052
- result.lt1 = resolvedColor;
14053
- break;
14054
- case "tx1":
14055
- result.dk1 = resolvedColor;
14056
- break;
14057
- case "bg2":
14058
- result.lt2 = resolvedColor;
14059
- break;
14060
- case "tx2":
14061
- result.dk2 = resolvedColor;
14062
- break;
14063
- default: {
14064
- const schemeKey = alias;
14065
- if (schemeKey in result) {
14066
- result[schemeKey] = resolvedColor;
14067
- }
14068
- break;
14069
- }
14070
- }
14071
- }
14072
- return result;
14073
- }
14074
- function hasNonTrivialOverride(override) {
14075
- if (!override) {
14076
- return false;
14077
- }
14078
- for (const key of COLOR_MAP_ALIAS_KEYS) {
14079
- const overrideValue = override[key];
14080
- if (overrideValue && overrideValue !== DEFAULT_COLOR_MAP[key]) {
14081
- return true;
14082
- }
14083
- }
14084
- return false;
14085
- }
14086
-
14087
14634
  // src/core/utils/clone-utils.ts
14088
14635
  function cloneTextStyle(style) {
14089
14636
  if (!style) {
@@ -17124,6 +17671,100 @@ function resolveLayoutCategory(layoutType) {
17124
17671
  return "list";
17125
17672
  }
17126
17673
 
17674
+ // src/core/utils/theme-override-utils.ts
17675
+ var COLOR_MAP_ALIAS_KEYS = [
17676
+ "bg1",
17677
+ "tx1",
17678
+ "bg2",
17679
+ "tx2",
17680
+ "accent1",
17681
+ "accent2",
17682
+ "accent3",
17683
+ "accent4",
17684
+ "accent5",
17685
+ "accent6",
17686
+ "hlink",
17687
+ "folHlink"
17688
+ ];
17689
+ var DEFAULT_COLOR_MAP = {
17690
+ bg1: "lt1",
17691
+ tx1: "dk1",
17692
+ bg2: "lt2",
17693
+ tx2: "dk2",
17694
+ accent1: "accent1",
17695
+ accent2: "accent2",
17696
+ accent3: "accent3",
17697
+ accent4: "accent4",
17698
+ accent5: "accent5",
17699
+ accent6: "accent6",
17700
+ hlink: "hlink",
17701
+ folHlink: "folHlink"
17702
+ };
17703
+ function buildClrMapOverrideXml(override) {
17704
+ if (!override || Object.keys(override).length === 0) {
17705
+ return { "a:masterClrMapping": {} };
17706
+ }
17707
+ const attrs2 = {};
17708
+ for (const key of COLOR_MAP_ALIAS_KEYS) {
17709
+ attrs2[`@_${key}`] = override[key] ?? DEFAULT_COLOR_MAP[key];
17710
+ }
17711
+ return { "a:overrideClrMapping": attrs2 };
17712
+ }
17713
+ function mergeThemeColorOverride(base, override) {
17714
+ if (!override || Object.keys(override).length === 0) {
17715
+ return { ...base };
17716
+ }
17717
+ const slotLookup = {};
17718
+ for (const key of THEME_COLOR_SCHEME_KEYS) {
17719
+ slotLookup[key] = base[key];
17720
+ }
17721
+ slotLookup["bg1"] = base.lt1;
17722
+ slotLookup["tx1"] = base.dk1;
17723
+ slotLookup["bg2"] = base.lt2;
17724
+ slotLookup["tx2"] = base.dk2;
17725
+ const result = { ...base };
17726
+ for (const [alias, targetSlot] of Object.entries(override)) {
17727
+ const resolvedColor = slotLookup[targetSlot] ?? base[targetSlot];
17728
+ if (!resolvedColor) {
17729
+ continue;
17730
+ }
17731
+ switch (alias) {
17732
+ case "bg1":
17733
+ result.lt1 = resolvedColor;
17734
+ break;
17735
+ case "tx1":
17736
+ result.dk1 = resolvedColor;
17737
+ break;
17738
+ case "bg2":
17739
+ result.lt2 = resolvedColor;
17740
+ break;
17741
+ case "tx2":
17742
+ result.dk2 = resolvedColor;
17743
+ break;
17744
+ default: {
17745
+ const schemeKey = alias;
17746
+ if (schemeKey in result) {
17747
+ result[schemeKey] = resolvedColor;
17748
+ }
17749
+ break;
17750
+ }
17751
+ }
17752
+ }
17753
+ return result;
17754
+ }
17755
+ function hasNonTrivialOverride(override) {
17756
+ if (!override) {
17757
+ return false;
17758
+ }
17759
+ for (const key of COLOR_MAP_ALIAS_KEYS) {
17760
+ const overrideValue = override[key];
17761
+ if (overrideValue && overrideValue !== DEFAULT_COLOR_MAP[key]) {
17762
+ return true;
17763
+ }
17764
+ }
17765
+ return false;
17766
+ }
17767
+
17127
17768
  // src/core/utils/encryption-detection.ts
17128
17769
  var OLE_MAGIC = new Uint8Array([208, 207, 17, 224, 161, 27, 26, 225]);
17129
17770
  var ZIP_MAGIC = new Uint8Array([80, 75]);
@@ -24348,7 +24989,7 @@ async function repairPptx(buffer) {
24348
24989
  }
24349
24990
 
24350
24991
  // src/core/utils/theme-switching.ts
24351
- function normalizeHex(hex) {
24992
+ function normalizeHex2(hex) {
24352
24993
  if (!hex) {
24353
24994
  return "";
24354
24995
  }
@@ -24358,8 +24999,8 @@ function buildColorRemapTable(oldColorMap, newColorMap) {
24358
24999
  const remap = /* @__PURE__ */ new Map();
24359
25000
  const allKeys = [...THEME_COLOR_SCHEME_KEYS, "tx1", "bg1", "tx2", "bg2"];
24360
25001
  for (const key of allKeys) {
24361
- const oldVal = normalizeHex(oldColorMap[key]);
24362
- const newVal = normalizeHex(newColorMap[key]);
25002
+ const oldVal = normalizeHex2(oldColorMap[key]);
25003
+ const newVal = normalizeHex2(newColorMap[key]);
24363
25004
  if (oldVal && newVal && oldVal !== newVal) {
24364
25005
  remap.set(oldVal, `#${newVal}`);
24365
25006
  remap.set(`#${oldVal}`, `#${newVal}`);
@@ -24371,7 +25012,7 @@ function remapColor(color, remap) {
24371
25012
  if (!color) {
24372
25013
  return color;
24373
25014
  }
24374
- const normalized = normalizeHex(color);
25015
+ const normalized = normalizeHex2(color);
24375
25016
  const remapped = remap.get(normalized) ?? remap.get(`#${normalized}`);
24376
25017
  return remapped ?? color;
24377
25018
  }
@@ -24511,7 +25152,7 @@ function remapSlideColors(slide, remap) {
24511
25152
  function buildThemeColorMap(colorScheme) {
24512
25153
  const map = {};
24513
25154
  for (const key of THEME_COLOR_SCHEME_KEYS) {
24514
- map[key] = normalizeHex(colorScheme[key]);
25155
+ map[key] = normalizeHex2(colorScheme[key]);
24515
25156
  }
24516
25157
  map.tx1 = map.dk1;
24517
25158
  map.bg1 = map.lt1;
@@ -25484,8 +26125,11 @@ function relayoutSmartArt(smartArtData, containerWidth, containerHeight) {
25484
26125
 
25485
26126
  // src/core/core/runtime/PptxHandlerRuntimeSaveParagraphHelpers.ts
25486
26127
  var EMU_PER_PX5 = 9525;
25487
- function buildParagraphPropertiesXml(textStyle, paragraphAlign, bulletInfo, spacing) {
26128
+ function buildParagraphPropertiesXml(textStyle, paragraphAlign, bulletInfo, spacing, level) {
25488
26129
  const paragraphProps = {};
26130
+ if (typeof level === "number" && Number.isFinite(level) && level > 0) {
26131
+ paragraphProps["@_lvl"] = String(Math.min(Math.max(Math.round(level), 0), 8));
26132
+ }
25489
26133
  if (paragraphAlign) {
25490
26134
  paragraphProps["@_algn"] = paragraphAlign;
25491
26135
  }
@@ -25557,23 +26201,28 @@ function applyBulletProperties(paragraphProps, bulletInfo) {
25557
26201
  paragraphProps["a:buNone"] = {};
25558
26202
  return;
25559
26203
  }
25560
- if (bulletInfo.color) {
26204
+ if (bulletInfo.colorInherit) {
26205
+ paragraphProps["a:buClrTx"] = {};
26206
+ } else if (bulletInfo.color) {
25561
26207
  const colorHex = bulletInfo.color.replace("#", "");
25562
26208
  paragraphProps["a:buClr"] = {
25563
26209
  "a:srgbClr": { "@_val": colorHex }
25564
26210
  };
25565
26211
  }
25566
- if (bulletInfo.sizePercent !== void 0) {
26212
+ if (bulletInfo.sizeInherit) {
26213
+ paragraphProps["a:buSzTx"] = {};
26214
+ } else if (bulletInfo.sizePercent !== void 0) {
25567
26215
  paragraphProps["a:buSzPct"] = {
25568
26216
  "@_val": String(Math.round(bulletInfo.sizePercent * 1e3))
25569
26217
  };
25570
- }
25571
- if (bulletInfo.sizePts !== void 0) {
26218
+ } else if (bulletInfo.sizePts !== void 0) {
25572
26219
  paragraphProps["a:buSzPts"] = {
25573
26220
  "@_val": String(Math.round(bulletInfo.sizePts * 100))
25574
26221
  };
25575
26222
  }
25576
- if (bulletInfo.fontFamily) {
26223
+ if (bulletInfo.fontInherit) {
26224
+ paragraphProps["a:buFontTx"] = {};
26225
+ } else if (bulletInfo.fontFamily) {
25577
26226
  paragraphProps["a:buFont"] = {
25578
26227
  "@_typeface": bulletInfo.fontFamily
25579
26228
  };
@@ -25596,7 +26245,7 @@ function applyBulletProperties(paragraphProps, bulletInfo) {
25596
26245
  };
25597
26246
  }
25598
26247
  }
25599
- function assembleParagraphXml(runs, paragraphProps) {
26248
+ function assembleParagraphXml(runs, paragraphProps, endParaRunProperties) {
25600
26249
  const paragraph = {
25601
26250
  "a:pPr": paragraphProps
25602
26251
  };
@@ -25618,7 +26267,11 @@ function assembleParagraphXml(runs, paragraphProps) {
25618
26267
  if (cleanRegularRuns.length === 0 && fieldRuns.length === 0) {
25619
26268
  paragraph["a:r"] = runs.length > 1 ? runs : runs[0];
25620
26269
  }
25621
- paragraph["a:endParaRPr"] = { "@_lang": "en-US" };
26270
+ if (endParaRunProperties && typeof endParaRunProperties === "object") {
26271
+ paragraph["a:endParaRPr"] = endParaRunProperties;
26272
+ } else {
26273
+ paragraph["a:endParaRPr"] = { "@_lang": "en-US" };
26274
+ }
25622
26275
  return paragraph;
25623
26276
  }
25624
26277
  function computeUniformSegmentOverrides(textStyle, textSegments) {
@@ -25922,6 +26575,140 @@ var PptxHandlerRuntime = class {
25922
26575
  * `p:clrMapOvr / a:overrideClrMapping`.
25923
26576
  */
25924
26577
  currentSlideClrMapOverride = null;
26578
+ /**
26579
+ * Per-master colour map alias dictionaries parsed from each master's
26580
+ * `<p:clrMap>` element (e.g. `bg1 → lt1`, `tx1 → dk1`, `accent1 → accent1`).
26581
+ *
26582
+ * `clrMap` is the *aliasing* layer between logical colour names used in
26583
+ * DrawingML and the raw theme scheme slots. Per ECMA-376 §19.3.1.7 it
26584
+ * lives on each `p:sldMaster`, and slide layouts/slides may further
26585
+ * override it via `p:clrMapOvr`. Resolution must happen at colour-lookup
26586
+ * time, *not* by baking it into {@link themeColorMap}.
26587
+ *
26588
+ * Phase 2 Stream B / C-H4.
26589
+ */
26590
+ masterClrMaps = /* @__PURE__ */ new Map();
26591
+ /**
26592
+ * Per-master theme color maps. Each master may reference its own theme
26593
+ * file via `_rels/slideMasterN.xml.rels`. For multi-master decks, slides
26594
+ * must resolve scheme colours against their *own* master's theme.
26595
+ *
26596
+ * Falls back to {@link themeColorMap} when a master entry is missing.
26597
+ *
26598
+ * Phase 2 Stream B / C-H4.
26599
+ */
26600
+ masterThemeColorMaps = /* @__PURE__ */ new Map();
26601
+ /**
26602
+ * Per-master theme font maps. Same rationale as
26603
+ * {@link masterThemeColorMaps}: multi-master decks may have one font
26604
+ * scheme per theme.
26605
+ */
26606
+ masterThemeFontMaps = /* @__PURE__ */ new Map();
26607
+ /**
26608
+ * Per-master format schemes (fmtScheme). For multi-master decks each
26609
+ * master's slides should resolve fill/line/effect refs against the
26610
+ * matrix from that master's theme.
26611
+ */
26612
+ masterThemeFormatSchemes = /* @__PURE__ */ new Map();
26613
+ /**
26614
+ * Per-master mapping from slide-master path to the theme path it
26615
+ * references via `_rels/slideMasterN.xml.rels`. Populated by
26616
+ * {@link loadPerMasterThemes} during load. Used by the save-side
26617
+ * theme writer to know which themeN.xml to (re)emit for each master.
26618
+ *
26619
+ * Phase 4 Stream A / C-H3.
26620
+ */
26621
+ masterThemePaths = /* @__PURE__ */ new Map();
26622
+ /**
26623
+ * Per-script font tables for major and minor fonts. Captured per master
26624
+ * theme. Keys are master paths; values map `mj`/`mn` -> script tag (e.g.
26625
+ * `Hans`, `Hant`, `Arab`, `Hebr`, `Thai`, `Beng`, …) -> typeface name.
26626
+ *
26627
+ * Phase 4 Stream A / M4.
26628
+ */
26629
+ masterThemeMajorFontScripts = /* @__PURE__ */ new Map();
26630
+ masterThemeMinorFontScripts = /* @__PURE__ */ new Map();
26631
+ /**
26632
+ * Theme name attribute (`<a:theme @name>`) per master theme path.
26633
+ * Captured for byte-stable round-trip.
26634
+ */
26635
+ masterThemeNames = /* @__PURE__ */ new Map();
26636
+ /**
26637
+ * `<a:fontScheme @name>` per master theme path.
26638
+ */
26639
+ masterThemeFontSchemeNames = /* @__PURE__ */ new Map();
26640
+ /**
26641
+ * `<a:clrScheme @name>` per master theme path.
26642
+ */
26643
+ masterThemeColorSchemeNames = /* @__PURE__ */ new Map();
26644
+ /**
26645
+ * Raw original theme XML keyed by theme path. Captured at load-time.
26646
+ * Used by the save pipeline to passthrough the full theme XML when no
26647
+ * in-memory mutation has occurred — preserving fillStyleLst /
26648
+ * lnStyleLst / effectStyleLst / bgFillStyleLst /
26649
+ * extraClrSchemeLst / objectDefaults / extLst exactly as written.
26650
+ *
26651
+ * Phase 4 Stream A / C-H3.
26652
+ */
26653
+ originalThemeXmlByPath = /* @__PURE__ */ new Map();
26654
+ /**
26655
+ * Set of theme paths whose in-memory state has been mutated since
26656
+ * load. Saving a theme path that's NOT dirty is a no-op (the original
26657
+ * file already exists in the ZIP). Saving a dirty theme path
26658
+ * regenerates the part from in-memory state.
26659
+ *
26660
+ * Phase 4 Stream A / C-H3.
26661
+ */
26662
+ dirtyThemePaths = /* @__PURE__ */ new Set();
26663
+ /**
26664
+ * Per-master parsed `<p:txStyles>` (titleStyle/bodyStyle/otherStyle).
26665
+ * Populated by {@link enrichSlideMastersWithTxStyles} during load so the
26666
+ * inheritance chain can find the master text-style cascade without
26667
+ * re-parsing master XML on every lookup. Phase 4 Stream B / P-H1.
26668
+ */
26669
+ masterTxStylesCache = /* @__PURE__ */ new Map();
26670
+ /**
26671
+ * Captured `<a:objectDefaults>` snapshot per master theme path. The
26672
+ * full ECMA-376 inheritance chain (master / layout / placeholder /
26673
+ * objectDefaults) is non-trivial; we store the raw spDef/lnDef/txDef
26674
+ * subtrees and re-emit them verbatim for round-trip.
26675
+ *
26676
+ * Phase 4 Stream A / M5.
26677
+ */
26678
+ masterThemeObjectDefaults = /* @__PURE__ */ new Map();
26679
+ /**
26680
+ * Captured `<a:extraClrSchemeLst>` raw subtree per master theme path
26681
+ * for verbatim round-trip.
26682
+ *
26683
+ * Phase 4 Stream A.
26684
+ */
26685
+ masterThemeExtraClrSchemeLst = /* @__PURE__ */ new Map();
26686
+ /**
26687
+ * Captured `<a:custClrLst>` raw subtree per master theme path
26688
+ * for verbatim round-trip.
26689
+ *
26690
+ * Phase 4 Stream A.
26691
+ */
26692
+ masterThemeCustClrLst = /* @__PURE__ */ new Map();
26693
+ /**
26694
+ * Captured theme-level `<a:extLst>` raw subtree per master theme path.
26695
+ */
26696
+ masterThemeExtLst = /* @__PURE__ */ new Map();
26697
+ /**
26698
+ * Active master's clrMap for the slide currently being parsed. Walked
26699
+ * after `currentSlideClrMapOverride` (slide and layout overrides take
26700
+ * precedence). `null` means "fall through to themeColorMap directly".
26701
+ */
26702
+ currentMasterClrMap = null;
26703
+ /**
26704
+ * Snapshot of the global theme state taken right after
26705
+ * {@link loadThemeData} completes. Used as the fallback when a slide's
26706
+ * master has no per-master theme entry, so per-slide multi-master
26707
+ * switching does not leak the previous slide's master state.
26708
+ */
26709
+ globalThemeColorMapSnapshot = {};
26710
+ globalThemeFontMapSnapshot = {};
26711
+ globalThemeFormatSchemeSnapshot;
25925
26712
  /** Thumbnail image data from `docProps/thumbnail.jpeg` preserved for round-trip. */
25926
26713
  thumbnailData = null;
25927
26714
  /** Raw VBA project binary preserved for macro-enabled (.pptm) round-trip. */
@@ -25932,6 +26719,19 @@ var PptxHandlerRuntime = class {
25932
26719
  signatureDetection = null;
25933
26720
  /** Custom XML data parts parsed from `customXml/` in the OPC package. */
25934
26721
  customXmlParts = [];
26722
+ /**
26723
+ * Maps an element's `rawXml` reference to the `mc:AlternateContent`
26724
+ * envelope that originally wrapped it (CC-4). Populated during slide
26725
+ * (and `p:grpSp`) parsing; consulted at save time to re-emit the
26726
+ * original `<mc:Choice>` / `<mc:Fallback>` shape so legacy renderers
26727
+ * keep their fallback content.
26728
+ *
26729
+ * Multiple sibling elements may share the same `AlternateContentBlock`
26730
+ * value (a single AC envelope often wraps several child shapes — e.g.
26731
+ * `p14:media` + its `p:pic` fallback nest one each). WeakMap so AC
26732
+ * envelopes are GC'd if the parsed XmlObject is dropped.
26733
+ */
26734
+ alternateContentBlockByRawXml = /* @__PURE__ */ new WeakMap();
25935
26735
  /** Embedded fonts extracted during load, preserved for automatic re-embedding on save. */
25936
26736
  loadedEmbeddedFonts = [];
25937
26737
  /** Map of comment author IDs to display names (from `ppt/commentAuthors.xml`). */
@@ -27745,7 +28545,12 @@ var PptxHandlerRuntime9 = class extends PptxHandlerRuntime8 {
27745
28545
  const bgColor = this.parseBackgroundColor(bg);
27746
28546
  const spTree = master["p:cSld"]?.["p:spTree"];
27747
28547
  const placeholders = this.extractPlaceholderList(spTree);
27748
- return { path, backgroundColor: bgColor, placeholders };
28548
+ const result = { path, backgroundColor: bgColor, placeholders };
28549
+ const hf = parseHeaderFooterFlags(master["p:hf"]);
28550
+ if (hf) {
28551
+ result.headerFooter = hf;
28552
+ }
28553
+ return result;
27749
28554
  } catch (e) {
27750
28555
  console.warn("Failed to parse handout master:", e);
27751
28556
  return void 0;
@@ -27771,7 +28576,12 @@ var PptxHandlerRuntime9 = class extends PptxHandlerRuntime8 {
27771
28576
  const bgColor = this.parseBackgroundColor(bg);
27772
28577
  const spTree = master["p:cSld"]?.["p:spTree"];
27773
28578
  const placeholders = this.extractPlaceholderList(spTree);
27774
- return { path, backgroundColor: bgColor, placeholders };
28579
+ const result = { path, backgroundColor: bgColor, placeholders };
28580
+ const hf = parseHeaderFooterFlags(master["p:hf"]);
28581
+ if (hf) {
28582
+ result.headerFooter = hf;
28583
+ }
28584
+ return result;
27775
28585
  } catch (e) {
27776
28586
  console.warn("Failed to parse notes master:", e);
27777
28587
  return void 0;
@@ -27816,6 +28626,10 @@ var PptxHandlerRuntime9 = class extends PptxHandlerRuntime8 {
27816
28626
  const uVal = String(userDrawn).trim().toLowerCase();
27817
28627
  layout.userDrawn = uVal === "1" || uVal === "true";
27818
28628
  }
28629
+ const hf = parseHeaderFooterFlags(sldLayout["p:hf"]);
28630
+ if (hf) {
28631
+ layout.headerFooter = hf;
28632
+ }
27819
28633
  const clrMapOvr = sldLayout["p:clrMapOvr"];
27820
28634
  if (clrMapOvr && clrMapOvr["a:masterClrMapping"] === void 0) {
27821
28635
  const overrideNode = clrMapOvr["a:overrideClrMapping"];
@@ -28421,6 +29235,18 @@ function buildClrChangeNode(style) {
28421
29235
  }
28422
29236
 
28423
29237
  // src/core/core/runtime/PptxHandlerRuntimeSaveRunProperties.ts
29238
+ function applyFontMetadata(fontNode, panose, pitchFamily, charset) {
29239
+ if (panose && panose.length > 0) {
29240
+ fontNode["@_panose"] = panose;
29241
+ }
29242
+ if (typeof pitchFamily === "number" && Number.isFinite(pitchFamily)) {
29243
+ fontNode["@_pitchFamily"] = String(pitchFamily);
29244
+ }
29245
+ if (typeof charset === "number" && Number.isFinite(charset)) {
29246
+ fontNode["@_charset"] = String(charset);
29247
+ }
29248
+ return fontNode;
29249
+ }
28424
29250
  var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime11 {
28425
29251
  createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId) {
28426
29252
  const runProps = {
@@ -28478,6 +29304,12 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
28478
29304
  if (style.bookmark) {
28479
29305
  runProps["@_bmk"] = style.bookmark;
28480
29306
  }
29307
+ if (style.altLanguage) {
29308
+ runProps["@_altLang"] = style.altLanguage;
29309
+ }
29310
+ if (typeof style.smartTagId === "number" && Number.isFinite(style.smartTagId)) {
29311
+ runProps["@_smtId"] = String(style.smartTagId);
29312
+ }
28481
29313
  if (style.textOutlineWidth || style.textOutlineColor) {
28482
29314
  const lnObj = {};
28483
29315
  if (typeof style.textOutlineWidth === "number" && style.textOutlineWidth > 0) {
@@ -28493,11 +29325,12 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
28493
29325
  runProps["a:ln"] = lnObj;
28494
29326
  }
28495
29327
  if (style.color) {
28496
- runProps["a:solidFill"] = {
28497
- "a:srgbClr": {
28498
- "@_val": style.color.replace("#", "")
28499
- }
28500
- };
29328
+ const resolvedOriginalColor = style.colorXml ? this.parseColor(style.colorXml) : void 0;
29329
+ runProps["a:solidFill"] = serializeColorChoice(
29330
+ style.colorXml,
29331
+ resolvedOriginalColor,
29332
+ style.color
29333
+ );
28501
29334
  } else if (style.textFillGradientStops && style.textFillGradientStops.length > 0) {
28502
29335
  const gradStops = style.textFillGradientStops.filter((stop) => Boolean(stop?.color)).map((stop) => {
28503
29336
  const rawPos = (stop.position ?? 0) / 100;
@@ -28570,16 +29403,32 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
28570
29403
  };
28571
29404
  }
28572
29405
  if (style.fontFamily) {
28573
- runProps["a:latin"] = { "@_typeface": style.fontFamily };
28574
- runProps["a:ea"] = {
28575
- "@_typeface": style.eastAsiaFont || style.fontFamily
28576
- };
28577
- runProps["a:cs"] = {
28578
- "@_typeface": style.complexScriptFont || style.fontFamily
28579
- };
29406
+ runProps["a:latin"] = applyFontMetadata(
29407
+ { "@_typeface": style.fontFamily },
29408
+ style.latinFontPanose,
29409
+ style.latinFontPitchFamily,
29410
+ style.latinFontCharset
29411
+ );
29412
+ runProps["a:ea"] = applyFontMetadata(
29413
+ { "@_typeface": style.eastAsiaFont || style.fontFamily },
29414
+ style.eastAsiaFontPanose,
29415
+ style.eastAsiaFontPitchFamily,
29416
+ style.eastAsiaFontCharset
29417
+ );
29418
+ runProps["a:cs"] = applyFontMetadata(
29419
+ { "@_typeface": style.complexScriptFont || style.fontFamily },
29420
+ style.complexScriptFontPanose,
29421
+ style.complexScriptFontPitchFamily,
29422
+ style.complexScriptFontCharset
29423
+ );
28580
29424
  }
28581
29425
  if (style.symbolFont) {
28582
- runProps["a:sym"] = { "@_typeface": style.symbolFont };
29426
+ runProps["a:sym"] = applyFontMetadata(
29427
+ { "@_typeface": style.symbolFont },
29428
+ style.symbolFontPanose,
29429
+ style.symbolFontPitchFamily,
29430
+ style.symbolFontCharset
29431
+ );
28583
29432
  }
28584
29433
  if (style.hyperlink && resolveHyperlinkRelationshipId) {
28585
29434
  const hyperlinkTarget = String(style.hyperlink).trim();
@@ -28654,14 +29503,15 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
28654
29503
  lineSpacing: this.createLineSpacingXmlFromMultiplier(textStyle?.lineSpacing),
28655
29504
  lineSpacingExactPt: textStyle?.lineSpacingExactPt
28656
29505
  };
28657
- const createParagraph = (runs, bulletInfo) => {
29506
+ const createParagraph = (runs, bulletInfo, level, endParaRunProperties) => {
28658
29507
  const paragraphProps = buildParagraphPropertiesXml(
28659
29508
  textStyle,
28660
29509
  paragraphAlign,
28661
29510
  bulletInfo,
28662
- spacing
29511
+ spacing,
29512
+ level
28663
29513
  );
28664
- return assembleParagraphXml(runs, paragraphProps);
29514
+ return assembleParagraphXml(runs, paragraphProps, endParaRunProperties);
28665
29515
  };
28666
29516
  const createRun = (runText, style) => ({
28667
29517
  "a:rPr": this.createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId),
@@ -28709,13 +29559,19 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
28709
29559
  const paragraphs = [];
28710
29560
  let currentRuns = [];
28711
29561
  let currentBulletInfo;
29562
+ let currentLevel;
29563
+ let currentEndParaRunProperties;
28712
29564
  const pushParagraph = () => {
28713
29565
  if (currentRuns.length === 0) {
28714
29566
  currentRuns.push(createRun("", textStyle));
28715
29567
  }
28716
- paragraphs.push(createParagraph(currentRuns, currentBulletInfo));
29568
+ paragraphs.push(
29569
+ createParagraph(currentRuns, currentBulletInfo, currentLevel, currentEndParaRunProperties)
29570
+ );
28717
29571
  currentRuns = [];
28718
29572
  currentBulletInfo = void 0;
29573
+ currentLevel = void 0;
29574
+ currentEndParaRunProperties = void 0;
28719
29575
  };
28720
29576
  if (textSegments && textSegments.length > 0) {
28721
29577
  const uniformSegmentOverrides = computeUniformSegmentOverrides(textStyle, textSegments);
@@ -28727,8 +29583,16 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
28727
29583
  };
28728
29584
  const segmentText = String(segment.text ?? "");
28729
29585
  const lineParts = segmentText.split("\n");
28730
- if (currentRuns.length === 0 && segment.bulletInfo) {
28731
- currentBulletInfo = segment.bulletInfo;
29586
+ if (currentRuns.length === 0) {
29587
+ if (segment.bulletInfo) {
29588
+ currentBulletInfo = segment.bulletInfo;
29589
+ }
29590
+ if (segment.paragraphLevel !== void 0) {
29591
+ currentLevel = segment.paragraphLevel;
29592
+ }
29593
+ if (segment.endParaRunProperties) {
29594
+ currentEndParaRunProperties = segment.endParaRunProperties;
29595
+ }
28732
29596
  }
28733
29597
  lineParts.forEach((linePart, lineIndex) => {
28734
29598
  if (segment.rubyText !== void 0) {
@@ -28826,6 +29690,9 @@ var PptxHandlerRuntime14 = class extends PptxHandlerRuntime13 {
28826
29690
  };
28827
29691
 
28828
29692
  // src/core/core/runtime/PptxHandlerRuntimeSaveShapeXml.ts
29693
+ var OLE_OBJECT_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject";
29694
+ var IMAGE_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
29695
+ var OLE_GRAPHIC_DATA_URI = "http://schemas.openxmlformats.org/presentationml/2006/ole";
28829
29696
  var PptxHandlerRuntime15 = class _PptxHandlerRuntime extends PptxHandlerRuntime14 {
28830
29697
  /**
28831
29698
  * Build a `p:graphicFrame` XML skeleton for an SDK-created table.
@@ -28876,6 +29743,148 @@ var PptxHandlerRuntime15 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
28876
29743
  }
28877
29744
  };
28878
29745
  }
29746
+ /**
29747
+ * Build a `p:graphicFrame` XML skeleton for an OLE object element.
29748
+ *
29749
+ * Used both for SDK-created OLE elements (no `rawXml`) and to refresh
29750
+ * a few key attributes on a loaded element when the typed fields have
29751
+ * been mutated. The output is the canonical
29752
+ * `p:graphicFrame > a:graphic > a:graphicData uri="…/ole" > p:oleObj`
29753
+ * shape per ECMA-376 §19.3.1.34 / §13.3.4.
29754
+ *
29755
+ * The caller (`processSlideElement`) is responsible for ensuring the
29756
+ * embed / preview-image relationships referenced from `r:id` / `r:embed`
29757
+ * exist in the slide's rels file. This method does not register them
29758
+ * itself because the typed model does not currently carry the binary
29759
+ * payload — the binary part must already be in the package (loaded from
29760
+ * the original file). A fully-fabricated SDK OLE element therefore
29761
+ * still requires the consumer to attach the binary out-of-band; this
29762
+ * method simply emits a schema-valid envelope referencing the
29763
+ * specified relationship ID.
29764
+ */
29765
+ createOleGraphicFrameXml(el, embedRelationshipId) {
29766
+ const EMU = _PptxHandlerRuntime.EMU_PER_PX;
29767
+ const offX = String(Math.round(el.x * EMU));
29768
+ const offY = String(Math.round(el.y * EMU));
29769
+ const extCx = String(Math.round(Math.max(el.width, 1) * EMU));
29770
+ const extCy = String(Math.round(Math.max(el.height, 1) * EMU));
29771
+ const oleObj = {
29772
+ "@_showAsIcon": "0",
29773
+ "@_imgW": extCx,
29774
+ "@_imgH": extCy
29775
+ };
29776
+ if (el.oleProgId) {
29777
+ oleObj["@_progId"] = el.oleProgId;
29778
+ }
29779
+ if (el.oleName) {
29780
+ oleObj["@_name"] = el.oleName;
29781
+ }
29782
+ if (el.oleClsId) {
29783
+ oleObj["@_classid"] = el.oleClsId;
29784
+ }
29785
+ if (embedRelationshipId) {
29786
+ oleObj["@_r:id"] = embedRelationshipId;
29787
+ }
29788
+ if (el.isLinked) {
29789
+ oleObj["p:link"] = {
29790
+ "@_r:id": embedRelationshipId,
29791
+ "@_updateAutomatic": "1"
29792
+ };
29793
+ } else {
29794
+ oleObj["p:embed"] = {};
29795
+ }
29796
+ oleObj["p:pic"] = {
29797
+ "p:nvPicPr": {
29798
+ "p:cNvPr": { "@_id": "0", "@_name": el.oleName || "OleObject" },
29799
+ "p:cNvPicPr": {},
29800
+ "p:nvPr": {}
29801
+ },
29802
+ "p:blipFill": {
29803
+ "a:blip": {},
29804
+ "a:stretch": { "a:fillRect": {} }
29805
+ },
29806
+ "p:spPr": {
29807
+ "a:xfrm": {
29808
+ "a:off": { "@_x": offX, "@_y": offY },
29809
+ "a:ext": { "@_cx": extCx, "@_cy": extCy }
29810
+ },
29811
+ "a:prstGeom": { "@_prst": "rect", "a:avLst": {} }
29812
+ }
29813
+ };
29814
+ return {
29815
+ "p:nvGraphicFramePr": {
29816
+ "p:cNvPr": { "@_id": "0", "@_name": el.oleName || el.fileName || "OleObject" },
29817
+ "p:cNvGraphicFramePr": {
29818
+ "a:graphicFrameLocks": { "@_noChangeAspect": "1" }
29819
+ },
29820
+ "p:nvPr": {}
29821
+ },
29822
+ "p:xfrm": {
29823
+ "a:off": { "@_x": offX, "@_y": offY },
29824
+ "a:ext": { "@_cx": extCx, "@_cy": extCy }
29825
+ },
29826
+ "a:graphic": {
29827
+ "a:graphicData": {
29828
+ "@_uri": OLE_GRAPHIC_DATA_URI,
29829
+ "p:oleObj": oleObj
29830
+ }
29831
+ }
29832
+ };
29833
+ }
29834
+ /**
29835
+ * Refresh editable typed-field attributes on a loaded OLE graphicFrame's
29836
+ * raw XML. Only attributes that round-trip through the typed model
29837
+ * (`progId`, `name`, `classid`) are touched so unknown extension data
29838
+ * passes through verbatim.
29839
+ */
29840
+ applyOleTypedFieldUpdates(shape, el) {
29841
+ const oleObj = shape["a:graphic"]?.["a:graphicData"]?.["p:oleObj"];
29842
+ if (!oleObj) {
29843
+ return;
29844
+ }
29845
+ if (el.oleProgId) {
29846
+ oleObj["@_progId"] = el.oleProgId;
29847
+ }
29848
+ if (el.oleName !== void 0) {
29849
+ if (el.oleName.length > 0) {
29850
+ oleObj["@_name"] = el.oleName;
29851
+ } else {
29852
+ delete oleObj["@_name"];
29853
+ }
29854
+ }
29855
+ if (el.oleClsId) {
29856
+ oleObj["@_classid"] = el.oleClsId;
29857
+ }
29858
+ }
29859
+ /** Look up the existing OLE binary relationship ID for this slide, if any. */
29860
+ resolveOleEmbedRelationshipId(slideRelationships, oleTarget) {
29861
+ if (!oleTarget) {
29862
+ return void 0;
29863
+ }
29864
+ const normalisedTarget = oleTarget.replace(/^ppt\//, "../").replace(/^\/+/, "");
29865
+ const lowerTarget = normalisedTarget.toLowerCase();
29866
+ for (const rel of slideRelationships) {
29867
+ const relType = String(rel?.["@_Type"] || "");
29868
+ if (relType !== OLE_OBJECT_RELATIONSHIP_TYPE) {
29869
+ continue;
29870
+ }
29871
+ const target = String(rel?.["@_Target"] || "").toLowerCase().trim();
29872
+ if (target === lowerTarget || target.endsWith(lowerTarget) || lowerTarget.endsWith(target)) {
29873
+ const relId = String(rel?.["@_Id"] || "").trim();
29874
+ if (relId.length > 0) {
29875
+ return relId;
29876
+ }
29877
+ }
29878
+ }
29879
+ const fallback = slideRelationships.find(
29880
+ (rel) => String(rel?.["@_Type"] || "") === OLE_OBJECT_RELATIONSHIP_TYPE
29881
+ );
29882
+ const fallbackId = String(fallback?.["@_Id"] || "").trim();
29883
+ return fallbackId.length > 0 ? fallbackId : void 0;
29884
+ }
29885
+ /** Constants are exposed so the element-writer mixin can reuse them. */
29886
+ static OLE_OBJECT_RELATIONSHIP_TYPE = OLE_OBJECT_RELATIONSHIP_TYPE;
29887
+ static OLE_IMAGE_RELATIONSHIP_TYPE = IMAGE_RELATIONSHIP_TYPE;
28879
29888
  /**
28880
29889
  * Build a p:sp XML object for an ink annotation element.
28881
29890
  * Each ink path becomes a separate a:path within a:pathLst,
@@ -29192,6 +30201,9 @@ var PptxHandlerRuntime16 = class extends PptxHandlerRuntime15 {
29192
30201
  buildOuterShadowXml(shapeStyle) {
29193
30202
  return this.colorStyleCodec.buildOuterShadowXml(shapeStyle);
29194
30203
  }
30204
+ buildPresetShadowXml(shapeStyle) {
30205
+ return this.colorStyleCodec.buildPresetShadowXml(shapeStyle);
30206
+ }
29195
30207
  buildInnerShadowXml(shapeStyle) {
29196
30208
  return this.colorStyleCodec.buildInnerShadowXml(shapeStyle);
29197
30209
  }
@@ -29742,6 +30754,10 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
29742
30754
  const solidFill = runProperties["a:solidFill"];
29743
30755
  if (solidFill) {
29744
30756
  style.color = this.parseColor(solidFill);
30757
+ const colorXml = extractColorChoiceXml(solidFill);
30758
+ if (colorXml) {
30759
+ style.colorXml = colorXml;
30760
+ }
29745
30761
  }
29746
30762
  this.applyHyperlinkStyle(style, runProperties, relationshipMap);
29747
30763
  const capAttr = String(runProperties["@_cap"] || "").trim().toLowerCase();
@@ -29789,12 +30805,86 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
29789
30805
  if (bmk) {
29790
30806
  style.bookmark = bmk;
29791
30807
  }
30808
+ const altLang = String(runProperties["@_altLang"] || "").trim();
30809
+ if (altLang) {
30810
+ style.altLanguage = altLang;
30811
+ }
30812
+ if (runProperties["@_smtId"] !== void 0) {
30813
+ const smtIdRaw = Number.parseInt(String(runProperties["@_smtId"]), 10);
30814
+ if (Number.isFinite(smtIdRaw)) {
30815
+ style.smartTagId = smtIdRaw;
30816
+ }
30817
+ }
30818
+ this.applyTextFontMetadata(style, latin, "latin");
30819
+ this.applyTextFontMetadata(style, eastAsian, "eastAsia");
30820
+ this.applyTextFontMetadata(style, complexScript, "complexScript");
30821
+ this.applyTextFontMetadata(style, runProperties["a:sym"], "symbol");
29792
30822
  const runEffectList = runProperties["a:effectLst"];
29793
30823
  if (runEffectList) {
29794
30824
  this.applyTextRunEffects(style, runEffectList);
29795
30825
  }
29796
30826
  return style;
29797
30827
  }
30828
+ /**
30829
+ * Copy `@panose` / `@pitchFamily` / `@charset` from a font child node
30830
+ * (`a:latin`, `a:ea`, `a:cs`, `a:sym`) onto the matching `*Font*`
30831
+ * fields of `style`.
30832
+ */
30833
+ applyTextFontMetadata(style, fontNode, kind) {
30834
+ if (!fontNode) {
30835
+ return;
30836
+ }
30837
+ const panose = String(fontNode["@_panose"] || "").trim();
30838
+ const pitchRaw = fontNode["@_pitchFamily"];
30839
+ const charsetRaw = fontNode["@_charset"];
30840
+ const pitch = pitchRaw !== void 0 && pitchRaw !== null ? Number.parseInt(String(pitchRaw), 10) : void 0;
30841
+ const charset = charsetRaw !== void 0 && charsetRaw !== null ? Number.parseInt(String(charsetRaw), 10) : void 0;
30842
+ if (kind === "latin") {
30843
+ if (panose) {
30844
+ style.latinFontPanose = panose;
30845
+ }
30846
+ if (typeof pitch === "number" && Number.isFinite(pitch)) {
30847
+ style.latinFontPitchFamily = pitch;
30848
+ }
30849
+ if (typeof charset === "number" && Number.isFinite(charset)) {
30850
+ style.latinFontCharset = charset;
30851
+ }
30852
+ return;
30853
+ }
30854
+ if (kind === "eastAsia") {
30855
+ if (panose) {
30856
+ style.eastAsiaFontPanose = panose;
30857
+ }
30858
+ if (typeof pitch === "number" && Number.isFinite(pitch)) {
30859
+ style.eastAsiaFontPitchFamily = pitch;
30860
+ }
30861
+ if (typeof charset === "number" && Number.isFinite(charset)) {
30862
+ style.eastAsiaFontCharset = charset;
30863
+ }
30864
+ return;
30865
+ }
30866
+ if (kind === "complexScript") {
30867
+ if (panose) {
30868
+ style.complexScriptFontPanose = panose;
30869
+ }
30870
+ if (typeof pitch === "number" && Number.isFinite(pitch)) {
30871
+ style.complexScriptFontPitchFamily = pitch;
30872
+ }
30873
+ if (typeof charset === "number" && Number.isFinite(charset)) {
30874
+ style.complexScriptFontCharset = charset;
30875
+ }
30876
+ return;
30877
+ }
30878
+ if (panose) {
30879
+ style.symbolFontPanose = panose;
30880
+ }
30881
+ if (typeof pitch === "number" && Number.isFinite(pitch)) {
30882
+ style.symbolFontPitchFamily = pitch;
30883
+ }
30884
+ if (typeof charset === "number" && Number.isFinite(charset)) {
30885
+ style.symbolFontCharset = charset;
30886
+ }
30887
+ }
29798
30888
  };
29799
30889
 
29800
30890
  // src/core/core/runtime/PptxHandlerRuntimeTextEditing.ts
@@ -30230,7 +31320,7 @@ var PptxHandlerRuntime21 = class extends PptxHandlerRuntime20 {
30230
31320
  };
30231
31321
 
30232
31322
  // src/core/core/runtime/table-cell-save-helpers.ts
30233
- function writeCellFill(tcPr, style) {
31323
+ function writeCellFill(tcPr, style, resolveColorXml) {
30234
31324
  if (style.fillMode === "gradient" && style.gradientFillStops && style.gradientFillStops.length > 0) {
30235
31325
  delete tcPr["a:solidFill"];
30236
31326
  delete tcPr["a:pattFill"];
@@ -30309,11 +31399,12 @@ function writeCellFill(tcPr, style) {
30309
31399
  } else if (style.backgroundColor) {
30310
31400
  delete tcPr["a:gradFill"];
30311
31401
  delete tcPr["a:pattFill"];
30312
- tcPr["a:solidFill"] = {
30313
- "a:srgbClr": {
30314
- "@_val": style.backgroundColor.replace("#", "")
30315
- }
30316
- };
31402
+ const resolvedOriginal = style.backgroundColorXml && resolveColorXml ? resolveColorXml(style.backgroundColorXml) : void 0;
31403
+ tcPr["a:solidFill"] = serializeColorChoice(
31404
+ style.backgroundColorXml,
31405
+ resolvedOriginal,
31406
+ style.backgroundColor
31407
+ );
30317
31408
  }
30318
31409
  }
30319
31410
  function writeDiagonalBorders(tcPr, style, emuPerPx) {
@@ -30444,7 +31535,7 @@ var PptxHandlerRuntime22 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
30444
31535
  xmlCell["a:tcPr"] = {};
30445
31536
  }
30446
31537
  const tcPr = xmlCell["a:tcPr"];
30447
- writeCellFill(tcPr, style);
31538
+ writeCellFill(tcPr, style, (colorXml) => this.parseColor(colorXml));
30448
31539
  if (style.vAlign) {
30449
31540
  const vAlignMap = {
30450
31541
  top: "t",
@@ -30526,35 +31617,29 @@ var PptxHandlerRuntime22 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
30526
31617
  }
30527
31618
  }
30528
31619
  }
30529
- if (style.marginLeft !== void 0 || style.marginRight !== void 0 || style.marginTop !== void 0 || style.marginBottom !== void 0) {
30530
- const emuPerPx = _PptxHandlerRuntime.EMU_PER_PX;
30531
- if (!tcPr["a:tcMar"]) {
30532
- tcPr["a:tcMar"] = {};
30533
- }
30534
- const tcMar = tcPr["a:tcMar"];
30535
- if (style.marginLeft !== void 0) {
30536
- tcMar["a:marL"] = {
30537
- "@_w": String(Math.round(style.marginLeft * emuPerPx))
30538
- };
30539
- }
30540
- if (style.marginRight !== void 0) {
30541
- tcMar["a:marR"] = {
30542
- "@_w": String(Math.round(style.marginRight * emuPerPx))
30543
- };
30544
- }
30545
- if (style.marginTop !== void 0) {
30546
- tcMar["a:marT"] = {
30547
- "@_w": String(Math.round(style.marginTop * emuPerPx))
30548
- };
30549
- }
30550
- if (style.marginBottom !== void 0) {
30551
- tcMar["a:marB"] = {
30552
- "@_w": String(Math.round(style.marginBottom * emuPerPx))
30553
- };
30554
- }
31620
+ const emuPerPx = _PptxHandlerRuntime.EMU_PER_PX;
31621
+ if (style.marginLeft !== void 0) {
31622
+ tcPr["@_marL"] = String(Math.round(style.marginLeft * emuPerPx));
31623
+ }
31624
+ if (style.marginRight !== void 0) {
31625
+ tcPr["@_marR"] = String(Math.round(style.marginRight * emuPerPx));
31626
+ }
31627
+ if (style.marginTop !== void 0) {
31628
+ tcPr["@_marT"] = String(Math.round(style.marginTop * emuPerPx));
31629
+ }
31630
+ if (style.marginBottom !== void 0) {
31631
+ tcPr["@_marB"] = String(Math.round(style.marginBottom * emuPerPx));
30555
31632
  }
31633
+ delete tcPr["a:tcMar"];
30556
31634
  writeDiagonalBorders(tcPr, style, _PptxHandlerRuntime.EMU_PER_PX);
30557
31635
  writeCellTextFormatting(xmlCell, style, this.ensureArray.bind(this));
31636
+ const reordered = reorderObjectKeys(tcPr, TC_PR_BORDERS_ORDER);
31637
+ for (const key of Object.keys(tcPr)) {
31638
+ delete tcPr[key];
31639
+ }
31640
+ for (const key of Object.keys(reordered)) {
31641
+ tcPr[key] = reordered[key];
31642
+ }
30558
31643
  }
30559
31644
  };
30560
31645
 
@@ -30658,6 +31743,49 @@ function createDefaultXmlCell() {
30658
31743
  // src/core/core/runtime/table-xml-rebuild.ts
30659
31744
  var GRID_COL_ID_EXT_URI = "{9D8B030D-6E8A-4147-A177-3AD203B41FA5}";
30660
31745
  var A16_NAMESPACE = "http://schemas.microsoft.com/office/drawing/2014/main";
31746
+ function ensureA16NamespaceOnSlideRoot(slideRoot) {
31747
+ if (!slideRoot["@_xmlns:a16"]) {
31748
+ slideRoot["@_xmlns:a16"] = A16_NAMESPACE;
31749
+ }
31750
+ if (!slideRoot["@_xmlns:mc"]) {
31751
+ slideRoot["@_xmlns:mc"] = "http://schemas.openxmlformats.org/markup-compatibility/2006";
31752
+ }
31753
+ const existingIgnorable = String(slideRoot["@_mc:Ignorable"] || "").trim();
31754
+ if (existingIgnorable.length === 0) {
31755
+ slideRoot["@_mc:Ignorable"] = "a16";
31756
+ return;
31757
+ }
31758
+ const tokens = existingIgnorable.split(/\s+/).filter((token) => token.length > 0);
31759
+ if (!tokens.includes("a16")) {
31760
+ tokens.push("a16");
31761
+ slideRoot["@_mc:Ignorable"] = tokens.join(" ");
31762
+ }
31763
+ }
31764
+ function slideContainsA16Element(node) {
31765
+ if (node === null || node === void 0) {
31766
+ return false;
31767
+ }
31768
+ if (Array.isArray(node)) {
31769
+ for (const entry of node) {
31770
+ if (slideContainsA16Element(entry)) {
31771
+ return true;
31772
+ }
31773
+ }
31774
+ return false;
31775
+ }
31776
+ if (typeof node !== "object") {
31777
+ return false;
31778
+ }
31779
+ for (const [key, value] of Object.entries(node)) {
31780
+ if (key.startsWith("a16:")) {
31781
+ return true;
31782
+ }
31783
+ if (slideContainsA16Element(value)) {
31784
+ return true;
31785
+ }
31786
+ }
31787
+ return false;
31788
+ }
30661
31789
  function randomColumnId() {
30662
31790
  return String(Math.floor(Math.random() * 4294967295));
30663
31791
  }
@@ -30688,8 +31816,10 @@ function rebuildTableXmlFromData(tbl, tableData, emuPerPx, ensureArrayFn) {
30688
31816
  "a:extLst": {
30689
31817
  "a:ext": {
30690
31818
  "@_uri": GRID_COL_ID_EXT_URI,
31819
+ // `xmlns:a16` is declared on the slide root by
31820
+ // `ensureA16NamespaceOnSlideRoot`; emitting it here too is
31821
+ // schema-redundant and PowerPoint flags it.
30691
31822
  "a16:colId": {
30692
- "@_xmlns:a16": A16_NAMESPACE,
30693
31823
  "@_val": existingColIds[i] || randomColumnId()
30694
31824
  }
30695
31825
  }
@@ -31048,26 +32178,64 @@ var PptxHandlerRuntime23 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
31048
32178
  continue;
31049
32179
  }
31050
32180
  const scalingNode = this.xmlLookupService.getChildByLocalName(axisNode, "scaling");
31051
- if (!scalingNode) {
31052
- continue;
32181
+ if (scalingNode) {
32182
+ if (matchingAxis.logBase !== void 0 && matchingAxis.logBase > 0) {
32183
+ const logBaseKey = Object.keys(scalingNode).find(
32184
+ (k) => this.compatibilityService.getXmlLocalName(k) === "logBase"
32185
+ );
32186
+ if (logBaseKey) {
32187
+ scalingNode[logBaseKey]["@_val"] = String(matchingAxis.logBase);
32188
+ } else {
32189
+ scalingNode["c:logBase"] = {
32190
+ "@_val": String(matchingAxis.logBase)
32191
+ };
32192
+ }
32193
+ } else if (matchingAxis.logScale === false) {
32194
+ const logBaseKey = Object.keys(scalingNode).find(
32195
+ (k) => this.compatibilityService.getXmlLocalName(k) === "logBase"
32196
+ );
32197
+ if (logBaseKey) {
32198
+ delete scalingNode[logBaseKey];
32199
+ }
32200
+ }
32201
+ this.upsertChartAxisChild(
32202
+ scalingNode,
32203
+ "min",
32204
+ matchingAxis.min !== void 0 ? String(matchingAxis.min) : void 0
32205
+ );
32206
+ this.upsertChartAxisChild(
32207
+ scalingNode,
32208
+ "max",
32209
+ matchingAxis.max !== void 0 ? String(matchingAxis.max) : void 0
32210
+ );
31053
32211
  }
31054
- if (matchingAxis.logBase !== void 0 && matchingAxis.logBase > 0) {
31055
- const logBaseKey = Object.keys(scalingNode).find(
31056
- (k) => this.compatibilityService.getXmlLocalName(k) === "logBase"
32212
+ if (matchingAxis.numFmt) {
32213
+ const numFmtKey = Object.keys(axisNode).find(
32214
+ (k) => this.compatibilityService.getXmlLocalName(k) === "numFmt"
31057
32215
  );
31058
- if (logBaseKey) {
31059
- scalingNode[logBaseKey]["@_val"] = String(matchingAxis.logBase);
32216
+ const numFmtAttrs = {
32217
+ "@_formatCode": matchingAxis.numFmt.formatCode,
32218
+ "@_sourceLinked": matchingAxis.numFmt.sourceLinked ? "1" : "0"
32219
+ };
32220
+ if (numFmtKey) {
32221
+ axisNode[numFmtKey] = numFmtAttrs;
31060
32222
  } else {
31061
- scalingNode["c:logBase"] = {
31062
- "@_val": String(matchingAxis.logBase)
31063
- };
32223
+ axisNode["c:numFmt"] = numFmtAttrs;
31064
32224
  }
31065
- } else if (matchingAxis.logScale === false) {
31066
- const logBaseKey = Object.keys(scalingNode).find(
31067
- (k) => this.compatibilityService.getXmlLocalName(k) === "logBase"
32225
+ }
32226
+ this.upsertChartAxisChild(
32227
+ axisNode,
32228
+ "majorUnit",
32229
+ matchingAxis.majorUnit !== void 0 ? String(matchingAxis.majorUnit) : void 0
32230
+ );
32231
+ if (matchingAxis.tickLblPos !== void 0) {
32232
+ const tickLblKey = Object.keys(axisNode).find(
32233
+ (k) => this.compatibilityService.getXmlLocalName(k) === "tickLblPos"
31068
32234
  );
31069
- if (logBaseKey) {
31070
- delete scalingNode[logBaseKey];
32235
+ if (tickLblKey) {
32236
+ axisNode[tickLblKey]["@_val"] = matchingAxis.tickLblPos;
32237
+ } else {
32238
+ axisNode["c:tickLblPos"] = { "@_val": matchingAxis.tickLblPos };
31071
32239
  }
31072
32240
  }
31073
32241
  }
@@ -31080,6 +32248,18 @@ var PptxHandlerRuntime23 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
31080
32248
  }
31081
32249
  this.pendingChartUpdates = void 0;
31082
32250
  }
32251
+ /**
32252
+ * Upsert a `c:<localName>` child with `@_val` on an axis or scaling node.
32253
+ * When `value` is undefined, removes any existing child of that local name.
32254
+ */
32255
+ upsertChartAxisChild(parent, localName, value) {
32256
+ upsertChartAxisChild(
32257
+ parent,
32258
+ localName,
32259
+ value,
32260
+ (key) => this.compatibilityService.getXmlLocalName(key)
32261
+ );
32262
+ }
31083
32263
  /**
31084
32264
  * Update the cached point values in a chart reference node
31085
32265
  * (numRef/strRef or numLit/strLit).
@@ -32359,17 +33539,13 @@ var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
32359
33539
  delete spPr["a:noFill"];
32360
33540
  delete spPr["a:gradFill"];
32361
33541
  delete spPr["a:blipFill"];
32362
- const solidFill = {
32363
- "a:srgbClr": {
32364
- "@_val": fillColor.replace("#", "")
32365
- }
32366
- };
32367
- if (typeof shapeStyle.fillOpacity === "number" && shapeStyle.fillOpacity >= 0 && shapeStyle.fillOpacity < 1) {
32368
- solidFill["a:srgbClr"]["a:alpha"] = {
32369
- "@_val": String(Math.round(this.clampUnitInterval(shapeStyle.fillOpacity) * 1e5))
32370
- };
32371
- }
32372
- spPr["a:solidFill"] = solidFill;
33542
+ const resolvedOriginal = shapeStyle.fillColorXml ? this.parseColor(shapeStyle.fillColorXml) : void 0;
33543
+ spPr["a:solidFill"] = serializeColorChoice(
33544
+ shapeStyle.fillColorXml,
33545
+ resolvedOriginal,
33546
+ fillColor,
33547
+ shapeStyle.fillOpacity
33548
+ );
32373
33549
  }
32374
33550
  }
32375
33551
  if (shapeStyle.strokeColor !== void 0) {
@@ -32384,17 +33560,13 @@ var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
32384
33560
  delete lineNode["a:solidFill"];
32385
33561
  } else {
32386
33562
  delete lineNode["a:noFill"];
32387
- const lineFill = {
32388
- "a:srgbClr": {
32389
- "@_val": shapeStyle.strokeColor.replace("#", "")
32390
- }
32391
- };
32392
- if (typeof shapeStyle.strokeOpacity === "number" && shapeStyle.strokeOpacity >= 0 && shapeStyle.strokeOpacity < 1) {
32393
- lineFill["a:srgbClr"]["a:alpha"] = {
32394
- "@_val": String(Math.round(this.clampUnitInterval(shapeStyle.strokeOpacity) * 1e5))
32395
- };
32396
- }
32397
- lineNode["a:solidFill"] = lineFill;
33563
+ const resolvedStrokeOriginal = shapeStyle.strokeColorXml ? this.parseColor(shapeStyle.strokeColorXml) : void 0;
33564
+ lineNode["a:solidFill"] = serializeColorChoice(
33565
+ shapeStyle.strokeColorXml,
33566
+ resolvedStrokeOriginal,
33567
+ shapeStyle.strokeColor,
33568
+ shapeStyle.strokeOpacity
33569
+ );
32398
33570
  }
32399
33571
  }
32400
33572
  if (shapeStyle.strokeDash !== void 0) {
@@ -32475,7 +33647,11 @@ var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
32475
33647
  } else if (shapeStyle.lineJoin === "bevel") {
32476
33648
  lineNode["a:bevel"] = {};
32477
33649
  } else if (shapeStyle.lineJoin === "miter") {
32478
- lineNode["a:miter"] = { "@_lim": "800000" };
33650
+ const miterNode = {};
33651
+ if (typeof shapeStyle.miterLimit === "number" && Number.isFinite(shapeStyle.miterLimit) && shapeStyle.miterLimit !== 8e5) {
33652
+ miterNode["@_lim"] = String(Math.round(shapeStyle.miterLimit));
33653
+ }
33654
+ lineNode["a:miter"] = miterNode;
32479
33655
  }
32480
33656
  }
32481
33657
  if (shapeStyle.lineCap !== void 0) {
@@ -32495,6 +33671,82 @@ var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
32495
33671
  spPr["a:ln"]["a:effectLst"] = lineEffectListXml;
32496
33672
  }
32497
33673
  }
33674
+ /**
33675
+ * Serialize the shape's `<p:style>` block (CT_ShapeStyle §20.1.2.2.36)
33676
+ * from the persisted ref indices/colour XML. Emits children in spec
33677
+ * order: `lnRef → fillRef → effectRef → fontRef`.
33678
+ *
33679
+ * When the original shape XML already contained a `<p:style>` we mutate
33680
+ * that node in place so any unmodelled attributes/children are preserved.
33681
+ * When it didn't, we create one. When the shape no longer has any ref
33682
+ * data we leave the existing `<p:style>` (if any) untouched — silently
33683
+ * dropping it would break round-tripping.
33684
+ *
33685
+ * Phase 2 Stream B / C-H2.
33686
+ */
33687
+ applyShapeStyleRefs(shape, shapeStyle) {
33688
+ const hasAnyRef = shapeStyle.lnRefIdx !== void 0 || shapeStyle.fillRefIdx !== void 0 || shapeStyle.effectRefIdx !== void 0 || shapeStyle.fontRefIdx !== void 0;
33689
+ if (!hasAnyRef) {
33690
+ return;
33691
+ }
33692
+ const existing = shape["p:style"];
33693
+ const styleNode = existing ?? {};
33694
+ if (shapeStyle.lnRefIdx !== void 0) {
33695
+ const lnRef = styleNode["a:lnRef"] ?? {};
33696
+ lnRef["@_idx"] = String(shapeStyle.lnRefIdx);
33697
+ this.replaceRefColorChoice(lnRef, shapeStyle.lnRefColorXml);
33698
+ styleNode["a:lnRef"] = lnRef;
33699
+ }
33700
+ if (shapeStyle.fillRefIdx !== void 0) {
33701
+ const fillRef = styleNode["a:fillRef"] ?? {};
33702
+ fillRef["@_idx"] = String(shapeStyle.fillRefIdx);
33703
+ this.replaceRefColorChoice(fillRef, shapeStyle.fillRefColorXml);
33704
+ styleNode["a:fillRef"] = fillRef;
33705
+ }
33706
+ if (shapeStyle.effectRefIdx !== void 0) {
33707
+ const effectRef = styleNode["a:effectRef"] ?? {};
33708
+ effectRef["@_idx"] = String(shapeStyle.effectRefIdx);
33709
+ this.replaceRefColorChoice(effectRef, shapeStyle.effectRefColorXml);
33710
+ styleNode["a:effectRef"] = effectRef;
33711
+ }
33712
+ if (shapeStyle.fontRefIdx !== void 0) {
33713
+ const fontRef = styleNode["a:fontRef"] ?? {};
33714
+ fontRef["@_idx"] = shapeStyle.fontRefIdx;
33715
+ this.replaceRefColorChoice(fontRef, shapeStyle.fontRefColorXml);
33716
+ styleNode["a:fontRef"] = fontRef;
33717
+ }
33718
+ const reordered = reorderObjectKeys(styleNode, SHAPE_STYLE_ORDER);
33719
+ for (const key of Object.keys(styleNode)) {
33720
+ delete styleNode[key];
33721
+ }
33722
+ for (const key of Object.keys(reordered)) {
33723
+ styleNode[key] = reordered[key];
33724
+ }
33725
+ shape["p:style"] = styleNode;
33726
+ }
33727
+ /**
33728
+ * Replace any existing colour-choice child on a style-matrix-reference
33729
+ * element with the given preserved XML, or strip all colour children
33730
+ * when the override is undefined.
33731
+ */
33732
+ replaceRefColorChoice(refNode, colorXml) {
33733
+ for (const key of [
33734
+ "a:scrgbClr",
33735
+ "a:srgbClr",
33736
+ "a:hslClr",
33737
+ "a:sysClr",
33738
+ "a:schemeClr",
33739
+ "a:prstClr"
33740
+ ]) {
33741
+ delete refNode[key];
33742
+ }
33743
+ if (!colorXml) {
33744
+ return;
33745
+ }
33746
+ for (const [key, value] of Object.entries(colorXml)) {
33747
+ refNode[key] = value;
33748
+ }
33749
+ }
32498
33750
  };
32499
33751
 
32500
33752
  // src/core/core/runtime/PptxHandlerRuntimeSaveEffectsWriter.ts
@@ -32504,17 +33756,22 @@ var PptxHandlerRuntime29 = class extends PptxHandlerRuntime28 {
32504
33756
  * effectDag, 3D scene, and 3D shape properties to the given spPr XML object.
32505
33757
  */
32506
33758
  applyEffectsAndThreeD(spPr, shapeStyle) {
32507
- const outerShadowXml = this.buildOuterShadowXml(shapeStyle);
33759
+ const presetShadowXml = shapeStyle.presetShadowName ? this.buildPresetShadowXml(shapeStyle) : void 0;
33760
+ const outerShadowXml = presetShadowXml ? void 0 : this.buildOuterShadowXml(shapeStyle);
32508
33761
  const innerShadowXml = this.buildInnerShadowXml(shapeStyle);
32509
33762
  const glowXml = this.buildGlowXml(shapeStyle);
32510
33763
  const softEdgeXml = this.buildSoftEdgeXml(shapeStyle);
32511
33764
  const reflectionXml = this.buildReflectionXml(shapeStyle);
32512
33765
  const blurXml = this.buildBlurXml(shapeStyle);
32513
- const hasAnyEffect = outerShadowXml || innerShadowXml || glowXml || softEdgeXml || reflectionXml || blurXml;
33766
+ const hasAnyEffect = outerShadowXml || presetShadowXml || innerShadowXml || glowXml || softEdgeXml || reflectionXml || blurXml;
32514
33767
  if (hasAnyEffect) {
32515
33768
  const effectList = spPr["a:effectLst"] || {};
32516
- if (outerShadowXml) {
33769
+ if (presetShadowXml) {
33770
+ effectList["a:prstShdw"] = presetShadowXml;
33771
+ delete effectList["a:outerShdw"];
33772
+ } else if (outerShadowXml) {
32517
33773
  effectList["a:outerShdw"] = outerShadowXml;
33774
+ delete effectList["a:prstShdw"];
32518
33775
  }
32519
33776
  if (innerShadowXml) {
32520
33777
  effectList["a:innerShdw"] = innerShadowXml;
@@ -32531,12 +33788,13 @@ var PptxHandlerRuntime29 = class extends PptxHandlerRuntime28 {
32531
33788
  if (blurXml) {
32532
33789
  effectList["a:blur"] = blurXml;
32533
33790
  }
32534
- spPr["a:effectLst"] = effectList;
33791
+ spPr["a:effectLst"] = reorderObjectKeys(effectList, EFFECT_LST_ORDER);
32535
33792
  } else {
32536
33793
  const effectList = spPr["a:effectLst"];
32537
33794
  if (effectList) {
32538
- if (shapeStyle.shadowColor !== void 0 && !outerShadowXml) {
33795
+ if (shapeStyle.shadowColor !== void 0 && !outerShadowXml && !presetShadowXml) {
32539
33796
  delete effectList["a:outerShdw"];
33797
+ delete effectList["a:prstShdw"];
32540
33798
  }
32541
33799
  if (shapeStyle.innerShadowColor !== void 0 && !innerShadowXml) {
32542
33800
  delete effectList["a:innerShdw"];
@@ -32555,6 +33813,8 @@ var PptxHandlerRuntime29 = class extends PptxHandlerRuntime28 {
32555
33813
  }
32556
33814
  if (Object.keys(effectList).length === 0) {
32557
33815
  delete spPr["a:effectLst"];
33816
+ } else {
33817
+ spPr["a:effectLst"] = reorderObjectKeys(effectList, EFFECT_LST_ORDER);
32558
33818
  }
32559
33819
  }
32560
33820
  }
@@ -32715,7 +33975,8 @@ var PptxHandlerRuntime30 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
32715
33975
  );
32716
33976
  }
32717
33977
  if (el.textStyle?.hOverflow) {
32718
- bodyPr["@_hOverflow"] = el.textStyle.hOverflow;
33978
+ bodyPr["@_horzOverflow"] = el.textStyle.hOverflow;
33979
+ delete bodyPr["@_hOverflow"];
32719
33980
  }
32720
33981
  if (el.textStyle?.vertOverflow) {
32721
33982
  bodyPr["@_vertOverflow"] = el.textStyle.vertOverflow;
@@ -32946,7 +34207,10 @@ var PptxHandlerRuntime31 = class extends PptxHandlerRuntime30 {
32946
34207
  const elWithPaths = el;
32947
34208
  if (elWithPaths.customGeometryPaths && elWithPaths.customGeometryPaths.length > 0) {
32948
34209
  delete spPr["a:prstGeom"];
32949
- spPr["a:custGeom"] = customGeometryPathsToXml(elWithPaths.customGeometryPaths);
34210
+ spPr["a:custGeom"] = customGeometryPathsToXml(
34211
+ elWithPaths.customGeometryPaths,
34212
+ elWithPaths.customGeometryRawData
34213
+ );
32950
34214
  } else if (spPr["a:prstGeom"]) {
32951
34215
  const presetGeometry = el.type === "connector" ? this.normalizePresetGeometry(el.shapeType || "straightConnector1") : this.normalizePresetGeometry(el.shapeType);
32952
34216
  const prstGeom = spPr["a:prstGeom"];
@@ -33071,6 +34335,42 @@ var PptxHandlerRuntime32 = class _PptxHandlerRuntime extends PptxHandlerRuntime3
33071
34335
  isGraphicFrameShape(shape) {
33072
34336
  return Boolean(shape["p:nvGraphicFramePr"] || shape["a:graphic"] && shape["p:xfrm"]);
33073
34337
  }
34338
+ /**
34339
+ * Reorder children of `p:spPr` to match CT_ShapeProperties (§20.1.2.2.35).
34340
+ * Also reorders any nested `a:blipFill` per CT_BlipFillProperties.
34341
+ * fast-xml-parser preserves insertion order; PowerPoint validates against
34342
+ * the schema's required order, so save-side mutations must be re-sorted.
34343
+ */
34344
+ finalizeSpPrSchemaOrder(shape) {
34345
+ const spPr = shape["p:spPr"];
34346
+ if (!spPr) {
34347
+ return;
34348
+ }
34349
+ const blipFill = spPr["a:blipFill"];
34350
+ if (blipFill) {
34351
+ this.reorderInPlace(blipFill, BLIP_FILL_ORDER);
34352
+ }
34353
+ this.reorderInPlace(spPr, SP_PR_ORDER);
34354
+ }
34355
+ /**
34356
+ * Reorder children of the picture-level `p:blipFill` (CT_BlipFillProperties).
34357
+ * Picture elements carry their blip data on the `p:pic` root, not under spPr.
34358
+ */
34359
+ finalizePictureBlipFillOrder(shape) {
34360
+ const pBlipFill = shape["p:blipFill"];
34361
+ if (pBlipFill) {
34362
+ this.reorderInPlace(pBlipFill, BLIP_FILL_ORDER);
34363
+ }
34364
+ }
34365
+ reorderInPlace(target, schemaOrder) {
34366
+ const reordered = reorderObjectKeys(target, schemaOrder);
34367
+ for (const key of Object.keys(target)) {
34368
+ delete target[key];
34369
+ }
34370
+ for (const key of Object.keys(reordered)) {
34371
+ target[key] = reordered[key];
34372
+ }
34373
+ }
33074
34374
  /** Whether an element ID indicates a template (layout/master) element. */
33075
34375
  isTemplateElementId(elementId) {
33076
34376
  return elementId.startsWith("layout-") || elementId.startsWith("master-");
@@ -33094,18 +34394,51 @@ var PptxHandlerRuntime32 = class _PptxHandlerRuntime extends PptxHandlerRuntime3
33094
34394
  }
33095
34395
  return;
33096
34396
  }
34397
+ if (el.type === "contentPart") {
34398
+ if (shape) {
34399
+ this.elementTransformUpdater.applyTransform(shape, el, _PptxHandlerRuntime.EMU_PER_PX);
34400
+ collectors.contentParts.push(shape);
34401
+ } else {
34402
+ this.compatibilityService.reportWarning({
34403
+ code: "SAVE_ELEMENT_SKIPPED",
34404
+ message: `Content part '${el.id}' has no rawXml and was skipped during save.`,
34405
+ scope: "save",
34406
+ slideId: ctx.slide.id,
34407
+ elementId: el.id
34408
+ });
34409
+ }
34410
+ return;
34411
+ }
33097
34412
  if (!shape && (el.type === "text" || el.type === "shape")) {
33098
34413
  shape = this.createElementXml(el);
33099
34414
  }
33100
34415
  if (!shape && el.type === "connector") {
33101
34416
  shape = this.createConnectorXml(el);
33102
34417
  }
33103
- if (!shape && el.type === "ink") {
33104
- shape = this.createInkShapeXml(el);
34418
+ if (el.type === "ink") {
34419
+ if (!shape) {
34420
+ shape = this.createInkShapeXml(el);
34421
+ this.compatibilityService.reportWarning({
34422
+ code: "SAVE_INK_ENCODED_AS_CUSTGEOM",
34423
+ message: "SDK-created ink element serialized as custGeom shape; pressure/tool metadata not represented in OOXML aink format.",
34424
+ scope: "save",
34425
+ slideId: ctx.slide.id,
34426
+ elementId: el.id
34427
+ });
34428
+ }
33105
34429
  }
33106
34430
  if (!shape && el.type === "table") {
33107
34431
  shape = this.createTableGraphicFrameXml(el);
33108
34432
  }
34433
+ if (el.type === "ole") {
34434
+ const oleEl = el;
34435
+ if (shape) {
34436
+ this.applyOleTypedFieldUpdates(shape, oleEl);
34437
+ } else {
34438
+ const embedRid = this.resolveOleEmbedRelationshipId(ctx.slideRelationships, oleEl.oleTarget) || ctx.slideRelationshipRegistry.nextRelationshipId();
34439
+ shape = this.createOleGraphicFrameXml(oleEl, embedRid);
34440
+ }
34441
+ }
33109
34442
  if (!shape) {
33110
34443
  this.compatibilityService.reportWarning({
33111
34444
  code: "SAVE_ELEMENT_SKIPPED",
@@ -33118,11 +34451,14 @@ var PptxHandlerRuntime32 = class _PptxHandlerRuntime extends PptxHandlerRuntime3
33118
34451
  }
33119
34452
  this.elementTransformUpdater.applyTransform(shape, el, _PptxHandlerRuntime.EMU_PER_PX);
33120
34453
  this.applyImageProperties(shape, el);
34454
+ this.finalizePictureBlipFillOrder(shape);
33121
34455
  this.applyGeometryUpdate(shape, el);
33122
34456
  if (hasShapeProperties(el) && el.shapeStyle && shape["p:spPr"]) {
33123
34457
  const spPr = shape["p:spPr"];
33124
34458
  this.applyFillAndStroke(spPr, el.shapeStyle);
33125
34459
  this.applyEffectsAndThreeD(spPr, el.shapeStyle);
34460
+ this.finalizeSpPrSchemaOrder(shape);
34461
+ this.applyShapeStyleRefs(shape, el.shapeStyle);
33126
34462
  }
33127
34463
  if (hasTextProperties(el)) {
33128
34464
  this.applyTextBodyContent(
@@ -33280,7 +34616,8 @@ var PptxHandlerRuntime33 = class extends PptxHandlerRuntime32 {
33280
34616
  connectors: [],
33281
34617
  graphicFrames: [],
33282
34618
  groups: [],
33283
- model3ds: []
34619
+ model3ds: [],
34620
+ contentParts: []
33284
34621
  };
33285
34622
  const ctx = {
33286
34623
  slide,
@@ -33312,6 +34649,12 @@ var PptxHandlerRuntime33 = class extends PptxHandlerRuntime32 {
33312
34649
  } else {
33313
34650
  delete spTree["p16:model3D"];
33314
34651
  }
34652
+ if (collectors.contentParts.length > 0) {
34653
+ spTree["p:contentPart"] = collectors.contentParts;
34654
+ } else {
34655
+ delete spTree["p:contentPart"];
34656
+ }
34657
+ this.reapplyAlternateContentEnvelopes(spTree, collectors);
33315
34658
  const reassigned = shapeIdValidator.validateAndDeduplicateIds(
33316
34659
  spTree,
33317
34660
  (v) => this.ensureArray(v)
@@ -33329,12 +34672,426 @@ var PptxHandlerRuntime33 = class extends PptxHandlerRuntime32 {
33329
34672
  this.zip.file(slideRelsPath, this.builder.build(slideRelsData));
33330
34673
  this.applySlideDrawingGuides(slideNode, slide);
33331
34674
  this.deduplicateExtensionLists(xmlObj);
34675
+ if (slideContainsA16Element(slideNode)) {
34676
+ ensureA16NamespaceOnSlideRoot(slideNode);
34677
+ }
33332
34678
  this.zip.file(slide.id, this.builder.build(xmlObj));
33333
34679
  }
34680
+ /**
34681
+ * Re-wrap selected children with their original `<mc:AlternateContent>`
34682
+ * envelope (CC-4).
34683
+ *
34684
+ * Parsing merged the selected branch (Choice when supported, otherwise
34685
+ * Fallback) into the spTree's tag arrays. Without re-wrapping, dirty
34686
+ * save would emit flat `<p:sp>`/`<p:pic>` etc. and drop the
34687
+ * `<mc:Fallback>` branch — losing legacy rendering for files originally
34688
+ * authored with newer-namespace features.
34689
+ *
34690
+ * Strategy: for each XmlObject in `collectors.*` that traces back to a
34691
+ * known AC block, group by block and:
34692
+ * 1. Remove the node from its flat collector / spTree array.
34693
+ * 2. Clone the original AC envelope.
34694
+ * 3. Replace the selected branch's `<{tag}>` children with the
34695
+ * live (possibly edited) nodes from the collectors.
34696
+ * 4. Leave the unselected branch verbatim.
34697
+ *
34698
+ * Final envelopes are appended to `spTree['mc:AlternateContent']`.
34699
+ */
34700
+ reapplyAlternateContentEnvelopes(spTree, collectors) {
34701
+ const TAG_TO_COLLECTOR = {
34702
+ "p:sp": collectors.shapes,
34703
+ "p:pic": collectors.pics,
34704
+ "p:cxnSp": collectors.connectors,
34705
+ "p:graphicFrame": collectors.graphicFrames,
34706
+ "p:grpSp": collectors.groups,
34707
+ "p:contentPart": collectors.contentParts,
34708
+ // `model3d` does not flow through SHAPE_TREE_ELEMENT_TAGS, but the
34709
+ // AC pathway in OpenXML decks frequently uses Choice = p16:model3D
34710
+ // + Fallback = p:pic, so map it for completeness.
34711
+ "p16:model3D": collectors.model3ds
34712
+ };
34713
+ const blockGroups = /* @__PURE__ */ new Map();
34714
+ for (const tag of Object.keys(TAG_TO_COLLECTOR)) {
34715
+ const collector = TAG_TO_COLLECTOR[tag];
34716
+ if (!collector) {
34717
+ continue;
34718
+ }
34719
+ for (const node of collector) {
34720
+ const block = this.alternateContentBlockByRawXml.get(node);
34721
+ if (!block) {
34722
+ continue;
34723
+ }
34724
+ let entries = blockGroups.get(block);
34725
+ if (!entries) {
34726
+ entries = [];
34727
+ blockGroups.set(block, entries);
34728
+ }
34729
+ entries.push({ tag, node, collector });
34730
+ }
34731
+ }
34732
+ if (blockGroups.size === 0) {
34733
+ return;
34734
+ }
34735
+ const envelopes = [];
34736
+ for (const [block, entries] of blockGroups) {
34737
+ for (const entry of entries) {
34738
+ const idx = entry.collector.indexOf(entry.node);
34739
+ if (idx !== -1) {
34740
+ entry.collector.splice(idx, 1);
34741
+ }
34742
+ }
34743
+ const clonedAc = { ...block.rawAc };
34744
+ const liveByTag = /* @__PURE__ */ new Map();
34745
+ for (const entry of entries) {
34746
+ let arr = liveByTag.get(entry.tag);
34747
+ if (!arr) {
34748
+ arr = [];
34749
+ liveByTag.set(entry.tag, arr);
34750
+ }
34751
+ arr.push(entry.node);
34752
+ }
34753
+ if (block.selectedBranch === "choice") {
34754
+ const choices = this.ensureArray(clonedAc["mc:Choice"]);
34755
+ const targetIdx = block.choiceIndex ?? 0;
34756
+ const original = choices[targetIdx];
34757
+ if (original) {
34758
+ const rebuilt = { ...original };
34759
+ for (const tag of SHAPE_TREE_ELEMENT_TAGS) {
34760
+ delete rebuilt[tag];
34761
+ }
34762
+ for (const [tag, nodes] of liveByTag) {
34763
+ rebuilt[tag] = nodes.length === 1 ? nodes[0] : nodes;
34764
+ }
34765
+ choices[targetIdx] = rebuilt;
34766
+ clonedAc["mc:Choice"] = choices.length === 1 ? choices[0] : choices;
34767
+ }
34768
+ } else {
34769
+ const fallback = clonedAc["mc:Fallback"];
34770
+ if (fallback) {
34771
+ const rebuilt = { ...fallback };
34772
+ for (const tag of SHAPE_TREE_ELEMENT_TAGS) {
34773
+ delete rebuilt[tag];
34774
+ }
34775
+ for (const [tag, nodes] of liveByTag) {
34776
+ rebuilt[tag] = nodes.length === 1 ? nodes[0] : nodes;
34777
+ }
34778
+ clonedAc["mc:Fallback"] = rebuilt;
34779
+ }
34780
+ }
34781
+ envelopes.push(clonedAc);
34782
+ }
34783
+ spTree["p:sp"] = collectors.shapes;
34784
+ spTree["p:pic"] = collectors.pics;
34785
+ spTree["p:cxnSp"] = collectors.connectors;
34786
+ spTree["p:graphicFrame"] = collectors.graphicFrames;
34787
+ if (collectors.groups.length > 0) {
34788
+ spTree["p:grpSp"] = collectors.groups;
34789
+ } else {
34790
+ delete spTree["p:grpSp"];
34791
+ }
34792
+ if (collectors.contentParts.length > 0) {
34793
+ spTree["p:contentPart"] = collectors.contentParts;
34794
+ } else {
34795
+ delete spTree["p:contentPart"];
34796
+ }
34797
+ if (collectors.model3ds.length > 0) {
34798
+ spTree["p16:model3D"] = collectors.model3ds;
34799
+ } else {
34800
+ delete spTree["p16:model3D"];
34801
+ }
34802
+ spTree["mc:AlternateContent"] = envelopes.length === 1 ? envelopes[0] : envelopes;
34803
+ }
34804
+ };
34805
+
34806
+ // src/core/core/runtime/PptxHandlerRuntimeSaveTheme.ts
34807
+ var PptxHandlerRuntime34 = class extends PptxHandlerRuntime33 {
34808
+ /**
34809
+ * Mark a theme path as dirty so the save pipeline will regenerate
34810
+ * the theme XML from in-memory state. Optional — without this the
34811
+ * original XML is preserved verbatim on save (C-H3).
34812
+ */
34813
+ markThemeDirty(themePath) {
34814
+ this.dirtyThemePaths.add(themePath);
34815
+ }
34816
+ /**
34817
+ * Mark all known theme paths dirty in one call.
34818
+ */
34819
+ markAllThemesDirty() {
34820
+ for (const themePath of this.originalThemeXmlByPath.keys()) {
34821
+ this.dirtyThemePaths.add(themePath);
34822
+ }
34823
+ for (const themePath of this.masterThemePaths.values()) {
34824
+ this.dirtyThemePaths.add(themePath);
34825
+ }
34826
+ }
34827
+ /**
34828
+ * Persist all theme parts during save. Called from the save pipeline
34829
+ * after master / layout XML have been flushed and before
34830
+ * presentation.xml is serialized.
34831
+ *
34832
+ * Order of operations per theme path:
34833
+ *
34834
+ * 1. If the path is *not* in {@link dirtyThemePaths}, the existing
34835
+ * ZIP entry is already correct — no-op. (Original XML was placed
34836
+ * into the ZIP at load time.)
34837
+ * 2. If the path is dirty, build a fresh `<a:theme>` document from
34838
+ * in-memory state and the captured raw subtrees, then overwrite
34839
+ * the ZIP entry.
34840
+ */
34841
+ async persistThemeParts() {
34842
+ const seenThemePaths = /* @__PURE__ */ new Set();
34843
+ for (const [masterPath, themePath] of this.masterThemePaths.entries()) {
34844
+ if (!themePath) {
34845
+ continue;
34846
+ }
34847
+ seenThemePaths.add(themePath);
34848
+ if (!this.dirtyThemePaths.has(themePath)) {
34849
+ continue;
34850
+ }
34851
+ const themeXml2 = this.buildThemeXml(themePath, masterPath);
34852
+ if (themeXml2) {
34853
+ this.zip.file(themePath, themeXml2);
34854
+ }
34855
+ }
34856
+ for (const [themePath] of this.originalThemeXmlByPath.entries()) {
34857
+ if (seenThemePaths.has(themePath)) {
34858
+ continue;
34859
+ }
34860
+ if (!this.dirtyThemePaths.has(themePath)) {
34861
+ continue;
34862
+ }
34863
+ const themeXml2 = this.buildThemeXml(themePath, void 0);
34864
+ if (themeXml2) {
34865
+ this.zip.file(themePath, themeXml2);
34866
+ }
34867
+ }
34868
+ }
34869
+ /**
34870
+ * Build a complete `<a:theme>` XML document from in-memory state.
34871
+ * Returns the serialized XML string (with XML prolog), or `undefined`
34872
+ * if there is no source data to emit.
34873
+ *
34874
+ * - Color scheme: built from per-master color map (or global fallback).
34875
+ * - Font scheme: built from per-master font map + per-script entries.
34876
+ * - Format scheme: re-emit the original XML subtree if available; else
34877
+ * build a minimal scheme from {@link themeFormatScheme}.
34878
+ * - objectDefaults / extraClrSchemeLst / custClrLst / extLst: re-emit
34879
+ * captured raw subtrees.
34880
+ */
34881
+ buildThemeXml(themePath, masterPath) {
34882
+ const colorMap = masterPath && this.masterThemeColorMaps.get(masterPath) || this.globalThemeColorMapSnapshot || this.themeColorMap;
34883
+ const fontMap = masterPath && this.masterThemeFontMaps.get(masterPath) || this.globalThemeFontMapSnapshot || this.themeFontMap;
34884
+ const themeName = this.masterThemeNames.get(themePath) || "Office Theme";
34885
+ const colorSchemeName = this.masterThemeColorSchemeNames.get(themePath) || themeName;
34886
+ const fontSchemeName = this.masterThemeFontSchemeNames.get(themePath) || themeName;
34887
+ const majorScripts = this.masterThemeMajorFontScripts.get(themePath) || {};
34888
+ const minorScripts = this.masterThemeMinorFontScripts.get(themePath) || {};
34889
+ const clrScheme = this.buildClrSchemeObject(colorSchemeName, colorMap);
34890
+ const fontScheme = this.buildFontSchemeObject(
34891
+ fontSchemeName,
34892
+ fontMap,
34893
+ majorScripts,
34894
+ minorScripts
34895
+ );
34896
+ const fmtScheme = this.extractRawSubtreeFromOriginal(themePath, [
34897
+ "a:theme",
34898
+ "a:themeElements",
34899
+ "a:fmtScheme"
34900
+ ]);
34901
+ const themeElements = {
34902
+ "a:clrScheme": clrScheme,
34903
+ "a:fontScheme": fontScheme
34904
+ };
34905
+ if (fmtScheme !== void 0) {
34906
+ themeElements["a:fmtScheme"] = fmtScheme;
34907
+ } else {
34908
+ themeElements["a:fmtScheme"] = this.buildMinimalFmtScheme(themeName);
34909
+ }
34910
+ const themeRoot = {
34911
+ "@_xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
34912
+ "@_name": themeName,
34913
+ "a:themeElements": themeElements
34914
+ };
34915
+ const objectDefaults = this.masterThemeObjectDefaults.get(themePath);
34916
+ if (objectDefaults && (objectDefaults.spDef || objectDefaults.lnDef || objectDefaults.txDef)) {
34917
+ const od = {};
34918
+ if (objectDefaults.spDef !== void 0) {
34919
+ od["a:spDef"] = objectDefaults.spDef;
34920
+ }
34921
+ if (objectDefaults.lnDef !== void 0) {
34922
+ od["a:lnDef"] = objectDefaults.lnDef;
34923
+ }
34924
+ if (objectDefaults.txDef !== void 0) {
34925
+ od["a:txDef"] = objectDefaults.txDef;
34926
+ }
34927
+ themeRoot["a:objectDefaults"] = od;
34928
+ } else {
34929
+ themeRoot["a:objectDefaults"] = {};
34930
+ }
34931
+ const extraClr = this.masterThemeExtraClrSchemeLst.get(themePath);
34932
+ themeRoot["a:extraClrSchemeLst"] = extraClr !== void 0 ? extraClr : {};
34933
+ const custClr = this.masterThemeCustClrLst.get(themePath);
34934
+ if (custClr !== void 0) {
34935
+ themeRoot["a:custClrLst"] = custClr;
34936
+ }
34937
+ const themeExt = this.masterThemeExtLst.get(themePath);
34938
+ if (themeExt !== void 0) {
34939
+ themeRoot["a:extLst"] = themeExt;
34940
+ }
34941
+ const doc = {
34942
+ "?xml": { "@_version": "1.0", "@_encoding": "UTF-8", "@_standalone": "yes" },
34943
+ "a:theme": themeRoot
34944
+ };
34945
+ try {
34946
+ return this.builder.build(doc);
34947
+ } catch (error) {
34948
+ console.warn(`Failed to build theme XML for ${themePath}:`, error);
34949
+ return void 0;
34950
+ }
34951
+ }
34952
+ /**
34953
+ * Build the `a:clrScheme` XmlObject from a colour map. Each slot
34954
+ * value is interpreted as either a `#RRGGBB` srgb hex or a known
34955
+ * sysClr token (currently always emitted as srgbClr — the in-memory
34956
+ * map is hex-typed; sysClr round-trip belongs to the broader C-H3
34957
+ * fix to preserve original color XML and is out of scope here).
34958
+ */
34959
+ buildClrSchemeObject(schemeName, colorMap) {
34960
+ const slot = (key) => {
34961
+ const hex = String(colorMap[key] || "").replace(/^#/, "");
34962
+ const srgb = hex.length === 6 ? hex.toUpperCase() : "000000";
34963
+ return { "a:srgbClr": { "@_val": srgb } };
34964
+ };
34965
+ return {
34966
+ "@_name": schemeName,
34967
+ "a:dk1": slot("dk1"),
34968
+ "a:lt1": slot("lt1"),
34969
+ "a:dk2": slot("dk2"),
34970
+ "a:lt2": slot("lt2"),
34971
+ "a:accent1": slot("accent1"),
34972
+ "a:accent2": slot("accent2"),
34973
+ "a:accent3": slot("accent3"),
34974
+ "a:accent4": slot("accent4"),
34975
+ "a:accent5": slot("accent5"),
34976
+ "a:accent6": slot("accent6"),
34977
+ "a:hlink": slot("hlink"),
34978
+ "a:folHlink": slot("folHlink")
34979
+ };
34980
+ }
34981
+ /**
34982
+ * Build the `a:fontScheme` XmlObject from a font map plus per-script
34983
+ * font tables.
34984
+ *
34985
+ * Phase 4 Stream A / M4.
34986
+ */
34987
+ buildFontSchemeObject(schemeName, fontMap, majorScripts, minorScripts) {
34988
+ const buildFontGroup = (latinKey, eaKey, csKey, scripts) => {
34989
+ const group = {
34990
+ "a:latin": { "@_typeface": fontMap[latinKey] || "Calibri" },
34991
+ "a:ea": { "@_typeface": fontMap[eaKey] || "" },
34992
+ "a:cs": { "@_typeface": fontMap[csKey] || "" }
34993
+ };
34994
+ const scriptKeys = Object.keys(scripts);
34995
+ if (scriptKeys.length > 0) {
34996
+ const fontEntries = scriptKeys.map((script) => ({
34997
+ "@_script": script,
34998
+ "@_typeface": scripts[script]
34999
+ }));
35000
+ group["a:font"] = fontEntries.length === 1 ? fontEntries[0] : fontEntries;
35001
+ }
35002
+ return group;
35003
+ };
35004
+ return {
35005
+ "@_name": schemeName,
35006
+ "a:majorFont": buildFontGroup("mj-lt", "mj-ea", "mj-cs", majorScripts),
35007
+ "a:minorFont": buildFontGroup("mn-lt", "mn-ea", "mn-cs", minorScripts)
35008
+ };
35009
+ }
35010
+ /**
35011
+ * Re-parse the original theme XML and pluck out a subtree by path,
35012
+ * returning the raw parser object. Returns `undefined` when the
35013
+ * original is missing or the path doesn't exist.
35014
+ *
35015
+ * Used to preserve `a:fmtScheme` byte-for-byte through a regenerate
35016
+ * round-trip, since the in-memory PptxThemeFormatScheme is lossy.
35017
+ */
35018
+ extractRawSubtreeFromOriginal(themePath, path) {
35019
+ const original = this.originalThemeXmlByPath.get(themePath);
35020
+ if (!original) {
35021
+ return void 0;
35022
+ }
35023
+ try {
35024
+ const parsed = this.parser.parse(original);
35025
+ let cursor = parsed;
35026
+ for (const segment of path) {
35027
+ if (cursor && typeof cursor === "object" && segment in cursor) {
35028
+ cursor = cursor[segment];
35029
+ } else {
35030
+ return void 0;
35031
+ }
35032
+ }
35033
+ return cursor;
35034
+ } catch {
35035
+ return void 0;
35036
+ }
35037
+ }
35038
+ /**
35039
+ * Last-resort minimal `<a:fmtScheme>` body. Mirrors the SDK new-deck
35040
+ * builder's output for new presentations, scaled down to the smallest
35041
+ * schema-valid form.
35042
+ */
35043
+ buildMinimalFmtScheme(name) {
35044
+ const phClrSolid = { "a:solidFill": { "a:schemeClr": { "@_val": "phClr" } } };
35045
+ return {
35046
+ "@_name": name,
35047
+ "a:fillStyleLst": {
35048
+ "a:solidFill": [{ "a:schemeClr": { "@_val": "phClr" } }],
35049
+ "a:gradFill": []
35050
+ },
35051
+ "a:lnStyleLst": {
35052
+ "a:ln": [
35053
+ {
35054
+ "@_w": "6350",
35055
+ "@_cap": "flat",
35056
+ "@_cmpd": "sng",
35057
+ "@_algn": "ctr",
35058
+ ...phClrSolid,
35059
+ "a:prstDash": { "@_val": "solid" },
35060
+ "a:miter": { "@_lim": "800000" }
35061
+ },
35062
+ {
35063
+ "@_w": "12700",
35064
+ "@_cap": "flat",
35065
+ "@_cmpd": "sng",
35066
+ "@_algn": "ctr",
35067
+ ...phClrSolid,
35068
+ "a:prstDash": { "@_val": "solid" },
35069
+ "a:miter": { "@_lim": "800000" }
35070
+ },
35071
+ {
35072
+ "@_w": "19050",
35073
+ "@_cap": "flat",
35074
+ "@_cmpd": "sng",
35075
+ "@_algn": "ctr",
35076
+ ...phClrSolid,
35077
+ "a:prstDash": { "@_val": "solid" },
35078
+ "a:miter": { "@_lim": "800000" }
35079
+ }
35080
+ ]
35081
+ },
35082
+ "a:effectStyleLst": {
35083
+ "a:effectStyle": [{ "a:effectLst": {} }, { "a:effectLst": {} }, { "a:effectLst": {} }]
35084
+ },
35085
+ "a:bgFillStyleLst": {
35086
+ "a:solidFill": [{ "a:schemeClr": { "@_val": "phClr" } }],
35087
+ "a:gradFill": []
35088
+ }
35089
+ };
35090
+ }
33334
35091
  };
33335
35092
 
33336
35093
  // src/core/core/runtime/PptxHandlerRuntimeSavePipeline.ts
33337
- var PptxHandlerRuntime34 = class _PptxHandlerRuntime extends PptxHandlerRuntime33 {
35094
+ var PptxHandlerRuntime35 = class _PptxHandlerRuntime extends PptxHandlerRuntime34 {
33338
35095
  /**
33339
35096
  * Resolve the effective conformance class for this save operation.
33340
35097
  *
@@ -33421,6 +35178,7 @@ var PptxHandlerRuntime34 = class _PptxHandlerRuntime extends PptxHandlerRuntime3
33421
35178
  for (const [masterPath, masterXmlObj] of this.masterXmlMap.entries()) {
33422
35179
  this.zip.file(masterPath, this.builder.build(masterXmlObj));
33423
35180
  }
35181
+ await this.persistThemeParts();
33424
35182
  await this.applyEmbeddedFontPreservation(options?.embeddedFonts);
33425
35183
  if (this.presentationData) {
33426
35184
  this.presentationSaveBuilder.applySaveOptions({
@@ -33510,7 +35268,7 @@ var PptxHandlerRuntime34 = class _PptxHandlerRuntime extends PptxHandlerRuntime3
33510
35268
  };
33511
35269
 
33512
35270
  // src/core/core/runtime/PptxHandlerRuntimeElementParsing.ts
33513
- var PptxHandlerRuntime35 = class _PptxHandlerRuntime extends PptxHandlerRuntime34 {
35271
+ var PptxHandlerRuntime36 = class _PptxHandlerRuntime extends PptxHandlerRuntime35 {
33514
35272
  /**
33515
35273
  * Parse media data (video/audio path and MIME type) from graphic frame data.
33516
35274
  */
@@ -33732,7 +35490,7 @@ var PptxHandlerRuntime35 = class _PptxHandlerRuntime extends PptxHandlerRuntime3
33732
35490
  };
33733
35491
 
33734
35492
  // src/core/core/runtime/PptxHandlerRuntimePlaceholderLookup.ts
33735
- var PptxHandlerRuntime36 = class extends PptxHandlerRuntime35 {
35493
+ var PptxHandlerRuntime37 = class extends PptxHandlerRuntime36 {
33736
35494
  findPlaceholderInShapeTree(spTree, expected) {
33737
35495
  if (!spTree) {
33738
35496
  return void 0;
@@ -33885,7 +35643,7 @@ var PptxHandlerRuntime36 = class extends PptxHandlerRuntime35 {
33885
35643
  };
33886
35644
 
33887
35645
  // src/core/core/runtime/PptxHandlerRuntimeGeometryParsing.ts
33888
- var PptxHandlerRuntime37 = class extends PptxHandlerRuntime36 {
35646
+ var PptxHandlerRuntime38 = class extends PptxHandlerRuntime37 {
33889
35647
  parseGeometryAdjustments(prstGeom) {
33890
35648
  if (!prstGeom) {
33891
35649
  return void 0;
@@ -33994,6 +35752,103 @@ var PptxHandlerRuntime37 = class extends PptxHandlerRuntime36 {
33994
35752
  }
33995
35753
  return handles.length > 0 ? handles : void 0;
33996
35754
  }
35755
+ /**
35756
+ * Extract `a:gdLst`/`a:ahLst`/`a:cxnLst`/`a:rect` raw XML from a `a:custGeom`
35757
+ * node so they can be re-emitted on save when the geometry is edited.
35758
+ * Returns `undefined` when none of these auxiliary children carry data.
35759
+ */
35760
+ extractCustomGeometryRawData(custGeom) {
35761
+ if (!custGeom) {
35762
+ return void 0;
35763
+ }
35764
+ const isNonEmpty = (node) => {
35765
+ if (node === void 0 || node === null) {
35766
+ return false;
35767
+ }
35768
+ if (typeof node !== "object") {
35769
+ return true;
35770
+ }
35771
+ return Object.keys(node).length > 0;
35772
+ };
35773
+ const result = {};
35774
+ const gdLst = custGeom["a:gdLst"];
35775
+ if (isNonEmpty(gdLst)) {
35776
+ result.gdLstXml = gdLst;
35777
+ }
35778
+ const ahLst = custGeom["a:ahLst"];
35779
+ if (isNonEmpty(ahLst)) {
35780
+ result.ahLstXml = ahLst;
35781
+ }
35782
+ const cxnLst = custGeom["a:cxnLst"];
35783
+ if (isNonEmpty(cxnLst)) {
35784
+ result.cxnLstXml = cxnLst;
35785
+ }
35786
+ const rect = custGeom["a:rect"];
35787
+ if (isNonEmpty(rect)) {
35788
+ result.rectXml = rect;
35789
+ }
35790
+ return Object.keys(result).length > 0 ? result : void 0;
35791
+ }
35792
+ /**
35793
+ * Build structured `CustomGeometryPath[]` from a parsed `a:custGeom` node,
35794
+ * including per-path `@fill`/`@stroke`/`@extrusionOk` attributes so they
35795
+ * survive a round-trip when the path list is later regenerated.
35796
+ *
35797
+ * Falls back to SVG → structured-path conversion when no structured path
35798
+ * info is otherwise available.
35799
+ */
35800
+ buildStructuredCustomGeometryPaths(custGeom, pathData, pathWidth, pathHeight) {
35801
+ if (!custGeom) {
35802
+ return void 0;
35803
+ }
35804
+ const pathLst = custGeom["a:pathLst"];
35805
+ if (!pathLst) {
35806
+ return void 0;
35807
+ }
35808
+ const pathNodes = this.ensureArray(pathLst["a:path"]);
35809
+ if (pathNodes.length === 0) {
35810
+ return void 0;
35811
+ }
35812
+ const segments = svgToCustomGeometryPaths(pathData, pathWidth, pathHeight);
35813
+ if (segments.length === 0) {
35814
+ return void 0;
35815
+ }
35816
+ const validFillModes = /* @__PURE__ */ new Set([
35817
+ "norm",
35818
+ "lighten",
35819
+ "lightenLess",
35820
+ "darken",
35821
+ "darkenLess",
35822
+ "none"
35823
+ ]);
35824
+ const parseBoolAttr2 = (value) => {
35825
+ if (value === void 0 || value === null || value === "") {
35826
+ return void 0;
35827
+ }
35828
+ if (value === "1" || value === "true" || value === true) {
35829
+ return true;
35830
+ }
35831
+ if (value === "0" || value === "false" || value === false) {
35832
+ return false;
35833
+ }
35834
+ return void 0;
35835
+ };
35836
+ const target = segments[0];
35837
+ const firstNode = pathNodes[0];
35838
+ const fillAttr = String(firstNode["@_fill"] ?? "").trim();
35839
+ if (validFillModes.has(fillAttr)) {
35840
+ target.fillMode = fillAttr;
35841
+ }
35842
+ const strokeAttr = parseBoolAttr2(firstNode["@_stroke"]);
35843
+ if (strokeAttr !== void 0) {
35844
+ target.stroke = strokeAttr;
35845
+ }
35846
+ const extrusionAttr = parseBoolAttr2(firstNode["@_extrusionOk"]);
35847
+ if (extrusionAttr !== void 0) {
35848
+ target.extrusionOk = extrusionAttr;
35849
+ }
35850
+ return segments;
35851
+ }
33997
35852
  parseCustomGeometry(custGeom, shapeWidth, shapeHeight) {
33998
35853
  if (!custGeom || !custGeom["a:pathLst"] || !custGeom["a:pathLst"]?.["a:path"]) {
33999
35854
  return null;
@@ -34062,7 +35917,7 @@ var PptxHandlerRuntime37 = class extends PptxHandlerRuntime36 {
34062
35917
  };
34063
35918
 
34064
35919
  // src/core/core/runtime/PptxHandlerRuntimeShapeImageFill.ts
34065
- var PptxHandlerRuntime38 = class _PptxHandlerRuntime extends PptxHandlerRuntime37 {
35920
+ var PptxHandlerRuntime39 = class _PptxHandlerRuntime extends PptxHandlerRuntime38 {
34066
35921
  /**
34067
35922
  * Parse a shape that has an image fill (a:blipFill inside spPr)
34068
35923
  * This handles shapes like rectangles filled with images (e.g., wood texture backgrounds)
@@ -34262,7 +36117,7 @@ var PptxHandlerRuntime38 = class _PptxHandlerRuntime extends PptxHandlerRuntime3
34262
36117
  };
34263
36118
 
34264
36119
  // src/core/core/runtime/PptxHandlerRuntimeTextDefaults.ts
34265
- var PptxHandlerRuntime39 = class extends PptxHandlerRuntime38 {
36120
+ var PptxHandlerRuntime40 = class extends PptxHandlerRuntime39 {
34266
36121
  /**
34267
36122
  * Apply {@link PlaceholderDefaults} body-level properties to a
34268
36123
  * {@link TextStyle} as fallback values (only sets fields that are
@@ -34386,7 +36241,7 @@ var PptxHandlerRuntime39 = class extends PptxHandlerRuntime38 {
34386
36241
  };
34387
36242
 
34388
36243
  // src/core/core/runtime/PptxHandlerRuntimeBulletParsing.ts
34389
- var PptxHandlerRuntime40 = class extends PptxHandlerRuntime39 {
36244
+ var PptxHandlerRuntime41 = class extends PptxHandlerRuntime40 {
34390
36245
  resolveParagraphBulletInfo(paragraph, paragraphIndex, txBody, inheritedTxBody, isBodyPlaceholder = false, slidePath) {
34391
36246
  if (!paragraph) {
34392
36247
  return null;
@@ -34417,7 +36272,7 @@ var PptxHandlerRuntime40 = class extends PptxHandlerRuntime39 {
34417
36272
  if (candidate["a:buNone"]) {
34418
36273
  return { none: true };
34419
36274
  }
34420
- if (candidate["a:buChar"] || candidate["a:buAutoNum"] || candidate["a:buBlip"]) {
36275
+ if (candidate["a:buChar"] || candidate["a:buAutoNum"] || candidate["a:buBlip"] || candidate["a:buFontTx"] !== void 0 || candidate["a:buClrTx"] !== void 0 || candidate["a:buSzTx"] !== void 0) {
34421
36276
  resolvedBulletProps = candidate;
34422
36277
  break;
34423
36278
  }
@@ -34431,6 +36286,7 @@ var PptxHandlerRuntime40 = class extends PptxHandlerRuntime39 {
34431
36286
  }
34432
36287
  const buFont = resolvedBulletProps["a:buFont"];
34433
36288
  const fontFamily = buFont?.["@_typeface"] ? String(buFont["@_typeface"]) : void 0;
36289
+ const fontInherit = resolvedBulletProps["a:buFontTx"] !== void 0;
34434
36290
  const buSzPct = resolvedBulletProps["a:buSzPct"];
34435
36291
  let sizePercent;
34436
36292
  if (buSzPct?.["@_val"] !== void 0) {
@@ -34447,6 +36303,7 @@ var PptxHandlerRuntime40 = class extends PptxHandlerRuntime39 {
34447
36303
  sizePts = ptsRaw / 100;
34448
36304
  }
34449
36305
  }
36306
+ const sizeInherit = resolvedBulletProps["a:buSzTx"] !== void 0;
34450
36307
  const buClr = resolvedBulletProps["a:buClr"];
34451
36308
  let color;
34452
36309
  if (buClr) {
@@ -34455,6 +36312,7 @@ var PptxHandlerRuntime40 = class extends PptxHandlerRuntime39 {
34455
36312
  color = String(srgb["@_val"]);
34456
36313
  }
34457
36314
  }
36315
+ const colorInherit = resolvedBulletProps["a:buClrTx"] !== void 0;
34458
36316
  const bulletChar = String(
34459
36317
  resolvedBulletProps["a:buChar"]?.["@_char"] || ""
34460
36318
  );
@@ -34464,7 +36322,10 @@ var PptxHandlerRuntime40 = class extends PptxHandlerRuntime39 {
34464
36322
  fontFamily,
34465
36323
  sizePercent,
34466
36324
  sizePts,
34467
- color
36325
+ color,
36326
+ ...fontInherit ? { fontInherit: true } : {},
36327
+ ...colorInherit ? { colorInherit: true } : {},
36328
+ ...sizeInherit ? { sizeInherit: true } : {}
34468
36329
  };
34469
36330
  }
34470
36331
  const autoNum = resolvedBulletProps["a:buAutoNum"];
@@ -34479,7 +36340,10 @@ var PptxHandlerRuntime40 = class extends PptxHandlerRuntime39 {
34479
36340
  fontFamily,
34480
36341
  sizePercent,
34481
36342
  sizePts,
34482
- color
36343
+ color,
36344
+ ...fontInherit ? { fontInherit: true } : {},
36345
+ ...colorInherit ? { colorInherit: true } : {},
36346
+ ...sizeInherit ? { sizeInherit: true } : {}
34483
36347
  };
34484
36348
  }
34485
36349
  const buBlip = resolvedBulletProps["a:buBlip"];
@@ -34591,7 +36455,7 @@ var PptxHandlerRuntime40 = class extends PptxHandlerRuntime39 {
34591
36455
  };
34592
36456
 
34593
36457
  // src/core/core/runtime/PptxHandlerRuntimeShapeBodyParsing.ts
34594
- var PptxHandlerRuntime41 = class _PptxHandlerRuntime extends PptxHandlerRuntime40 {
36458
+ var PptxHandlerRuntime42 = class _PptxHandlerRuntime extends PptxHandlerRuntime41 {
34595
36459
  /**
34596
36460
  * Parse `a:spLocks` attributes into a structured {@link PptxShapeLocks} object.
34597
36461
  * Returns `undefined` when the node is absent or contains no lock attributes.
@@ -34686,7 +36550,8 @@ var PptxHandlerRuntime41 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
34686
36550
  if (Number.isFinite(spcColRaw) && spcColRaw > 0) {
34687
36551
  textStyle.columnSpacing = spcColRaw / _PptxHandlerRuntime.EMU_PER_PX;
34688
36552
  }
34689
- const hOverflow = String(bodyPr["@_hOverflow"] || "").trim();
36553
+ const hOverflowRaw = bodyPr["@_horzOverflow"] ?? bodyPr["@_hOverflow"];
36554
+ const hOverflow = String(hOverflowRaw || "").trim();
34690
36555
  if (hOverflow === "overflow" || hOverflow === "clip") {
34691
36556
  textStyle.hOverflow = hOverflow;
34692
36557
  }
@@ -34869,7 +36734,7 @@ var PptxHandlerRuntime41 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
34869
36734
  };
34870
36735
 
34871
36736
  // src/core/core/runtime/PptxHandlerRuntimeShapeTextParsing.ts
34872
- var PptxHandlerRuntime42 = class _PptxHandlerRuntime extends PptxHandlerRuntime41 {
36737
+ var PptxHandlerRuntime43 = class _PptxHandlerRuntime extends PptxHandlerRuntime42 {
34873
36738
  /**
34874
36739
  * Resolve paragraph-level styles (alignment, spacing, margins, tabs,
34875
36740
  * level styles) for a single paragraph. Modifies `textStyle` in place
@@ -35051,7 +36916,7 @@ var PptxHandlerRuntime42 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
35051
36916
  };
35052
36917
 
35053
36918
  // src/core/core/runtime/PptxHandlerRuntimeShapeParagraphContentParsing.ts
35054
- var PptxHandlerRuntime43 = class extends PptxHandlerRuntime42 {
36919
+ var PptxHandlerRuntime44 = class extends PptxHandlerRuntime43 {
35055
36920
  /**
35056
36921
  * Collect text content (runs, fields, equations, bullets) for a single
35057
36922
  * paragraph and return text parts + segments. The returned `seedStyle`
@@ -35234,6 +37099,23 @@ var PptxHandlerRuntime43 = class extends PptxHandlerRuntime42 {
35234
37099
  parts.push("\n");
35235
37100
  segments.push({ text: "\n", style: { ...mergedDefaultRunStyle } });
35236
37101
  }
37102
+ const firstSegmentIndex = segments.length === 0 ? -1 : 0;
37103
+ if (firstSegmentIndex >= 0) {
37104
+ const pPrRaw = p["a:pPr"];
37105
+ const lvlRaw = pPrRaw?.["@_lvl"];
37106
+ if (lvlRaw !== void 0) {
37107
+ const lvlParsed = Number.parseInt(String(lvlRaw), 10);
37108
+ if (Number.isFinite(lvlParsed) && lvlParsed > 0) {
37109
+ segments[firstSegmentIndex].paragraphLevel = Math.min(Math.max(lvlParsed, 0), 8);
37110
+ }
37111
+ }
37112
+ const endParaRPrRaw = p["a:endParaRPr"];
37113
+ if (endParaRPrRaw && typeof endParaRPrRaw === "object") {
37114
+ segments[firstSegmentIndex].endParaRunProperties = {
37115
+ ...endParaRPrRaw
37116
+ };
37117
+ }
37118
+ }
35237
37119
  return { parts, segments, seedStyle };
35238
37120
  }
35239
37121
  /**
@@ -35343,7 +37225,7 @@ var PptxHandlerRuntime43 = class extends PptxHandlerRuntime42 {
35343
37225
  };
35344
37226
 
35345
37227
  // src/core/core/runtime/PptxHandlerRuntimeShapeParsing.ts
35346
- var PptxHandlerRuntime44 = class _PptxHandlerRuntime extends PptxHandlerRuntime43 {
37228
+ var PptxHandlerRuntime45 = class _PptxHandlerRuntime extends PptxHandlerRuntime44 {
35347
37229
  parseShape(shape, id, slidePath) {
35348
37230
  try {
35349
37231
  const spPr = shape["p:spPr"];
@@ -35379,6 +37261,7 @@ var PptxHandlerRuntime44 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
35379
37261
  let pathData;
35380
37262
  let pathWidth;
35381
37263
  let pathHeight;
37264
+ let customGeometryRawData;
35382
37265
  const custGeom = effectiveSpPr?.["a:custGeom"];
35383
37266
  if (custGeom) {
35384
37267
  const customPath = this.parseCustomGeometry(
@@ -35391,6 +37274,7 @@ var PptxHandlerRuntime44 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
35391
37274
  pathData = customPath.pathData;
35392
37275
  pathWidth = customPath.pathWidth;
35393
37276
  pathHeight = customPath.pathHeight;
37277
+ customGeometryRawData = this.extractCustomGeometryRawData(custGeom);
35394
37278
  }
35395
37279
  }
35396
37280
  const geomNode = custGeom ?? effectiveSpPr?.["a:prstGeom"];
@@ -35548,7 +37432,8 @@ var PptxHandlerRuntime44 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
35548
37432
  type: "shape",
35549
37433
  pathData,
35550
37434
  pathWidth,
35551
- pathHeight
37435
+ pathHeight,
37436
+ customGeometryRawData
35552
37437
  };
35553
37438
  } catch (e) {
35554
37439
  console.warn(`[pptx] Skipping shape element (${id}):`, e);
@@ -35558,7 +37443,7 @@ var PptxHandlerRuntime44 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
35558
37443
  };
35559
37444
 
35560
37445
  // src/core/core/runtime/PptxHandlerRuntimePictureParsing.ts
35561
- var PptxHandlerRuntime45 = class _PptxHandlerRuntime extends PptxHandlerRuntime44 {
37446
+ var PptxHandlerRuntime46 = class _PptxHandlerRuntime extends PptxHandlerRuntime45 {
35562
37447
  async parsePicture(pic, id, slidePath) {
35563
37448
  try {
35564
37449
  const spPr = pic["p:spPr"];
@@ -35797,7 +37682,7 @@ var PptxHandlerRuntime45 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
35797
37682
  };
35798
37683
 
35799
37684
  // src/core/core/runtime/PptxHandlerRuntimeSpTreeParsing.ts
35800
- var PptxHandlerRuntime46 = class _PptxHandlerRuntime extends PptxHandlerRuntime45 {
37685
+ var PptxHandlerRuntime47 = class _PptxHandlerRuntime extends PptxHandlerRuntime46 {
35801
37686
  /**
35802
37687
  * Known element tag names that appear as direct children of `p:spTree`
35803
37688
  * (or `p:grpSp`) and represent renderable shapes/objects.
@@ -36142,9 +38027,18 @@ var PptxHandlerRuntime46 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
36142
38027
  * Unwrap mc:AlternateContent elements within a shape tree (or group),
36143
38028
  * merging selected branch children into the parent element arrays.
36144
38029
  * Delegates to the standalone alternate-content utility.
38030
+ *
38031
+ * Records each consumed AC envelope in {@link alternateContentBlockByRawXml}
38032
+ * so the save layer can re-emit the original `<mc:Choice>` /
38033
+ * `<mc:Fallback>` shape on dirty save (CC-4).
36145
38034
  */
36146
38035
  unwrapAlternateContent(container) {
36147
- unwrapAlternateContent(container);
38036
+ const blocks = unwrapAlternateContent(container);
38037
+ for (const block of blocks) {
38038
+ for (const ref of block.childRefs) {
38039
+ this.alternateContentBlockByRawXml.set(ref.node, block);
38040
+ }
38041
+ }
36148
38042
  }
36149
38043
  /**
36150
38044
  * Forward declaration – implemented in PptxHandlerRuntimeGroupParsing.
@@ -36155,7 +38049,7 @@ var PptxHandlerRuntime46 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
36155
38049
  };
36156
38050
 
36157
38051
  // src/core/core/runtime/PptxHandlerRuntimeGroupParsing.ts
36158
- var PptxHandlerRuntime47 = class _PptxHandlerRuntime extends PptxHandlerRuntime46 {
38052
+ var PptxHandlerRuntime48 = class _PptxHandlerRuntime extends PptxHandlerRuntime47 {
36159
38053
  async parseGroupShape(group, baseId, slidePath, rawXmlStr) {
36160
38054
  const grpSpPr = group["p:grpSpPr"];
36161
38055
  const xfrm = grpSpPr?.["a:xfrm"];
@@ -36328,7 +38222,7 @@ var PptxHandlerRuntime47 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
36328
38222
  };
36329
38223
 
36330
38224
  // src/core/core/runtime/PptxHandlerRuntimeSlideParsing.ts
36331
- var PptxHandlerRuntime48 = class extends PptxHandlerRuntime47 {
38225
+ var PptxHandlerRuntime49 = class extends PptxHandlerRuntime48 {
36332
38226
  /**
36333
38227
  * Parse text body from a connector shape (p:cxnSp > p:txBody).
36334
38228
  * Uses the same text run extraction logic as regular shapes but
@@ -36440,7 +38334,7 @@ var PptxHandlerRuntime48 = class extends PptxHandlerRuntime47 {
36440
38334
  };
36441
38335
 
36442
38336
  // src/core/core/runtime/PptxHandlerRuntimeColorAndEffects.ts
36443
- var PptxHandlerRuntime49 = class extends PptxHandlerRuntime48 {
38337
+ var PptxHandlerRuntime50 = class extends PptxHandlerRuntime49 {
36444
38338
  /**
36445
38339
  * Forward declaration – implemented in PptxHandlerRuntimeThemeProcessing.
36446
38340
  * Re-resolves gradient stops by substituting `phClr` with the given colour.
@@ -36481,8 +38375,9 @@ var PptxHandlerRuntime49 = class extends PptxHandlerRuntime48 {
36481
38375
  return void 0;
36482
38376
  }
36483
38377
  const resolvedKey = normalized === "phclr" ? "accent1" : normalized;
36484
- if (this.currentSlideClrMapOverride) {
36485
- const remapped = this.currentSlideClrMapOverride[resolvedKey];
38378
+ const overrideMap = this.currentSlideClrMapOverride ?? this.currentMasterClrMap;
38379
+ if (overrideMap) {
38380
+ const remapped = overrideMap[resolvedKey];
36486
38381
  if (remapped) {
36487
38382
  return this.themeColorMap[remapped] || this.getDefaultSchemeColorMap()[remapped];
36488
38383
  }
@@ -36565,7 +38460,7 @@ var PptxHandlerRuntime49 = class extends PptxHandlerRuntime48 {
36565
38460
  };
36566
38461
 
36567
38462
  // src/core/core/runtime/PptxHandlerRuntimeBackgroundParsing.ts
36568
- var PptxHandlerRuntime50 = class extends PptxHandlerRuntime49 {
38463
+ var PptxHandlerRuntime51 = class extends PptxHandlerRuntime50 {
36569
38464
  async extractBackgroundImage(slideXml2, slidePath, rootElement = "p:sld") {
36570
38465
  try {
36571
38466
  const bg = slideXml2[rootElement]?.["p:cSld"]?.["p:bg"];
@@ -36776,7 +38671,7 @@ var PptxHandlerRuntime50 = class extends PptxHandlerRuntime49 {
36776
38671
  };
36777
38672
 
36778
38673
  // src/core/core/runtime/PptxHandlerRuntimeSlideUtils.ts
36779
- var PptxHandlerRuntime51 = class extends PptxHandlerRuntime50 {
38674
+ var PptxHandlerRuntime52 = class extends PptxHandlerRuntime51 {
36780
38675
  /**
36781
38676
  * Retrieve the background gradient from a layout, falling back to master.
36782
38677
  */
@@ -36847,6 +38742,64 @@ var PptxHandlerRuntime51 = class extends PptxHandlerRuntime50 {
36847
38742
  }
36848
38743
  return void 0;
36849
38744
  }
38745
+ /**
38746
+ * Find the master file path referenced by a layout via its relationships.
38747
+ */
38748
+ findMasterPathForLayoutBase(layoutPath) {
38749
+ const layoutRels = this.slideRelsMap.get(layoutPath);
38750
+ if (!layoutRels) {
38751
+ return void 0;
38752
+ }
38753
+ for (const [, target] of layoutRels.entries()) {
38754
+ if (target.includes("slideMaster")) {
38755
+ const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
38756
+ return target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${target.replace("../", "")}`;
38757
+ }
38758
+ }
38759
+ return void 0;
38760
+ }
38761
+ /**
38762
+ * Switch the active master state (clrMap + theme color/font/format
38763
+ * scheme) so that scheme-colour resolution for the slide currently
38764
+ * being parsed walks through the correct master.
38765
+ *
38766
+ * Multi-master decks must resolve scheme colours against each slide's
38767
+ * own master rather than always against `masterFiles[0]`.
38768
+ *
38769
+ * Phase 2 Stream B / C-H4.
38770
+ */
38771
+ async setActiveMasterForSlide(slidePath) {
38772
+ const layoutPath = this.findLayoutPathForSlide(slidePath);
38773
+ if (!layoutPath) {
38774
+ this.currentMasterClrMap = null;
38775
+ this.themeColorMap = { ...this.globalThemeColorMapSnapshot };
38776
+ this.themeFontMap = { ...this.globalThemeFontMapSnapshot };
38777
+ this.themeFormatScheme = this.globalThemeFormatSchemeSnapshot;
38778
+ return;
38779
+ }
38780
+ if (!this.slideRelsMap.has(layoutPath)) {
38781
+ const layoutRelsPath = `${layoutPath.replace("slideLayouts/", "slideLayouts/_rels/")}.rels`;
38782
+ try {
38783
+ await this.loadSlideRelationships(layoutPath, layoutRelsPath);
38784
+ } catch {
38785
+ }
38786
+ }
38787
+ const masterPath = this.findMasterPathForLayoutBase(layoutPath);
38788
+ if (!masterPath) {
38789
+ this.currentMasterClrMap = null;
38790
+ this.themeColorMap = { ...this.globalThemeColorMapSnapshot };
38791
+ this.themeFontMap = { ...this.globalThemeFontMapSnapshot };
38792
+ this.themeFormatScheme = this.globalThemeFormatSchemeSnapshot;
38793
+ return;
38794
+ }
38795
+ this.currentMasterClrMap = this.masterClrMaps.get(masterPath) ?? null;
38796
+ const masterColorMap = this.masterThemeColorMaps.get(masterPath);
38797
+ this.themeColorMap = masterColorMap ? { ...masterColorMap } : { ...this.globalThemeColorMapSnapshot };
38798
+ const masterFontMap = this.masterThemeFontMaps.get(masterPath);
38799
+ this.themeFontMap = masterFontMap ? { ...masterFontMap } : { ...this.globalThemeFontMapSnapshot };
38800
+ const masterFormatScheme = this.masterThemeFormatSchemes.get(masterPath);
38801
+ this.themeFormatScheme = masterFormatScheme ?? this.globalThemeFormatSchemeSnapshot;
38802
+ }
36850
38803
  /**
36851
38804
  * Extract the `p:bg/@showAnimation` flag from a slide's XML.
36852
38805
  * Returns `true` when the background should animate, `false` when
@@ -36987,7 +38940,7 @@ var PptxHandlerRuntime51 = class extends PptxHandlerRuntime50 {
36987
38940
  };
36988
38941
 
36989
38942
  // src/core/core/runtime/PptxHandlerRuntimePlaceholderStyles.ts
36990
- var PptxHandlerRuntime52 = class _PptxHandlerRuntime extends PptxHandlerRuntime51 {
38943
+ var PptxHandlerRuntime53 = class _PptxHandlerRuntime extends PptxHandlerRuntime52 {
36991
38944
  /**
36992
38945
  * Parse a single `a:lvlXpPr` node into a structured
36993
38946
  * {@link PlaceholderTextLevelStyle}.
@@ -37108,7 +39061,7 @@ var PptxHandlerRuntime52 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
37108
39061
  };
37109
39062
 
37110
39063
  // src/core/core/runtime/PptxHandlerRuntimePlaceholderDefaults.ts
37111
- var PptxHandlerRuntime53 = class _PptxHandlerRuntime extends PptxHandlerRuntime52 {
39064
+ var PptxHandlerRuntime54 = class _PptxHandlerRuntime extends PptxHandlerRuntime53 {
37112
39065
  /**
37113
39066
  * Extract structured {@link PlaceholderDefaults} from a layout or master
37114
39067
  * shape that carries a `p:ph` element.
@@ -37251,7 +39204,118 @@ var PptxHandlerRuntime53 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
37251
39204
  };
37252
39205
 
37253
39206
  // src/core/core/runtime/PptxHandlerRuntimeMasterElements.ts
37254
- var PptxHandlerRuntime54 = class extends PptxHandlerRuntime53 {
39207
+ function parseHeaderFooterFlags(hf) {
39208
+ if (!hf) {
39209
+ return void 0;
39210
+ }
39211
+ const result = {};
39212
+ if (hf["@_hdr"] !== void 0) {
39213
+ result.hasHeader = String(hf["@_hdr"]) !== "0";
39214
+ }
39215
+ if (hf["@_ftr"] !== void 0) {
39216
+ result.hasFooter = String(hf["@_ftr"]) !== "0";
39217
+ }
39218
+ if (hf["@_dt"] !== void 0) {
39219
+ result.hasDateTime = String(hf["@_dt"]) !== "0";
39220
+ }
39221
+ if (hf["@_sldNum"] !== void 0) {
39222
+ result.hasSlideNumber = String(hf["@_sldNum"]) !== "0";
39223
+ }
39224
+ return Object.keys(result).length > 0 ? result : void 0;
39225
+ }
39226
+ var PptxHandlerRuntime55 = class extends PptxHandlerRuntime54 {
39227
+ /**
39228
+ * Parse a `CT_TextListStyle` node (`a:defPPr` + `a:lvl1pPr` … `a:lvl9pPr`)
39229
+ * into a level-keyed style map. Used for `<p:txStyles>` children
39230
+ * (`p:titleStyle`, `p:bodyStyle`, `p:otherStyle`) — see ECMA-376 §19.3.1.52.
39231
+ */
39232
+ parseTextListStyle(node) {
39233
+ if (!node) {
39234
+ return void 0;
39235
+ }
39236
+ const levels = {};
39237
+ const defParsed = this.parsePlaceholderLevelStyle(node["a:defPPr"]);
39238
+ if (defParsed) {
39239
+ levels[-1] = defParsed;
39240
+ }
39241
+ for (let lvl = 1; lvl <= 9; lvl++) {
39242
+ const parsed = this.parsePlaceholderLevelStyle(
39243
+ node[`a:lvl${lvl}pPr`]
39244
+ );
39245
+ if (parsed) {
39246
+ levels[lvl - 1] = parsed;
39247
+ }
39248
+ }
39249
+ return Object.keys(levels).length > 0 ? levels : void 0;
39250
+ }
39251
+ /**
39252
+ * Parse `<p:txStyles>` from a slide-master XML object into a structured
39253
+ * {@link PptxMasterTextStyles}. Used to populate `PptxSlideMaster.txStyles`
39254
+ * so the title/body/other text-style cascade (P-H1) is visible on the
39255
+ * typed model.
39256
+ */
39257
+ parseMasterTxStyles(masterXml) {
39258
+ const txStyles = masterXml?.["p:txStyles"];
39259
+ if (!txStyles) {
39260
+ return void 0;
39261
+ }
39262
+ const titleStyle = this.parseTextListStyle(txStyles["p:titleStyle"]);
39263
+ const bodyStyle = this.parseTextListStyle(txStyles["p:bodyStyle"]);
39264
+ const otherStyle = this.parseTextListStyle(txStyles["p:otherStyle"]);
39265
+ if (!titleStyle && !bodyStyle && !otherStyle) {
39266
+ return void 0;
39267
+ }
39268
+ const result = {};
39269
+ if (titleStyle) {
39270
+ result.titleStyle = titleStyle;
39271
+ }
39272
+ if (bodyStyle) {
39273
+ result.bodyStyle = bodyStyle;
39274
+ }
39275
+ if (otherStyle) {
39276
+ result.otherStyle = otherStyle;
39277
+ }
39278
+ return result;
39279
+ }
39280
+ /**
39281
+ * Enrich an array of {@link PptxSlideMaster} entries (already produced by
39282
+ * `parseSlideMasters`) with parsed `<p:txStyles>`. Loads each master's XML
39283
+ * once, parses, and caches it in `masterXmlMap` for downstream consumers.
39284
+ *
39285
+ * Also stores the parsed result on the per-master cache so that the
39286
+ * inheritance chain in `applyMasterTextStyleCascade` can find it without
39287
+ * re-parsing.
39288
+ */
39289
+ async enrichSlideMastersWithTxStyles(slideMasters) {
39290
+ for (const master of slideMasters) {
39291
+ try {
39292
+ let masterXmlObj = this.masterXmlMap.get(master.path);
39293
+ if (!masterXmlObj) {
39294
+ const xmlStr = await this.zip.file(master.path)?.async("string");
39295
+ if (!xmlStr) {
39296
+ continue;
39297
+ }
39298
+ masterXmlObj = this.parser.parse(xmlStr);
39299
+ this.masterXmlMap.set(master.path, masterXmlObj);
39300
+ }
39301
+ const sldMaster = masterXmlObj["p:sldMaster"];
39302
+ if (!sldMaster) {
39303
+ continue;
39304
+ }
39305
+ const parsed = this.parseMasterTxStyles(sldMaster);
39306
+ if (parsed) {
39307
+ master.txStyles = parsed;
39308
+ this.masterTxStylesCache.set(master.path, parsed);
39309
+ }
39310
+ const hf = parseHeaderFooterFlags(sldMaster["p:hf"]);
39311
+ if (hf) {
39312
+ master.headerFooter = hf;
39313
+ }
39314
+ } catch (e) {
39315
+ console.warn("Failed to parse master txStyles:", e);
39316
+ }
39317
+ }
39318
+ }
37255
39319
  parsePresentationDefaultTextStyle() {
37256
39320
  const presentation = this.presentationData?.["p:presentation"];
37257
39321
  const defaultTextStyle = presentation?.["p:defaultTextStyle"];
@@ -37407,7 +39471,7 @@ var PptxHandlerRuntime54 = class extends PptxHandlerRuntime53 {
37407
39471
  };
37408
39472
 
37409
39473
  // src/core/core/runtime/PptxHandlerRuntimeLayoutElements.ts
37410
- var PptxHandlerRuntime55 = class extends PptxHandlerRuntime54 {
39474
+ var PptxHandlerRuntime56 = class extends PptxHandlerRuntime55 {
37411
39475
  async getLayoutElements(slidePath) {
37412
39476
  const slideRels = this.slideRelsMap.get(slidePath);
37413
39477
  if (!slideRels) {
@@ -37531,10 +39595,10 @@ var PptxHandlerRuntime55 = class extends PptxHandlerRuntime54 {
37531
39595
  }
37532
39596
  }
37533
39597
  }
37534
- this.currentSlideClrMapOverride = prevClrMapOverride;
37535
39598
  const layoutShowMasterSp = layoutXmlObj["p:sldLayout"]?.["@_showMasterSp"];
37536
39599
  const showMasterSp = layoutShowMasterSp === void 0 || String(layoutShowMasterSp).trim().toLowerCase() !== "0" && String(layoutShowMasterSp).trim().toLowerCase() !== "false";
37537
39600
  const masterElements = showMasterSp ? await this.getMasterElements(layoutPath) : [];
39601
+ this.currentSlideClrMapOverride = prevClrMapOverride;
37538
39602
  const allElements = [...masterElements, ...elements];
37539
39603
  this.layoutCache.set(layoutPath, allElements);
37540
39604
  return allElements;
@@ -37546,7 +39610,7 @@ var PptxHandlerRuntime55 = class extends PptxHandlerRuntime54 {
37546
39610
  };
37547
39611
 
37548
39612
  // src/core/core/runtime/PptxHandlerRuntimeThemeFormatScheme.ts
37549
- var PptxHandlerRuntime56 = class _PptxHandlerRuntime extends PptxHandlerRuntime55 {
39613
+ var PptxHandlerRuntime57 = class _PptxHandlerRuntime extends PptxHandlerRuntime56 {
37550
39614
  /**
37551
39615
  * Collect fill-style children from a style list node, preserving
37552
39616
  * document order. Handles `a:solidFill`, `a:gradFill`, `a:pattFill`,
@@ -37788,7 +39852,7 @@ var PptxHandlerRuntime56 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
37788
39852
  };
37789
39853
 
37790
39854
  // src/core/core/runtime/PptxHandlerRuntimeThemeOverrides.ts
37791
- var PptxHandlerRuntime57 = class extends PptxHandlerRuntime56 {
39855
+ var PptxHandlerRuntime58 = class extends PptxHandlerRuntime57 {
37792
39856
  /**
37793
39857
  * Parse the `a:fmtScheme` element from the theme into a structured
37794
39858
  * {@link PptxThemeFormatScheme}. Each sub-list (fillStyleLst, lnStyleLst,
@@ -37985,8 +40049,10 @@ var PptxHandlerRuntime57 = class extends PptxHandlerRuntime56 {
37985
40049
  }
37986
40050
  const fontScheme = root["a:fontScheme"];
37987
40051
  if (fontScheme) {
37988
- const majorLatin = fontScheme["a:majorFont"]?.["a:latin"];
37989
- const minorLatin = fontScheme["a:minorFont"]?.["a:latin"];
40052
+ const majorFontNode = fontScheme["a:majorFont"];
40053
+ const minorFontNode = fontScheme["a:minorFont"];
40054
+ const majorLatin = majorFontNode?.["a:latin"];
40055
+ const minorLatin = minorFontNode?.["a:latin"];
37990
40056
  const majorFont = this.normalizeTypefaceToken(String(majorLatin?.["@_typeface"] || ""));
37991
40057
  const minorFont = this.normalizeTypefaceToken(String(minorLatin?.["@_typeface"] || ""));
37992
40058
  if (!result.colorOverrides) {
@@ -38009,13 +40075,46 @@ var PptxHandlerRuntime57 = class extends PptxHandlerRuntime56 {
38009
40075
  };
38010
40076
 
38011
40077
  // src/core/core/runtime/PptxHandlerRuntimeThemeRefResolution.ts
38012
- var PptxHandlerRuntime58 = class extends PptxHandlerRuntime57 {
40078
+ var COLOR_CHOICE_KEYS2 = [
40079
+ "a:scrgbClr",
40080
+ "a:srgbClr",
40081
+ "a:hslClr",
40082
+ "a:sysClr",
40083
+ "a:schemeClr",
40084
+ "a:prstClr"
40085
+ ];
40086
+ var PptxHandlerRuntime59 = class extends PptxHandlerRuntime58 {
40087
+ /**
40088
+ * Pull the verbatim colour-choice child out of a style-matrix-reference
40089
+ * element (`a:lnRef`/`a:fillRef`/`a:effectRef`/`a:fontRef`). Returns the
40090
+ * full child object so it can be round-tripped at save time, preserving
40091
+ * any contained colour transforms (`a:lumMod`, `a:tint`, etc.).
40092
+ */
40093
+ extractRefColorXml(refNode) {
40094
+ if (!refNode) {
40095
+ return void 0;
40096
+ }
40097
+ for (const key of COLOR_CHOICE_KEYS2) {
40098
+ const child = refNode[key];
40099
+ if (child !== void 0) {
40100
+ return { [key]: child };
40101
+ }
40102
+ }
40103
+ return void 0;
40104
+ }
38013
40105
  /**
38014
40106
  * Resolve a `a:effectRef` element into concrete effect properties
38015
40107
  * by looking up `@_idx` in the theme format scheme's effect style list.
38016
40108
  */
38017
40109
  resolveThemeEffectRef(refNode, style) {
38018
40110
  const idx = parseInt(String(refNode["@_idx"] || "0"), 10);
40111
+ if (Number.isFinite(idx) && idx > 0) {
40112
+ style.effectRefIdx = idx;
40113
+ }
40114
+ const overrideColorXml = this.extractRefColorXml(refNode);
40115
+ if (overrideColorXml) {
40116
+ style.effectRefColorXml = overrideColorXml;
40117
+ }
38019
40118
  if (!Number.isFinite(idx) || idx <= 0 || !this.themeFormatScheme || idx > this.themeFormatScheme.effectStyles.length) {
38020
40119
  return;
38021
40120
  }
@@ -38068,6 +40167,13 @@ var PptxHandlerRuntime58 = class extends PptxHandlerRuntime57 {
38068
40167
  resolveThemeLineRef(refNode, style) {
38069
40168
  const idx = parseInt(String(refNode["@_idx"] || "0"), 10);
38070
40169
  const overrideColor = this.parseColor(refNode);
40170
+ if (Number.isFinite(idx) && idx > 0) {
40171
+ style.lnRefIdx = idx;
40172
+ }
40173
+ const overrideColorXml = this.extractRefColorXml(refNode);
40174
+ if (overrideColorXml) {
40175
+ style.lnRefColorXml = overrideColorXml;
40176
+ }
38071
40177
  if (!Number.isFinite(idx) || idx <= 0 || !this.themeFormatScheme || idx > this.themeFormatScheme.lineStyles.length) {
38072
40178
  style.strokeColor = overrideColor;
38073
40179
  if (overrideColor) {
@@ -38139,6 +40245,13 @@ var PptxHandlerRuntime58 = class extends PptxHandlerRuntime57 {
38139
40245
  */
38140
40246
  resolveThemeFillRef(refNode, style) {
38141
40247
  const idx = parseInt(String(refNode["@_idx"] || "0"), 10);
40248
+ if (Number.isFinite(idx) && idx > 0) {
40249
+ style.fillRefIdx = idx;
40250
+ }
40251
+ const overrideColorXml = this.extractRefColorXml(refNode);
40252
+ if (overrideColorXml) {
40253
+ style.fillRefColorXml = overrideColorXml;
40254
+ }
38142
40255
  if (!Number.isFinite(idx) || idx <= 0 || !this.themeFormatScheme) {
38143
40256
  style.fillMode = "theme";
38144
40257
  style.fillColor = this.parseColor(refNode);
@@ -38204,7 +40317,7 @@ var PptxHandlerRuntime58 = class extends PptxHandlerRuntime57 {
38204
40317
  };
38205
40318
 
38206
40319
  // src/core/core/runtime/PptxHandlerRuntimeThemeLoading.ts
38207
- var PptxHandlerRuntime59 = class extends PptxHandlerRuntime58 {
40320
+ var PptxHandlerRuntime60 = class extends PptxHandlerRuntime59 {
38208
40321
  async resolvePrimaryThemePath() {
38209
40322
  const masterFiles = this.zip.file(/^ppt\/slideMasters\/slideMaster\d+\.xml$/);
38210
40323
  if (!masterFiles || masterFiles.length === 0) {
@@ -38314,62 +40427,97 @@ var PptxHandlerRuntime59 = class extends PptxHandlerRuntime58 {
38314
40427
  formatScheme: this.themeFormatScheme
38315
40428
  };
38316
40429
  }
38317
- async applySlideMasterColorMap(defaultMap) {
40430
+ /**
40431
+ * Parse every slide master's `<p:clrMap>` element and store the alias
40432
+ * dictionaries on {@link masterClrMaps}. Do *not* mutate
40433
+ * {@link themeColorMap} — alias resolution happens at colour-lookup
40434
+ * time so that:
40435
+ *
40436
+ * 1. The raw theme scheme stays the source of truth (clrMap is a
40437
+ * routing layer, not a colour table).
40438
+ * 2. Multi-master decks resolve each slide against its own master's
40439
+ * clrMap rather than always against `masterFiles[0]`.
40440
+ * 3. Layout `clrMapOvr` semantics work correctly when a slide's master
40441
+ * differs from the deck's first master.
40442
+ *
40443
+ * Phase 2 Stream B / C-H4.
40444
+ */
40445
+ async applySlideMasterColorMap(_defaultMap) {
38318
40446
  const masterFiles = this.zip.file(/^ppt\/slideMasters\/slideMaster\d+\.xml$/);
38319
40447
  if (!masterFiles || masterFiles.length === 0) {
38320
40448
  return;
38321
40449
  }
38322
- try {
38323
- const masterXml = await masterFiles[0].async("string");
38324
- const masterData = this.parser.parse(masterXml);
38325
- const clrMap = masterData?.["p:sldMaster"]?.["p:clrMap"];
38326
- if (!clrMap) {
38327
- return;
38328
- }
38329
- const aliasKeys = [
38330
- "bg1",
38331
- "tx1",
38332
- "bg2",
38333
- "tx2",
38334
- "accent1",
38335
- "accent2",
38336
- "accent3",
38337
- "accent4",
38338
- "accent5",
38339
- "accent6",
38340
- "hlink",
38341
- "folHlink"
38342
- ];
38343
- for (const aliasKey of aliasKeys) {
38344
- const mappedKey = String(clrMap[`@_${aliasKey}`] || "").trim().toLowerCase();
38345
- if (!mappedKey) {
40450
+ const aliasKeys = [
40451
+ "bg1",
40452
+ "tx1",
40453
+ "bg2",
40454
+ "tx2",
40455
+ "accent1",
40456
+ "accent2",
40457
+ "accent3",
40458
+ "accent4",
40459
+ "accent5",
40460
+ "accent6",
40461
+ "hlink",
40462
+ "folHlink"
40463
+ ];
40464
+ for (const file of masterFiles) {
40465
+ try {
40466
+ const masterXml = await file.async("string");
40467
+ const masterData = this.parser.parse(masterXml);
40468
+ const clrMap = masterData?.["p:sldMaster"]?.["p:clrMap"];
40469
+ if (!clrMap) {
38346
40470
  continue;
38347
40471
  }
38348
- const mappedColor = this.themeColorMap[mappedKey] || defaultMap[mappedKey];
38349
- if (mappedColor) {
38350
- this.themeColorMap[aliasKey] = mappedColor;
40472
+ const aliasMap = {};
40473
+ for (const aliasKey of aliasKeys) {
40474
+ const mappedKey = String(clrMap[`@_${aliasKey}`] || "").trim().toLowerCase();
40475
+ if (mappedKey) {
40476
+ aliasMap[aliasKey] = mappedKey;
40477
+ }
40478
+ }
40479
+ if (Object.keys(aliasMap).length > 0) {
40480
+ this.masterClrMaps.set(file.name, aliasMap);
38351
40481
  }
40482
+ } catch (error) {
40483
+ console.warn(`Failed to parse slide master color map for ${file.name}:`, error);
38352
40484
  }
38353
- } catch (error) {
38354
- console.warn("Failed to parse slide master color map:", error);
38355
40485
  }
38356
40486
  }
38357
- async loadThemeData() {
38358
- const themeFiles = this.zip.file(/^ppt\/theme\/theme\d+\.xml$/);
38359
- if (!themeFiles || themeFiles.length === 0) {
38360
- return;
40487
+ /**
40488
+ * Parse a single theme part into structured colour, font, and format
40489
+ * scheme dictionaries. Used both for the global default theme and for
40490
+ * each master's per-master theme (multi-master support).
40491
+ *
40492
+ * Phase 2 Stream B / C-H4.
40493
+ */
40494
+ async parseThemePart(themePath) {
40495
+ const themeFile = this.zip.file(themePath);
40496
+ if (!themeFile) {
40497
+ return null;
38361
40498
  }
38362
- const preferredThemePath = await this.resolvePrimaryThemePath();
38363
- const preferredThemeFile = preferredThemePath ? themeFiles.find((file) => file.name === preferredThemePath) : void 0;
38364
- const themeFile = preferredThemeFile ?? themeFiles[0];
38365
40499
  const themeXml2 = await themeFile.async("string");
40500
+ this.originalThemeXmlByPath.set(themePath, themeXml2);
38366
40501
  const themeData = this.parser.parse(themeXml2);
38367
40502
  const themeRoot = themeData["a:theme"];
38368
40503
  const themeElements = themeRoot?.["a:themeElements"];
38369
40504
  const colorScheme = themeElements?.["a:clrScheme"];
38370
40505
  const fontScheme = themeElements?.["a:fontScheme"];
40506
+ const fmtScheme = themeElements?.["a:fmtScheme"];
40507
+ const themeName = String(themeRoot?.["@_name"] || "").trim();
40508
+ if (themeName) {
40509
+ this.masterThemeNames.set(themePath, themeName);
40510
+ }
40511
+ const colorSchemeName = String(colorScheme?.["@_name"] || "").trim();
40512
+ if (colorSchemeName) {
40513
+ this.masterThemeColorSchemeNames.set(themePath, colorSchemeName);
40514
+ }
40515
+ const fontSchemeName = String(fontScheme?.["@_name"] || "").trim();
40516
+ if (fontSchemeName) {
40517
+ this.masterThemeFontSchemeNames.set(themePath, fontSchemeName);
40518
+ }
38371
40519
  const defaultMap = this.getDefaultSchemeColorMap();
38372
- this.themeColorMap = { ...defaultMap };
40520
+ const colorMap = { ...defaultMap };
38373
40521
  if (colorScheme) {
38374
40522
  const schemeKeys = [
38375
40523
  "dk1",
@@ -38389,39 +40537,196 @@ var PptxHandlerRuntime59 = class extends PptxHandlerRuntime58 {
38389
40537
  const colorNode = colorScheme[`a:${key}`];
38390
40538
  const parsed = this.parseColorChoice(colorNode);
38391
40539
  if (parsed) {
38392
- this.themeColorMap[key] = parsed;
40540
+ colorMap[key] = parsed;
38393
40541
  }
38394
40542
  }
38395
40543
  }
38396
- this.themeColorMap["tx1"] = this.themeColorMap["dk1"] || defaultMap["dk1"];
38397
- this.themeColorMap["bg1"] = this.themeColorMap["lt1"] || defaultMap["lt1"];
38398
- this.themeColorMap["tx2"] = this.themeColorMap["dk2"] || defaultMap["dk2"];
38399
- this.themeColorMap["bg2"] = this.themeColorMap["lt2"] || defaultMap["lt2"];
38400
- await this.applySlideMasterColorMap(defaultMap);
38401
- const majorLatin = fontScheme?.["a:majorFont"]?.["a:latin"];
38402
- const minorLatin = fontScheme?.["a:minorFont"]?.["a:latin"];
40544
+ colorMap["tx1"] = colorMap["dk1"] || defaultMap["dk1"];
40545
+ colorMap["bg1"] = colorMap["lt1"] || defaultMap["lt1"];
40546
+ colorMap["tx2"] = colorMap["dk2"] || defaultMap["dk2"];
40547
+ colorMap["bg2"] = colorMap["lt2"] || defaultMap["lt2"];
40548
+ const majorFontNode = fontScheme?.["a:majorFont"];
40549
+ const minorFontNode = fontScheme?.["a:minorFont"];
40550
+ const majorLatin = majorFontNode?.["a:latin"];
40551
+ const minorLatin = minorFontNode?.["a:latin"];
38403
40552
  const majorFont = this.normalizeTypefaceToken(String(majorLatin?.["@_typeface"] || ""));
38404
40553
  const minorFont = this.normalizeTypefaceToken(String(minorLatin?.["@_typeface"] || ""));
38405
- this.themeFontMap = {};
40554
+ const fontMap = {};
38406
40555
  if (majorFont) {
38407
- this.themeFontMap["mj-lt"] = majorFont;
38408
- this.themeFontMap["mj-ea"] = majorFont;
38409
- this.themeFontMap["mj-cs"] = majorFont;
40556
+ fontMap["mj-lt"] = majorFont;
40557
+ fontMap["mj-ea"] = majorFont;
40558
+ fontMap["mj-cs"] = majorFont;
38410
40559
  }
38411
40560
  if (minorFont) {
38412
- this.themeFontMap["mn-lt"] = minorFont;
38413
- this.themeFontMap["mn-ea"] = minorFont;
38414
- this.themeFontMap["mn-cs"] = minorFont;
40561
+ fontMap["mn-lt"] = minorFont;
40562
+ fontMap["mn-ea"] = minorFont;
40563
+ fontMap["mn-cs"] = minorFont;
38415
40564
  }
38416
- const fmtScheme = themeElements?.["a:fmtScheme"];
38417
- if (fmtScheme) {
38418
- this.themeFormatScheme = this.parseFormatScheme(fmtScheme);
40565
+ const majorEa = this.normalizeTypefaceToken(
40566
+ String(majorFontNode?.["a:ea"]?.["@_typeface"] || "")
40567
+ );
40568
+ if (majorEa) {
40569
+ fontMap["mj-ea"] = majorEa;
40570
+ }
40571
+ const majorCs = this.normalizeTypefaceToken(
40572
+ String(majorFontNode?.["a:cs"]?.["@_typeface"] || "")
40573
+ );
40574
+ if (majorCs) {
40575
+ fontMap["mj-cs"] = majorCs;
40576
+ }
40577
+ const minorEa = this.normalizeTypefaceToken(
40578
+ String(minorFontNode?.["a:ea"]?.["@_typeface"] || "")
40579
+ );
40580
+ if (minorEa) {
40581
+ fontMap["mn-ea"] = minorEa;
40582
+ }
40583
+ const minorCs = this.normalizeTypefaceToken(
40584
+ String(minorFontNode?.["a:cs"]?.["@_typeface"] || "")
40585
+ );
40586
+ if (minorCs) {
40587
+ fontMap["mn-cs"] = minorCs;
40588
+ }
40589
+ const majorScripts = this.collectFontScriptOverrides(majorFontNode);
40590
+ if (Object.keys(majorScripts).length > 0) {
40591
+ this.masterThemeMajorFontScripts.set(themePath, majorScripts);
40592
+ }
40593
+ const minorScripts = this.collectFontScriptOverrides(minorFontNode);
40594
+ if (Object.keys(minorScripts).length > 0) {
40595
+ this.masterThemeMinorFontScripts.set(themePath, minorScripts);
40596
+ }
40597
+ const objectDefaultsNode = themeRoot?.["a:objectDefaults"];
40598
+ if (objectDefaultsNode) {
40599
+ const od = {
40600
+ spDef: objectDefaultsNode["a:spDef"],
40601
+ lnDef: objectDefaultsNode["a:lnDef"],
40602
+ txDef: objectDefaultsNode["a:txDef"]
40603
+ };
40604
+ if (od.spDef !== void 0 || od.lnDef !== void 0 || od.txDef !== void 0) {
40605
+ this.masterThemeObjectDefaults.set(themePath, od);
40606
+ }
40607
+ }
40608
+ const extraClrSchemeLst = themeRoot?.["a:extraClrSchemeLst"];
40609
+ if (extraClrSchemeLst !== void 0) {
40610
+ this.masterThemeExtraClrSchemeLst.set(themePath, extraClrSchemeLst);
40611
+ }
40612
+ const custClrLst = themeRoot?.["a:custClrLst"];
40613
+ if (custClrLst !== void 0) {
40614
+ this.masterThemeCustClrLst.set(themePath, custClrLst);
40615
+ }
40616
+ const themeExtLst = themeRoot?.["a:extLst"];
40617
+ if (themeExtLst !== void 0) {
40618
+ this.masterThemeExtLst.set(themePath, themeExtLst);
40619
+ }
40620
+ const formatScheme = fmtScheme ? this.parseFormatScheme(fmtScheme) : void 0;
40621
+ return { colorMap, fontMap, formatScheme };
40622
+ }
40623
+ /**
40624
+ * Parse `<a:font script="…" typeface="…"/>` children of a major or
40625
+ * minor font node into a `script -> typeface` dictionary.
40626
+ *
40627
+ * fast-xml-parser collapses repeated tags into arrays, so iterate
40628
+ * over the array form regardless of how many siblings are present.
40629
+ *
40630
+ * Phase 4 Stream A / M4.
40631
+ */
40632
+ collectFontScriptOverrides(fontNode) {
40633
+ const overrides = {};
40634
+ if (!fontNode) {
40635
+ return overrides;
40636
+ }
40637
+ const fontEntries = this.ensureArray(fontNode["a:font"]);
40638
+ for (const entry of fontEntries) {
40639
+ const script = String(entry?.["@_script"] || "").trim();
40640
+ const typeface = this.normalizeTypefaceToken(String(entry?.["@_typeface"] || ""));
40641
+ if (script && typeface) {
40642
+ overrides[script] = typeface;
40643
+ }
40644
+ }
40645
+ return overrides;
40646
+ }
40647
+ /**
40648
+ * Resolve the theme file path referenced by a given master's `.rels`.
40649
+ * Returns `undefined` when the master has no theme relationship.
40650
+ */
40651
+ async resolveThemePathForMaster(masterPath) {
40652
+ const relsPath = masterPath.replace(
40653
+ /ppt\/slideMasters\/(slideMaster\d+)\.xml/,
40654
+ "ppt/slideMasters/_rels/$1.xml.rels"
40655
+ );
40656
+ const relsXml = this.zip.file(relsPath);
40657
+ if (!relsXml) {
40658
+ return void 0;
40659
+ }
40660
+ const relsData = this.parser.parse(await relsXml.async("string"));
40661
+ const relNodes = this.ensureArray(relsData?.Relationships?.Relationship);
40662
+ for (const rel of relNodes) {
40663
+ const target = String(rel["@_Target"] || "");
40664
+ if (!target.includes("theme")) {
40665
+ continue;
40666
+ }
40667
+ const themePath = target.startsWith("..") ? this.resolvePath(masterPath.substring(0, masterPath.lastIndexOf("/") + 1), target) : target.startsWith("/") ? target.slice(1) : `ppt/${target.replace(/^\.?\//, "")}`;
40668
+ if (themePath.startsWith("ppt/theme/")) {
40669
+ return themePath;
40670
+ }
40671
+ }
40672
+ return void 0;
40673
+ }
40674
+ /**
40675
+ * Populate {@link masterThemeColorMaps}, {@link masterThemeFontMaps},
40676
+ * and {@link masterThemeFormatSchemes} for every slide master in the
40677
+ * deck. Multi-master support — Phase 2 Stream B / C-H4.
40678
+ */
40679
+ async loadPerMasterThemes() {
40680
+ const masterFiles = this.zip.file(/^ppt\/slideMasters\/slideMaster\d+\.xml$/);
40681
+ if (!masterFiles || masterFiles.length === 0) {
40682
+ return;
40683
+ }
40684
+ for (const file of masterFiles) {
40685
+ try {
40686
+ const themePath = await this.resolveThemePathForMaster(file.name);
40687
+ if (!themePath) {
40688
+ continue;
40689
+ }
40690
+ this.masterThemePaths.set(file.name, themePath);
40691
+ const parsed = await this.parseThemePart(themePath);
40692
+ if (!parsed) {
40693
+ continue;
40694
+ }
40695
+ this.masterThemeColorMaps.set(file.name, parsed.colorMap);
40696
+ this.masterThemeFontMaps.set(file.name, parsed.fontMap);
40697
+ if (parsed.formatScheme) {
40698
+ this.masterThemeFormatSchemes.set(file.name, parsed.formatScheme);
40699
+ }
40700
+ } catch (error) {
40701
+ console.warn(`Failed to load per-master theme for ${file.name}:`, error);
40702
+ }
40703
+ }
40704
+ }
40705
+ async loadThemeData() {
40706
+ const themeFiles = this.zip.file(/^ppt\/theme\/theme\d+\.xml$/);
40707
+ if (!themeFiles || themeFiles.length === 0) {
40708
+ return;
38419
40709
  }
40710
+ const preferredThemePath = await this.resolvePrimaryThemePath();
40711
+ const themeFile = preferredThemePath ? themeFiles.find((file) => file.name === preferredThemePath) ?? themeFiles[0] : themeFiles[0];
40712
+ const parsed = await this.parseThemePart(themeFile.name);
40713
+ if (parsed) {
40714
+ this.themeColorMap = parsed.colorMap;
40715
+ this.themeFontMap = parsed.fontMap;
40716
+ if (parsed.formatScheme) {
40717
+ this.themeFormatScheme = parsed.formatScheme;
40718
+ }
40719
+ }
40720
+ await this.applySlideMasterColorMap(this.getDefaultSchemeColorMap());
40721
+ await this.loadPerMasterThemes();
40722
+ this.globalThemeColorMapSnapshot = { ...this.themeColorMap };
40723
+ this.globalThemeFontMapSnapshot = { ...this.themeFontMap };
40724
+ this.globalThemeFormatSchemeSnapshot = this.themeFormatScheme;
38420
40725
  }
38421
40726
  };
38422
40727
 
38423
40728
  // src/core/core/runtime/PptxHandlerRuntimeThemeProcessing.ts
38424
- var PptxHandlerRuntime60 = class extends PptxHandlerRuntime59 {
40729
+ var PptxHandlerRuntime61 = class extends PptxHandlerRuntime60 {
38425
40730
  // ---------------------------------------------------------------------------
38426
40731
  // Theme editing — update colour scheme, font scheme, and name in the zip
38427
40732
  // ---------------------------------------------------------------------------
@@ -38571,7 +40876,7 @@ var PptxHandlerRuntime60 = class extends PptxHandlerRuntime59 {
38571
40876
  };
38572
40877
 
38573
40878
  // src/core/core/runtime/PptxHandlerRuntimeComments.ts
38574
- var PptxHandlerRuntime61 = class _PptxHandlerRuntime extends PptxHandlerRuntime60 {
40879
+ var PptxHandlerRuntime62 = class _PptxHandlerRuntime extends PptxHandlerRuntime61 {
38575
40880
  /**
38576
40881
  * Parse modern threaded comments (PowerPoint 2019+ / Office 365).
38577
40882
  * Modern comments use `p188:cmLst`/`p15:cmLst` roots within
@@ -38804,7 +41109,7 @@ var PptxHandlerRuntime61 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
38804
41109
  };
38805
41110
 
38806
41111
  // src/core/core/runtime/PptxHandlerRuntimeSmartArtXmlUtils.ts
38807
- var PptxHandlerRuntime62 = class extends PptxHandlerRuntime61 {
41112
+ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
38808
41113
  async readXmlPartByRelationshipId(slidePath, relationshipId) {
38809
41114
  const normalizedRelationshipId = String(relationshipId || "").trim();
38810
41115
  if (normalizedRelationshipId.length === 0) {
@@ -38959,7 +41264,7 @@ var PptxHandlerRuntime62 = class extends PptxHandlerRuntime61 {
38959
41264
  };
38960
41265
 
38961
41266
  // src/core/core/runtime/PptxHandlerRuntimeSmartArtParsing.ts
38962
- var PptxHandlerRuntime63 = class _PptxHandlerRuntime extends PptxHandlerRuntime62 {
41267
+ var PptxHandlerRuntime64 = class _PptxHandlerRuntime extends PptxHandlerRuntime63 {
38963
41268
  /**
38964
41269
  * Parse quick style from `ppt/diagrams/quickStyles*.xml`.
38965
41270
  */
@@ -39118,7 +41423,7 @@ var PptxHandlerRuntime63 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
39118
41423
  };
39119
41424
 
39120
41425
  // src/core/core/runtime/PptxHandlerRuntimeSmartArt.ts
39121
- var PptxHandlerRuntime64 = class extends PptxHandlerRuntime63 {
41426
+ var PptxHandlerRuntime65 = class _PptxHandlerRuntime extends PptxHandlerRuntime64 {
39122
41427
  async getSmartArtDataForGraphicFrame(slidePath, graphicFrame) {
39123
41428
  const graphicData = this.xmlLookupService.getChildByLocalName(
39124
41429
  this.xmlLookupService.getChildByLocalName(graphicFrame, "graphic"),
@@ -39169,10 +41474,14 @@ var PptxHandlerRuntime64 = class extends PptxHandlerRuntime63 {
39169
41474
  const layoutPart = layoutRelationshipId.length > 0 ? await this.readXmlPartByRelationshipId(slidePath, layoutRelationshipId) : void 0;
39170
41475
  const layoutType = layoutPart?.partPath?.split("/").pop()?.replace(/\.[^.]+$/, "") || void 0;
39171
41476
  const chrome = this.parseSmartArtChrome(dataModel);
39172
- const drawingRelationshipId = String(relationshipIds["@_r:cs"] || "").trim();
39173
- const drawingShapes = await this.parseSmartArtDrawingShapes(slidePath, drawingRelationshipId);
39174
41477
  const colorsRelationshipId = String(relationshipIds["@_r:cs"] || "").trim();
39175
41478
  const colorTransform = await this.parseSmartArtColorTransform(slidePath, colorsRelationshipId);
41479
+ const drawingResolution = await this.resolveSmartArtDrawingPart(
41480
+ slidePath,
41481
+ diagramDataRelationshipId
41482
+ );
41483
+ const drawingShapes = drawingResolution ? await this.parseSmartArtDrawingShapesFromPath(drawingResolution.path) : [];
41484
+ const drawingRelationshipId = drawingResolution?.relId;
39176
41485
  const styleRelationshipId = String(relationshipIds["@_r:qs"] || "").trim();
39177
41486
  const quickStyle = await this.parseSmartArtQuickStyle(slidePath, styleRelationshipId);
39178
41487
  return {
@@ -39184,11 +41493,87 @@ var PptxHandlerRuntime64 = class extends PptxHandlerRuntime63 {
39184
41493
  colorTransform,
39185
41494
  quickStyle,
39186
41495
  dataRelId: diagramDataRelationshipId,
39187
- drawingRelId: drawingRelationshipId.length > 0 ? drawingRelationshipId : void 0,
41496
+ drawingRelId: drawingRelationshipId && drawingRelationshipId.length > 0 ? drawingRelationshipId : void 0,
39188
41497
  colorsRelId: colorsRelationshipId.length > 0 ? colorsRelationshipId : void 0,
39189
41498
  styleRelId: styleRelationshipId.length > 0 ? styleRelationshipId : void 0
39190
41499
  };
39191
41500
  }
41501
+ /**
41502
+ * Resolve the SmartArt drawing-shapes part path + relationship id.
41503
+ *
41504
+ * Strategy:
41505
+ * 1. Locate the data-model part's rels file
41506
+ * (`ppt/diagrams/_rels/data*.xml.rels`) via `slideRelsMap`.
41507
+ * 2. Find a relationship whose `Type` matches the `…/diagramDrawing`
41508
+ * URI. PowerPoint emits this for any deck that has had its
41509
+ * SmartArt rendered to drawing shapes.
41510
+ * 3. Return the matched part path (so the caller can load it
41511
+ * directly) and the relationship id (for round-trip preservation).
41512
+ */
41513
+ async resolveSmartArtDrawingPart(slidePath, diagramDataRelationshipId) {
41514
+ if (diagramDataRelationshipId.length === 0) {
41515
+ return void 0;
41516
+ }
41517
+ const slideRels = this.slideRelsMap.get(slidePath);
41518
+ const dataTarget = slideRels?.get(diagramDataRelationshipId);
41519
+ if (!dataTarget) {
41520
+ return void 0;
41521
+ }
41522
+ const dataPath = this.resolveImagePath(slidePath, dataTarget);
41523
+ const dataDir = dataPath.replace(/\/[^/]+$/, "");
41524
+ const dataFile = dataPath.split("/").pop() ?? "";
41525
+ const dataRelsPath = `${dataDir}/_rels/${dataFile}.rels`;
41526
+ const relsXml = await this.zip.file(dataRelsPath)?.async("string");
41527
+ if (!relsXml) {
41528
+ return void 0;
41529
+ }
41530
+ try {
41531
+ const parsed = this.parser.parse(relsXml);
41532
+ const relsRoot = parsed["Relationships"];
41533
+ if (!relsRoot) {
41534
+ return void 0;
41535
+ }
41536
+ const rels = this.ensureArray(relsRoot["Relationship"]);
41537
+ const drawingRel = rels.find(
41538
+ (rel) => String(rel?.["@_Type"] || "").endsWith("/diagramDrawing")
41539
+ );
41540
+ const id = String(drawingRel?.["@_Id"] || "").trim();
41541
+ const target = String(drawingRel?.["@_Target"] || "").trim();
41542
+ if (id.length === 0 || target.length === 0) {
41543
+ return void 0;
41544
+ }
41545
+ const drawingPath = this.resolveImagePath(dataPath, target);
41546
+ return { relId: id, path: drawingPath };
41547
+ } catch {
41548
+ return void 0;
41549
+ }
41550
+ }
41551
+ /**
41552
+ * Parse SmartArt drawing shapes given an absolute part path.
41553
+ *
41554
+ * Wraps `parseSmartArtDrawingShapes` (which expects a slide-relative
41555
+ * relationship id) with a path-based lookup so the resolution layer
41556
+ * can pull the part from anywhere in the package.
41557
+ */
41558
+ async parseSmartArtDrawingShapesFromPath(drawingPath) {
41559
+ const xmlString = await this.zip.file(drawingPath)?.async("string");
41560
+ if (!xmlString) {
41561
+ return [];
41562
+ }
41563
+ try {
41564
+ const xml = this.parser.parse(xmlString);
41565
+ const drawing = this.xmlLookupService.getChildByLocalName(xml, "drawing");
41566
+ const spTree = this.xmlLookupService.getChildByLocalName(drawing || xml, "spTree");
41567
+ if (!spTree) {
41568
+ return [];
41569
+ }
41570
+ const shapes = this.xmlLookupService.getChildrenArrayByLocalName(spTree, "sp");
41571
+ const emuPerPx = _PptxHandlerRuntime.EMU_PER_PX;
41572
+ return shapes.map((sp, index) => this.parseDrawingShape(sp, index, emuPerPx)).filter((entry) => entry !== null);
41573
+ } catch {
41574
+ return [];
41575
+ }
41576
+ }
39192
41577
  parseSmartArtConnections(dataModel) {
39193
41578
  const connectionList = this.xmlLookupService.getChildByLocalName(dataModel, "cxnLst");
39194
41579
  const rawConnections = this.xmlLookupService.getChildrenArrayByLocalName(connectionList, "cxn");
@@ -39219,7 +41604,7 @@ var PptxHandlerRuntime64 = class extends PptxHandlerRuntime63 {
39219
41604
  };
39220
41605
 
39221
41606
  // src/core/core/runtime/PptxHandlerRuntimeChartDetection.ts
39222
- var PptxHandlerRuntime65 = class extends PptxHandlerRuntime64 {
41607
+ var PptxHandlerRuntime66 = class extends PptxHandlerRuntime65 {
39223
41608
  detectChartType(plotArea) {
39224
41609
  if (!plotArea) {
39225
41610
  return "unknown";
@@ -39328,7 +41713,7 @@ var PptxHandlerRuntime65 = class extends PptxHandlerRuntime64 {
39328
41713
  };
39329
41714
 
39330
41715
  // src/core/core/runtime/PptxHandlerRuntimeChartParsingHelpers.ts
39331
- var PptxHandlerRuntime66 = class extends PptxHandlerRuntime65 {
41716
+ var PptxHandlerRuntime67 = class extends PptxHandlerRuntime66 {
39332
41717
  /**
39333
41718
  * Parse `c:plotVisOnly` from the chart root element.
39334
41719
  *
@@ -39389,7 +41774,7 @@ var PptxHandlerRuntime66 = class extends PptxHandlerRuntime65 {
39389
41774
  };
39390
41775
 
39391
41776
  // src/core/core/runtime/PptxHandlerRuntimeChartExternalData.ts
39392
- var PptxHandlerRuntime67 = class extends PptxHandlerRuntime66 {
41777
+ var PptxHandlerRuntime68 = class extends PptxHandlerRuntime67 {
39393
41778
  /**
39394
41779
  * Parse `c:externalData` from the chart's `c:chartSpace` and resolve
39395
41780
  * the external relationship target from the chart part's .rels file.
@@ -39505,7 +41890,7 @@ var PptxHandlerRuntime67 = class extends PptxHandlerRuntime66 {
39505
41890
  };
39506
41891
 
39507
41892
  // src/core/core/runtime/PptxHandlerRuntimeChartColorStyle.ts
39508
- var PptxHandlerRuntime68 = class extends PptxHandlerRuntime67 {
41893
+ var PptxHandlerRuntime69 = class extends PptxHandlerRuntime68 {
39509
41894
  /**
39510
41895
  * Parse the Office 2013+ chart color style part (`chartColorStyle*.xml`)
39511
41896
  * referenced from the chart's relationships.
@@ -39612,7 +41997,7 @@ var PptxHandlerRuntime68 = class extends PptxHandlerRuntime67 {
39612
41997
  };
39613
41998
 
39614
41999
  // src/core/core/runtime/PptxHandlerRuntimeChartParsing.ts
39615
- var PptxHandlerRuntime69 = class extends PptxHandlerRuntime68 {
42000
+ var PptxHandlerRuntime70 = class extends PptxHandlerRuntime69 {
39616
42001
  /**
39617
42002
  * Parse chart data from a graphic frame element on a slide.
39618
42003
  *
@@ -39859,7 +42244,7 @@ var PptxHandlerRuntime69 = class extends PptxHandlerRuntime68 {
39859
42244
  };
39860
42245
 
39861
42246
  // src/core/core/runtime/PptxHandlerRuntimePresentationStructure.ts
39862
- var PptxHandlerRuntime70 = class extends PptxHandlerRuntime69 {
42247
+ var PptxHandlerRuntime71 = class extends PptxHandlerRuntime70 {
39863
42248
  parseEditorAnimations(slideXml2) {
39864
42249
  return this.editorAnimationService.parseEditorAnimations(slideXml2);
39865
42250
  }
@@ -40104,7 +42489,7 @@ var PptxHandlerRuntime70 = class extends PptxHandlerRuntime69 {
40104
42489
  };
40105
42490
 
40106
42491
  // src/core/core/runtime/PptxHandlerRuntimeEmbeddedFonts.ts
40107
- var PptxHandlerRuntime71 = class extends PptxHandlerRuntime70 {
42492
+ var PptxHandlerRuntime72 = class extends PptxHandlerRuntime71 {
40108
42493
  async getEmbeddedFonts() {
40109
42494
  const embeddedFontEntries = this.ensureArray(
40110
42495
  this.presentationData?.["p:presentation"]?.["p:embeddedFontLst"]?.["p:embeddedFont"]
@@ -40276,7 +42661,7 @@ var PptxHandlerRuntime71 = class extends PptxHandlerRuntime70 {
40276
42661
  };
40277
42662
 
40278
42663
  // src/core/core/runtime/PptxHandlerRuntimeLoadSession.ts
40279
- var PptxHandlerRuntime72 = class _PptxHandlerRuntime extends PptxHandlerRuntime71 {
42664
+ var PptxHandlerRuntime73 = class _PptxHandlerRuntime extends PptxHandlerRuntime72 {
40280
42665
  isZipContainer(data) {
40281
42666
  const bytes = new Uint8Array(data);
40282
42667
  if (bytes.byteLength < 4) {
@@ -40319,6 +42704,23 @@ var PptxHandlerRuntime72 = class _PptxHandlerRuntime extends PptxHandlerRuntime7
40319
42704
  this.imageDataCache.clear();
40320
42705
  this.themeColorMap = {};
40321
42706
  this.themeFontMap = {};
42707
+ this.masterClrMaps.clear();
42708
+ this.masterThemeColorMaps.clear();
42709
+ this.masterThemeFontMaps.clear();
42710
+ this.masterThemeFormatSchemes.clear();
42711
+ this.masterThemePaths.clear();
42712
+ this.masterThemeMajorFontScripts.clear();
42713
+ this.masterThemeMinorFontScripts.clear();
42714
+ this.masterThemeNames.clear();
42715
+ this.masterThemeFontSchemeNames.clear();
42716
+ this.masterThemeColorSchemeNames.clear();
42717
+ this.originalThemeXmlByPath.clear();
42718
+ this.dirtyThemePaths.clear();
42719
+ this.masterThemeObjectDefaults.clear();
42720
+ this.masterThemeExtraClrSchemeLst.clear();
42721
+ this.masterThemeCustClrLst.clear();
42722
+ this.masterThemeExtLst.clear();
42723
+ this.currentMasterClrMap = null;
40322
42724
  this.presentationDefaultTextStyle = void 0;
40323
42725
  this.commentAuthorMap.clear();
40324
42726
  this.commentAuthorDetails.clear();
@@ -40473,6 +42875,7 @@ var PptxHandlerRuntime72 = class _PptxHandlerRuntime extends PptxHandlerRuntime7
40473
42875
  setCurrentSlideClrMapOverride: (override) => {
40474
42876
  this.currentSlideClrMapOverride = override;
40475
42877
  },
42878
+ setActiveMasterForSlide: (slidePath) => this.setActiveMasterForSlide(slidePath),
40476
42879
  findLayoutPathForSlide: (slidePath) => this.findLayoutPathForSlide(slidePath),
40477
42880
  loadThemeOverride: (partBasePath) => this.loadThemeOverride(partBasePath),
40478
42881
  applyThemeOverrideState: (override) => this.applyThemeOverrideState(override),
@@ -40503,7 +42906,7 @@ var PptxHandlerRuntime72 = class _PptxHandlerRuntime extends PptxHandlerRuntime7
40503
42906
  };
40504
42907
 
40505
42908
  // src/core/core/runtime/PptxHandlerRuntimeLoadPipeline.ts
40506
- var PptxHandlerRuntime73 = class extends PptxHandlerRuntime72 {
42909
+ var PptxHandlerRuntime74 = class extends PptxHandlerRuntime73 {
40507
42910
  async buildLoadData(presentationState, slidesWithWarnings) {
40508
42911
  const headerFooter = this.extractHeaderFooter();
40509
42912
  const presentationProperties = await this.parsePresentationProperties();
@@ -40515,6 +42918,7 @@ var PptxHandlerRuntime73 = class extends PptxHandlerRuntime72 {
40515
42918
  const notesMaster = await this.parseNotesMaster();
40516
42919
  const handoutMaster = await this.parseHandoutMaster();
40517
42920
  const slideMasters = await this.parseSlideMasters();
42921
+ await this.enrichSlideMastersWithTxStyles(slideMasters);
40518
42922
  const tags = await this.parseTags();
40519
42923
  const customProperties = await this.parseCustomProperties();
40520
42924
  const coreProperties = await this.parseCoreProperties();
@@ -40849,7 +43253,7 @@ var PptxHandlerRuntime73 = class extends PptxHandlerRuntime72 {
40849
43253
  };
40850
43254
 
40851
43255
  // src/core/core/runtime/PptxHandlerRuntimeImplementation.ts
40852
- var PptxHandlerRuntime74 = class _PptxHandlerRuntime extends PptxHandlerRuntime73 {
43256
+ var PptxHandlerRuntime75 = class _PptxHandlerRuntime extends PptxHandlerRuntime74 {
40853
43257
  constructor(dependencyFactory = new PptxRuntimeDependencyFactory()) {
40854
43258
  super();
40855
43259
  this.dependencyFactory = dependencyFactory;
@@ -40897,6 +43301,9 @@ var PptxHandlerRuntime74 = class _PptxHandlerRuntime extends PptxHandlerRuntime7
40897
43301
  extractGradientPathType: (gradFill) => this.colorStyleCodec.extractGradientPathType(gradFill),
40898
43302
  extractGradientFocalPoint: (gradFill) => this.colorStyleCodec.extractGradientFocalPoint(gradFill),
40899
43303
  extractGradientFillToRect: (gradFill) => this.colorStyleCodec.extractGradientFillToRect(gradFill),
43304
+ extractGradientFlip: (gradFill) => this.colorStyleCodec.extractGradientFlip(gradFill),
43305
+ extractGradientRotWithShape: (gradFill) => this.colorStyleCodec.extractGradientRotWithShape(gradFill),
43306
+ extractGradientScaled: (gradFill) => this.colorStyleCodec.extractGradientScaled(gradFill),
40900
43307
  normalizeStrokeDashType: (value) => this.normalizeStrokeDashType(value),
40901
43308
  normalizeConnectorArrowType: (value) => this.normalizeConnectorArrowType(value),
40902
43309
  ensureArray: (value) => this.ensureArray(value),
@@ -40970,7 +43377,7 @@ var PptxHandlerRuntime74 = class _PptxHandlerRuntime extends PptxHandlerRuntime7
40970
43377
  };
40971
43378
 
40972
43379
  // src/core/core/PptxHandlerRuntime.ts
40973
- var PptxHandlerRuntime75 = class extends PptxHandlerRuntime74 {
43380
+ var PptxHandlerRuntime76 = class extends PptxHandlerRuntime75 {
40974
43381
  };
40975
43382
 
40976
43383
  // src/core/core/PptxHandlerRuntimeFactory.ts
@@ -40981,10 +43388,10 @@ var PptxHandlerRuntimeFactory = class {
40981
43388
  * @returns A freshly constructed runtime ready for loading a PPTX file.
40982
43389
  */
40983
43390
  createRuntime() {
40984
- return new PptxHandlerRuntime75();
43391
+ return new PptxHandlerRuntime76();
40985
43392
  }
40986
43393
  };
40987
- var createDefaultPptxHandlerRuntime = () => new PptxHandlerRuntime75();
43394
+ var createDefaultPptxHandlerRuntime = () => new PptxHandlerRuntime76();
40988
43395
 
40989
43396
  // src/core/PptxHandlerCore.ts
40990
43397
  var PptxHandlerCore = class {
@@ -42354,10 +44761,12 @@ function getConnectorPathGeometry(element) {
42354
44761
  const height = Math.max(element.height, 1);
42355
44762
  const normalizedType = (element.shapeType || "").toLowerCase();
42356
44763
  const point = (x, y) => `${Math.round(x)} ${Math.round(y)}`;
42357
- const startX = 0;
42358
- const startY = 0;
42359
- const endX = width;
42360
- const endY = height;
44764
+ const flipH = Boolean(element.flipHorizontal);
44765
+ const flipV = Boolean(element.flipVertical);
44766
+ const startX = flipH ? width : 0;
44767
+ const startY = flipV ? height : 0;
44768
+ const endX = flipH ? 0 : width;
44769
+ const endY = flipV ? 0 : height;
42361
44770
  if (normalizedType.includes("bentconnector5")) {
42362
44771
  const adj1 = getConnectorAdjustment(element, "adj1", 0.5);
42363
44772
  const adj2 = getConnectorAdjustment(element, "adj2", 0.5);
@@ -42370,7 +44779,7 @@ function getConnectorPathGeometry(element) {
42370
44779
  startY,
42371
44780
  endX,
42372
44781
  endY,
42373
- pathData: `M ${point(0, 0)} L ${point(x1, 0)} L ${point(x1, yMid)} L ${point(x2, yMid)} L ${point(x2, height)} L ${point(width, height)}`
44782
+ pathData: `M ${point(startX, startY)} L ${point(x1, startY)} L ${point(x1, yMid)} L ${point(x2, yMid)} L ${point(x2, endY)} L ${point(endX, endY)}`
42374
44783
  };
42375
44784
  }
42376
44785
  if (normalizedType.includes("bentconnector4")) {
@@ -42383,7 +44792,7 @@ function getConnectorPathGeometry(element) {
42383
44792
  startY,
42384
44793
  endX,
42385
44794
  endY,
42386
- pathData: `M ${point(0, 0)} L ${point(midX, 0)} L ${point(midX, midY)} L ${point(width, midY)} L ${point(width, height)}`
44795
+ pathData: `M ${point(startX, startY)} L ${point(midX, startY)} L ${point(midX, midY)} L ${point(endX, midY)} L ${point(endX, endY)}`
42387
44796
  };
42388
44797
  }
42389
44798
  if (normalizedType.includes("bentconnector3")) {
@@ -42394,7 +44803,7 @@ function getConnectorPathGeometry(element) {
42394
44803
  startY,
42395
44804
  endX,
42396
44805
  endY,
42397
- pathData: `M ${point(0, 0)} L ${point(midX, 0)} L ${point(midX, height)} L ${point(width, height)}`
44806
+ pathData: `M ${point(startX, startY)} L ${point(midX, startY)} L ${point(midX, endY)} L ${point(endX, endY)}`
42398
44807
  };
42399
44808
  }
42400
44809
  if (normalizedType.includes("bentconnector2")) {
@@ -42403,7 +44812,7 @@ function getConnectorPathGeometry(element) {
42403
44812
  startY,
42404
44813
  endX,
42405
44814
  endY,
42406
- pathData: `M ${point(0, 0)} L ${point(width, 0)} L ${point(width, height)}`
44815
+ pathData: `M ${point(startX, startY)} L ${point(endX, startY)} L ${point(endX, endY)}`
42407
44816
  };
42408
44817
  }
42409
44818
  if (normalizedType.includes("curvedconnector5")) {
@@ -42413,12 +44822,14 @@ function getConnectorPathGeometry(element) {
42413
44822
  const x1 = width * adj1;
42414
44823
  const yMid = height * adj2;
42415
44824
  const x2 = width * adj3;
44825
+ const yQuarter = startY + (yMid - startY) * 0.5;
44826
+ const yThreeQ = yMid + (endY - yMid) * 0.5;
42416
44827
  return {
42417
44828
  startX,
42418
44829
  startY,
42419
44830
  endX,
42420
44831
  endY,
42421
- pathData: `M ${point(0, 0)} C ${point(x1, 0)} ${point(x1, 0)} ${point(x1, yMid * 0.5)} C ${point(x1, yMid)} ${point(x1, yMid)} ${point((x1 + x2) / 2, yMid)} C ${point(x2, yMid)} ${point(x2, yMid)} ${point(x2, (yMid + height) / 2)} C ${point(x2, height)} ${point(x2, height)} ${point(width, height)}`
44832
+ pathData: `M ${point(startX, startY)} C ${point(x1, startY)} ${point(x1, startY)} ${point(x1, yQuarter)} C ${point(x1, yMid)} ${point(x1, yMid)} ${point((x1 + x2) / 2, yMid)} C ${point(x2, yMid)} ${point(x2, yMid)} ${point(x2, yThreeQ)} C ${point(x2, endY)} ${point(x2, endY)} ${point(endX, endY)}`
42422
44833
  };
42423
44834
  }
42424
44835
  if (normalizedType.includes("curvedconnector4")) {
@@ -42426,12 +44837,13 @@ function getConnectorPathGeometry(element) {
42426
44837
  const adj2 = getConnectorAdjustment(element, "adj2", 0.5);
42427
44838
  const midX = width * adj1;
42428
44839
  const midY = height * adj2;
44840
+ const yQuarter = startY + (midY - startY) * 0.5;
42429
44841
  return {
42430
44842
  startX,
42431
44843
  startY,
42432
44844
  endX,
42433
44845
  endY,
42434
- pathData: `M ${point(0, 0)} C ${point(midX, 0)} ${point(midX, 0)} ${point(midX, midY * 0.5)} C ${point(midX, midY)} ${point(midX, midY)} ${point((midX + width) / 2, midY)} C ${point(width, midY)} ${point(width, midY)} ${point(width, height)}`
44846
+ pathData: `M ${point(startX, startY)} C ${point(midX, startY)} ${point(midX, startY)} ${point(midX, yQuarter)} C ${point(midX, midY)} ${point(midX, midY)} ${point((midX + endX) / 2, midY)} C ${point(endX, midY)} ${point(endX, midY)} ${point(endX, endY)}`
42435
44847
  };
42436
44848
  }
42437
44849
  if (normalizedType.includes("curvedconnector3")) {
@@ -42443,7 +44855,7 @@ function getConnectorPathGeometry(element) {
42443
44855
  startY,
42444
44856
  endX,
42445
44857
  endY,
42446
- pathData: `M ${point(0, 0)} C ${point(midX, 0)} ${point(midX, 0)} ${point(midX, midY)} C ${point(midX, height)} ${point(midX, height)} ${point(width, height)}`
44858
+ pathData: `M ${point(startX, startY)} C ${point(midX, startY)} ${point(midX, startY)} ${point(midX, midY)} C ${point(midX, endY)} ${point(midX, endY)} ${point(endX, endY)}`
42447
44859
  };
42448
44860
  }
42449
44861
  if (normalizedType.includes("curvedconnector2")) {
@@ -42452,7 +44864,7 @@ function getConnectorPathGeometry(element) {
42452
44864
  startY,
42453
44865
  endX,
42454
44866
  endY,
42455
- pathData: `M ${point(0, 0)} Q ${point(width, 0)} ${point(width, height)}`
44867
+ pathData: `M ${point(startX, startY)} Q ${point(endX, startY)} ${point(endX, endY)}`
42456
44868
  };
42457
44869
  }
42458
44870
  return {
@@ -42460,7 +44872,7 @@ function getConnectorPathGeometry(element) {
42460
44872
  startY,
42461
44873
  endX,
42462
44874
  endY,
42463
- pathData: `M ${point(0, 0)} L ${point(width, height)}`
44875
+ pathData: `M ${point(startX, startY)} L ${point(endX, endY)}`
42464
44876
  };
42465
44877
  }
42466
44878
 
@@ -50621,4 +53033,4 @@ var SvgExporter = class _SvgExporter {
50621
53033
  }
50622
53034
  };
50623
53035
 
50624
- export { ALL_ANIMATION_PRESETS, COLOR_MAP_ALIAS_KEYS, CONNECTOR_ARROW_OPTIONS, CONNECTOR_GEOMETRY_OPTIONS, ChartBuilder, ConnectorBuilder, ConnectorXmlFactory, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, DEFAULT_COLOR_MAP, DEFAULT_FILL_COLOR, DEFAULT_FONT_FAMILY, DEFAULT_SCHEME_COLOR_MAP, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_COLOR, DEFAULT_TEXT_FONT_SIZE, DIGEST_ALGORITHM_TO_HASH, DIGEST_ALGORITHM_TO_WEB_CRYPTO, DIGITAL_SIGNATURE_ORIGIN_REL_TYPE, DIGITAL_SIGNATURE_REL_TYPE, DataIntegrityError, DocumentConverter, EMPHASIS_PRESETS, EMU_PER_INCH, EMU_PER_PIXEL2 as EMU_PER_PIXEL, EMU_PER_POINT, EMU_PER_PX, ENTERPRISE_FAIL_ON_REVOCATION_UNKNOWN_ENV, ENTERPRISE_REQUIRE_REVOCATION_ENV, ENTERPRISE_REQUIRE_TIMESTAMP_ENV, ENTERPRISE_TRUST_ROOTS_FILE_ENV, ENTERPRISE_TRUST_ROOTS_PEM_ENV, ENTRANCE_PRESETS, EXIT_PRESETS, EncryptedFileError, FONT_SUBSTITUTION_MAP, FreeformPathBuilder, GroupBuilder, ImageBuilder, IncorrectPasswordError, MIN_ELEMENT_SIZE, MOTION_PATH_PRESETS, MediaBuilder, MediaContext, MediaGraphicFrameXmlFactory, OPC_RELATIONSHIP_TRANSFORM, Ole2ParseError, P14_GUIDE_URI, P15_GUIDE_URI, PANOSE_FAMILY_MAP, PANOSE_MONOSPACE_PROPORTION, PANOSE_SANS_SERIF_STYLES, PANOSE_WEIGHT_MAP, POWERPOINT_PRESENCE_KEY, PPTX_VIEWER_MANIFEST_NS, PRESET_COLOR_MAP, PRESET_SHAPE_CATEGORY_LABELS, PRESET_SHAPE_CLIP_PATHS, PRESET_SHAPE_DEFINITIONS, PRESET_TO_OOXML, PictureXmlFactory, PptxAnimationWriteService, PptxColorStyleCodec, PptxCommentAuthorsXmlFactory, PptxCommentXmlFactoryProvider, PptxCompatibilityService, PptxConnectorParser, PptxContentTypesBuilder, PptxDocumentPropertiesUpdater, PptxEditorAnimationService, PptxElementTransformUpdater, PptxElementXmlBuilder, PptxGraphicFrameParser, PptxHandler, PptxHandlerRuntime75 as PptxHandlerRuntime, PptxHandlerRuntimeFactory, PptxLoadDataBuilder, PptxMarkdownConverter, PptxMediaDataParser, PptxNativeAnimationService, PptxPresentationSaveBuilder, PptxPresentationSlidesReconciler, PptxRuntimeDependencyFactory, PptxSaveConstantsFactory, PptxSaveState as PptxSaveSession, PptxSaveStateBuilder as PptxSaveSessionBuilder, PptxSaveState, PptxSaveStateBuilder, PptxShapeIdValidator, PptxShapeStyleExtractor, PptxSlideBackgroundBuilder, PptxSlideBuilder, PptxSlideCommentPartWriter, PptxSlideCommentsXmlFactory, PptxSlideElementsBuilder, PptxSlideLoaderService, PptxSlideMediaRelationshipBuilder, PptxSlideNotesBuilder, PptxSlideNotesPartUpdater, PptxSlideRelationshipRegistry, PptxSlideTransitionService, PptxTableDataParser, PptxTemplateBackgroundService, PptxXmlBuilder, PptxXmlFactoryProvider, PptxXmlLookupService, Presentation, PresentationBuilder, SHAPE_TREE_ELEMENT_TAGS, STROKE_DASH_OPTIONS, SUPPORTED_XML_CANON_TRANSFORMS, SWITCHABLE_LAYOUT_TYPES, SYSTEM_COLOR_MAP, ShapeBuilder, SlideBuilder, SlideProcessor, SlideSizes, SvgExporter, THEME_COLOR_SCHEME_KEYS, THEME_PRESETS, TRANSITION_VALID_DIRECTIONS, TableBuilder, TextBuilder, TextShapeXmlFactory, ThemePresets, VML_SHAPE_TAGS, XMLDSIG_NS, XML_TRANSFORM_ENVELOPED_SIGNATURE, addChartCategory, addChartSeries, addSection, addSmartArtNode, addSmartArtNodeAsChild, applyDrawingColorTransforms, applyKinsokuToXml, applyTemplate, applyThemeToData, areNamespacesSupported, buildCalloutLeaderLineSvgPath, buildClrMapOverrideXml, buildFontFamilyString, buildGuideListExtension, buildLinkedTextBoxChains, buildOle2, buildSingleEffectNode, buildThemeColorMap, catmullRomToBezier, chartDataAddCategory, chartDataAddSeries, chartDataChangeType, chartDataRemoveCategory, chartDataRemoveSeries, chartDataUpdatePoint, checkBlankSlide, checkComplexTables, checkDuplicateTitles, checkLowContrast, checkMissingAltText, checkMissingSlideTitle, checkPresentation, clampUnitInterval, classifyPanose, cloneElement, cloneShapeStyle, cloneSlide, cloneTemplateElementsBySlideId, cloneTextStyle, cloneXmlObject, cm, cmToEmu, colorWithOpacity, combineShapes, computeContrastRatio, computeCycleLayout, computeDetailStatus, computeDigestBase64 as computeDigestBase64WebCrypto, computeHierarchyLayout, computeLinearLayout, computeMatrixLayout, computePyramidLayout, computeSmartArtLayout, computeSnakeLayout, computeVerificationStatus, convertEmfToDataUrl, convertWmfToDataUrl, convertXmlToStrict, createArrayBufferCopy, createBuiltinVariables, createChartElement, createConnectorElement, createDefaultPptxHandlerRuntime, createEditorId, createFreeformElement, createGroupElement, createImageElement, createLayout, createLayouts, createMediaElement, createModifyVerifier, createPptxSaveConstants, createShapeElement, createTableElement, createTemplateConnectorRawXml, createTemplateShapeRawXml, createTextElement, createUniformTextSegments, dataUrlToMediaBytes, decomposeSmartArt, decryptPptx, demoteSmartArtNode, deobfuscateFont, deriveOutputPath, detectDigitalSignatures, detectFileFormat, detectFontFormat, detectOleObjectType, detectStrictConformance, diffPresentations, diffSlides, distributeSegmentsAcrossChain, douglasPeucker, duplicateElement, duplicateSlide, elementActionToPptxAction, elementHasAction, emuToPixels, encryptPptx, ensureArrayValue, escapeXmlAttr, estimateTextBoxCapacity, evaluateGeometryPaths, evaluateGuides, extractAllTagText, extractFirstTagText, extractGuidFromPartName, extractModel3DTransform, extractTagAttribute, fetchUrlToBytes, findCustomShow, findLayoutByName, findLayoutByType, findPlaceholders, findText, formatCommentTimestamp, fragmentShapes, generateFontGuid, generateLayoutXml, generateMediaFilename, getAnimationPresetInfo, getCalloutLeaderLineGeometry, getCalloutTier, getCalloutViewBoxBounds, getCommentMarkerPosition, getConnectorAdjustment, getConnectorPathGeometry, getCssBorderDashStyle, getCustomShowNames, getCustomShowPositionLabel, getDirectory, getElementLabel, getElementTextContent, getElementTransform, getImageMaskStyle, getLinkedTextBoxSegments, getOleObjectTypeLabel, getPanoseWeight, getPresetShapeClipPath, getPresetsByCategory, getRoundRectRadiusPx, getSectionForSlide, getSectionSlideRange, getShapeClipPath, getShapeType, getSignaturePathsToStrip, getSubstituteFontFamily, getSubstituteFonts, getSupportedNamespaces, getSvgStrokeDasharray, getTextCompensationTransform, getThemePreset, getZoomElements, getZoomTargetSlideIndexes, guidToKey, guideEmuToPx, guidePxToEmu, hasDirectSubstitution, hasNonTrivialOverride, hasShapeProperties, hasTextProperties, hexToRgbChannels, hslToRgb, inches, inchesToEmu, inferOleExtensionFromTarget, interpolateShapeGeometry, intersectPolygons, intersectShapes, intersectSvgPaths, isCalloutShape, isConnectorElement, isEditableTextElement, isImageLikeElement, isInkElement, isNamespaceSupported, isShapeElement, isStrictNamespaceUri, isSummaryZoomSlide, isSwitchableLayoutType, isTemplateElement, isTextElement, isTransitionalNamespaceUri, isZoomElement, isZoomElement2 as isZoomElementUtil, layoutEngineShapesToDrawingShapes, mailMerge, mergePresentation, mergeShapes, mergeStyleParts, mergeThemeColorOverride, mm, moveSlidesToSection, navigateCustomShow, normalizeHexColor, normalizeNamespaceUri, normalizePartPath, normalizePath, normalizeStrictXml, normalizeStrokeDashType, obfuscateFont, ooxmlArcToSvg, parseActiveXControlsFromSlide, parseAdjustmentValues, parseBodyPrBooleanAttrs, parseChart3DSurfaces, parseChartAxes, parseCondition, parseConditionList, parseCxChartSeries, parseDataTable, parseDataUrlToBytes, parseDrawingColor, parseDrawingColorChoice, parseDrawingColorOpacity, parseDrawingFraction, parseDrawingHueDegrees, parseDrawingPercent, parseEmbeddedXlsx, parseGuideDefinitions, parseHexColor, parseKinsoku, parseLayoutDefinition, parseLineStyle, parseMarker, parseOle2, parsePanoseBytes, parsePanoseString, parsePresentationDrawingGuides, parseSeriesDataLabels, parseSeriesDataPoints, parseSeriesErrBars, parseSeriesExplosion, parseSeriesTrendlines, parseShapeProps, parseSignatureXml, parseSlideDrawingGuides, parseSvgPath, parseVmlElement, parseVmlElements, pixelsToEmu, polygonsToSvgPath, pptxActionToElementAction, promoteSmartArtNode, pt, reResolveSlideColors, readFileAsDataUrl, reflowSmartArtLayout, relativeLuminance, relayoutSmartArt, removeChartCategory, removeChartSeries, removeSection, removeSmartArtNode, reorderSections, reorderSmartArtNode, reorderSmartArtNodeToIndex, repairPptx, replaceShapeGeometry, replaceText, replaceTextInSlide, replaceWithCustomGeometry, resetCloneIdCounter, resetDecomposeCounter, resetIdCounter, resetSectionIdCounter, resetSmartArtEditCounter, resolveCoordinate, resolveCustomShowSlideIndices, resolveModel3DMimeType, resolveReferenceUriToPart, resolveTableCellStyle, rgbToHsl, selectAlternateContentBranch, serializeCondition, serializeConditionList, serializeSvgPath, setChartCategories, setChartGrouping, setChartTitle, setChartType, shouldRenderFallbackLabel, shouldReturnToZoomSlide, subtractPolygons, subtractShapes, subtractSvgPaths, svgPathToPolygons, switchSmartArtLayout, toHex, toStrictNamespaceUri, unionPolygons, unionShapes, unionSvgPaths, unwrapAlternateContent, updateChartDataPoint, updateChartSeriesValues, updateSmartArtNodeText, validatePptx, verifyModifyPassword, verifyPassword, verifySignatureDigests, writeBodyPrBooleanAttrs };
53036
+ export { ALL_ANIMATION_PRESETS, BLIP_FILL_ORDER, COLOR_MAP_ALIAS_KEYS, CONNECTOR_ARROW_OPTIONS, CONNECTOR_GEOMETRY_OPTIONS, ChartBuilder, ConnectorBuilder, ConnectorXmlFactory, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, DEFAULT_COLOR_MAP, DEFAULT_FILL_COLOR, DEFAULT_FONT_FAMILY, DEFAULT_SCHEME_COLOR_MAP, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_COLOR, DEFAULT_TEXT_FONT_SIZE, DIGEST_ALGORITHM_TO_HASH, DIGEST_ALGORITHM_TO_WEB_CRYPTO, DIGITAL_SIGNATURE_ORIGIN_REL_TYPE, DIGITAL_SIGNATURE_REL_TYPE, DataIntegrityError, DocumentConverter, EFFECT_LST_ORDER, EMPHASIS_PRESETS, EMU_PER_INCH, EMU_PER_PIXEL2 as EMU_PER_PIXEL, EMU_PER_POINT, EMU_PER_PX, ENTERPRISE_FAIL_ON_REVOCATION_UNKNOWN_ENV, ENTERPRISE_REQUIRE_REVOCATION_ENV, ENTERPRISE_REQUIRE_TIMESTAMP_ENV, ENTERPRISE_TRUST_ROOTS_FILE_ENV, ENTERPRISE_TRUST_ROOTS_PEM_ENV, ENTRANCE_PRESETS, EXIT_PRESETS, EncryptedFileError, FONT_SUBSTITUTION_MAP, FreeformPathBuilder, GroupBuilder, ImageBuilder, IncorrectPasswordError, MIN_ELEMENT_SIZE, MOTION_PATH_PRESETS, MediaBuilder, MediaContext, MediaGraphicFrameXmlFactory, OPC_RELATIONSHIP_TRANSFORM, Ole2ParseError, P14_GUIDE_URI, P15_GUIDE_URI, PANOSE_FAMILY_MAP, PANOSE_MONOSPACE_PROPORTION, PANOSE_SANS_SERIF_STYLES, PANOSE_WEIGHT_MAP, POWERPOINT_PRESENCE_KEY, PPTX_VIEWER_MANIFEST_NS, PRESET_COLOR_MAP, PRESET_SHAPE_CATEGORY_LABELS, PRESET_SHAPE_CLIP_PATHS, PRESET_SHAPE_DEFINITIONS, PRESET_TO_OOXML, PictureXmlFactory, PptxAnimationWriteService, PptxColorStyleCodec, PptxCommentAuthorsXmlFactory, PptxCommentXmlFactoryProvider, PptxCompatibilityService, PptxConnectorParser, PptxContentTypesBuilder, PptxDocumentPropertiesUpdater, PptxEditorAnimationService, PptxElementTransformUpdater, PptxElementXmlBuilder, PptxGraphicFrameParser, PptxHandler, PptxHandlerRuntime76 as PptxHandlerRuntime, PptxHandlerRuntimeFactory, PptxLoadDataBuilder, PptxMarkdownConverter, PptxMediaDataParser, PptxNativeAnimationService, PptxPresentationSaveBuilder, PptxPresentationSlidesReconciler, PptxRuntimeDependencyFactory, PptxSaveConstantsFactory, PptxSaveState as PptxSaveSession, PptxSaveStateBuilder as PptxSaveSessionBuilder, PptxSaveState, PptxSaveStateBuilder, PptxShapeIdValidator, PptxShapeStyleExtractor, PptxSlideBackgroundBuilder, PptxSlideBuilder, PptxSlideCommentPartWriter, PptxSlideCommentsXmlFactory, PptxSlideElementsBuilder, PptxSlideLoaderService, PptxSlideMediaRelationshipBuilder, PptxSlideNotesBuilder, PptxSlideNotesPartUpdater, PptxSlideRelationshipRegistry, PptxSlideTransitionService, PptxTableDataParser, PptxTemplateBackgroundService, PptxXmlBuilder, PptxXmlFactoryProvider, PptxXmlLookupService, Presentation, PresentationBuilder, SHAPE_TREE_ELEMENT_TAGS, SP_PR_ORDER, STROKE_DASH_OPTIONS, SUPPORTED_XML_CANON_TRANSFORMS, SWITCHABLE_LAYOUT_TYPES, SYSTEM_COLOR_MAP, ShapeBuilder, SlideBuilder, SlideProcessor, SlideSizes, SvgExporter, TC_PR_BORDERS_ORDER, THEME_COLOR_SCHEME_KEYS, THEME_PRESETS, TRANSITION_VALID_DIRECTIONS, TableBuilder, TextBuilder, TextShapeXmlFactory, ThemePresets, VML_SHAPE_TAGS, XMLDSIG_NS, XML_TRANSFORM_ENVELOPED_SIGNATURE, addChartCategory, addChartSeries, addSection, addSmartArtNode, addSmartArtNodeAsChild, applyDrawingColorTransforms, applyKinsokuToXml, applyTemplate, applyThemeToData, areNamespacesSupported, buildCalloutLeaderLineSvgPath, buildClrMapOverrideXml, buildFontFamilyString, buildGuideListExtension, buildLinkedTextBoxChains, buildOle2, buildSingleEffectNode, buildSrgbColorChoice, buildThemeColorMap, catmullRomToBezier, chartDataAddCategory, chartDataAddSeries, chartDataChangeType, chartDataRemoveCategory, chartDataRemoveSeries, chartDataUpdatePoint, checkBlankSlide, checkComplexTables, checkDuplicateTitles, checkLowContrast, checkMissingAltText, checkMissingSlideTitle, checkPresentation, clampUnitInterval, classifyPanose, cloneElement, cloneShapeStyle, cloneSlide, cloneTemplateElementsBySlideId, cloneTextStyle, cloneXmlObject, cm, cmToEmu, colorWithOpacity, colorsEqual, combineShapes, computeContrastRatio, computeCycleLayout, computeDetailStatus, computeDigestBase64 as computeDigestBase64WebCrypto, computeHierarchyLayout, computeLinearLayout, computeMatrixLayout, computePyramidLayout, computeSmartArtLayout, computeSnakeLayout, computeVerificationStatus, convertEmfToDataUrl, convertWmfToDataUrl, convertXmlToStrict, createArrayBufferCopy, createBuiltinVariables, createChartElement, createConnectorElement, createDefaultPptxHandlerRuntime, createEditorId, createFreeformElement, createGroupElement, createImageElement, createLayout, createLayouts, createMediaElement, createModifyVerifier, createPptxSaveConstants, createShapeElement, createTableElement, createTemplateConnectorRawXml, createTemplateShapeRawXml, createTextElement, createUniformTextSegments, dataUrlToMediaBytes, decomposeSmartArt, decryptPptx, demoteSmartArtNode, deobfuscateFont, deriveOutputPath, detectDigitalSignatures, detectFileFormat, detectFontFormat, detectOleObjectType, detectStrictConformance, diffPresentations, diffSlides, distributeSegmentsAcrossChain, douglasPeucker, duplicateElement, duplicateSlide, elementActionToPptxAction, elementHasAction, emuToPixels, encryptPptx, ensureArrayValue, escapeXmlAttr, estimateTextBoxCapacity, evaluateGeometryPaths, evaluateGuides, extractAllTagText, extractColorChoiceXml, extractFirstTagText, extractGuidFromPartName, extractModel3DTransform, extractTagAttribute, fetchUrlToBytes, findCustomShow, findLayoutByName, findLayoutByType, findPlaceholders, findText, formatCommentTimestamp, fragmentShapes, generateFontGuid, generateLayoutXml, generateMediaFilename, getAnimationPresetInfo, getCalloutLeaderLineGeometry, getCalloutTier, getCalloutViewBoxBounds, getCommentMarkerPosition, getConnectorAdjustment, getConnectorPathGeometry, getCssBorderDashStyle, getCustomShowNames, getCustomShowPositionLabel, getDirectory, getElementLabel, getElementTextContent, getElementTransform, getImageMaskStyle, getLinkedTextBoxSegments, getOleObjectTypeLabel, getPanoseWeight, getPresetShapeClipPath, getPresetsByCategory, getRoundRectRadiusPx, getSectionForSlide, getSectionSlideRange, getShapeClipPath, getShapeType, getSignaturePathsToStrip, getSubstituteFontFamily, getSubstituteFonts, getSupportedNamespaces, getSvgStrokeDasharray, getTextCompensationTransform, getThemePreset, getZoomElements, getZoomTargetSlideIndexes, guidToKey, guideEmuToPx, guidePxToEmu, hasDirectSubstitution, hasNonTrivialOverride, hasShapeProperties, hasTextProperties, hexToRgbChannels, hslToRgb, inches, inchesToEmu, inferOleExtensionFromTarget, interpolateShapeGeometry, intersectPolygons, intersectShapes, intersectSvgPaths, isCalloutShape, isConnectorElement, isEditableTextElement, isImageLikeElement, isInkElement, isNamespaceSupported, isShapeElement, isStrictNamespaceUri, isSummaryZoomSlide, isSwitchableLayoutType, isTemplateElement, isTextElement, isTransitionalNamespaceUri, isZoomElement, isZoomElement2 as isZoomElementUtil, layoutEngineShapesToDrawingShapes, mailMerge, mergePresentation, mergeShapes, mergeStyleParts, mergeThemeColorOverride, mm, moveSlidesToSection, navigateCustomShow, normalizeHexColor, normalizeNamespaceUri, normalizePartPath, normalizePath, normalizeStrictXml, normalizeStrokeDashType, obfuscateFont, ooxmlArcToSvg, parseActiveXControlsFromSlide, parseAdjustmentValues, parseBodyPrBooleanAttrs, parseChart3DSurfaces, parseChartAxes, parseCondition, parseConditionList, parseCxChartSeries, parseDataTable, parseDataUrlToBytes, parseDrawingColor, parseDrawingColorChoice, parseDrawingColorOpacity, parseDrawingFraction, parseDrawingHueDegrees, parseDrawingPercent, parseEmbeddedXlsx, parseGuideDefinitions, parseHexColor, parseKinsoku, parseLayoutDefinition, parseLineStyle, parseMarker, parseOle2, parsePanoseBytes, parsePanoseString, parsePresentationDrawingGuides, parseSeriesDataLabels, parseSeriesDataPoints, parseSeriesErrBars, parseSeriesExplosion, parseSeriesTrendlines, parseShapeProps, parseSignatureXml, parseSlideDrawingGuides, parseSvgPath, parseVmlElement, parseVmlElements, pixelsToEmu, polygonsToSvgPath, pptxActionToElementAction, promoteSmartArtNode, pt, reResolveSlideColors, readFileAsDataUrl, reflowSmartArtLayout, relativeLuminance, relayoutSmartArt, removeChartCategory, removeChartSeries, removeSection, removeSmartArtNode, reorderObjectKeys, reorderSections, reorderSmartArtNode, reorderSmartArtNodeToIndex, repairPptx, replaceShapeGeometry, replaceText, replaceTextInSlide, replaceWithCustomGeometry, resetCloneIdCounter, resetDecomposeCounter, resetIdCounter, resetSectionIdCounter, resetSmartArtEditCounter, resolveCoordinate, resolveCustomShowSlideIndices, resolveModel3DMimeType, resolveReferenceUriToPart, resolveTableCellStyle, rgbToHsl, selectAlternateContentBranch, serializeColorChoice, serializeCondition, serializeConditionList, serializeSvgPath, setChartCategories, setChartGrouping, setChartTitle, setChartType, shouldRenderFallbackLabel, shouldReturnToZoomSlide, subtractPolygons, subtractShapes, subtractSvgPaths, svgPathToPolygons, switchSmartArtLayout, toHex, toStrictNamespaceUri, unionPolygons, unionShapes, unionSvgPaths, unwrapAlternateContent, updateChartDataPoint, updateChartSeriesValues, updateSmartArtNodeText, validatePptx, verifyModifyPassword, verifyPassword, verifySignatureDigests, writeBodyPrBooleanAttrs };