pptx-viewer-core 1.6.9 → 1.6.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2594,6 +2594,7 @@ var TextShapeXmlFactory = class {
2594
2594
  createXmlElement(init) {
2595
2595
  const { element } = init;
2596
2596
  const isText = element.type === "text";
2597
+ const isTextBox = element.locks?.txBox ?? isText;
2597
2598
  const name = isText ? "TextBox" : "Rectangle";
2598
2599
  const geometry = this.context.normalizePresetGeometry(element.shapeType);
2599
2600
  const adjustmentEntries = Object.entries(element.shapeAdjustments || {}).filter(
@@ -2613,7 +2614,7 @@ var TextShapeXmlFactory = class {
2613
2614
  "@_name": `${name} ${elementId}`
2614
2615
  },
2615
2616
  "p:cNvSpPr": {
2616
- "@_txBox": isText ? "1" : "0"
2617
+ "@_txBox": isTextBox ? "1" : "0"
2617
2618
  },
2618
2619
  "p:nvPr": {}
2619
2620
  },
@@ -3239,6 +3240,21 @@ function cloneXmlObject(value) {
3239
3240
 
3240
3241
  // src/core/utils/presentation-collections.ts
3241
3242
  var SECTION_EXTENSION_URI = "{521415D9-36F7-43E2-AB2F-B90AF26B5E84}";
3243
+ function remapReferenceList(references, mapping, removed) {
3244
+ const result = [];
3245
+ for (const reference of references) {
3246
+ const mapped = mapping.get(reference);
3247
+ if (mapped !== void 0) {
3248
+ result.push(mapped);
3249
+ continue;
3250
+ }
3251
+ if (removed.has(reference)) {
3252
+ continue;
3253
+ }
3254
+ result.push(reference);
3255
+ }
3256
+ return result;
3257
+ }
3242
3258
  function localName4(key) {
3243
3259
  return key.split(":").pop() ?? key;
3244
3260
  }
@@ -3305,7 +3321,7 @@ function updateCustomShow(show, existing) {
3305
3321
  replaceChildren(node, "sldLst", slideList, "p:sldLst");
3306
3322
  return node;
3307
3323
  }
3308
- function applyCustomShows(presentation, shows, lookup) {
3324
+ function applyCustomShows(presentation, shows, lookup, remap) {
3309
3325
  if (shows === void 0) {
3310
3326
  return;
3311
3327
  }
@@ -3319,14 +3335,18 @@ function applyCustomShows(presentation, shows, lookup) {
3319
3335
  const oldList = key ? presentation[key] : void 0;
3320
3336
  const list = cloneXmlObject(oldList) ?? {};
3321
3337
  const oldShows = lookup.getChildrenArrayByLocalName(oldList, "custShow");
3322
- const updated = shows.map(
3323
- (show) => updateCustomShow(
3324
- show,
3338
+ const updated = shows.map((show) => {
3339
+ const effective = remap && remap.changed ? {
3340
+ ...show,
3341
+ slideRIds: remapReferenceList(show.slideRIds, remap.rIdByOldRId, remap.removedRIds)
3342
+ } : show;
3343
+ return updateCustomShow(
3344
+ effective,
3325
3345
  oldShows.find(
3326
3346
  (node) => String(node[attributeKey(node, "id") ?? ""]) === show.id || String(node[attributeKey(node, "name") ?? ""]) === show.name
3327
3347
  )
3328
- )
3329
- );
3348
+ );
3349
+ });
3330
3350
  replaceChildren(list, "custShow", updated, "p:custShow");
3331
3351
  presentation[key ?? "p:custShowLst"] = list;
3332
3352
  }
@@ -3375,7 +3395,7 @@ function updateSection(section) {
3375
3395
  }
3376
3396
  return node;
3377
3397
  }
3378
- function applySections(presentation, sections, lookup) {
3398
+ function applySections(presentation, sections, lookup, remap) {
3379
3399
  if (sections === void 0) {
3380
3400
  return;
3381
3401
  }
@@ -3397,7 +3417,15 @@ function applySections(presentation, sections, lookup) {
3397
3417
  location = { parent: ext, key: "p14:sectionLst", list: ext["p14:sectionLst"] };
3398
3418
  }
3399
3419
  const list = cloneXmlObject(location.list) ?? {};
3400
- replaceChildren(list, "section", sections.map(updateSection), "p14:section");
3420
+ const effectiveSections = remap && remap.changed ? sections.map((section) => ({
3421
+ ...section,
3422
+ slideIds: remapReferenceList(
3423
+ section.slideIds,
3424
+ remap.sldIdByOldSldId,
3425
+ remap.removedSldIds
3426
+ )
3427
+ })) : sections;
3428
+ replaceChildren(list, "section", effectiveSections.map(updateSection), "p14:section");
3401
3429
  location.parent[location.key] = list;
3402
3430
  }
3403
3431
 
@@ -3418,8 +3446,18 @@ var PptxPresentationSaveBuilder = class {
3418
3446
  init.rawSlideHeightEmu,
3419
3447
  init.rawSlideSizeType
3420
3448
  );
3421
- applyCustomShows(presentation, init.options?.customShows, init.xmlLookupService);
3422
- applySections(presentation, init.options?.sections, init.xmlLookupService);
3449
+ applyCustomShows(
3450
+ presentation,
3451
+ init.options?.customShows,
3452
+ init.xmlLookupService,
3453
+ init.slideReferenceRemap
3454
+ );
3455
+ applySections(
3456
+ presentation,
3457
+ init.options?.sections,
3458
+ init.xmlLookupService,
3459
+ init.slideReferenceRemap
3460
+ );
3423
3461
  this.applyPhotoAlbum(presentation, init.options?.photoAlbum);
3424
3462
  presentation = this.applyKinsoku(presentation, init.options?.kinsoku);
3425
3463
  this.applyModifyVerifier(presentation, init.options?.modifyVerifier);
@@ -3514,6 +3552,53 @@ var PptxPresentationSaveBuilder = class {
3514
3552
  }
3515
3553
  };
3516
3554
 
3555
+ // src/core/core/builders/slide-reference-remap.ts
3556
+ function buildSlideReferenceRemap(init) {
3557
+ const pathToNewRId = /* @__PURE__ */ new Map();
3558
+ for (const slide of init.slides) {
3559
+ pathToNewRId.set(slide.id, slide.rId);
3560
+ }
3561
+ const newRIdToNumeric = /* @__PURE__ */ new Map();
3562
+ for (const entry of init.rebuiltSlideIds) {
3563
+ const relationshipId2 = String(entry?.["@_r:id"] ?? "");
3564
+ const numericSlideId = String(entry?.["@_id"] ?? "");
3565
+ if (relationshipId2.length > 0 && numericSlideId.length > 0) {
3566
+ newRIdToNumeric.set(relationshipId2, numericSlideId);
3567
+ }
3568
+ }
3569
+ const rIdByOldRId = /* @__PURE__ */ new Map();
3570
+ const removedRIds = /* @__PURE__ */ new Set();
3571
+ let changed = false;
3572
+ for (const [oldRId, path] of init.originalRIdToPath.entries()) {
3573
+ const newRId = pathToNewRId.get(path);
3574
+ if (newRId === void 0) {
3575
+ removedRIds.add(oldRId);
3576
+ changed = true;
3577
+ continue;
3578
+ }
3579
+ rIdByOldRId.set(oldRId, newRId);
3580
+ if (newRId !== oldRId) {
3581
+ changed = true;
3582
+ }
3583
+ }
3584
+ const sldIdByOldSldId = /* @__PURE__ */ new Map();
3585
+ const removedSldIds = /* @__PURE__ */ new Set();
3586
+ for (const [oldSldId, path] of init.originalSldIdToPath.entries()) {
3587
+ const newRId = pathToNewRId.get(path);
3588
+ const newSldId = newRId === void 0 ? void 0 : newRIdToNumeric.get(newRId);
3589
+ if (newSldId === void 0) {
3590
+ removedSldIds.add(oldSldId);
3591
+ changed = true;
3592
+ continue;
3593
+ }
3594
+ sldIdByOldSldId.set(oldSldId, newSldId);
3595
+ if (newSldId !== oldSldId) {
3596
+ changed = true;
3597
+ }
3598
+ }
3599
+ return { rIdByOldRId, sldIdByOldSldId, removedRIds, removedSldIds, changed };
3600
+ }
3601
+
3517
3602
  // src/core/core/builders/PptxPresentationSlidesReconciler.ts
3518
3603
  var PptxPresentationSlidesReconciler = class {
3519
3604
  async reconcile(input) {
@@ -3559,6 +3644,10 @@ var PptxPresentationSlidesReconciler = class {
3559
3644
  const existingSlideIds = slideIdList ? this.ensureArray(slideIdList["p:sldId"]) : [];
3560
3645
  const slideIdByRid = /* @__PURE__ */ new Map();
3561
3646
  let maxNumericSlideId = 255;
3647
+ const originalRIdToPath = /* @__PURE__ */ new Map();
3648
+ for (const [relationshipId2, target] of slideTargetByRid.entries()) {
3649
+ originalRIdToPath.set(relationshipId2, input.toSlidePathFromTarget(target));
3650
+ }
3562
3651
  for (const slideIdEntry of existingSlideIds) {
3563
3652
  const relationshipId2 = slideIdEntry?.["@_r:id"];
3564
3653
  if (typeof relationshipId2 === "string" && relationshipId2.length > 0) {
@@ -3569,6 +3658,15 @@ var PptxPresentationSlidesReconciler = class {
3569
3658
  maxNumericSlideId = Math.max(maxNumericSlideId, numericSlideId);
3570
3659
  }
3571
3660
  }
3661
+ const originalSldIdToPath = /* @__PURE__ */ new Map();
3662
+ for (const slideIdEntry of existingSlideIds) {
3663
+ const relationshipId2 = String(slideIdEntry?.["@_r:id"] ?? "");
3664
+ const numericSlideId = String(slideIdEntry?.["@_id"] ?? "");
3665
+ const slidePath = originalRIdToPath.get(relationshipId2);
3666
+ if (numericSlideId.length > 0 && slidePath !== void 0) {
3667
+ originalSldIdToPath.set(numericSlideId, slidePath);
3668
+ }
3669
+ }
3572
3670
  for (let index = 0; index < input.slides.length; index++) {
3573
3671
  const slide = input.slides[index];
3574
3672
  slide.slideNumber = index + 1;
@@ -3605,6 +3703,7 @@ var PptxPresentationSlidesReconciler = class {
3605
3703
  ];
3606
3704
  presentationRelsData["Relationships"] = relRoot;
3607
3705
  input.zip.file("ppt/_rels/presentation.xml.rels", input.xmlBuilder.build(presentationRelsData));
3706
+ const rebuiltSlideIds = [];
3608
3707
  if (presentation && slideIdList && input.presentationData) {
3609
3708
  slideIdList["p:sldId"] = input.slides.map((slide) => {
3610
3709
  const existing = slideIdByRid.get(slide.rId);
@@ -3617,11 +3716,18 @@ var PptxPresentationSlidesReconciler = class {
3617
3716
  "@_r:id": slide.rId
3618
3717
  };
3619
3718
  });
3719
+ rebuiltSlideIds.push(...slideIdList["p:sldId"]);
3620
3720
  input.presentationData["p:presentation"] = this.insertSlideIdListInOrder(
3621
3721
  presentation,
3622
3722
  slideIdList
3623
3723
  );
3624
3724
  }
3725
+ return buildSlideReferenceRemap({
3726
+ slides: input.slides,
3727
+ originalRIdToPath,
3728
+ originalSldIdToPath,
3729
+ rebuiltSlideIds
3730
+ });
3625
3731
  }
3626
3732
  /**
3627
3733
  * Return a new presentation XML object whose `p:sldIdLst` child sits in the
@@ -4283,7 +4389,7 @@ var SHAPE_STYLE_ORDER = [
4283
4389
 
4284
4390
  // src/core/core/builders/PptxSlideBackgroundBuilder.ts
4285
4391
  var PptxSlideBackgroundBuilder = class {
4286
- applyBackground(init) {
4392
+ async applyBackground(init) {
4287
4393
  const hasBackgroundColor = typeof init.slide.backgroundColor === "string" && init.slide.backgroundColor.length > 0 && init.slide.backgroundColor !== "transparent";
4288
4394
  const rawBackgroundImage = typeof init.slide.backgroundImage === "string" ? init.slide.backgroundImage : "";
4289
4395
  const hasBackgroundImage = rawBackgroundImage.length > 0;
@@ -4304,8 +4410,8 @@ var PptxSlideBackgroundBuilder = class {
4304
4410
  return;
4305
4411
  }
4306
4412
  const backgroundProperties = {};
4307
- if (hasDataUrlBackgroundImage) {
4308
- const parsedBackgroundImage = init.parseDataUrlToBytes(rawBackgroundImage);
4413
+ if (hasBackgroundImage) {
4414
+ const parsedBackgroundImage = await init.resolveImageToBytes(rawBackgroundImage);
4309
4415
  if (parsedBackgroundImage) {
4310
4416
  const backgroundImagePath = init.saveState.nextMediaPath(parsedBackgroundImage.extension);
4311
4417
  init.zip.file(backgroundImagePath, parsedBackgroundImage.bytes);
@@ -4323,8 +4429,11 @@ var PptxSlideBackgroundBuilder = class {
4323
4429
  },
4324
4430
  BLIP_FILL_ORDER
4325
4431
  );
4432
+ } else {
4433
+ init.reportUnsupportedBackground?.(rawBackgroundImage);
4326
4434
  }
4327
- } else if (hasBackgroundColor && init.slide.backgroundColor) {
4435
+ }
4436
+ if (backgroundProperties["a:blipFill"] === void 0 && hasBackgroundColor && init.slide.backgroundColor) {
4328
4437
  backgroundProperties["a:solidFill"] = {
4329
4438
  "a:srgbClr": {
4330
4439
  "@_val": init.slide.backgroundColor.replace("#", "").toUpperCase()
@@ -4341,6 +4450,11 @@ var PptxSlideBackgroundBuilder = class {
4341
4450
  backgroundProperties["@_shadeToTitle"] = "0";
4342
4451
  }
4343
4452
  if (!hasFillChild) {
4453
+ if (existingBg !== void 0) {
4454
+ this.reorderCSldBgFirst(cSld, existingBg);
4455
+ init.slideNode["p:cSld"] = cSld;
4456
+ return;
4457
+ }
4344
4458
  delete cSld["p:bg"];
4345
4459
  init.slideNode["p:cSld"] = cSld;
4346
4460
  return;
@@ -4414,6 +4528,11 @@ function parseDrawingPercent(value) {
4414
4528
  }
4415
4529
  return clampUnitInterval(parsed / 1e5);
4416
4530
  }
4531
+ function scrgbLinearToSrgb8(linear) {
4532
+ const l = Math.min(1, Math.max(0, linear));
4533
+ const companded = l <= 31308e-7 ? 12.92 * l : 1.055 * l ** (1 / 2.4) - 0.055;
4534
+ return Math.min(255, Math.max(0, Math.round(companded * 255)));
4535
+ }
4417
4536
  function toHex(value) {
4418
4537
  return Math.min(255, Math.max(0, Math.round(value))).toString(16).padStart(2, "0").toUpperCase();
4419
4538
  }
@@ -4967,11 +5086,15 @@ var PptxColorTransformCodec = class {
4967
5086
  }
4968
5087
  if (colorChoice["a:scrgbClr"]) {
4969
5088
  const scrgb = colorChoice["a:scrgbClr"];
4970
- const red = this.percentAttrToUnit(scrgb["@_r"]);
4971
- const green = this.percentAttrToUnit(scrgb["@_g"]);
4972
- const blue = this.percentAttrToUnit(scrgb["@_b"]);
5089
+ const red = parseDrawingFraction(scrgb["@_r"]);
5090
+ const green = parseDrawingFraction(scrgb["@_g"]);
5091
+ const blue = parseDrawingFraction(scrgb["@_b"]);
4973
5092
  if (red !== void 0 && green !== void 0 && blue !== void 0) {
4974
- const base = this.rgbToHex(red * 255, green * 255, blue * 255);
5093
+ const base = this.rgbToHex(
5094
+ scrgbLinearToSrgb8(red),
5095
+ scrgbLinearToSrgb8(green),
5096
+ scrgbLinearToSrgb8(blue)
5097
+ );
4975
5098
  return this.applyColorTransforms(base, scrgb);
4976
5099
  }
4977
5100
  }
@@ -5062,8 +5185,8 @@ var PptxColorTransformCodec = class {
5062
5185
  };
5063
5186
  }
5064
5187
  rgbToHex(r, g, b) {
5065
- const toHex3 = (channelValue) => this.clampColorChannel(channelValue).toString(16).padStart(2, "0").toUpperCase();
5066
- return `#${toHex3(r)}${toHex3(g)}${toHex3(b)}`;
5188
+ const toHex4 = (channelValue) => this.clampColorChannel(channelValue).toString(16).padStart(2, "0").toUpperCase();
5189
+ return `#${toHex4(r)}${toHex4(g)}${toHex4(b)}`;
5067
5190
  }
5068
5191
  applyColorTransforms(baseColor, colorNode) {
5069
5192
  return applyDrawingColorTransforms(baseColor, colorNode);
@@ -5151,6 +5274,22 @@ function mergeDrawingFillXml(original, generated, modeledChildren, childOrder2)
5151
5274
  }
5152
5275
 
5153
5276
  // src/core/core/builders/PptxGradientStyleCodec.ts
5277
+ function extractGradientTileRect(gradFill) {
5278
+ const tileRect = drawingChild(gradFill, "tileRect");
5279
+ if (!tileRect) {
5280
+ return void 0;
5281
+ }
5282
+ const toFraction = (raw) => {
5283
+ const parsed = Number.parseInt(String(raw ?? "0"), 10);
5284
+ return Number.isFinite(parsed) ? parsed / 1e5 : 0;
5285
+ };
5286
+ return {
5287
+ l: toFraction(tileRect["@_l"]),
5288
+ t: toFraction(tileRect["@_t"]),
5289
+ r: toFraction(tileRect["@_r"]),
5290
+ b: toFraction(tileRect["@_b"])
5291
+ };
5292
+ }
5154
5293
  var PptxGradientStyleCodec = class {
5155
5294
  context;
5156
5295
  constructor(context) {
@@ -5261,6 +5400,9 @@ var PptxGradientStyleCodec = class {
5261
5400
  b: Number.isFinite(b) ? this.context.clampUnitInterval(b / 1e5) : 0
5262
5401
  };
5263
5402
  }
5403
+ extractGradientTileRect(gradFill) {
5404
+ return extractGradientTileRect(gradFill);
5405
+ }
5264
5406
  extractGradientFlip(gradFill) {
5265
5407
  const flipRaw = String(gradFill["@_flip"] || "").trim().toLowerCase();
5266
5408
  if (flipRaw === "x" || flipRaw === "y" || flipRaw === "xy" || flipRaw === "none") {
@@ -5432,6 +5574,15 @@ var PptxGradientStyleCodec = class {
5432
5574
  }
5433
5575
  gradientXml["a:lin"] = linNode;
5434
5576
  }
5577
+ if (shapeStyle.fillGradientTileRect) {
5578
+ const tr = shapeStyle.fillGradientTileRect;
5579
+ gradientXml["a:tileRect"] = {
5580
+ "@_l": String(Math.round(tr.l * 1e5)),
5581
+ "@_t": String(Math.round(tr.t * 1e5)),
5582
+ "@_r": String(Math.round(tr.r * 1e5)),
5583
+ "@_b": String(Math.round(tr.b * 1e5))
5584
+ };
5585
+ }
5435
5586
  return mergeDrawingFillXml(
5436
5587
  shapeStyle.fillGradientXml,
5437
5588
  gradientXml,
@@ -6965,7 +7116,7 @@ var PptxColorStyleCodec = class {
6965
7116
  const alphaMod = this.percentAttrToUnit(
6966
7117
  choiceNode["a:alphaMod"]?.["@_val"]
6967
7118
  );
6968
- const alphaOff = this.percentAttrToUnit(
7119
+ const alphaOff = this.signedPercentToUnit(
6969
7120
  choiceNode["a:alphaOff"]?.["@_val"]
6970
7121
  );
6971
7122
  if (alpha === void 0 && alphaMod === void 0 && alphaOff === void 0) {
@@ -6980,6 +7131,18 @@ var PptxColorStyleCodec = class {
6980
7131
  }
6981
7132
  return this.clampUnitInterval(opacity2);
6982
7133
  }
7134
+ /**
7135
+ * Parse an OOXML percentage (thousandths, `100000` = 100%) into a fraction
7136
+ * WITHOUT clamping to [0, 1]. Used for additive offsets like `a:alphaOff`
7137
+ * that legitimately carry negative values.
7138
+ */
7139
+ signedPercentToUnit(value) {
7140
+ const parsed = Number.parseFloat(String(value ?? "").trim());
7141
+ if (!Number.isFinite(parsed)) {
7142
+ return void 0;
7143
+ }
7144
+ return parsed / 1e5;
7145
+ }
6983
7146
  colorWithOpacity(color2, opacity2) {
6984
7147
  if (opacity2 === void 0) {
6985
7148
  return color2;
@@ -7163,10 +7326,12 @@ function applyLineProperties(lineNode, shapeProps, style, context, resolveHidden
7163
7326
  }
7164
7327
  const hiddenLineFill = hiddenLineProps["a:solidFill"];
7165
7328
  if (hiddenLineFill) {
7329
+ style.strokeFillMode = "solid";
7166
7330
  style.strokeColor = context.parseColor(hiddenLineFill);
7167
7331
  style.strokeOpacity = context.extractColorOpacity(hiddenLineFill);
7168
7332
  }
7169
7333
  } else {
7334
+ style.strokeFillMode = "none";
7170
7335
  style.strokeWidth = 0;
7171
7336
  style.strokeColor = "transparent";
7172
7337
  }
@@ -7184,6 +7349,7 @@ function applyLineProperties(lineNode, shapeProps, style, context, resolveHidden
7184
7349
  }
7185
7350
  function applyStrokeColor(lineNode, style, context) {
7186
7351
  if (lineNode["a:solidFill"]) {
7352
+ style.strokeFillMode = "solid";
7187
7353
  const lineFill = lineNode["a:solidFill"];
7188
7354
  style.strokeColor = context.parseColor(lineFill);
7189
7355
  style.strokeOpacity = context.extractColorOpacity(lineFill);
@@ -7192,10 +7358,15 @@ function applyStrokeColor(lineNode, style, context) {
7192
7358
  style.strokeColorXml = strokeColorXml;
7193
7359
  }
7194
7360
  } else if (lineNode["a:gradFill"]) {
7195
- style.strokeColor = context.extractGradientFillColor(lineNode["a:gradFill"]);
7196
- style.strokeOpacity = context.extractGradientOpacity(lineNode["a:gradFill"]);
7361
+ style.strokeFillMode = "gradient";
7362
+ const lineGradFill = lineNode["a:gradFill"];
7363
+ style.strokeGradientXml = lineGradFill;
7364
+ style.strokeColor = context.extractGradientFillColor(lineGradFill);
7365
+ style.strokeOpacity = context.extractGradientOpacity(lineGradFill);
7197
7366
  } else if (lineNode["a:pattFill"]) {
7367
+ style.strokeFillMode = "pattern";
7198
7368
  const linePatternFill = lineNode["a:pattFill"];
7369
+ style.strokePatternXml = linePatternFill;
7199
7370
  style.strokeColor = context.parseColor(linePatternFill["a:fgClr"]) || context.parseColor(linePatternFill["a:bgClr"]);
7200
7371
  style.strokeOpacity = context.extractColorOpacity(linePatternFill["a:fgClr"]) || context.extractColorOpacity(linePatternFill["a:bgClr"]);
7201
7372
  }
@@ -7324,6 +7495,10 @@ var PptxShapeStyleExtractor = class {
7324
7495
  style.fillGradientPathType = this.context.extractGradientPathType(gradFill);
7325
7496
  style.fillGradientFocalPoint = this.context.extractGradientFocalPoint(gradFill);
7326
7497
  style.fillGradientFillToRect = this.context.extractGradientFillToRect(gradFill);
7498
+ const gradTileRect = extractGradientTileRect(gradFill);
7499
+ if (gradTileRect) {
7500
+ style.fillGradientTileRect = gradTileRect;
7501
+ }
7327
7502
  const gradFlip = this.context.extractGradientFlip(gradFill);
7328
7503
  if (gradFlip) {
7329
7504
  style.fillGradientFlip = gradFlip;
@@ -8776,6 +8951,7 @@ var PptxLoadDataBuilder = class {
8776
8951
  layoutOptions = [];
8777
8952
  headerFooter;
8778
8953
  presentationProperties;
8954
+ viewProperties;
8779
8955
  customShows;
8780
8956
  sections;
8781
8957
  warnings = [];
@@ -8835,6 +9011,10 @@ var PptxLoadDataBuilder = class {
8835
9011
  this.presentationProperties = presentationProperties;
8836
9012
  return this;
8837
9013
  }
9014
+ withViewProperties(viewProperties) {
9015
+ this.viewProperties = viewProperties;
9016
+ return this;
9017
+ }
8838
9018
  withCustomShows(customShows) {
8839
9019
  this.customShows = customShows;
8840
9020
  return this;
@@ -8972,6 +9152,7 @@ var PptxLoadDataBuilder = class {
8972
9152
  layoutOptions: this.layoutOptions,
8973
9153
  headerFooter: this.headerFooter,
8974
9154
  presentationProperties: this.presentationProperties,
9155
+ viewProperties: this.viewProperties,
8975
9156
  customShows: this.customShows,
8976
9157
  sections: this.sections,
8977
9158
  warnings: this.warnings,
@@ -9354,7 +9535,7 @@ var PptxSlideCommentsXmlFactory = class {
9354
9535
  const createdAtIso = this.resolveCreatedAt(comment.createdAt);
9355
9536
  const x = init.saveState.toEmu(comment.x, 0);
9356
9537
  const y = init.saveState.toEmu(comment.y, 0);
9357
- return {
9538
+ const node = {
9358
9539
  ...withoutChildrenByLocalName(comment.rawXml ?? {}, /* @__PURE__ */ new Set(["pos", "text"])),
9359
9540
  "@_authorId": authorId,
9360
9541
  "@_dt": createdAtIso,
@@ -9365,6 +9546,28 @@ var PptxSlideCommentsXmlFactory = class {
9365
9546
  },
9366
9547
  "p:text": String(comment.text || "")
9367
9548
  };
9549
+ this.applyResolvedState(node, comment);
9550
+ return node;
9551
+ }
9552
+ /**
9553
+ * Reflect the (possibly edited) `resolved` flag onto the legacy comment
9554
+ * node. PowerPoint's legacy comment schema has no standard resolved marker,
9555
+ * but the parser reads a non-standard `@_done` / `@_resolved` attribute, so
9556
+ * we re-emit the current state rather than leaving the stale value carried
9557
+ * over from `rawXml`. The original attribute name is preserved when present.
9558
+ */
9559
+ applyResolvedState(node, comment) {
9560
+ const raw = comment.rawXml;
9561
+ const hadResolvedAttr = raw?.["@_resolved"] !== void 0;
9562
+ const hadDoneAttr = raw?.["@_done"] !== void 0;
9563
+ const key = hadResolvedAttr && !hadDoneAttr ? "@_resolved" : "@_done";
9564
+ delete node["@_done"];
9565
+ delete node["@_resolved"];
9566
+ if (comment.resolved === true) {
9567
+ node[key] = "1";
9568
+ } else if (hadResolvedAttr || hadDoneAttr) {
9569
+ node[key] = "0";
9570
+ }
9368
9571
  }
9369
9572
  resolveCreatedAt(createdAt) {
9370
9573
  const candidate = String(createdAt || "").trim();
@@ -10677,6 +10880,226 @@ var PptxCompatibilityService = class {
10677
10880
  }
10678
10881
  };
10679
10882
 
10883
+ // src/core/utils/xml-access.ts
10884
+ var ATTR_PREFIX = "@_";
10885
+ var TEXT_KEY = "#text";
10886
+ function isXmlObject(value) {
10887
+ return typeof value === "object" && value !== null && !Array.isArray(value);
10888
+ }
10889
+ function coerceString(value) {
10890
+ if (typeof value === "string") {
10891
+ return value;
10892
+ }
10893
+ if (typeof value === "number" || typeof value === "boolean") {
10894
+ return String(value);
10895
+ }
10896
+ return void 0;
10897
+ }
10898
+ function xmlChild(node, key) {
10899
+ if (!isXmlObject(node)) {
10900
+ return void 0;
10901
+ }
10902
+ const value = node[key];
10903
+ if (Array.isArray(value)) {
10904
+ const first = value[0];
10905
+ return isXmlObject(first) ? first : void 0;
10906
+ }
10907
+ return isXmlObject(value) ? value : void 0;
10908
+ }
10909
+ function xmlChildren(node, key) {
10910
+ if (!isXmlObject(node)) {
10911
+ return [];
10912
+ }
10913
+ const value = node[key];
10914
+ if (value === void 0 || value === null) {
10915
+ return [];
10916
+ }
10917
+ if (Array.isArray(value)) {
10918
+ return value.filter(isXmlObject);
10919
+ }
10920
+ return isXmlObject(value) ? [value] : [];
10921
+ }
10922
+ function xmlHasChild(node, key) {
10923
+ return isXmlObject(node) && Object.hasOwn(node, key);
10924
+ }
10925
+ function xmlAttr(node, name) {
10926
+ if (!isXmlObject(node)) {
10927
+ return void 0;
10928
+ }
10929
+ return coerceString(node[ATTR_PREFIX + name]);
10930
+ }
10931
+ function xmlAttrNumber(node, name) {
10932
+ const raw = xmlAttr(node, name);
10933
+ if (raw === void 0) {
10934
+ return void 0;
10935
+ }
10936
+ const parsed = Number(raw);
10937
+ return Number.isFinite(parsed) ? parsed : void 0;
10938
+ }
10939
+ function xmlAttrBool(node, name) {
10940
+ const raw = xmlAttr(node, name);
10941
+ if (raw === void 0) {
10942
+ return void 0;
10943
+ }
10944
+ const normalized = raw.trim().toLowerCase();
10945
+ if (normalized === "1" || normalized === "true") {
10946
+ return true;
10947
+ }
10948
+ if (normalized === "0" || normalized === "false") {
10949
+ return false;
10950
+ }
10951
+ return void 0;
10952
+ }
10953
+ function xmlText(node) {
10954
+ if (typeof node === "string") {
10955
+ return node;
10956
+ }
10957
+ if (!isXmlObject(node)) {
10958
+ return void 0;
10959
+ }
10960
+ return coerceString(node[TEXT_KEY]);
10961
+ }
10962
+ function xmlPath(node, ...keys) {
10963
+ let current = isXmlObject(node) ? node : void 0;
10964
+ for (const key of keys) {
10965
+ if (!current) {
10966
+ return void 0;
10967
+ }
10968
+ current = xmlChild(current, key);
10969
+ }
10970
+ return current;
10971
+ }
10972
+ function isXmlNode(value) {
10973
+ return isXmlObject(value);
10974
+ }
10975
+
10976
+ // src/core/utils/app-properties-titles.ts
10977
+ var SLIDE_TITLES_NAME = "Slide Titles";
10978
+ function coerceText(value) {
10979
+ if (typeof value === "string") {
10980
+ return value;
10981
+ }
10982
+ if (typeof value === "number" || typeof value === "boolean") {
10983
+ return String(value);
10984
+ }
10985
+ if (isXmlNode(value)) {
10986
+ const text2 = value["#text"];
10987
+ return text2 === void 0 || text2 === null ? "" : String(text2);
10988
+ }
10989
+ return "";
10990
+ }
10991
+ function coerceCount(value) {
10992
+ const parsed = Number.parseInt(coerceText(value), 10);
10993
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
10994
+ }
10995
+ function readLpstrList(vector) {
10996
+ if (!vector) {
10997
+ return [];
10998
+ }
10999
+ const raw = vector["vt:lpstr"];
11000
+ if (raw === void 0 || raw === null) {
11001
+ return [];
11002
+ }
11003
+ return (Array.isArray(raw) ? raw : [raw]).map(coerceText);
11004
+ }
11005
+ function isSlideTitlesCategory(name) {
11006
+ const normalized = name.trim().toLowerCase();
11007
+ return normalized === "slide titles" || normalized.includes("slide") && normalized.includes("title");
11008
+ }
11009
+ function readCategories(headingPairs, titlesOfParts) {
11010
+ const variants = xmlChildren(xmlChild(headingPairs, "vt:vector"), "vt:variant");
11011
+ const entries = readLpstrList(xmlChild(titlesOfParts, "vt:vector"));
11012
+ const categories = [];
11013
+ let offset = 0;
11014
+ for (let i = 0; i + 1 < variants.length; i += 2) {
11015
+ const name = coerceText(variants[i]["vt:lpstr"]);
11016
+ const count = coerceCount(variants[i + 1]["vt:i4"]);
11017
+ categories.push({ name, entries: entries.slice(offset, offset + count) });
11018
+ offset += count;
11019
+ }
11020
+ return categories;
11021
+ }
11022
+ function writeHeadingPairs(appProps, categories) {
11023
+ const variants = [];
11024
+ for (const category of categories) {
11025
+ variants.push({ "vt:lpstr": category.name });
11026
+ variants.push({ "vt:i4": String(category.entries.length) });
11027
+ }
11028
+ appProps["HeadingPairs"] = {
11029
+ "vt:vector": {
11030
+ "@_size": String(variants.length),
11031
+ "@_baseType": "variant",
11032
+ "vt:variant": variants
11033
+ }
11034
+ };
11035
+ }
11036
+ function writeTitlesOfParts(appProps, categories) {
11037
+ const allEntries = categories.flatMap((category) => category.entries);
11038
+ const lpstr = allEntries.map((entry) => ({ "#text": entry }));
11039
+ appProps["TitlesOfParts"] = {
11040
+ "vt:vector": {
11041
+ "@_size": String(allEntries.length),
11042
+ "@_baseType": "lpstr",
11043
+ "vt:lpstr": lpstr
11044
+ }
11045
+ };
11046
+ }
11047
+ function applySlideTitlesToAppProps(appProps, titles) {
11048
+ const headingPairs = xmlChild(appProps, "HeadingPairs");
11049
+ if (!headingPairs) {
11050
+ return;
11051
+ }
11052
+ const titlesOfParts = xmlChild(appProps, "TitlesOfParts");
11053
+ const categories = readCategories(headingPairs, titlesOfParts);
11054
+ const slideCategory = categories.find((category) => isSlideTitlesCategory(category.name));
11055
+ if (slideCategory) {
11056
+ slideCategory.entries = titles;
11057
+ } else {
11058
+ categories.push({ name: SLIDE_TITLES_NAME, entries: titles });
11059
+ }
11060
+ writeHeadingPairs(appProps, categories);
11061
+ writeTitlesOfParts(appProps, categories);
11062
+ }
11063
+
11064
+ // src/core/utils/slide-title.ts
11065
+ var TITLE_PLACEHOLDER_TYPES = /* @__PURE__ */ new Set(["title", "ctrtitle"]);
11066
+ function getElementPlaceholderType(element) {
11067
+ const explicit = element.placeholderType;
11068
+ if (typeof explicit === "string" && explicit.trim().length > 0) {
11069
+ return explicit.trim().toLowerCase();
11070
+ }
11071
+ const ph = xmlPath(element.rawXml, "p:nvSpPr", "p:nvPr", "p:ph");
11072
+ const type = xmlAttr(ph, "type");
11073
+ return type ? type.trim().toLowerCase() : void 0;
11074
+ }
11075
+ function getElementPlainText(element) {
11076
+ const maybe = element;
11077
+ if (typeof maybe.text === "string" && maybe.text.trim().length > 0) {
11078
+ return maybe.text.trim();
11079
+ }
11080
+ if (Array.isArray(maybe.textSegments)) {
11081
+ const joined = maybe.textSegments.map((segment) => typeof segment?.text === "string" ? segment.text : "").join("");
11082
+ return joined.trim();
11083
+ }
11084
+ return "";
11085
+ }
11086
+ function deriveSlideTitle(slide) {
11087
+ const elements2 = slide.elements ?? [];
11088
+ for (const element of elements2) {
11089
+ const phType = getElementPlaceholderType(element);
11090
+ if (phType && TITLE_PLACEHOLDER_TYPES.has(phType)) {
11091
+ const text2 = getElementPlainText(element);
11092
+ if (text2) {
11093
+ return text2;
11094
+ }
11095
+ }
11096
+ }
11097
+ return "";
11098
+ }
11099
+ function deriveSlideTitles(slides) {
11100
+ return slides.map((slide) => deriveSlideTitle(slide));
11101
+ }
11102
+
10680
11103
  // src/core/services/PptxDocumentPropertiesUpdater.ts
10681
11104
  var PptxDocumentPropertiesUpdater = class {
10682
11105
  context;
@@ -10740,6 +11163,7 @@ var PptxDocumentPropertiesUpdater = class {
10740
11163
  appProps["Slides"] = String(slides.length);
10741
11164
  appProps["HiddenSlides"] = String(hiddenSlidesCount);
10742
11165
  appProps["Notes"] = String(notesCount);
11166
+ this.updateSlideTitleProperties(appProps, slides);
10743
11167
  appData["Properties"] = appProps;
10744
11168
  this.context.zip.file("docProps/app.xml", this.context.builder.build(appData));
10745
11169
  } catch (error) {
@@ -10782,6 +11206,15 @@ var PptxDocumentPropertiesUpdater = class {
10782
11206
  }
10783
11207
  }
10784
11208
  }
11209
+ /**
11210
+ * Recompute `TitlesOfParts` / `HeadingPairs` from the current slide set so
11211
+ * the per-slide title list in `app.xml` stays consistent after slides are
11212
+ * added, removed, or retitled. Delegates the vector rebuild to a pure
11213
+ * helper; here we only derive the ordered titles.
11214
+ */
11215
+ updateSlideTitleProperties(appProps, slides) {
11216
+ applySlideTitlesToAppProps(appProps, deriveSlideTitles(slides));
11217
+ }
10785
11218
  applyAppPropertiesOverrides(appProps, overrides10) {
10786
11219
  if (!overrides10) {
10787
11220
  return;
@@ -12610,6 +13043,16 @@ function extractChildKeyframes(childTnList) {
12610
13043
  }
12611
13044
  return void 0;
12612
13045
  }
13046
+ function parseTimingPercentFraction(raw) {
13047
+ if (raw === void 0 || raw === null) {
13048
+ return void 0;
13049
+ }
13050
+ const parsed = Number.parseInt(String(raw), 10);
13051
+ if (!Number.isFinite(parsed) || parsed <= 0) {
13052
+ return void 0;
13053
+ }
13054
+ return Math.min(1, parsed / 1e5);
13055
+ }
12613
13056
  function extractRepeatInfo(cTn) {
12614
13057
  let repeatCount;
12615
13058
  let autoReverse;
@@ -12753,11 +13196,11 @@ function ensureArray4(value) {
12753
13196
  return [];
12754
13197
  }
12755
13198
  if (!Array.isArray(value)) {
12756
- return isXmlObject(value) ? [value] : [];
13199
+ return isXmlObject2(value) ? [value] : [];
12757
13200
  }
12758
- return value.filter((entry) => isXmlObject(entry));
13201
+ return value.filter((entry) => isXmlObject2(entry));
12759
13202
  }
12760
- function isXmlObject(value) {
13203
+ function isXmlObject2(value) {
12761
13204
  return typeof value === "object" && value !== null && !Array.isArray(value);
12762
13205
  }
12763
13206
  var VALID_CONDITION_EVENTS = /* @__PURE__ */ new Set([
@@ -13125,6 +13568,8 @@ var PptxNativeAnimationService = class {
13125
13568
  const presetSubtype = cTn["@_presetSubtype"] !== void 0 ? Number.parseInt(String(cTn["@_presetSubtype"]), 10) : void 0;
13126
13569
  const durationMs = cTn["@_dur"] ? Number.parseInt(String(cTn["@_dur"]), 10) : void 0;
13127
13570
  const delayMs = cTn["@_delay"] ? Number.parseInt(String(cTn["@_delay"]), 10) : void 0;
13571
+ const accel = parseTimingPercentFraction(cTn["@_accel"]);
13572
+ const decel = parseTimingPercentFraction(cTn["@_decel"]);
13128
13573
  let trigger = currentTrigger;
13129
13574
  if (nodeType === "afterPrevious" || nodeType === "afterPrev") {
13130
13575
  trigger = "afterPrevious";
@@ -13177,6 +13622,8 @@ var PptxNativeAnimationService = class {
13177
13622
  presetSubtype,
13178
13623
  durationMs,
13179
13624
  delayMs,
13625
+ accel,
13626
+ decel,
13180
13627
  triggerDelayMs: trigger === "afterDelay" ? delayMs : void 0,
13181
13628
  motionPath: childMotion.motionPath,
13182
13629
  motionOrigin: childMotion.motionOrigin,
@@ -14417,7 +14864,7 @@ function updateEffectNodeAttributes(cTn, anim, currentPresetClass) {
14417
14864
  if (stCondList && anim.delayMs !== void 0) {
14418
14865
  const conditions = ensureArray4(stCondList["p:cond"]);
14419
14866
  for (const cond of conditions) {
14420
- if (isXmlObject(cond)) {
14867
+ if (isXmlObject2(cond)) {
14421
14868
  cond["@_delay"] = String(anim.delayMs);
14422
14869
  }
14423
14870
  }
@@ -24508,7 +24955,7 @@ function getCalloutViewBoxBounds(width, height, geometry, padding = 2) {
24508
24955
  }
24509
24956
 
24510
24957
  // src/core/core/runtime/omml-sibling-order.ts
24511
- function isXmlObject2(value) {
24958
+ function isXmlObject3(value) {
24512
24959
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
24513
24960
  }
24514
24961
  function ensureItems(value) {
@@ -24611,7 +25058,7 @@ function collectParsedOmathNodes(root) {
24611
25058
  }
24612
25059
  if (localName9(key) === "oMath") {
24613
25060
  for (const item of ensureItems(value)) {
24614
- if (isXmlObject2(item)) {
25061
+ if (isXmlObject3(item)) {
24615
25062
  result.push(item);
24616
25063
  }
24617
25064
  }
@@ -24674,7 +25121,7 @@ function reorderContainer(node, rawInner) {
24674
25121
  occurrence.set(child20.tag, index + 1);
24675
25122
  const value = ensureItems(node[child20.tag])[index];
24676
25123
  resolved.push({ tag: child20.tag, value });
24677
- if (isXmlObject2(value) && child20.inner) {
25124
+ if (isXmlObject3(value) && child20.inner) {
24678
25125
  reorderContainer(value, child20.inner);
24679
25126
  }
24680
25127
  }
@@ -24718,7 +25165,7 @@ function localName10(name) {
24718
25165
  const colon = name.indexOf(":");
24719
25166
  return colon >= 0 ? name.slice(colon + 1) : name;
24720
25167
  }
24721
- function isXmlObject3(value) {
25168
+ function isXmlObject4(value) {
24722
25169
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
24723
25170
  }
24724
25171
  function collectParsedParagraphs(root) {
@@ -24743,7 +25190,7 @@ function collectParsedParagraphs(root) {
24743
25190
  continue;
24744
25191
  }
24745
25192
  paragraphs.push(
24746
- ...(Array.isArray(childValue) ? childValue : [childValue]).filter(isXmlObject3)
25193
+ ...(Array.isArray(childValue) ? childValue : [childValue]).filter(isXmlObject4)
24747
25194
  );
24748
25195
  }
24749
25196
  } else {
@@ -24790,7 +25237,7 @@ function directChildrenByLocalName(paragraphs, name) {
24790
25237
  return [];
24791
25238
  }
24792
25239
  const values = Array.isArray(value) ? value : [value];
24793
- return values.filter(isXmlObject3);
25240
+ return values.filter(isXmlObject4);
24794
25241
  })
24795
25242
  );
24796
25243
  }
@@ -26205,99 +26652,6 @@ function detectFontFormat(data) {
26205
26652
  return "truetype";
26206
26653
  }
26207
26654
 
26208
- // src/core/utils/xml-access.ts
26209
- var ATTR_PREFIX = "@_";
26210
- var TEXT_KEY = "#text";
26211
- function isXmlObject4(value) {
26212
- return typeof value === "object" && value !== null && !Array.isArray(value);
26213
- }
26214
- function coerceString(value) {
26215
- if (typeof value === "string") {
26216
- return value;
26217
- }
26218
- if (typeof value === "number" || typeof value === "boolean") {
26219
- return String(value);
26220
- }
26221
- return void 0;
26222
- }
26223
- function xmlChild(node, key) {
26224
- if (!isXmlObject4(node)) {
26225
- return void 0;
26226
- }
26227
- const value = node[key];
26228
- if (Array.isArray(value)) {
26229
- const first = value[0];
26230
- return isXmlObject4(first) ? first : void 0;
26231
- }
26232
- return isXmlObject4(value) ? value : void 0;
26233
- }
26234
- function xmlChildren(node, key) {
26235
- if (!isXmlObject4(node)) {
26236
- return [];
26237
- }
26238
- const value = node[key];
26239
- if (value === void 0 || value === null) {
26240
- return [];
26241
- }
26242
- if (Array.isArray(value)) {
26243
- return value.filter(isXmlObject4);
26244
- }
26245
- return isXmlObject4(value) ? [value] : [];
26246
- }
26247
- function xmlHasChild(node, key) {
26248
- return isXmlObject4(node) && Object.hasOwn(node, key);
26249
- }
26250
- function xmlAttr(node, name) {
26251
- if (!isXmlObject4(node)) {
26252
- return void 0;
26253
- }
26254
- return coerceString(node[ATTR_PREFIX + name]);
26255
- }
26256
- function xmlAttrNumber(node, name) {
26257
- const raw = xmlAttr(node, name);
26258
- if (raw === void 0) {
26259
- return void 0;
26260
- }
26261
- const parsed = Number(raw);
26262
- return Number.isFinite(parsed) ? parsed : void 0;
26263
- }
26264
- function xmlAttrBool(node, name) {
26265
- const raw = xmlAttr(node, name);
26266
- if (raw === void 0) {
26267
- return void 0;
26268
- }
26269
- const normalized = raw.trim().toLowerCase();
26270
- if (normalized === "1" || normalized === "true") {
26271
- return true;
26272
- }
26273
- if (normalized === "0" || normalized === "false") {
26274
- return false;
26275
- }
26276
- return void 0;
26277
- }
26278
- function xmlText(node) {
26279
- if (typeof node === "string") {
26280
- return node;
26281
- }
26282
- if (!isXmlObject4(node)) {
26283
- return void 0;
26284
- }
26285
- return coerceString(node[TEXT_KEY]);
26286
- }
26287
- function xmlPath(node, ...keys) {
26288
- let current = isXmlObject4(node) ? node : void 0;
26289
- for (const key of keys) {
26290
- if (!current) {
26291
- return void 0;
26292
- }
26293
- current = xmlChild(current, key);
26294
- }
26295
- return current;
26296
- }
26297
- function isXmlNode(value) {
26298
- return isXmlObject4(value);
26299
- }
26300
-
26301
26655
  // src/core/utils/presentation-section-parser.ts
26302
26656
  function findSectionList2(presentation, lookup) {
26303
26657
  const direct = lookup.getChildByLocalName(presentation, "sectionLst");
@@ -29633,6 +29987,7 @@ function getSvgStrokeDasharray(dashType, strokeWidth, customDashSegments) {
29633
29987
  // src/core/utils/element-xml-builders.ts
29634
29988
  function createTemplateShapeRawXml(element) {
29635
29989
  const isText = element.type === "text";
29990
+ const isTextBox = element.locks?.txBox ?? isText;
29636
29991
  const name = isText ? "TextBox" : "Rectangle";
29637
29992
  const geometry = element.shapeType === "cylinder" ? "can" : element.shapeType || "rect";
29638
29993
  const adjustmentEntries = Object.entries(element.shapeAdjustments || {}).filter(
@@ -29651,7 +30006,7 @@ function createTemplateShapeRawXml(element) {
29651
30006
  "@_name": `${name} ${Math.floor(Math.random() * 100)}`
29652
30007
  },
29653
30008
  "p:cNvSpPr": {
29654
- "@_txBox": isText ? "1" : "0"
30009
+ "@_txBox": isTextBox ? "1" : "0"
29655
30010
  },
29656
30011
  "p:nvPr": {}
29657
30012
  },
@@ -32842,6 +33197,122 @@ function applyNodeStylesToElements(elements2, nodes) {
32842
33197
  });
32843
33198
  }
32844
33199
 
33200
+ // src/core/utils/smartart-pres-layout-vars.ts
33201
+ var CONTAINER_LOCAL_NAMES = /* @__PURE__ */ new Set(["presLayoutVars", "varLst"]);
33202
+ function localNameOf2(key) {
33203
+ const idx = key.indexOf(":");
33204
+ return idx >= 0 ? key.slice(idx + 1) : key;
33205
+ }
33206
+ function findVarsContainer(node) {
33207
+ if (!node || typeof node !== "object") {
33208
+ return void 0;
33209
+ }
33210
+ if (Array.isArray(node)) {
33211
+ for (const entry of node) {
33212
+ const found = findVarsContainer(entry);
33213
+ if (found) {
33214
+ return found;
33215
+ }
33216
+ }
33217
+ return void 0;
33218
+ }
33219
+ for (const [key, value] of Object.entries(node)) {
33220
+ if (key.startsWith("@_")) {
33221
+ continue;
33222
+ }
33223
+ if (CONTAINER_LOCAL_NAMES.has(localNameOf2(key))) {
33224
+ const container = Array.isArray(value) ? value[0] : value;
33225
+ if (container && typeof container === "object") {
33226
+ return container;
33227
+ }
33228
+ }
33229
+ const nested = findVarsContainer(value);
33230
+ if (nested) {
33231
+ return nested;
33232
+ }
33233
+ }
33234
+ return void 0;
33235
+ }
33236
+ function varValue(container, name) {
33237
+ for (const [key, value] of Object.entries(container)) {
33238
+ if (key.startsWith("@_") || localNameOf2(key) !== name) {
33239
+ continue;
33240
+ }
33241
+ const node = Array.isArray(value) ? value[0] : value;
33242
+ if (node && typeof node === "object") {
33243
+ const raw = node["@_val"];
33244
+ const str = String(raw ?? "").trim();
33245
+ return str.length > 0 ? str : void 0;
33246
+ }
33247
+ }
33248
+ return void 0;
33249
+ }
33250
+ function boolValue2(container, name) {
33251
+ const raw = varValue(container, name);
33252
+ if (raw === void 0) {
33253
+ return void 0;
33254
+ }
33255
+ const lower = raw.toLowerCase();
33256
+ return lower === "1" || lower === "true" || lower === "on";
33257
+ }
33258
+ function intValue(container, name) {
33259
+ const raw = varValue(container, name);
33260
+ if (raw === void 0) {
33261
+ return void 0;
33262
+ }
33263
+ const parsed = Number.parseInt(raw, 10);
33264
+ return Number.isFinite(parsed) ? parsed : void 0;
33265
+ }
33266
+ var DIRECTIONS = /* @__PURE__ */ new Set(["norm", "rev"]);
33267
+ var HIER_BRANCHES = /* @__PURE__ */ new Set(["std", "init", "l", "r", "hang"]);
33268
+ function parseSmartArtPresLayoutVars(container) {
33269
+ if (!container) {
33270
+ return void 0;
33271
+ }
33272
+ const vars = findVarsContainer(container);
33273
+ if (!vars) {
33274
+ return void 0;
33275
+ }
33276
+ const result = {};
33277
+ const direction = varValue(vars, "dir");
33278
+ if (direction && DIRECTIONS.has(direction)) {
33279
+ result.direction = direction;
33280
+ }
33281
+ const hierBranch = varValue(vars, "hierBranch");
33282
+ if (hierBranch && HIER_BRANCHES.has(hierBranch)) {
33283
+ result.hierarchyBranch = hierBranch;
33284
+ }
33285
+ const orgChart = boolValue2(vars, "orgChart");
33286
+ if (orgChart !== void 0) {
33287
+ result.orgChart = orgChart;
33288
+ }
33289
+ const chMax = intValue(vars, "chMax");
33290
+ if (chMax !== void 0) {
33291
+ result.childMax = chMax;
33292
+ }
33293
+ const chPref = intValue(vars, "chPref");
33294
+ if (chPref !== void 0) {
33295
+ result.childPreferred = chPref;
33296
+ }
33297
+ const bulletEnabled = boolValue2(vars, "bulletEnabled");
33298
+ if (bulletEnabled !== void 0) {
33299
+ result.bulletEnabled = bulletEnabled;
33300
+ }
33301
+ const animLvl = varValue(vars, "animLvl");
33302
+ if (animLvl !== void 0) {
33303
+ result.animationLevel = animLvl;
33304
+ }
33305
+ const animOne = varValue(vars, "animOne");
33306
+ if (animOne !== void 0) {
33307
+ result.animateOne = animOne;
33308
+ }
33309
+ const resizeHandles = varValue(vars, "resizeHandles");
33310
+ if (resizeHandles !== void 0) {
33311
+ result.resizeHandles = resizeHandles;
33312
+ }
33313
+ return Object.keys(result).length > 0 ? result : void 0;
33314
+ }
33315
+
32845
33316
  // src/core/utils/smartart-decompose.ts
32846
33317
  function quickStyleStrokeScale(quickStyle) {
32847
33318
  if (!quickStyle?.effectIntensity) {
@@ -32947,15 +33418,27 @@ function decomposeSmartArt(smartArtData, containerBounds, themeColorMap, layoutD
32947
33418
  smartArtData.colorTransform?.fillColors
32948
33419
  );
32949
33420
  const layoutType = resolveEffectiveLayoutType(smartArtData);
33421
+ const layoutVars = smartArtData.presLayoutVars ?? parseSmartArtPresLayoutVars(smartArtData.layoutDefinition?.rawXml);
33422
+ const orderedNodes = layoutVars?.direction === "rev" ? [...nodes].reverse() : nodes;
32950
33423
  const namedLayout = smartArtData.layout;
32951
33424
  if (namedLayout) {
32952
- const namedResult = dispatchNamedLayout(namedLayout, nodes, containerBounds, effectiveThemeMap);
33425
+ const namedResult = dispatchNamedLayout(
33426
+ namedLayout,
33427
+ orderedNodes,
33428
+ containerBounds,
33429
+ effectiveThemeMap
33430
+ );
32953
33431
  if (namedResult) {
32954
- return applyNodeStylesToElements(namedResult, nodes);
33432
+ return applyNodeStylesToElements(namedResult, orderedNodes);
32955
33433
  }
32956
33434
  }
32957
- const algorithmic = dispatchLayoutByType(layoutType, nodes, containerBounds, effectiveThemeMap);
32958
- return algorithmic ? applyNodeStylesToElements(algorithmic, nodes) : algorithmic;
33435
+ const algorithmic = dispatchLayoutByType(
33436
+ layoutType,
33437
+ orderedNodes,
33438
+ containerBounds,
33439
+ effectiveThemeMap
33440
+ );
33441
+ return algorithmic ? applyNodeStylesToElements(algorithmic, orderedNodes) : algorithmic;
32959
33442
  }
32960
33443
  function dispatchLayoutByType(layoutType, nodes, containerBounds, effectiveThemeMap) {
32961
33444
  switch (layoutType) {
@@ -42734,6 +43217,128 @@ function applySmartArtConnectionAttributes(xml, connection, fallbackModelId) {
42734
43217
  applyNullableAttribute(xml, "@_presId", connection.presentationId);
42735
43218
  }
42736
43219
 
43220
+ // src/core/utils/smartart-color-lists.ts
43221
+ var COLOR_LOCAL_NAMES = /* @__PURE__ */ new Set([
43222
+ "srgbClr",
43223
+ "schemeClr",
43224
+ "scrgbClr",
43225
+ "sysClr",
43226
+ "prstClr",
43227
+ "hslClr"
43228
+ ]);
43229
+ var COLOR_METHODS2 = /* @__PURE__ */ new Set(["span", "cycle", "repeat"]);
43230
+ var HUE_DIRECTIONS2 = /* @__PURE__ */ new Set(["cw", "ccw"]);
43231
+ var PRIMARY_LABEL_PRIORITY = ["node0", "node1", "node2", "node3", "node4", "node"];
43232
+ function localNameOf3(key) {
43233
+ const idx = key.indexOf(":");
43234
+ return idx >= 0 ? key.slice(idx + 1) : key;
43235
+ }
43236
+ function parseSmartArtColorListHexes(list, deps) {
43237
+ if (!list) {
43238
+ return [];
43239
+ }
43240
+ const out = [];
43241
+ for (const [key, value] of Object.entries(list)) {
43242
+ if (key.startsWith("@_")) {
43243
+ continue;
43244
+ }
43245
+ const local = localNameOf3(key);
43246
+ if (!COLOR_LOCAL_NAMES.has(local)) {
43247
+ continue;
43248
+ }
43249
+ const nodes = Array.isArray(value) ? value : [value];
43250
+ for (const node of nodes) {
43251
+ if (!node || typeof node !== "object") {
43252
+ continue;
43253
+ }
43254
+ const wrapper = { [`a:${local}`]: node };
43255
+ const hex10 = deps.parseColorChoice(wrapper) ?? deps.resolveScheme(node);
43256
+ if (hex10) {
43257
+ out.push(hex10);
43258
+ }
43259
+ }
43260
+ }
43261
+ return out;
43262
+ }
43263
+ function listInterpolation(list) {
43264
+ if (!list) {
43265
+ return void 0;
43266
+ }
43267
+ const method = String(list["@_meth"] ?? "").trim();
43268
+ const hueDir = String(list["@_hueDir"] ?? "").trim();
43269
+ const meta = {};
43270
+ if (COLOR_METHODS2.has(method)) {
43271
+ meta.method = method;
43272
+ }
43273
+ if (HUE_DIRECTIONS2.has(hueDir)) {
43274
+ meta.hueDirection = hueDir;
43275
+ }
43276
+ return meta.method || meta.hueDirection ? meta : void 0;
43277
+ }
43278
+ function parseLabel(lbl, deps) {
43279
+ const fillList = deps.getChild(lbl, "fillClrLst");
43280
+ const lineList = deps.getChild(lbl, "linClrLst");
43281
+ return {
43282
+ name: String(lbl["@_name"] ?? "").trim(),
43283
+ fill: parseSmartArtColorListHexes(fillList, deps),
43284
+ line: parseSmartArtColorListHexes(lineList, deps),
43285
+ textFill: parseSmartArtColorListHexes(deps.getChild(lbl, "txFillClrLst"), deps),
43286
+ textLine: parseSmartArtColorListHexes(deps.getChild(lbl, "txLinClrLst"), deps),
43287
+ effect: parseSmartArtColorListHexes(deps.getChild(lbl, "effectClrLst"), deps),
43288
+ textEffect: parseSmartArtColorListHexes(deps.getChild(lbl, "txEffectClrLst"), deps),
43289
+ fillInterpolation: listInterpolation(fillList),
43290
+ lineInterpolation: listInterpolation(lineList)
43291
+ };
43292
+ }
43293
+ function selectPrimary(parsed) {
43294
+ const byName = new Map(parsed.map((p) => [p.name, p]));
43295
+ for (const name of PRIMARY_LABEL_PRIORITY) {
43296
+ const candidate = byName.get(name);
43297
+ if (candidate && candidate.fill.length > 0) {
43298
+ return candidate;
43299
+ }
43300
+ }
43301
+ for (const name of PRIMARY_LABEL_PRIORITY) {
43302
+ const candidate = byName.get(name);
43303
+ if (candidate && (candidate.line.length > 0 || candidate.fill.length > 0)) {
43304
+ return candidate;
43305
+ }
43306
+ }
43307
+ return parsed.find((p) => p.fill.length > 0) ?? parsed.find((p) => p.line.length > 0);
43308
+ }
43309
+ function buildSmartArtColorLists(styleLbls, deps) {
43310
+ const parsed = styleLbls.map((lbl) => parseLabel(lbl, deps));
43311
+ const primary = selectPrimary(parsed);
43312
+ let fillColors = primary?.fill ?? [];
43313
+ let lineColors = primary?.line ?? [];
43314
+ if (fillColors.length === 0) {
43315
+ fillColors = parsed.map((p) => p.fill[0]).filter((c) => Boolean(c));
43316
+ }
43317
+ if (lineColors.length === 0) {
43318
+ lineColors = parsed.map((p) => p.line[0]).filter((c) => Boolean(c));
43319
+ }
43320
+ const result = { fillColors, lineColors };
43321
+ if (primary?.textFill.length) {
43322
+ result.textFillColors = primary.textFill;
43323
+ }
43324
+ if (primary?.textLine.length) {
43325
+ result.textLineColors = primary.textLine;
43326
+ }
43327
+ if (primary?.effect.length) {
43328
+ result.effectColors = primary.effect;
43329
+ }
43330
+ if (primary?.textEffect.length) {
43331
+ result.textEffectColors = primary.textEffect;
43332
+ }
43333
+ if (primary?.fillInterpolation) {
43334
+ result.fillInterpolation = primary.fillInterpolation;
43335
+ }
43336
+ if (primary?.lineInterpolation) {
43337
+ result.lineInterpolation = primary.lineInterpolation;
43338
+ }
43339
+ return result;
43340
+ }
43341
+
42737
43342
  // src/core/utils/modern-comment-constants.ts
42738
43343
  var MODERN_COMMENT_NAMESPACE = "http://schemas.microsoft.com/office/powerpoint/2018/8/main";
42739
43344
  var MODERN_COMMENT_RELATIONSHIP = "http://schemas.microsoft.com/office/2018/10/relationships/comments";
@@ -45040,6 +45645,28 @@ function buildGeneratedChartAxis(axId, crossId, pos2, formatting) {
45040
45645
  return axis;
45041
45646
  }
45042
45647
 
45648
+ // src/core/utils/chart-xml-container-map.ts
45649
+ var CONTAINER_MAP = {
45650
+ pie: { tag: "c:pieChart", family: "pie" },
45651
+ pie3D: { tag: "c:pie3DChart", family: "pie" },
45652
+ ofPie: { tag: "c:ofPieChart", family: "ofPie" },
45653
+ doughnut: { tag: "c:doughnutChart", family: "doughnut" },
45654
+ scatter: { tag: "c:scatterChart", family: "scatter" },
45655
+ bubble: { tag: "c:bubbleChart", family: "bubble" },
45656
+ line: { tag: "c:lineChart", family: "line" },
45657
+ line3D: { tag: "c:line3DChart", family: "line" },
45658
+ area: { tag: "c:areaChart", family: "area" },
45659
+ area3D: { tag: "c:area3DChart", family: "area" },
45660
+ radar: { tag: "c:radarChart", family: "radar" },
45661
+ stock: { tag: "c:stockChart", family: "stock" },
45662
+ surface: { tag: "c:surfaceChart", family: "surface" },
45663
+ bar: { tag: "c:barChart", family: "bar" },
45664
+ bar3D: { tag: "c:bar3DChart", family: "bar" }
45665
+ };
45666
+ function resolveChartContainerType(type) {
45667
+ return CONTAINER_MAP[type] ?? { tag: "c:barChart", family: "bar" };
45668
+ }
45669
+
45043
45670
  // src/core/utils/chart-xml-generator.ts
45044
45671
  var NS_C = "http://schemas.openxmlformats.org/drawingml/2006/chart";
45045
45672
  var NS_A2 = "http://schemas.openxmlformats.org/drawingml/2006/main";
@@ -45070,29 +45697,6 @@ function strLit(values) {
45070
45697
  }
45071
45698
  };
45072
45699
  }
45073
- function resolveType(type) {
45074
- switch (type) {
45075
- case "pie":
45076
- case "pie3D":
45077
- return { tag: "c:pieChart", family: "pie" };
45078
- case "doughnut":
45079
- return { tag: "c:doughnutChart", family: "doughnut" };
45080
- case "scatter":
45081
- return { tag: "c:scatterChart", family: "scatter" };
45082
- case "bubble":
45083
- return { tag: "c:bubbleChart", family: "bubble" };
45084
- case "line":
45085
- case "line3D":
45086
- return { tag: "c:lineChart", family: "line" };
45087
- case "area":
45088
- case "area3D":
45089
- return { tag: "c:areaChart", family: "area" };
45090
- case "radar":
45091
- return { tag: "c:radarChart", family: "radar" };
45092
- default:
45093
- return { tag: "c:barChart", family: "bar" };
45094
- }
45095
- }
45096
45700
  function fillSpPr(color2, asLine) {
45097
45701
  const h = hex6(color2);
45098
45702
  if (!h) {
@@ -45160,7 +45764,10 @@ function buildChartTypeContainer(chartData, family) {
45160
45764
  } else if (family === "scatter") {
45161
45765
  container["c:scatterStyle"] = { "@_val": "lineMarker" };
45162
45766
  container["c:varyColors"] = { "@_val": "0" };
45163
- } else {
45767
+ } else if (family === "ofPie") {
45768
+ container["c:ofPieType"] = { "@_val": "pie" };
45769
+ container["c:varyColors"] = { "@_val": "1" };
45770
+ } else if (family === "stock" || family === "surface") ; else {
45164
45771
  container["c:varyColors"] = { "@_val": family === "bubble" ? "0" : "1" };
45165
45772
  }
45166
45773
  container["c:ser"] = chartData.series.map(
@@ -45172,12 +45779,13 @@ function buildChartTypeContainer(chartData, family) {
45172
45779
  if (family === "line" && chartData.upDownBars !== void 0) {
45173
45780
  applyChartUpDownBars(container, chartData.upDownBars, (key) => key.replace(/^.*:/u, ""));
45174
45781
  }
45175
- if (family === "bar") {
45782
+ if (family === "bar" || family === "ofPie") {
45176
45783
  container["c:gapWidth"] = { "@_val": "150" };
45177
- container["c:axId"] = [{ "@_val": String(CAT_AX_ID) }, { "@_val": String(VAL_AX_ID) }];
45178
- } else if (family === "line" || family === "area" || family === "radar") {
45179
- container["c:axId"] = [{ "@_val": String(CAT_AX_ID) }, { "@_val": String(VAL_AX_ID) }];
45180
- } else if (family === "scatter" || family === "bubble") {
45784
+ }
45785
+ if (family === "stock") {
45786
+ container["c:hiLowLines"] = {};
45787
+ }
45788
+ if (family === "bar" || family === "line" || family === "area" || family === "radar" || family === "scatter" || family === "bubble" || family === "stock" || family === "surface") {
45181
45789
  container["c:axId"] = [{ "@_val": String(CAT_AX_ID) }, { "@_val": String(VAL_AX_ID) }];
45182
45790
  } else if (family === "doughnut") {
45183
45791
  container["c:holeSize"] = { "@_val": "50" };
@@ -45190,7 +45798,8 @@ function buildPlotArea(chartData, tag, family) {
45190
45798
  if (chartData.style) {
45191
45799
  applyChartDataLabelsToXml(plotArea, chartData.style, (key) => key.replace(/^.*:/u, ""));
45192
45800
  }
45193
- if (family !== "pie" && family !== "doughnut" && SCATTER_LIKE.has(chartData.chartType)) {
45801
+ const hasAxes = family !== "pie" && family !== "doughnut" && family !== "ofPie";
45802
+ if (hasAxes && SCATTER_LIKE.has(chartData.chartType)) {
45194
45803
  plotArea["c:valAx"] = [
45195
45804
  buildGeneratedChartAxis(
45196
45805
  CAT_AX_ID,
@@ -45205,7 +45814,7 @@ function buildPlotArea(chartData, tag, family) {
45205
45814
  axisFormatting(chartData, "valAx", VAL_AX_ID, 1)
45206
45815
  )
45207
45816
  ];
45208
- } else if (family !== "pie" && family !== "doughnut") {
45817
+ } else if (hasAxes) {
45209
45818
  const dateAxis = chartData.dateCategories ? axisFormatting(chartData, "dateAx", CAT_AX_ID) : void 0;
45210
45819
  plotArea[dateAxis ? "c:dateAx" : "c:catAx"] = buildGeneratedChartAxis(
45211
45820
  CAT_AX_ID,
@@ -45224,7 +45833,7 @@ function buildPlotArea(chartData, tag, family) {
45224
45833
  return plotArea;
45225
45834
  }
45226
45835
  function buildChartSpaceXml(chartData) {
45227
- const { tag, family } = resolveType(chartData.chartType);
45836
+ const { tag, family } = resolveChartContainerType(chartData.chartType);
45228
45837
  const chart = {};
45229
45838
  if (chartData.title) {
45230
45839
  chart["c:title"] = {
@@ -47156,6 +47765,7 @@ function parseMediaExtensionData(mediaNode, cMediaNode, shapeId, ensureArray16)
47156
47765
  let playbackSpeed;
47157
47766
  let trimStartMs;
47158
47767
  let trimEndMs;
47768
+ let embedRId;
47159
47769
  const bookmarks = [];
47160
47770
  const extLst = mediaNode["p:extLst"] ?? cMediaNode["p:extLst"];
47161
47771
  if (extLst) {
@@ -47163,6 +47773,13 @@ function parseMediaExtensionData(mediaNode, cMediaNode, shapeId, ensureArray16)
47163
47773
  for (const ext of exts) {
47164
47774
  const p14Media = ext["p14:media"];
47165
47775
  if (p14Media) {
47776
+ if (embedRId === void 0) {
47777
+ const embedRaw = p14Media["@_r:embed"] ?? p14Media["@_embed"];
47778
+ const embedStr = embedRaw === void 0 ? "" : String(embedRaw).trim();
47779
+ if (embedStr.length > 0) {
47780
+ embedRId = embedStr;
47781
+ }
47782
+ }
47166
47783
  const p14Trim = p14Media["p14:trim"];
47167
47784
  if (p14Trim) {
47168
47785
  const st = p14Trim["@_st"];
@@ -47232,7 +47849,8 @@ function parseMediaExtensionData(mediaNode, cMediaNode, shapeId, ensureArray16)
47232
47849
  fadeInDuration,
47233
47850
  fadeOutDuration,
47234
47851
  playbackSpeed,
47235
- bookmarks
47852
+ bookmarks,
47853
+ embedRId
47236
47854
  };
47237
47855
  }
47238
47856
 
@@ -47462,6 +48080,12 @@ var PptxHandlerRuntime = class {
47462
48080
  loadedEmbeddedFonts = [];
47463
48081
  /** Typed source metadata for lossless embedded-font list round trips. */
47464
48082
  loadedEmbeddedFontList;
48083
+ /**
48084
+ * View properties parsed from `ppt/viewProps.xml` during load, preserved so
48085
+ * an unmodified load -> save round-trips the typed model and callers that do
48086
+ * not override `saveOptions.viewProperties` still persist the loaded state.
48087
+ */
48088
+ loadedViewProperties;
47465
48089
  /** Map of comment author IDs to display names (from `ppt/commentAuthors.xml`). */
47466
48090
  commentAuthorMap = /* @__PURE__ */ new Map();
47467
48091
  /** Full comment author details keyed by author ID, preserving initials/lastIdx/clrIdx for round-trip. */
@@ -47688,19 +48312,179 @@ function parseTableStyleBorders(tcStyle) {
47688
48312
  return has ? result : void 0;
47689
48313
  }
47690
48314
 
48315
+ // src/core/core/runtime/table-style-fill-parse.ts
48316
+ function toHex3(raw) {
48317
+ const hex10 = String(raw ?? "").trim();
48318
+ if (!hex10) {
48319
+ return void 0;
48320
+ }
48321
+ return hex10.startsWith("#") ? hex10 : `#${hex10}`;
48322
+ }
48323
+ function parseColorChoiceFill(node) {
48324
+ if (!node) {
48325
+ return void 0;
48326
+ }
48327
+ const scheme = parseSolidFillStyle(node);
48328
+ if (scheme) {
48329
+ return scheme;
48330
+ }
48331
+ const srgb = node["a:srgbClr"];
48332
+ const color2 = toHex3(srgb?.["@_val"]);
48333
+ if (!color2) {
48334
+ return void 0;
48335
+ }
48336
+ const fill = { schemeColor: "", color: color2 };
48337
+ const tintRaw = srgb?.["a:tint"];
48338
+ const tint = tintRaw ? parseInt(String(tintRaw["@_val"] || "0"), 10) || void 0 : void 0;
48339
+ if (tint !== void 0) {
48340
+ fill.tint = tint;
48341
+ }
48342
+ const shadeRaw = srgb?.["a:shade"];
48343
+ const shade = shadeRaw ? parseInt(String(shadeRaw["@_val"] || "0"), 10) || void 0 : void 0;
48344
+ if (shade !== void 0) {
48345
+ fill.shade = shade;
48346
+ }
48347
+ return fill;
48348
+ }
48349
+ function parseGradientFill(gradFill) {
48350
+ const gsLst = gradFill["a:gsLst"];
48351
+ const rawStops = gsLst?.["a:gs"];
48352
+ const gsNodes = Array.isArray(rawStops) ? rawStops : rawStops ? [rawStops] : [];
48353
+ const stops = [];
48354
+ for (const gs of gsNodes) {
48355
+ const fill = parseColorChoiceFill(gs);
48356
+ if (!fill) {
48357
+ continue;
48358
+ }
48359
+ const position2 = (parseInt(String(gs["@_pos"] || "0"), 10) || 0) / 1e3;
48360
+ stops.push({ position: position2, fill });
48361
+ }
48362
+ if (stops.length === 0) {
48363
+ return void 0;
48364
+ }
48365
+ const lin = gradFill["a:lin"];
48366
+ if (lin) {
48367
+ const angRaw = parseInt(String(lin["@_ang"] || "0"), 10) || 0;
48368
+ const angle = (angRaw / 6e4 % 360 + 360) % 360;
48369
+ return { stops, angle, type: "linear" };
48370
+ }
48371
+ if (gradFill["a:path"] !== void 0) {
48372
+ return { stops, type: "radial" };
48373
+ }
48374
+ return { stops, type: "linear" };
48375
+ }
48376
+ function parsePatternFill(pattFill) {
48377
+ const preset = String(pattFill["@_prst"] || "").trim();
48378
+ if (!preset) {
48379
+ return void 0;
48380
+ }
48381
+ const pattern = { preset };
48382
+ const foreground = parseColorChoiceFill(pattFill["a:fgClr"]);
48383
+ if (foreground) {
48384
+ pattern.foreground = foreground;
48385
+ }
48386
+ const background = parseColorChoiceFill(pattFill["a:bgClr"]);
48387
+ if (background) {
48388
+ pattern.background = background;
48389
+ }
48390
+ return pattern;
48391
+ }
48392
+ function parseTableStyleSectionFill(section) {
48393
+ if (!section) {
48394
+ return void 0;
48395
+ }
48396
+ const tcStyle = section["a:tcStyle"];
48397
+ const fillWrap = tcStyle?.["a:fill"];
48398
+ if (!fillWrap) {
48399
+ return void 0;
48400
+ }
48401
+ if (fillWrap["a:noFill"] !== void 0) {
48402
+ return { schemeColor: "", noFill: true };
48403
+ }
48404
+ const solid = fillWrap["a:solidFill"];
48405
+ if (solid) {
48406
+ return parseColorChoiceFill(solid);
48407
+ }
48408
+ const grad = fillWrap["a:gradFill"];
48409
+ if (grad) {
48410
+ const gradient = parseGradientFill(grad);
48411
+ if (gradient) {
48412
+ return { schemeColor: "", gradient };
48413
+ }
48414
+ }
48415
+ const patt = fillWrap["a:pattFill"];
48416
+ if (patt) {
48417
+ const pattern = parsePatternFill(patt);
48418
+ if (pattern) {
48419
+ return { schemeColor: "", pattern };
48420
+ }
48421
+ }
48422
+ return void 0;
48423
+ }
48424
+ function parseTableStyleSectionText(section) {
48425
+ const tcTxStyle = section?.["a:tcTxStyle"];
48426
+ if (!tcTxStyle) {
48427
+ return void 0;
48428
+ }
48429
+ const result = {};
48430
+ let hasProps = false;
48431
+ if (tcTxStyle["@_b"] === "on") {
48432
+ result.bold = true;
48433
+ hasProps = true;
48434
+ }
48435
+ if (tcTxStyle["@_i"] === "on") {
48436
+ result.italic = true;
48437
+ hasProps = true;
48438
+ }
48439
+ const underline = String(tcTxStyle["@_u"] || "").trim();
48440
+ if (underline && underline !== "none") {
48441
+ result.underline = true;
48442
+ hasProps = true;
48443
+ }
48444
+ const font = tcTxStyle["a:font"];
48445
+ const face = font ? String(font["@_typeface"] || "").trim() : "";
48446
+ if (face) {
48447
+ result.fontFace = face;
48448
+ hasProps = true;
48449
+ }
48450
+ const fontRef = tcTxStyle["a:fontRef"];
48451
+ const idx = fontRef ? String(fontRef["@_idx"] || "").trim() : "";
48452
+ if (idx) {
48453
+ result.fontRefIdx = idx;
48454
+ hasProps = true;
48455
+ }
48456
+ const schemeClr = fontRef?.["a:schemeClr"] ?? tcTxStyle["a:schemeClr"];
48457
+ if (schemeClr) {
48458
+ const val = String(schemeClr["@_val"] || "").trim();
48459
+ if (val) {
48460
+ result.fontSchemeColor = val;
48461
+ hasProps = true;
48462
+ const tintNode = schemeClr["a:tint"];
48463
+ if (tintNode) {
48464
+ result.fontTint = parseInt(String(tintNode["@_val"] || "0"), 10) || void 0;
48465
+ }
48466
+ const shadeNode = schemeClr["a:shade"];
48467
+ if (shadeNode) {
48468
+ result.fontShade = parseInt(String(shadeNode["@_val"] || "0"), 10) || void 0;
48469
+ }
48470
+ }
48471
+ } else {
48472
+ const srgb = fontRef?.["a:srgbClr"] ?? tcTxStyle["a:srgbClr"];
48473
+ const hex10 = toHex3(srgb?.["@_val"]);
48474
+ if (hex10) {
48475
+ result.fontColor = hex10;
48476
+ hasProps = true;
48477
+ }
48478
+ }
48479
+ return hasProps ? result : void 0;
48480
+ }
48481
+
47691
48482
  // src/core/core/runtime/PptxHandlerRuntimeTableStyles.ts
47692
48483
  var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
47693
48484
  /**
47694
- * Export slides to a raster/vector format.
47695
- *
47696
- * This is a stub that signals export intent. Actual rendering requires a
47697
- * platform-specific canvas or PDF library (e.g. Puppeteer, node-canvas,
47698
- * pdfkit). Host applications should override or extend this method with
47699
- * their own rendering pipeline.
47700
- *
47701
- * @param _slides The slides to export.
47702
- * @param _options Export options (format, DPI, slide indices, etc.).
47703
- * @returns A map of slide index → exported binary data.
48485
+ * Export slides to a raster/vector format. This is a stub that signals
48486
+ * export intent; actual rendering requires a platform-specific canvas or
48487
+ * PDF backend that host applications wire in by overriding this method.
47704
48488
  */
47705
48489
  async exportSlides(slides, options) {
47706
48490
  this.compatibilityService.reportWarning({
@@ -47765,15 +48549,11 @@ var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
47765
48549
  }
47766
48550
  /**
47767
48551
  * Extract fill information from a table style section element
47768
- * (e.g. `a:wholeTbl`, `a:band1H`, `a:firstRow`).
48552
+ * (e.g. `a:wholeTbl`, `a:band1H`, `a:firstRow`). Handles scheme + sRGB
48553
+ * solids, gradients, preset patterns, and `a:noFill` (issue #95).
47769
48554
  */
47770
48555
  extractTableStyleSectionFill(section) {
47771
- if (!section) {
47772
- return void 0;
47773
- }
47774
- const tcStyle = section["a:tcStyle"];
47775
- const fill = tcStyle?.["a:fill"];
47776
- return parseSolidFillStyle(fill?.["a:solidFill"]);
48556
+ return parseTableStyleSectionFill(section);
47777
48557
  }
47778
48558
  /**
47779
48559
  * Extract border styling from a table style section's
@@ -47783,44 +48563,12 @@ var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
47783
48563
  return parseTableStyleBorders(section?.["a:tcStyle"]);
47784
48564
  }
47785
48565
  /**
47786
- * Extract text properties from a:tcTxStyle in a table style section.
48566
+ * Extract text properties from `a:tcTxStyle` in a table style section.
48567
+ * Captures bold/italic/underline, typeface, font-collection index, and the
48568
+ * font colour (scheme or sRGB) (issue #95).
47787
48569
  */
47788
48570
  extractTableStyleSectionText(section) {
47789
- if (!section) {
47790
- return void 0;
47791
- }
47792
- const tcTxStyle = section["a:tcTxStyle"];
47793
- if (!tcTxStyle) {
47794
- return void 0;
47795
- }
47796
- const result = {};
47797
- let hasProps = false;
47798
- if (tcTxStyle["@_b"] === "on") {
47799
- result.bold = true;
47800
- hasProps = true;
47801
- }
47802
- if (tcTxStyle["@_i"] === "on") {
47803
- result.italic = true;
47804
- hasProps = true;
47805
- }
47806
- const fontClr = tcTxStyle["a:fontRef"];
47807
- const schemeClr = fontClr?.["a:schemeClr"] ?? tcTxStyle["a:schemeClr"];
47808
- if (schemeClr) {
47809
- const val = String(schemeClr["@_val"] || "").trim();
47810
- if (val) {
47811
- result.fontSchemeColor = val;
47812
- hasProps = true;
47813
- const tintNode = schemeClr["a:tint"];
47814
- if (tintNode) {
47815
- result.fontTint = parseInt(String(tintNode["@_val"] || "0"), 10) || void 0;
47816
- }
47817
- const shadeNode = schemeClr["a:shade"];
47818
- if (shadeNode) {
47819
- result.fontShade = parseInt(String(shadeNode["@_val"] || "0"), 10) || void 0;
47820
- }
47821
- }
47822
- }
47823
- return hasProps ? result : void 0;
48571
+ return parseTableStyleSectionText(section);
47824
48572
  }
47825
48573
  ensureArray(val) {
47826
48574
  if (!val) {
@@ -48500,6 +49248,7 @@ var PptxHandlerRuntime6 = class extends PptxHandlerRuntime5 {
48500
49248
  );
48501
49249
  const trimStartMs = timing.trimStartMs ?? extData.trimStartMs;
48502
49250
  const trimEndMs = timing.trimEndMs ?? extData.trimEndMs;
49251
+ const mediaEmbedPath = extData.embedRId ? this.resolveRelationshipTarget(slidePath, extData.embedRId) : void 0;
48503
49252
  result.set(shapeId, {
48504
49253
  trimStartMs: trimStartMs !== void 0 && !isNaN(trimStartMs) ? trimStartMs : void 0,
48505
49254
  trimEndMs: trimEndMs !== void 0 && !isNaN(trimEndMs) ? trimEndMs : void 0,
@@ -48513,7 +49262,8 @@ var PptxHandlerRuntime6 = class extends PptxHandlerRuntime5 {
48513
49262
  playAcrossSlides: timing.playAcrossSlides || void 0,
48514
49263
  hideWhenNotPlaying: hideWhenNotPlaying || void 0,
48515
49264
  bookmarks: extData.bookmarks.length > 0 ? extData.bookmarks : void 0,
48516
- playbackSpeed: extData.playbackSpeed
49265
+ playbackSpeed: extData.playbackSpeed,
49266
+ mediaEmbedPath
48517
49267
  });
48518
49268
  }
48519
49269
  }
@@ -48689,6 +49439,10 @@ var PptxHandlerRuntime7 = class extends PptxHandlerRuntime6 {
48689
49439
  if (!timing) {
48690
49440
  continue;
48691
49441
  }
49442
+ if (timing.mediaEmbedPath && (typeof el.mediaPath !== "string" || el.mediaPath.length === 0)) {
49443
+ el.mediaPath = timing.mediaEmbedPath;
49444
+ el.mediaMimeType = this.getImageMimeType(timing.mediaEmbedPath);
49445
+ }
48692
49446
  if (timing.trimStartMs !== void 0) {
48693
49447
  el.trimStartMs = timing.trimStartMs;
48694
49448
  }
@@ -49695,7 +50449,7 @@ var PptxHandlerRuntime11 = class extends PptxHandlerRuntime10 {
49695
50449
  }
49696
50450
  }
49697
50451
  async reconcilePresentationSlidesForSave(params) {
49698
- await this.presentationSlidesReconciler.reconcile({
50452
+ return await this.presentationSlidesReconciler.reconcile({
49699
50453
  ...params,
49700
50454
  zip: this.zip,
49701
50455
  parser: this.parser,
@@ -49988,6 +50742,31 @@ function applyFontMetadata(fontNode, panose, pitchFamily, charset) {
49988
50742
  }
49989
50743
  return fontNode;
49990
50744
  }
50745
+ function buildUnderlineLineXml(line2) {
50746
+ const uln = {};
50747
+ if (typeof line2.widthEmu === "number" && Number.isFinite(line2.widthEmu)) {
50748
+ uln["@_w"] = String(Math.round(line2.widthEmu));
50749
+ }
50750
+ if (line2.compound) {
50751
+ uln["@_cmpd"] = line2.compound;
50752
+ }
50753
+ if (line2.cap) {
50754
+ uln["@_cap"] = line2.cap;
50755
+ }
50756
+ if (line2.algn) {
50757
+ uln["@_algn"] = line2.algn;
50758
+ }
50759
+ if (line2.prstDash) {
50760
+ uln["a:prstDash"] = { "@_val": line2.prstDash };
50761
+ }
50762
+ if (line2.headEndXml) {
50763
+ uln["a:headEnd"] = line2.headEndXml;
50764
+ }
50765
+ if (line2.tailEndXml) {
50766
+ uln["a:tailEnd"] = line2.tailEndXml;
50767
+ }
50768
+ return uln;
50769
+ }
49991
50770
  var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime11 {
49992
50771
  createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId) {
49993
50772
  const runProps = {
@@ -50008,6 +50787,8 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
50008
50787
  }
50009
50788
  if (style.underline) {
50010
50789
  runProps["@_u"] = style.underlineStyle || "sng";
50790
+ } else if (style.underlineExplicitNone) {
50791
+ runProps["@_u"] = "none";
50011
50792
  }
50012
50793
  if (style.strikethrough !== void 0) {
50013
50794
  runProps["@_strike"] = style.strikethrough ? style.strikeType || "sngStrike" : "noStrike";
@@ -50023,6 +50804,8 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
50023
50804
  }
50024
50805
  if (style.textCaps && style.textCaps !== "none") {
50025
50806
  runProps["@_cap"] = style.textCaps;
50807
+ } else if (style.textCapsExplicitNone) {
50808
+ runProps["@_cap"] = "none";
50026
50809
  }
50027
50810
  if (style.kumimoji !== void 0) {
50028
50811
  runProps["@_kumimoji"] = style.kumimoji ? "1" : "0";
@@ -50131,13 +50914,21 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
50131
50914
  runProps["a:effectDag"] = style.textEffectDagXml;
50132
50915
  }
50133
50916
  if (style.highlightColor) {
50134
- runProps["a:highlight"] = {
50135
- "a:srgbClr": {
50136
- "@_val": style.highlightColor.replace("#", "")
50137
- }
50138
- };
50917
+ const resolvedHighlight = style.highlightColorXml ? this.parseColor(style.highlightColorXml) : void 0;
50918
+ runProps["a:highlight"] = serializeColorChoice(
50919
+ style.highlightColorXml,
50920
+ resolvedHighlight,
50921
+ style.highlightColor
50922
+ );
50923
+ }
50924
+ if (style.underlineLineFollowsText) {
50925
+ runProps["a:uLnTx"] = {};
50926
+ } else if (style.underlineLine) {
50927
+ runProps["a:uLn"] = buildUnderlineLineXml(style.underlineLine);
50139
50928
  }
50140
- if (style.underline && style.underlineColor) {
50929
+ if (style.underlineFillFollowsText) {
50930
+ runProps["a:uFillTx"] = {};
50931
+ } else if (style.underline && style.underlineColor) {
50141
50932
  runProps["a:uFill"] = {
50142
50933
  "a:solidFill": {
50143
50934
  "a:srgbClr": {
@@ -50146,21 +50937,28 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
50146
50937
  }
50147
50938
  };
50148
50939
  }
50149
- if (style.fontFamily) {
50940
+ const latinFace = style.latinFontThemeToken ?? style.fontFamily;
50941
+ if (latinFace) {
50150
50942
  runProps["a:latin"] = applyFontMetadata(
50151
- { "@_typeface": style.fontFamily },
50943
+ { "@_typeface": latinFace },
50152
50944
  style.latinFontPanose,
50153
50945
  style.latinFontPitchFamily,
50154
50946
  style.latinFontCharset
50155
50947
  );
50948
+ }
50949
+ const eastAsiaFace = style.eastAsiaFontThemeToken ?? style.eastAsiaFont;
50950
+ if (eastAsiaFace) {
50156
50951
  runProps["a:ea"] = applyFontMetadata(
50157
- { "@_typeface": style.eastAsiaFont || style.fontFamily },
50952
+ { "@_typeface": eastAsiaFace },
50158
50953
  style.eastAsiaFontPanose,
50159
50954
  style.eastAsiaFontPitchFamily,
50160
50955
  style.eastAsiaFontCharset
50161
50956
  );
50957
+ }
50958
+ const complexScriptFace = style.complexScriptFontThemeToken ?? style.complexScriptFont;
50959
+ if (complexScriptFace) {
50162
50960
  runProps["a:cs"] = applyFontMetadata(
50163
- { "@_typeface": style.complexScriptFont || style.fontFamily },
50961
+ { "@_typeface": complexScriptFace },
50164
50962
  style.complexScriptFontPanose,
50165
50963
  style.complexScriptFontPitchFamily,
50166
50964
  style.complexScriptFontCharset
@@ -50210,12 +51008,17 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
50210
51008
  if (mouseOverTarget.length > 0) {
50211
51009
  const mouseOverRelId = resolveHyperlinkRelationshipId(mouseOverTarget);
50212
51010
  if (mouseOverRelId) {
50213
- runProps["a:hlinkMouseOver"] = {
50214
- "@_r:id": mouseOverRelId
50215
- };
51011
+ const mouseOverNode = { "@_r:id": mouseOverRelId };
51012
+ if (style.hyperlinkMouseOverSoundXml && typeof style.hyperlinkMouseOverSoundXml === "object") {
51013
+ mouseOverNode["a:snd"] = style.hyperlinkMouseOverSoundXml;
51014
+ }
51015
+ runProps["a:hlinkMouseOver"] = mouseOverNode;
50216
51016
  }
50217
51017
  }
50218
51018
  }
51019
+ if (style.runPropertiesExtLstXml && typeof style.runPropertiesExtLstXml === "object") {
51020
+ runProps["a:extLst"] = style.runPropertiesExtLstXml;
51021
+ }
50219
51022
  return runProps;
50220
51023
  }
50221
51024
  applyHyperlinkExtraAttrs(hlinkNode, style) {
@@ -50234,22 +51037,26 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
50234
51037
  if (style.hyperlinkEndSound !== void 0) {
50235
51038
  hlinkNode["@_endSnd"] = style.hyperlinkEndSound ? "1" : "0";
50236
51039
  }
51040
+ if (style.hyperlinkSoundXml && typeof style.hyperlinkSoundXml === "object") {
51041
+ hlinkNode["a:snd"] = style.hyperlinkSoundXml;
51042
+ }
50237
51043
  }
50238
51044
  };
50239
51045
 
50240
51046
  // src/core/core/runtime/PptxHandlerRuntimeSaveParagraphs.ts
50241
51047
  var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
50242
51048
  createParagraphsFromTextContent(text2, textStyle, textSegments, resolveHyperlinkRelationshipId) {
50243
- const paragraphAlign = this.textAlignToDrawingValue(textStyle?.align);
50244
- const spacing = {
50245
- spacingBefore: this.createParagraphSpacingXmlFromPx(textStyle?.paragraphSpacingBefore),
50246
- spacingAfter: this.createParagraphSpacingXmlFromPx(textStyle?.paragraphSpacingAfter),
50247
- lineSpacing: this.createLineSpacingXmlFromMultiplier(textStyle?.lineSpacing),
50248
- lineSpacingExactPt: textStyle?.lineSpacingExactPt
50249
- };
50250
- const createParagraph = (runs, bulletInfo, level, endParaRunProperties) => {
51049
+ const createParagraph = (runs, bulletInfo, level, endParaRunProperties, paragraphProperties2) => {
51050
+ const effectiveStyle = paragraphProperties2 ? { ...textStyle, ...paragraphProperties2 } : textStyle;
51051
+ const paragraphAlign = this.textAlignToDrawingValue(effectiveStyle?.align);
51052
+ const spacing = {
51053
+ spacingBefore: this.createParagraphSpacingXmlFromPx(effectiveStyle?.paragraphSpacingBefore),
51054
+ spacingAfter: this.createParagraphSpacingXmlFromPx(effectiveStyle?.paragraphSpacingAfter),
51055
+ lineSpacing: this.createLineSpacingXmlFromMultiplier(effectiveStyle?.lineSpacing),
51056
+ lineSpacingExactPt: effectiveStyle?.lineSpacingExactPt
51057
+ };
50251
51058
  const paragraphProps = buildParagraphPropertiesXml(
50252
- textStyle,
51059
+ effectiveStyle,
50253
51060
  paragraphAlign,
50254
51061
  bulletInfo,
50255
51062
  spacing,
@@ -50261,12 +51068,22 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
50261
51068
  "a:rPr": this.createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId),
50262
51069
  "a:t": runText
50263
51070
  });
50264
- const createFieldRun = (runText, style, fieldType, fieldGuid) => ({
50265
- "@_type": fieldType,
50266
- ...fieldGuid ? { "@_id": fieldGuid } : {},
50267
- "a:rPr": this.createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId),
50268
- "a:t": runText
50269
- });
51071
+ const createFieldRun = (runText, style, fieldType, fieldGuid, fieldGuidAttr, fieldParagraphPropertiesXml) => {
51072
+ const fld = { "@_type": fieldType };
51073
+ if (fieldGuid) {
51074
+ if (fieldGuidAttr === "uuid") {
51075
+ fld["@_uuid"] = fieldGuid;
51076
+ } else {
51077
+ fld["@_id"] = fieldGuid;
51078
+ }
51079
+ }
51080
+ fld["a:rPr"] = this.createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId);
51081
+ if (fieldParagraphPropertiesXml && typeof fieldParagraphPropertiesXml === "object") {
51082
+ fld["a:pPr"] = fieldParagraphPropertiesXml;
51083
+ }
51084
+ fld["a:t"] = runText;
51085
+ return fld;
51086
+ };
50270
51087
  const createRubyRun = (segment, style) => {
50271
51088
  const rubyPr = {};
50272
51089
  if (segment.rubyAlignment) {
@@ -50305,17 +51122,27 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
50305
51122
  let currentBulletInfo;
50306
51123
  let currentLevel;
50307
51124
  let currentEndParaRunProperties;
51125
+ let currentParagraphProperties;
51126
+ let capturedParagraphMeta = false;
50308
51127
  const pushParagraph = () => {
50309
51128
  if (currentRuns.length === 0) {
50310
51129
  currentRuns.push(createRun("", textStyle));
50311
51130
  }
50312
51131
  paragraphs.push(
50313
- createParagraph(currentRuns, currentBulletInfo, currentLevel, currentEndParaRunProperties)
51132
+ createParagraph(
51133
+ currentRuns,
51134
+ currentBulletInfo,
51135
+ currentLevel,
51136
+ currentEndParaRunProperties,
51137
+ currentParagraphProperties
51138
+ )
50314
51139
  );
50315
51140
  currentRuns = [];
50316
51141
  currentBulletInfo = void 0;
50317
51142
  currentLevel = void 0;
50318
51143
  currentEndParaRunProperties = void 0;
51144
+ currentParagraphProperties = void 0;
51145
+ capturedParagraphMeta = false;
50319
51146
  };
50320
51147
  if (textSegments && textSegments.length > 0) {
50321
51148
  const uniformSegmentOverrides = computeUniformSegmentOverrides(textStyle, textSegments);
@@ -50325,7 +51152,7 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
50325
51152
  ...segment.style,
50326
51153
  ...uniformSegmentOverrides
50327
51154
  };
50328
- if (currentRuns.length === 0) {
51155
+ if (!capturedParagraphMeta) {
50329
51156
  if (segment.bulletInfo) {
50330
51157
  currentBulletInfo = segment.bulletInfo;
50331
51158
  }
@@ -50335,6 +51162,10 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
50335
51162
  if (segment.endParaRunProperties) {
50336
51163
  currentEndParaRunProperties = segment.endParaRunProperties;
50337
51164
  }
51165
+ if (segment.paragraphProperties) {
51166
+ currentParagraphProperties = segment.paragraphProperties;
51167
+ }
51168
+ capturedParagraphMeta = true;
50338
51169
  }
50339
51170
  if (segment.isLineBreak) {
50340
51171
  const brNode = {};
@@ -50369,7 +51200,9 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
50369
51200
  linePart,
50370
51201
  segmentStyle,
50371
51202
  segment.fieldType,
50372
- segment.fieldGuid
51203
+ segment.fieldGuid,
51204
+ segment.fieldGuidAttr,
51205
+ segment.fieldParagraphPropertiesXml
50373
51206
  );
50374
51207
  fieldRun.__isField = true;
50375
51208
  currentRuns.push(fieldRun);
@@ -51134,7 +51967,95 @@ var PptxHandlerRuntime16 = class extends PptxHandlerRuntime15 {
51134
51967
  };
51135
51968
 
51136
51969
  // src/core/core/runtime/PptxHandlerRuntimeTextStyleUtils.ts
51970
+ var SCRIPT_CANDIDATES = {
51971
+ cjk: ["Hans", "Hant", "Jpan", "Hang"],
51972
+ kana: ["Jpan", "Hans", "Hant"],
51973
+ hangul: ["Hang"],
51974
+ arabic: ["Arab"],
51975
+ hebrew: ["Hebr"],
51976
+ thai: ["Thai"]
51977
+ };
51978
+ function aggregateFontScriptOverrides(perPathMap) {
51979
+ const aggregate = {};
51980
+ for (const overrides10 of perPathMap.values()) {
51981
+ for (const [script, typeface] of Object.entries(overrides10)) {
51982
+ if (!(script in aggregate)) {
51983
+ aggregate[script] = typeface;
51984
+ }
51985
+ }
51986
+ }
51987
+ return aggregate;
51988
+ }
51989
+ function detectDominantScript(text2) {
51990
+ const counts = {};
51991
+ for (const ch of text2) {
51992
+ const code = ch.codePointAt(0) ?? 0;
51993
+ let cat;
51994
+ if (code >= 4352 && code <= 4607) {
51995
+ cat = "hangul";
51996
+ } else if (code >= 44032 && code <= 55215) {
51997
+ cat = "hangul";
51998
+ } else if (code >= 12352 && code <= 12543) {
51999
+ cat = "kana";
52000
+ } else if (code >= 19968 && code <= 40959 || code >= 13312 && code <= 19903 || code >= 63744 && code <= 64255) {
52001
+ cat = "cjk";
52002
+ } else if (code >= 1536 && code <= 1791) {
52003
+ cat = "arabic";
52004
+ } else if (code >= 1424 && code <= 1535) {
52005
+ cat = "hebrew";
52006
+ } else if (code >= 3584 && code <= 3711) {
52007
+ cat = "thai";
52008
+ }
52009
+ if (cat) {
52010
+ counts[cat] = (counts[cat] ?? 0) + 1;
52011
+ }
52012
+ }
52013
+ let best;
52014
+ let bestCount = 0;
52015
+ for (const [cat, count] of Object.entries(counts)) {
52016
+ if (count > bestCount) {
52017
+ best = cat;
52018
+ bestCount = count;
52019
+ }
52020
+ }
52021
+ return best;
52022
+ }
51137
52023
  var PptxHandlerRuntime17 = class extends PptxHandlerRuntime16 {
52024
+ /**
52025
+ * Resolve the automatic per-script fallback face for a run's text from the
52026
+ * theme's `<a:font script="...">` overrides (#83). Body (minor) fonts win
52027
+ * over heading (major) fonts. Returns `undefined` when the deck declares no
52028
+ * script overrides or the text needs no fallback.
52029
+ */
52030
+ resolveScriptFallbackFont(text2) {
52031
+ if (!text2) {
52032
+ return void 0;
52033
+ }
52034
+ if (this.masterThemeMinorFontScripts.size === 0 && this.masterThemeMajorFontScripts.size === 0) {
52035
+ return void 0;
52036
+ }
52037
+ const category = detectDominantScript(text2);
52038
+ if (!category) {
52039
+ return void 0;
52040
+ }
52041
+ const candidates = SCRIPT_CANDIDATES[category];
52042
+ if (!candidates) {
52043
+ return void 0;
52044
+ }
52045
+ const minor = aggregateFontScriptOverrides(this.masterThemeMinorFontScripts);
52046
+ for (const key of candidates) {
52047
+ if (minor[key]) {
52048
+ return minor[key];
52049
+ }
52050
+ }
52051
+ const major = aggregateFontScriptOverrides(this.masterThemeMajorFontScripts);
52052
+ for (const key of candidates) {
52053
+ if (major[key]) {
52054
+ return major[key];
52055
+ }
52056
+ }
52057
+ return void 0;
52058
+ }
51138
52059
  textStylesEqual(left, right) {
51139
52060
  const keys = [
51140
52061
  "fontFamily",
@@ -51295,6 +52216,10 @@ var PptxHandlerRuntime18 = class extends PptxHandlerRuntime17 {
51295
52216
  const esVal = String(endSnd).trim().toLowerCase();
51296
52217
  style.hyperlinkEndSound = esVal === "1" || esVal === "true";
51297
52218
  }
52219
+ const clickSnd = hyperlinkNode["a:snd"];
52220
+ if (clickSnd && typeof clickSnd === "object") {
52221
+ style.hyperlinkSoundXml = clickSnd;
52222
+ }
51298
52223
  }
51299
52224
  const actionStr = String(hyperlinkNode?.["@_action"] || "").trim();
51300
52225
  if (actionStr) {
@@ -51324,6 +52249,10 @@ var PptxHandlerRuntime18 = class extends PptxHandlerRuntime17 {
51324
52249
  } else {
51325
52250
  style.hyperlinkMouseOver = mouseOverRelId;
51326
52251
  }
52252
+ const mouseOverSnd = hlinkMouseOver["a:snd"];
52253
+ if (mouseOverSnd && typeof mouseOverSnd === "object") {
52254
+ style.hyperlinkMouseOverSoundXml = mouseOverSnd;
52255
+ }
51327
52256
  }
51328
52257
  }
51329
52258
  }
@@ -51550,6 +52479,8 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
51550
52479
  if (rawU.length > 0 && rawU !== "none") {
51551
52480
  style.underlineStyle = rawU;
51552
52481
  }
52482
+ } else if (underlineToken === "none") {
52483
+ style.underlineExplicitNone = true;
51553
52484
  }
51554
52485
  }
51555
52486
  const uFill = runProperties2["a:uFill"];
@@ -51561,6 +52492,46 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
51561
52492
  style.underlineColor = underlineColor;
51562
52493
  }
51563
52494
  }
52495
+ if (uLn) {
52496
+ const line2 = {};
52497
+ const widthEmu = Number.parseInt(String(uLn["@_w"] ?? ""), 10);
52498
+ if (Number.isFinite(widthEmu)) {
52499
+ line2.widthEmu = widthEmu;
52500
+ }
52501
+ const compound = String(uLn["@_cmpd"] ?? "").trim();
52502
+ if (compound) {
52503
+ line2.compound = compound;
52504
+ }
52505
+ const cap = String(uLn["@_cap"] ?? "").trim();
52506
+ if (cap) {
52507
+ line2.cap = cap;
52508
+ }
52509
+ const algn = String(uLn["@_algn"] ?? "").trim();
52510
+ if (algn) {
52511
+ line2.algn = algn;
52512
+ }
52513
+ const prstDash = String(uLn["a:prstDash"]?.["@_val"] ?? "").trim();
52514
+ if (prstDash) {
52515
+ line2.prstDash = prstDash;
52516
+ }
52517
+ const headEnd = uLn["a:headEnd"];
52518
+ if (headEnd && typeof headEnd === "object") {
52519
+ line2.headEndXml = headEnd;
52520
+ }
52521
+ const tailEnd = uLn["a:tailEnd"];
52522
+ if (tailEnd && typeof tailEnd === "object") {
52523
+ line2.tailEndXml = tailEnd;
52524
+ }
52525
+ if (Object.keys(line2).length > 0) {
52526
+ style.underlineLine = line2;
52527
+ }
52528
+ }
52529
+ if (runProperties2["a:uLnTx"] !== void 0) {
52530
+ style.underlineLineFollowsText = true;
52531
+ }
52532
+ if (runProperties2["a:uFillTx"] !== void 0) {
52533
+ style.underlineFillFollowsText = true;
52534
+ }
51564
52535
  if (runProperties2["@_strike"] !== void 0) {
51565
52536
  const strikeToken = String(runProperties2["@_strike"] || "").trim().toLowerCase();
51566
52537
  style.strikethrough = strikeToken.length > 0 && strikeToken !== "nostrike" && strikeToken !== "none" && strikeToken !== "0" && strikeToken !== "false";
@@ -51604,10 +52575,15 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
51604
52575
  }
51605
52576
  }
51606
52577
  if (runProperties2["a:highlight"]) {
51607
- const highlightHex = this.parseColor(xmlChild(runProperties2, "a:highlight"));
52578
+ const highlightNode = xmlChild(runProperties2, "a:highlight");
52579
+ const highlightHex = this.parseColor(highlightNode);
51608
52580
  if (highlightHex) {
51609
52581
  style.highlightColor = highlightHex;
51610
52582
  }
52583
+ const highlightXml = extractColorChoiceXml(highlightNode);
52584
+ if (highlightXml) {
52585
+ style.highlightColorXml = highlightXml;
52586
+ }
51611
52587
  }
51612
52588
  const textFillVariants = this.extractTextFillVariants(runProperties2);
51613
52589
  if (textFillVariants.textFillGradient) {
@@ -51628,16 +52604,28 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
51628
52604
  const latin = xmlChild(runProperties2, "a:latin");
51629
52605
  const eastAsian = xmlChild(runProperties2, "a:ea");
51630
52606
  const complexScript = xmlChild(runProperties2, "a:cs");
51631
- const chosenTypeface = xmlAttr(latin, "typeface") || xmlAttr(eastAsian, "typeface") || xmlAttr(complexScript, "typeface");
52607
+ const latinTypefaceToken = xmlAttr(latin, "typeface");
52608
+ const eaTypefaceToken = xmlAttr(eastAsian, "typeface");
52609
+ const csTypefaceToken = xmlAttr(complexScript, "typeface");
52610
+ const chosenTypeface = latinTypefaceToken || eaTypefaceToken || csTypefaceToken;
51632
52611
  const resolvedTypeface = this.resolveThemeTypeface(chosenTypeface);
51633
52612
  if (resolvedTypeface) {
51634
52613
  style.fontFamily = resolvedTypeface;
51635
52614
  }
51636
- const eaTypeface = this.resolveThemeTypeface(xmlAttr(eastAsian, "typeface"));
52615
+ if (latinTypefaceToken && latinTypefaceToken.startsWith("+")) {
52616
+ style.latinFontThemeToken = latinTypefaceToken;
52617
+ }
52618
+ if (eaTypefaceToken && eaTypefaceToken.startsWith("+")) {
52619
+ style.eastAsiaFontThemeToken = eaTypefaceToken;
52620
+ }
52621
+ if (csTypefaceToken && csTypefaceToken.startsWith("+")) {
52622
+ style.complexScriptFontThemeToken = csTypefaceToken;
52623
+ }
52624
+ const eaTypeface = this.resolveThemeTypeface(eaTypefaceToken);
51637
52625
  if (eaTypeface) {
51638
52626
  style.eastAsiaFont = eaTypeface;
51639
52627
  }
51640
- const csTypeface = this.resolveThemeTypeface(xmlAttr(complexScript, "typeface"));
52628
+ const csTypeface = this.resolveThemeTypeface(csTypefaceToken);
51641
52629
  if (csTypeface) {
51642
52630
  style.complexScriptFont = csTypeface;
51643
52631
  }
@@ -51653,6 +52641,9 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
51653
52641
  const capAttr = String(runProperties2["@_cap"] || "").trim().toLowerCase();
51654
52642
  if (capAttr === "all" || capAttr === "small") {
51655
52643
  style.textCaps = capAttr;
52644
+ } else if (capAttr === "none") {
52645
+ style.textCaps = "none";
52646
+ style.textCapsExplicitNone = true;
51656
52647
  }
51657
52648
  const symNode = xmlChild(runProperties2, "a:sym");
51658
52649
  if (symNode) {
@@ -51712,6 +52703,12 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
51712
52703
  this.applyTextRunEffects(style, runEffectList);
51713
52704
  }
51714
52705
  this.applyTextRunEffectDag(style, runProperties2);
52706
+ if (includeDefaultAlignment) {
52707
+ const runExtLst = runProperties2["a:extLst"];
52708
+ if (runExtLst && typeof runExtLst === "object") {
52709
+ style.runPropertiesExtLstXml = runExtLst;
52710
+ }
52711
+ }
51715
52712
  return style;
51716
52713
  }
51717
52714
  /**
@@ -52383,12 +53380,63 @@ function writeCellTextFormatting(xmlCell, style, ensureArray16) {
52383
53380
  }
52384
53381
 
52385
53382
  // src/core/core/runtime/PptxHandlerRuntimeSaveTableStyles.ts
53383
+ function flattenCellTxBodyText(txBody, ensureArray16) {
53384
+ if (!txBody) {
53385
+ return "";
53386
+ }
53387
+ const paragraphs = ensureArray16(txBody["a:p"]);
53388
+ const lines = [];
53389
+ for (const paragraph of paragraphs) {
53390
+ const runs = ensureArray16(paragraph?.["a:r"]);
53391
+ const fields = ensureArray16(paragraph?.["a:fld"]);
53392
+ let lineText = "";
53393
+ for (const run of runs) {
53394
+ lineText += String(run?.["a:t"] ?? "");
53395
+ }
53396
+ for (const field of fields) {
53397
+ lineText += String(field?.["a:t"] ?? "");
53398
+ }
53399
+ lines.push(lineText);
53400
+ }
53401
+ return lines.join("\n");
53402
+ }
53403
+ function isRichCellTxBody(txBody, ensureArray16) {
53404
+ if (!txBody) {
53405
+ return false;
53406
+ }
53407
+ const paragraphs = ensureArray16(txBody["a:p"]);
53408
+ let totalRuns = 0;
53409
+ for (const paragraph of paragraphs) {
53410
+ const runs = ensureArray16(paragraph?.["a:r"]);
53411
+ totalRuns += runs.length;
53412
+ if (totalRuns > 1) {
53413
+ return true;
53414
+ }
53415
+ if (ensureArray16(paragraph?.["a:fld"]).length > 0) {
53416
+ return true;
53417
+ }
53418
+ for (const run of runs) {
53419
+ const rPr = run?.["a:rPr"];
53420
+ if (rPr?.["a:hlinkClick"] !== void 0) {
53421
+ return true;
53422
+ }
53423
+ }
53424
+ }
53425
+ return false;
53426
+ }
52386
53427
  var PptxHandlerRuntime22 = class _PptxHandlerRuntime extends PptxHandlerRuntime21 {
52387
53428
  /**
52388
53429
  * Write plain text into a table cell's txBody, preserving
52389
53430
  * existing run properties where possible.
52390
53431
  */
52391
53432
  writeTableCellText(xmlCell, text2) {
53433
+ const ensureArray16 = this.ensureArray.bind(this);
53434
+ const existingTxBody = xmlCell["a:txBody"];
53435
+ if (existingTxBody && ensureArray16(existingTxBody["a:p"]).length > 0) {
53436
+ if (flattenCellTxBodyText(existingTxBody, ensureArray16) === text2) {
53437
+ return;
53438
+ }
53439
+ }
52392
53440
  if (!xmlCell["a:txBody"]) {
52393
53441
  xmlCell["a:txBody"] = { "a:bodyPr": {}, "a:p": {} };
52394
53442
  }
@@ -52516,7 +53564,9 @@ var PptxHandlerRuntime22 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
52516
53564
  }
52517
53565
  delete tcPr["a:tcMar"];
52518
53566
  writeDiagonalBorders(tcPr, style, _PptxHandlerRuntime.EMU_PER_PX);
52519
- writeCellTextFormatting(xmlCell, style, this.ensureArray.bind(this));
53567
+ if (!isRichCellTxBody(xmlCell["a:txBody"], this.ensureArray.bind(this))) {
53568
+ writeCellTextFormatting(xmlCell, style, this.ensureArray.bind(this));
53569
+ }
52520
53570
  const reordered = reorderObjectKeys(tcPr, TC_PR_BORDERS_ORDER);
52521
53571
  for (const key of Object.keys(tcPr)) {
52522
53572
  delete tcPr[key];
@@ -54201,7 +55251,7 @@ function findKey19(obj, name, getLocalName2) {
54201
55251
  function hex9(value) {
54202
55252
  return value.replace("#", "");
54203
55253
  }
54204
- var COLOR_LOCAL_NAMES = /* @__PURE__ */ new Set([
55254
+ var COLOR_LOCAL_NAMES2 = /* @__PURE__ */ new Set([
54205
55255
  "srgbClr",
54206
55256
  "schemeClr",
54207
55257
  "sysClr",
@@ -54210,7 +55260,7 @@ var COLOR_LOCAL_NAMES = /* @__PURE__ */ new Set([
54210
55260
  "hslClr"
54211
55261
  ]);
54212
55262
  function applyColorToList(list, value, getLocalName2) {
54213
- const colorKey = Object.keys(list).find((k) => COLOR_LOCAL_NAMES.has(getLocalName2(k)));
55263
+ const colorKey = Object.keys(list).find((k) => COLOR_LOCAL_NAMES2.has(getLocalName2(k)));
54214
55264
  const srgb = { "@_val": hex9(value) };
54215
55265
  if (!colorKey) {
54216
55266
  list["a:srgbClr"] = srgb;
@@ -56702,6 +57752,33 @@ var PptxHandlerRuntime27 = class extends PptxHandlerRuntime26 {
56702
57752
  }
56703
57753
  };
56704
57754
 
57755
+ // src/core/core/runtime/save-line-fill.ts
57756
+ function writeLineFill(lineNode, shapeStyle, parseColor) {
57757
+ delete lineNode["a:noFill"];
57758
+ delete lineNode["a:solidFill"];
57759
+ delete lineNode["a:gradFill"];
57760
+ delete lineNode["a:pattFill"];
57761
+ if (shapeStyle.strokeColor === "transparent" || shapeStyle.strokeWidth === 0) {
57762
+ lineNode["a:noFill"] = {};
57763
+ return;
57764
+ }
57765
+ if (shapeStyle.strokeFillMode === "gradient" && shapeStyle.strokeGradientXml) {
57766
+ lineNode["a:gradFill"] = shapeStyle.strokeGradientXml;
57767
+ return;
57768
+ }
57769
+ if (shapeStyle.strokeFillMode === "pattern" && shapeStyle.strokePatternXml) {
57770
+ lineNode["a:pattFill"] = shapeStyle.strokePatternXml;
57771
+ return;
57772
+ }
57773
+ const resolvedStrokeOriginal = shapeStyle.strokeColorXml ? parseColor(shapeStyle.strokeColorXml) : void 0;
57774
+ lineNode["a:solidFill"] = serializeColorChoice(
57775
+ shapeStyle.strokeColorXml,
57776
+ resolvedStrokeOriginal,
57777
+ shapeStyle.strokeColor ?? "#000000",
57778
+ shapeStyle.strokeOpacity
57779
+ );
57780
+ }
57781
+
56705
57782
  // src/core/core/runtime/PptxHandlerRuntimeSaveShapeStyleWriter.ts
56706
57783
  var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime27 {
56707
57784
  /**
@@ -56772,26 +57849,14 @@ var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
56772
57849
  );
56773
57850
  }
56774
57851
  }
56775
- if (shapeStyle.strokeColor !== void 0) {
57852
+ if (shapeStyle.strokeColor !== void 0 || shapeStyle.strokeFillMode === "gradient" || shapeStyle.strokeFillMode === "pattern") {
56776
57853
  if (!spPr["a:ln"]) {
56777
57854
  spPr["a:ln"] = {};
56778
57855
  }
56779
57856
  const lineNode = spPr["a:ln"];
56780
57857
  const w = Math.round((shapeStyle.strokeWidth || 1) * _PptxHandlerRuntime.EMU_PER_PX);
56781
57858
  lineNode["@_w"] = String(w);
56782
- if (shapeStyle.strokeColor === "transparent" || shapeStyle.strokeWidth === 0) {
56783
- lineNode["a:noFill"] = {};
56784
- delete lineNode["a:solidFill"];
56785
- } else {
56786
- delete lineNode["a:noFill"];
56787
- const resolvedStrokeOriginal = shapeStyle.strokeColorXml ? this.parseColor(shapeStyle.strokeColorXml) : void 0;
56788
- lineNode["a:solidFill"] = serializeColorChoice(
56789
- shapeStyle.strokeColorXml,
56790
- resolvedStrokeOriginal,
56791
- shapeStyle.strokeColor,
56792
- shapeStyle.strokeOpacity
56793
- );
56794
- }
57859
+ this.applyLineFill(lineNode, shapeStyle);
56795
57860
  }
56796
57861
  if (shapeStyle.strokeDash !== void 0) {
56797
57862
  if (!spPr["a:ln"]) {
@@ -56881,6 +57946,15 @@ var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
56881
57946
  spPr["a:ln"]["a:effectLst"] = lineEffectListXml;
56882
57947
  }
56883
57948
  }
57949
+ /**
57950
+ * Emit the single fill child of an `<a:ln>` (CT_LineProperties allows at
57951
+ * most one of noFill/solidFill/gradFill/pattFill). Delegates to
57952
+ * {@link writeLineFill} so the logic stays unit-testable without the full
57953
+ * save runtime (issue #87).
57954
+ */
57955
+ applyLineFill(lineNode, shapeStyle) {
57956
+ writeLineFill(lineNode, shapeStyle, (colorNode) => this.parseColor(colorNode));
57957
+ }
56884
57958
  /**
56885
57959
  * Serialize the shape's `<p:style>` block (CT_ShapeStyle §20.1.2.2.36)
56886
57960
  * from the persisted ref indices/colour XML. Emits children in spec
@@ -59220,14 +60294,20 @@ var PptxHandlerRuntime41 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
59220
60294
  relationshipType: constants.slideSyncRelationshipType,
59221
60295
  contentType: constants.slideSyncContentType
59222
60296
  });
59223
- this.slideBackgroundBuilder.applyBackground({
60297
+ await this.slideBackgroundBuilder.applyBackground({
59224
60298
  slideNode,
59225
60299
  slide,
59226
60300
  zip: this.zip,
59227
60301
  saveState: saveSession,
59228
60302
  relationshipRegistry: slideRelationshipRegistry,
59229
60303
  slideImageRelationshipType: constants.slideImageRelationshipType,
59230
- parseDataUrlToBytes: (dataUrl) => this.parseDataUrlToBytes(dataUrl)
60304
+ resolveImageToBytes: (url) => this.resolveMediaToBytes(url),
60305
+ reportUnsupportedBackground: (imageUrl) => this.compatibilityService.reportWarning({
60306
+ code: "SAVE_BACKGROUND_IMAGE_UNSUPPORTED",
60307
+ message: `Slide background image could not be embedded and was preserved as-is or omitted: ${imageUrl.slice(0, 120)}`,
60308
+ scope: "save",
60309
+ slideId: slide.id
60310
+ })
59231
60311
  });
59232
60312
  this.slideCommentPartWriter.writeComments({
59233
60313
  slide,
@@ -60732,7 +61812,7 @@ var PptxHandlerRuntime51 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
60732
61812
  } = saveConstants;
60733
61813
  this.compatibilityService.resetWarnings();
60734
61814
  const saveSession = new PptxSaveStateBuilder().withZip(this.zip).withCommentAuthorMap(this.commentAuthorMap).withCommentAuthorDetails(this.commentAuthorDetails).withCommentAuthorsRootXml(this.commentAuthorsRootXml).withEmuPerPx(_PptxHandlerRuntime.EMU_PER_PX).build();
60735
- await this.reconcilePresentationSlidesForSave({
61815
+ const slideReferenceRemap = await this.reconcilePresentationSlidesForSave({
60736
61816
  slides,
60737
61817
  saveSession,
60738
61818
  slideRelationshipType,
@@ -60827,7 +61907,8 @@ var PptxHandlerRuntime51 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
60827
61907
  rawSlideWidthEmu: this.rawSlideWidthEmu,
60828
61908
  rawSlideHeightEmu: this.rawSlideHeightEmu,
60829
61909
  rawSlideSizeType: this.rawSlideSizeType,
60830
- xmlLookupService: this.xmlLookupService
61910
+ xmlLookupService: this.xmlLookupService,
61911
+ slideReferenceRemap
60831
61912
  });
60832
61913
  this.deduplicateExtensionLists(this.presentationData);
60833
61914
  if (effectiveConformance === "transitional") {
@@ -60844,7 +61925,7 @@ var PptxHandlerRuntime51 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
60844
61925
  printSlidesPerPage: options.handoutMaster.slidesPerPage
60845
61926
  } : options?.presentationProperties;
60846
61927
  await this.applyPresentationPropertiesPart(presentationProperties);
60847
- await this.applyViewPropertiesPart(options?.viewProperties);
61928
+ await this.applyViewPropertiesPart(options?.viewProperties ?? this.loadedViewProperties);
60848
61929
  await this.applyTableStylesPart(options?.tableStyles);
60849
61930
  await this.documentPropertiesUpdater.updateOnSave(slides, {
60850
61931
  coreProperties: options?.coreProperties,
@@ -61132,26 +62213,16 @@ var PptxHandlerRuntime52 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
61132
62213
  return true;
61133
62214
  }
61134
62215
  const typesMatch = source.type === target.type || source.type === "ctrtitle" && target.type === "title" || source.type === "subtitle" && target.type === "body";
61135
- if (source.idx !== void 0 && target.idx !== void 0) {
61136
- if (source.idx !== target.idx) {
61137
- return false;
61138
- }
61139
- if (source.type && target.type && !typesMatch) {
61140
- return false;
61141
- }
61142
- return true;
61143
- }
61144
- if (source.idx !== void 0 && target.idx === void 0) {
61145
- const singletonTypes = /* @__PURE__ */ new Set(["title", "ctrtitle", "subtitle", "dt", "ftr", "sldnum"]);
61146
- if (source.type && singletonTypes.has(source.type)) {
61147
- return typesMatch;
61148
- }
62216
+ const sourceIdx = source.idx ?? "0";
62217
+ const targetIdx = target.idx ?? "0";
62218
+ if (sourceIdx !== targetIdx) {
61149
62219
  return false;
61150
62220
  }
61151
62221
  if (source.type && target.type && !typesMatch) {
61152
62222
  return false;
61153
62223
  }
61154
- if (source.type && !target.type) {
62224
+ const bothHaveExplicitIdx = source.idx !== void 0 && target.idx !== void 0;
62225
+ if (!bothHaveExplicitIdx && source.type && !target.type) {
61155
62226
  return false;
61156
62227
  }
61157
62228
  return true;
@@ -62597,6 +63668,19 @@ var PptxHandlerRuntime61 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
62597
63668
  });
62598
63669
  return hasAny ? locks : void 0;
62599
63670
  }
63671
+ /**
63672
+ * Parse the `@txBox` attribute from a `p:cNvSpPr` node. Returns `true` /
63673
+ * `false` when the attribute is present, or `undefined` when absent so
63674
+ * callers can distinguish "not a text box" from "unspecified".
63675
+ */
63676
+ parseTxBoxFlag(cNvSpPr) {
63677
+ const raw = cNvSpPr?.["@_txBox"];
63678
+ if (raw === void 0) {
63679
+ return void 0;
63680
+ }
63681
+ const val = String(raw).trim().toLowerCase();
63682
+ return val === "1" || val === "true";
63683
+ }
62600
63684
  /**
62601
63685
  * Extract body-level text properties from `a:bodyPr` and apply them to the
62602
63686
  * provided {@link TextStyle}. Returns linked-textbox info when present.
@@ -62779,6 +63863,62 @@ var PptxHandlerRuntime61 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
62779
63863
 
62780
63864
  // src/core/core/runtime/PptxHandlerRuntimeShapeTextParsing.ts
62781
63865
  var PptxHandlerRuntime62 = class _PptxHandlerRuntime extends PptxHandlerRuntime61 {
63866
+ /**
63867
+ * Extract a paragraph's OWN `a:pPr` geometry (align, spacing, margins,
63868
+ * indent, tabs, rtl) as a partial {@link TextStyle} so per-paragraph
63869
+ * formatting round-trips rather than collapsing to one shape-level pPr
63870
+ * (#69). Inherited layout/master values are not re-stamped.
63871
+ */
63872
+ extractParagraphOwnProperties(p, basisFontSize) {
63873
+ const pPr = p["a:pPr"];
63874
+ if (!pPr) {
63875
+ return void 0;
63876
+ }
63877
+ const pp = { ...parseParagraphMargins(pPr) };
63878
+ const align = pPr["@_algn"] !== void 0 ? parseAlignmentAttr2(String(pPr["@_algn"])) : void 0;
63879
+ if (align) {
63880
+ pp.align = align;
63881
+ }
63882
+ const rtl = parseParagraphRtl(pPr);
63883
+ if (rtl !== void 0) {
63884
+ pp.rtl = rtl;
63885
+ }
63886
+ const spcBef = this.parseParagraphSpacingPx(
63887
+ pPr["a:spcBef"],
63888
+ basisFontSize
63889
+ );
63890
+ if (spcBef !== void 0) {
63891
+ pp.paragraphSpacingBefore = spcBef;
63892
+ }
63893
+ const spcAft = this.parseParagraphSpacingPx(
63894
+ pPr["a:spcAft"],
63895
+ basisFontSize
63896
+ );
63897
+ if (spcAft !== void 0) {
63898
+ pp.paragraphSpacingAfter = spcAft;
63899
+ }
63900
+ const lnSpcNode = pPr["a:lnSpc"];
63901
+ const lineSpacing = this.parseLineSpacingMultiplier(lnSpcNode);
63902
+ const exactPt = lineSpacing === void 0 ? this.parseLineSpacingExactPt(lnSpcNode) : void 0;
63903
+ if (lineSpacing !== void 0) {
63904
+ pp.lineSpacing = lineSpacing;
63905
+ } else if (exactPt !== void 0) {
63906
+ pp.lineSpacingExactPt = exactPt;
63907
+ }
63908
+ const tabStops = parseTabStops(pPr);
63909
+ if (tabStops && tabStops.length > 0) {
63910
+ pp.tabStops = tabStops;
63911
+ }
63912
+ const defRPr = pPr["a:defRPr"];
63913
+ if (defRPr && typeof defRPr === "object") {
63914
+ pp.paragraphDefaultRunPropertiesXml = defRPr;
63915
+ }
63916
+ const pPrExtLst = pPr["a:extLst"];
63917
+ if (pPrExtLst && typeof pPrExtLst === "object") {
63918
+ pp.paragraphPropertiesExtLstXml = pPrExtLst;
63919
+ }
63920
+ return Object.keys(pp).length > 0 ? pp : void 0;
63921
+ }
62782
63922
  /**
62783
63923
  * Resolve paragraph-level styles (alignment, spacing, margins, tabs,
62784
63924
  * level styles) for a single paragraph. Modifies `textStyle` in place
@@ -63027,6 +64167,12 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
63027
64167
  ...mergedDefaultRunStyle,
63028
64168
  ...this.extractTextRunStyle(runProps, paraAlign, ctx.slideRelationshipMap)
63029
64169
  };
64170
+ if (!runStyle2.scriptFallbackFont) {
64171
+ const fallback = this.resolveScriptFallbackFont(runText);
64172
+ if (fallback) {
64173
+ runStyle2.scriptFallbackFont = fallback;
64174
+ }
64175
+ }
63030
64176
  parts.push(runText);
63031
64177
  segments.push({ text: runText, style: runStyle2 });
63032
64178
  maybeSeed(runStyle2);
@@ -63068,14 +64214,25 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
63068
64214
  )
63069
64215
  };
63070
64216
  const fldType = String(field["@_type"] || "").trim() || void 0;
63071
- const fldGuid = String(field["@_uuid"] || field["@_id"] || "").trim() || void 0;
64217
+ const uuidAttr = String(field["@_uuid"] || "").trim();
64218
+ const idAttr = String(field["@_id"] || "").trim();
64219
+ const fldGuid = uuidAttr || idAttr || void 0;
64220
+ const fldGuidAttr = uuidAttr ? "uuid" : idAttr ? "id" : void 0;
63072
64221
  parts.push(fieldText);
63073
- segments.push({
64222
+ const fieldSegment = {
63074
64223
  text: fieldText,
63075
64224
  style: fieldRunStyle,
63076
64225
  fieldType: fldType,
63077
64226
  fieldGuid: fldGuid
63078
- });
64227
+ };
64228
+ if (fldGuidAttr) {
64229
+ fieldSegment.fieldGuidAttr = fldGuidAttr;
64230
+ }
64231
+ const fieldPPr = field["a:pPr"];
64232
+ if (fieldPPr && typeof fieldPPr === "object") {
64233
+ fieldSegment.fieldParagraphPropertiesXml = fieldPPr;
64234
+ }
64235
+ segments.push(fieldSegment);
63079
64236
  maybeSeed(fieldRunStyle);
63080
64237
  };
63081
64238
  const processMathElement = (mathEl) => {
@@ -63202,6 +64359,11 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
63202
64359
  ...endParaRPrRaw
63203
64360
  };
63204
64361
  }
64362
+ const basisFontSize = typeof mergedDefaultRunStyle.fontSize === "number" ? mergedDefaultRunStyle.fontSize : void 0;
64363
+ const paragraphOwnProps = this.extractParagraphOwnProperties(p, basisFontSize);
64364
+ if (paragraphOwnProps) {
64365
+ segments[firstSegmentIndex].paragraphProperties = paragraphOwnProps;
64366
+ }
63205
64367
  }
63206
64368
  return { parts, segments, seedStyle };
63207
64369
  }
@@ -63510,7 +64672,11 @@ var PptxHandlerRuntime64 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
63510
64672
  const inheritedCNvSpPr = xmlPath(inheritedPlaceholder?.shape, "p:nvSpPr", "p:cNvSpPr") ?? xmlPath(inheritedPlaceholder?.picture, "p:nvPicPr", "p:cNvPicPr");
63511
64673
  const inheritedLockNode = inheritedCNvSpPr?.["a:spLocks"] ?? inheritedCNvSpPr?.["a:picLocks"];
63512
64674
  const inheritedLocks = this.parseShapeLocks(inheritedLockNode);
63513
- const locks = inheritedLocks ? { ...inheritedLocks, ...slideLocks } : slideLocks;
64675
+ let locks = inheritedLocks ? { ...inheritedLocks, ...slideLocks } : slideLocks;
64676
+ const txBox = this.parseTxBoxFlag(cNvSpPr);
64677
+ if (txBox !== void 0) {
64678
+ locks = { ...locks ?? {}, txBox };
64679
+ }
63514
64680
  const promptText = !hasText && phDefaults?.promptText ? phDefaults.promptText : void 0;
63515
64681
  const opaqueExtLstXml = this.extractOpaqueSpPrExtLst(effectiveSpPr);
63516
64682
  const commonProps = {
@@ -67063,16 +68229,20 @@ var PptxHandlerRuntime80 = class extends PptxHandlerRuntime79 {
67063
68229
  }
67064
68230
  let fontScheme;
67065
68231
  if (hasFonts) {
68232
+ const majorByScript = this.aggregateFontScriptOverrides(this.masterThemeMajorFontScripts);
68233
+ const minorByScript = this.aggregateFontScriptOverrides(this.masterThemeMinorFontScripts);
67066
68234
  fontScheme = {
67067
68235
  majorFont: {
67068
68236
  latin: this.themeFontMap["mj-lt"],
67069
68237
  eastAsia: this.themeFontMap["mj-ea"],
67070
- complexScript: this.themeFontMap["mj-cs"]
68238
+ complexScript: this.themeFontMap["mj-cs"],
68239
+ ...Object.keys(majorByScript).length > 0 ? { byScript: majorByScript } : {}
67071
68240
  },
67072
68241
  minorFont: {
67073
68242
  latin: this.themeFontMap["mn-lt"],
67074
68243
  eastAsia: this.themeFontMap["mn-ea"],
67075
- complexScript: this.themeFontMap["mn-cs"]
68244
+ complexScript: this.themeFontMap["mn-cs"],
68245
+ ...Object.keys(minorByScript).length > 0 ? { byScript: minorByScript } : {}
67076
68246
  }
67077
68247
  };
67078
68248
  }
@@ -67280,6 +68450,23 @@ var PptxHandlerRuntime80 = class extends PptxHandlerRuntime79 {
67280
68450
  *
67281
68451
  * Phase 4 Stream A / M4.
67282
68452
  */
68453
+ /**
68454
+ * Flatten a per-theme-path script-override map (`themePath -> {script ->
68455
+ * typeface}`) into a single `{script -> typeface}` lookup for
68456
+ * {@link buildThemeObject}. Earlier entries win on collision, which matches
68457
+ * the primary-theme-first parse order. Phase 4 Stream A / M4 (#83).
68458
+ */
68459
+ aggregateFontScriptOverrides(perPathMap) {
68460
+ const aggregate = {};
68461
+ for (const overrides10 of perPathMap.values()) {
68462
+ for (const [script, typeface] of Object.entries(overrides10)) {
68463
+ if (!(script in aggregate)) {
68464
+ aggregate[script] = typeface;
68465
+ }
68466
+ }
68467
+ }
68468
+ return aggregate;
68469
+ }
67283
68470
  collectFontScriptOverrides(fontNode) {
67284
68471
  const overrides10 = {};
67285
68472
  if (!fontNode) {
@@ -67915,33 +69102,16 @@ var PptxHandlerRuntime83 = class extends PptxHandlerRuntime82 {
67915
69102
  const metadata = parseSmartArtDefinitionMetadata(colorsDef, localName22);
67916
69103
  const labels = parseSmartArtColorStyleLabels(colorsDef, localName22);
67917
69104
  const name = metadata.titles?.[0]?.value || String(colorsDef["@_title"] || colorsDef["@_uniqueId"] || "").trim() || void 0;
67918
- const fillColors = [];
67919
- const lineColors = [];
67920
69105
  const styleLbls = this.xmlLookupService.getChildrenArrayByLocalName(colorsDef, "styleLbl");
67921
- for (const lbl of styleLbls) {
67922
- const fillClrLst = this.xmlLookupService.getChildByLocalName(lbl, "fillClrLst");
67923
- const linClrLst = this.xmlLookupService.getChildByLocalName(lbl, "linClrLst");
67924
- if (fillClrLst) {
67925
- const color2 = this.parseColor(fillClrLst) ?? this.resolveSmartArtSchemeColor(
67926
- this.xmlLookupService.getChildByLocalName(fillClrLst, "schemeClr")
67927
- );
67928
- if (color2) {
67929
- fillColors.push(color2);
67930
- }
67931
- }
67932
- if (linClrLst) {
67933
- const color2 = this.parseColor(linClrLst) ?? this.resolveSmartArtSchemeColor(
67934
- this.xmlLookupService.getChildByLocalName(linClrLst, "schemeClr")
67935
- );
67936
- if (color2) {
67937
- lineColors.push(color2);
67938
- }
67939
- }
67940
- }
67941
- if (fillColors.length === 0 && lineColors.length === 0) {
69106
+ const colorLists = buildSmartArtColorLists(styleLbls, {
69107
+ getChild: (node, childName) => this.xmlLookupService.getChildByLocalName(node, childName),
69108
+ parseColorChoice: (colorChoice) => this.parseColor(colorChoice),
69109
+ resolveScheme: (colorNode) => this.resolveSmartArtSchemeColor(colorNode)
69110
+ });
69111
+ if (colorLists.fillColors.length === 0 && colorLists.lineColors.length === 0) {
67942
69112
  return void 0;
67943
69113
  }
67944
- return { ...metadata, name, fillColors, lineColors, labels };
69114
+ return { ...metadata, name, ...colorLists, labels };
67945
69115
  } catch {
67946
69116
  return void 0;
67947
69117
  }
@@ -68293,6 +69463,109 @@ var PptxHandlerRuntime84 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
68293
69463
  }
68294
69464
  };
68295
69465
 
69466
+ // src/core/core/runtime/smartart-drawing-blip.ts
69467
+ function collectDrawingShapeNodes(root, getChildren) {
69468
+ const out = [];
69469
+ const walk = (container) => {
69470
+ if (!container) {
69471
+ return;
69472
+ }
69473
+ for (const sp of getChildren(container, "sp")) {
69474
+ out.push({ node: sp, isPic: false });
69475
+ }
69476
+ for (const pic of getChildren(container, "pic")) {
69477
+ out.push({ node: pic, isPic: true });
69478
+ }
69479
+ for (const grp of getChildren(container, "grpSp")) {
69480
+ walk(grp);
69481
+ }
69482
+ };
69483
+ walk(root);
69484
+ return out;
69485
+ }
69486
+ function picBlipEmbedId(pic, getChild) {
69487
+ const blip = getChild(getChild(pic, "blipFill"), "blip");
69488
+ if (!blip) {
69489
+ return void 0;
69490
+ }
69491
+ const embed = String(blip["@_r:embed"] || blip["@_embed"] || blip["@_r:link"] || "").trim();
69492
+ return embed.length > 0 ? embed : void 0;
69493
+ }
69494
+ function parseDrawingRelTargets(relsXml, parse, ensureArray16) {
69495
+ const map = /* @__PURE__ */ new Map();
69496
+ try {
69497
+ const relsRoot = parse(relsXml)["Relationships"];
69498
+ if (!relsRoot) {
69499
+ return map;
69500
+ }
69501
+ for (const rel of ensureArray16(relsRoot["Relationship"])) {
69502
+ const id = String(rel?.["@_Id"] || "").trim();
69503
+ const target = String(rel?.["@_Target"] || "").trim();
69504
+ if (id.length > 0 && target.length > 0) {
69505
+ map.set(id, target);
69506
+ }
69507
+ }
69508
+ } catch {
69509
+ }
69510
+ return map;
69511
+ }
69512
+ async function resolveDrawingBlipFills(shapes, drawingPath, deps) {
69513
+ const pending = shapes.filter((shape) => shape.fillBlipEmbedId && !shape.fillImageUrl);
69514
+ if (pending.length === 0) {
69515
+ return;
69516
+ }
69517
+ const dir = drawingPath.replace(/\/[^/]+$/u, "");
69518
+ const file = drawingPath.split("/").pop() ?? "";
69519
+ const relsXml = await deps.readText(`${dir}/_rels/${file}.rels`);
69520
+ if (!relsXml) {
69521
+ return;
69522
+ }
69523
+ const targets = parseDrawingRelTargets(relsXml, deps.parse, deps.ensureArray);
69524
+ for (const shape of pending) {
69525
+ const target = targets.get(shape.fillBlipEmbedId ?? "");
69526
+ if (!target) {
69527
+ continue;
69528
+ }
69529
+ const source = /^(?:https?:|data:)/u.test(target) ? target : deps.resolveImagePath(drawingPath, target);
69530
+ const resolved = await deps.getImageData(source);
69531
+ if (resolved) {
69532
+ shape.fillImageUrl = resolved;
69533
+ }
69534
+ }
69535
+ }
69536
+ async function parseDrawingShapesFromPart(drawingPath, deps) {
69537
+ const xmlString = await deps.readText(drawingPath);
69538
+ if (!xmlString) {
69539
+ return [];
69540
+ }
69541
+ try {
69542
+ const xml = deps.parse(xmlString);
69543
+ const drawing = deps.getChild(xml, "drawing");
69544
+ const spTree = deps.getChild(drawing || xml, "spTree");
69545
+ if (!spTree) {
69546
+ return [];
69547
+ }
69548
+ const shapes = [];
69549
+ collectDrawingShapeNodes(spTree, deps.getChildren).forEach(({ node, isPic }, index) => {
69550
+ const shape = deps.parseDrawingShape(node, index, deps.emuPerPx);
69551
+ if (!shape) {
69552
+ return;
69553
+ }
69554
+ if (isPic && !shape.fillBlipEmbedId) {
69555
+ const embed = picBlipEmbedId(node, deps.getChild);
69556
+ if (embed) {
69557
+ shape.fillBlipEmbedId = embed;
69558
+ }
69559
+ }
69560
+ shapes.push(shape);
69561
+ });
69562
+ await resolveDrawingBlipFills(shapes, drawingPath, deps);
69563
+ return shapes;
69564
+ } catch {
69565
+ return [];
69566
+ }
69567
+ }
69568
+
68296
69569
  // src/core/core/runtime/smartart-layout-category.ts
68297
69570
  var CATEGORY_FAMILY = {
68298
69571
  list: "list",
@@ -68428,6 +69701,7 @@ var PptxHandlerRuntime85 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
68428
69701
  layoutDefinition,
68429
69702
  nodes,
68430
69703
  connections: parsedConnections.length > 0 ? parsedConnections : void 0,
69704
+ presLayoutVars: parseSmartArtPresLayoutVars(dataModel),
68431
69705
  drawingShapes: drawingShapes.length > 0 ? drawingShapes : void 0,
68432
69706
  chrome,
68433
69707
  colorTransform,
@@ -68506,30 +69780,28 @@ var PptxHandlerRuntime85 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
68506
69780
  }
68507
69781
  }
68508
69782
  /**
68509
- * Parse SmartArt drawing shapes given an absolute part path.
69783
+ * Parse cached SmartArt drawing shapes from an absolute part path.
68510
69784
  *
68511
- * Wraps `parseSmartArtDrawingShapes` (which expects a slide-relative
68512
- * relationship id) with a path-based lookup so the resolution layer
68513
- * can pull the part from anywhere in the package.
69785
+ * Enumerates `dsp:sp` / bare `dsp:pic` (incl. nested `dsp:grpSp`) and
69786
+ * resolves picture (blip) fills to data URLs via the drawing part's own
69787
+ * relationships. Delegates to a pure helper with an injected dep bundle.
68514
69788
  */
68515
69789
  async parseSmartArtDrawingShapesFromPath(drawingPath) {
68516
- const xmlString = await this.zip.file(drawingPath)?.async("string");
68517
- if (!xmlString) {
68518
- return [];
68519
- }
68520
- try {
68521
- const xml = this.parser.parse(xmlString);
68522
- const drawing = this.xmlLookupService.getChildByLocalName(xml, "drawing");
68523
- const spTree = this.xmlLookupService.getChildByLocalName(drawing || xml, "spTree");
68524
- if (!spTree) {
68525
- return [];
68526
- }
68527
- const shapes = this.xmlLookupService.getChildrenArrayByLocalName(spTree, "sp");
68528
- const emuPerPx = _PptxHandlerRuntime.EMU_PER_PX;
68529
- return shapes.map((sp, index) => this.parseDrawingShape(sp, index, emuPerPx)).filter((entry) => entry !== null);
68530
- } catch {
68531
- return [];
68532
- }
69790
+ return parseDrawingShapesFromPart(drawingPath, this.drawingBlipDeps());
69791
+ }
69792
+ /** Bind runtime zip / parser / lookup / image helpers for the drawing parser. */
69793
+ drawingBlipDeps() {
69794
+ return {
69795
+ readText: (path) => this.zip.file(path)?.async("string") ?? Promise.resolve(void 0),
69796
+ parse: (xml) => this.parser.parse(xml),
69797
+ getChild: (node, local) => this.xmlLookupService.getChildByLocalName(node, local),
69798
+ getChildren: (node, local) => this.xmlLookupService.getChildrenArrayByLocalName(node, local),
69799
+ parseDrawingShape: (sp, index, emuPerPx) => this.parseDrawingShape(sp, index, emuPerPx),
69800
+ emuPerPx: _PptxHandlerRuntime.EMU_PER_PX,
69801
+ ensureArray: (value) => this.ensureArray(value),
69802
+ resolveImagePath: (base, target) => this.resolveImagePath(base, target),
69803
+ getImageData: (path) => this.getImageData(path)
69804
+ };
68533
69805
  }
68534
69806
  };
68535
69807
 
@@ -69227,6 +70499,11 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
69227
70499
  grouping = "clustered";
69228
70500
  }
69229
70501
  }
70502
+ const varyColors = this.parseChartBoolVal(seriesContainer, "varyColors");
70503
+ const firstSliceAngle = this.parseChartNumberVal(seriesContainer, "firstSliceAng");
70504
+ const doughnutHoleSize = this.parseChartNumberVal(seriesContainer, "holeSize");
70505
+ const barGapWidth = this.parseChartNumberVal(seriesContainer, "gapWidth");
70506
+ const barOverlap = this.parseChartNumberVal(seriesContainer, "overlap");
69230
70507
  const chartPartPath = chartPart.partPath;
69231
70508
  const dataTable = parseDataTable(plotArea, this.xmlLookupService);
69232
70509
  const dropLines = parseLineStyle(
@@ -69303,6 +70580,11 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
69303
70580
  title: titleTextValues[0],
69304
70581
  style: chartStyle,
69305
70582
  grouping,
70583
+ ...varyColors !== void 0 ? { varyColors } : {},
70584
+ ...firstSliceAngle !== void 0 ? { firstSliceAngle } : {},
70585
+ ...doughnutHoleSize !== void 0 ? { doughnutHoleSize } : {},
70586
+ ...barGapWidth !== void 0 ? { barGapWidth } : {},
70587
+ ...barOverlap !== void 0 ? { barOverlap } : {},
69306
70588
  chartPartPath,
69307
70589
  chartRelationshipId,
69308
70590
  ...dataTable ? { dataTable } : {},
@@ -69379,6 +70661,35 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
69379
70661
  }
69380
70662
  return { categories, series };
69381
70663
  }
70664
+ /**
70665
+ * Read a numeric `@val` from a named child of a chart-type container.
70666
+ * Returns `undefined` when the child or its `@val` is absent/non-finite.
70667
+ */
70668
+ parseChartNumberVal(container, localName22) {
70669
+ const node = this.xmlLookupService.getChildByLocalName(container, localName22);
70670
+ const raw = node?.["@_val"];
70671
+ if (raw === void 0 || raw === null || raw === "") {
70672
+ return void 0;
70673
+ }
70674
+ const num = Number.parseFloat(String(raw));
70675
+ return Number.isFinite(num) ? num : void 0;
70676
+ }
70677
+ /**
70678
+ * Read a boolean `@val` from a named child of a chart-type container.
70679
+ * A present element with no `@val` follows the OOXML `CT_Boolean` default
70680
+ * of `true`; `undefined` when the child is absent.
70681
+ */
70682
+ parseChartBoolVal(container, localName22) {
70683
+ const node = this.xmlLookupService.getChildByLocalName(container, localName22);
70684
+ if (!node) {
70685
+ return void 0;
70686
+ }
70687
+ const raw = node["@_val"];
70688
+ if (raw === void 0 || raw === null || raw === "") {
70689
+ return true;
70690
+ }
70691
+ return !(raw === "0" || raw === "false");
70692
+ }
69382
70693
  /**
69383
70694
  * Build the series array from raw OOXML `c:ser` nodes.
69384
70695
  *
@@ -69422,6 +70733,10 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
69422
70733
  );
69423
70734
  const dataLabels = parseSeriesDataLabels(seriesNode, this.xmlLookupService);
69424
70735
  const explosion = parseSeriesExplosion(seriesNode, this.xmlLookupService);
70736
+ const smoothNode = this.xmlLookupService.getChildByLocalName(seriesNode, "smooth");
70737
+ const smooth = smoothNode ? !(smoothNode["@_val"] === "0" || smoothNode["@_val"] === "false") : void 0;
70738
+ const invertNode = this.xmlLookupService.getChildByLocalName(seriesNode, "invertIfNegative");
70739
+ const invertIfNegative = invertNode ? !(invertNode["@_val"] === "0" || invertNode["@_val"] === "false") : void 0;
69425
70740
  return {
69426
70741
  name: seriesName.trim().length > 0 ? seriesName : `Series ${seriesIndex + 1}`,
69427
70742
  values: fallbackValues,
@@ -69432,6 +70747,8 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
69432
70747
  ...seriesMarker ? { marker: seriesMarker } : {},
69433
70748
  ...dataLabels.length > 0 ? { dataLabels } : {},
69434
70749
  ...explosion !== void 0 ? { explosion } : {},
70750
+ ...invertIfNegative !== void 0 ? { invertIfNegative } : {},
70751
+ ...smooth !== void 0 ? { smooth } : {},
69435
70752
  ...axisId !== void 0 ? { axisId } : {},
69436
70753
  ...seriesChartType ? { seriesChartType } : {}
69437
70754
  };
@@ -70258,6 +71575,8 @@ var PptxHandlerRuntime94 = class extends PptxHandlerRuntime93 {
70258
71575
  async buildLoadData(presentationState, slidesWithWarnings, slideMasters) {
70259
71576
  const headerFooter = this.extractHeaderFooter();
70260
71577
  const presentationProperties = await this.parsePresentationProperties();
71578
+ const viewProperties = await this.parseViewProperties();
71579
+ this.loadedViewProperties = viewProperties;
70261
71580
  const customShows = this.parseCustomShows();
70262
71581
  const tableStyleMap = await this.parseTableStyles();
70263
71582
  const embeddedFontList = parseEmbeddedFontList(this.presentationData);
@@ -70287,7 +71606,7 @@ var PptxHandlerRuntime94 = class extends PptxHandlerRuntime93 {
70287
71606
  presentationState.height,
70288
71607
  this.rawSlideWidthEmu,
70289
71608
  this.rawSlideHeightEmu
70290
- ).withNotesDimensions(presentationState.notesWidthEmu, presentationState.notesHeightEmu).withSlides(slidesWithWarnings).withLayoutOptions(this.getLayoutOptions()).withHeaderFooter(headerFooter).withPresentationProperties(presentationProperties).withCustomShows(customShows).withSections(
71609
+ ).withNotesDimensions(presentationState.notesWidthEmu, presentationState.notesHeightEmu).withSlides(slidesWithWarnings).withLayoutOptions(this.getLayoutOptions()).withHeaderFooter(headerFooter).withPresentationProperties(presentationProperties).withViewProperties(viewProperties).withCustomShows(customShows).withSections(
70291
71610
  presentationState.orderedSections.length > 0 ? presentationState.orderedSections : void 0
70292
71611
  ).withWarnings(this.compatibilityService.getWarnings()).withThemeColorMap({ ...this.themeColorMap }).withTheme(this.buildThemeObject()).withThemeOptions(themeOptions.length > 0 ? themeOptions : void 0).withTableStyleMap(tableStyleMap).withEmbeddedFonts(embeddedFonts.length > 0 ? embeddedFonts : void 0).withEmbeddedFontList(embeddedFontList).withMruColors(presentationProperties?.mruColors).withNotesMaster(notesMaster).withHandoutMaster(handoutMaster).withSlideMasters(slideMasters.length > 0 ? slideMasters : void 0).withTags(tags.length > 0 ? tags : void 0).withCustomProperties(customProperties.length > 0 ? customProperties : void 0).withCoreProperties(coreProperties).withAppProperties(appProperties).withHasMacros(this.vbaProjectBin !== null ? true : void 0).withHasDigitalSignatures(this.signatureDetection?.hasSignatures || void 0).withDigitalSignatureCount(
70293
71612
  this.signatureDetection?.signatureCount && this.signatureDetection.signatureCount > 0 ? this.signatureDetection.signatureCount : void 0
@@ -70418,6 +71737,7 @@ var PptxHandlerRuntime94 = class extends PptxHandlerRuntime93 {
70418
71737
  this.customXmlParts = [];
70419
71738
  this.loadedEmbeddedFonts = [];
70420
71739
  this.loadedEmbeddedFontList = void 0;
71740
+ this.loadedViewProperties = void 0;
70421
71741
  this.orderedSlidePaths = [];
70422
71742
  this.zip = null;
70423
71743
  }
@@ -71375,11 +72695,13 @@ function parseDrawingColorChoice(colorNode) {
71375
72695
  }
71376
72696
  if (colorNode["a:scrgbClr"]) {
71377
72697
  const scrgb = colorNode["a:scrgbClr"];
71378
- const red = parseDrawingPercent(scrgb["@_r"]);
71379
- const green = parseDrawingPercent(scrgb["@_g"]);
71380
- const blue = parseDrawingPercent(scrgb["@_b"]);
72698
+ const red = parseDrawingFraction(scrgb["@_r"]);
72699
+ const green = parseDrawingFraction(scrgb["@_g"]);
72700
+ const blue = parseDrawingFraction(scrgb["@_b"]);
71381
72701
  if (red !== void 0 && green !== void 0 && blue !== void 0) {
71382
- const base = `#${toHex(red * 255)}${toHex(green * 255)}${toHex(blue * 255)}`;
72702
+ const base = `#${toHex(scrgbLinearToSrgb8(red))}${toHex(scrgbLinearToSrgb8(green))}${toHex(
72703
+ scrgbLinearToSrgb8(blue)
72704
+ )}`;
71383
72705
  return applyDrawingColorTransforms(base, scrgb);
71384
72706
  }
71385
72707
  }
@@ -71464,7 +72786,7 @@ function parseDrawingColorOpacity(colorNode) {
71464
72786
  const alphaMod = parseDrawingPercent(
71465
72787
  colorChoice["a:alphaMod"]?.["@_val"]
71466
72788
  );
71467
- const alphaOff = parseDrawingPercent(
72789
+ const alphaOff = parseDrawingFraction(
71468
72790
  colorChoice["a:alphaOff"]?.["@_val"]
71469
72791
  );
71470
72792
  if (alpha === void 0 && alphaMod === void 0 && alphaOff === void 0) {
@@ -85726,6 +87048,7 @@ exports.buildInkMlContent = buildInkMlContent;
85726
87048
  exports.buildLinkedTextBoxChains = buildLinkedTextBoxChains;
85727
87049
  exports.buildOle2 = buildOle2;
85728
87050
  exports.buildSingleEffectNode = buildSingleEffectNode;
87051
+ exports.buildSlideReferenceRemap = buildSlideReferenceRemap;
85729
87052
  exports.buildSrgbColorChoice = buildSrgbColorChoice;
85730
87053
  exports.buildThemeColorMap = buildThemeColorMap;
85731
87054
  exports.catmullRomToBezier = catmullRomToBezier;
@@ -85797,6 +87120,8 @@ exports.decryptPptx = decryptPptx;
85797
87120
  exports.demoteSmartArtNode = demoteSmartArtNode;
85798
87121
  exports.deobfuscateFont = deobfuscateFont;
85799
87122
  exports.deriveOutputPath = deriveOutputPath;
87123
+ exports.deriveSlideTitle = deriveSlideTitle;
87124
+ exports.deriveSlideTitles = deriveSlideTitles;
85800
87125
  exports.detectDigitalSignatures = detectDigitalSignatures;
85801
87126
  exports.detectFileFormat = detectFileFormat;
85802
87127
  exports.detectFontFormat = detectFontFormat;