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.
@@ -5165,6 +5165,11 @@ function parseDrawingPercent(value) {
5165
5165
  }
5166
5166
  return clampUnitInterval(parsed / 1e5);
5167
5167
  }
5168
+ function scrgbLinearToSrgb8(linear) {
5169
+ const l = Math.min(1, Math.max(0, linear));
5170
+ const companded = l <= 31308e-7 ? 12.92 * l : 1.055 * l ** (1 / 2.4) - 0.055;
5171
+ return Math.min(255, Math.max(0, Math.round(companded * 255)));
5172
+ }
5168
5173
  function toHex(value) {
5169
5174
  return Math.min(255, Math.max(0, Math.round(value))).toString(16).padStart(2, "0").toUpperCase();
5170
5175
  }
@@ -6532,6 +6537,21 @@ function cloneXmlObject(value) {
6532
6537
 
6533
6538
  // src/core/utils/presentation-collections.ts
6534
6539
  var SECTION_EXTENSION_URI = "{521415D9-36F7-43E2-AB2F-B90AF26B5E84}";
6540
+ function remapReferenceList(references, mapping, removed) {
6541
+ const result = [];
6542
+ for (const reference of references) {
6543
+ const mapped = mapping.get(reference);
6544
+ if (mapped !== void 0) {
6545
+ result.push(mapped);
6546
+ continue;
6547
+ }
6548
+ if (removed.has(reference)) {
6549
+ continue;
6550
+ }
6551
+ result.push(reference);
6552
+ }
6553
+ return result;
6554
+ }
6535
6555
  function localName2(key) {
6536
6556
  return key.split(":").pop() ?? key;
6537
6557
  }
@@ -6598,7 +6618,7 @@ function updateCustomShow(show, existing) {
6598
6618
  replaceChildren(node, "sldLst", slideList, "p:sldLst");
6599
6619
  return node;
6600
6620
  }
6601
- function applyCustomShows(presentation, shows, lookup) {
6621
+ function applyCustomShows(presentation, shows, lookup, remap) {
6602
6622
  if (shows === void 0) {
6603
6623
  return;
6604
6624
  }
@@ -6612,14 +6632,18 @@ function applyCustomShows(presentation, shows, lookup) {
6612
6632
  const oldList = key ? presentation[key] : void 0;
6613
6633
  const list = cloneXmlObject(oldList) ?? {};
6614
6634
  const oldShows = lookup.getChildrenArrayByLocalName(oldList, "custShow");
6615
- const updated = shows.map(
6616
- (show) => updateCustomShow(
6617
- show,
6635
+ const updated = shows.map((show) => {
6636
+ const effective = remap && remap.changed ? {
6637
+ ...show,
6638
+ slideRIds: remapReferenceList(show.slideRIds, remap.rIdByOldRId, remap.removedRIds)
6639
+ } : show;
6640
+ return updateCustomShow(
6641
+ effective,
6618
6642
  oldShows.find(
6619
6643
  (node) => String(node[attributeKey(node, "id") ?? ""]) === show.id || String(node[attributeKey(node, "name") ?? ""]) === show.name
6620
6644
  )
6621
- )
6622
- );
6645
+ );
6646
+ });
6623
6647
  replaceChildren(list, "custShow", updated, "p:custShow");
6624
6648
  presentation[key ?? "p:custShowLst"] = list;
6625
6649
  }
@@ -6668,7 +6692,7 @@ function updateSection(section) {
6668
6692
  }
6669
6693
  return node;
6670
6694
  }
6671
- function applySections(presentation, sections, lookup) {
6695
+ function applySections(presentation, sections, lookup, remap) {
6672
6696
  if (sections === void 0) {
6673
6697
  return;
6674
6698
  }
@@ -6690,7 +6714,15 @@ function applySections(presentation, sections, lookup) {
6690
6714
  location = { parent: ext, key: "p14:sectionLst", list: ext["p14:sectionLst"] };
6691
6715
  }
6692
6716
  const list = cloneXmlObject(location.list) ?? {};
6693
- replaceChildren(list, "section", sections.map(updateSection), "p14:section");
6717
+ const effectiveSections = remap && remap.changed ? sections.map((section) => ({
6718
+ ...section,
6719
+ slideIds: remapReferenceList(
6720
+ section.slideIds,
6721
+ remap.sldIdByOldSldId,
6722
+ remap.removedSldIds
6723
+ )
6724
+ })) : sections;
6725
+ replaceChildren(list, "section", effectiveSections.map(updateSection), "p14:section");
6694
6726
  location.parent[location.key] = list;
6695
6727
  }
6696
6728
 
@@ -10685,6 +10717,122 @@ function applyNodeStylesToElements(elements, nodes) {
10685
10717
  });
10686
10718
  }
10687
10719
 
10720
+ // src/core/utils/smartart-pres-layout-vars.ts
10721
+ var CONTAINER_LOCAL_NAMES = /* @__PURE__ */ new Set(["presLayoutVars", "varLst"]);
10722
+ function localNameOf2(key) {
10723
+ const idx = key.indexOf(":");
10724
+ return idx >= 0 ? key.slice(idx + 1) : key;
10725
+ }
10726
+ function findVarsContainer(node) {
10727
+ if (!node || typeof node !== "object") {
10728
+ return void 0;
10729
+ }
10730
+ if (Array.isArray(node)) {
10731
+ for (const entry of node) {
10732
+ const found = findVarsContainer(entry);
10733
+ if (found) {
10734
+ return found;
10735
+ }
10736
+ }
10737
+ return void 0;
10738
+ }
10739
+ for (const [key, value] of Object.entries(node)) {
10740
+ if (key.startsWith("@_")) {
10741
+ continue;
10742
+ }
10743
+ if (CONTAINER_LOCAL_NAMES.has(localNameOf2(key))) {
10744
+ const container = Array.isArray(value) ? value[0] : value;
10745
+ if (container && typeof container === "object") {
10746
+ return container;
10747
+ }
10748
+ }
10749
+ const nested = findVarsContainer(value);
10750
+ if (nested) {
10751
+ return nested;
10752
+ }
10753
+ }
10754
+ return void 0;
10755
+ }
10756
+ function varValue(container, name) {
10757
+ for (const [key, value] of Object.entries(container)) {
10758
+ if (key.startsWith("@_") || localNameOf2(key) !== name) {
10759
+ continue;
10760
+ }
10761
+ const node = Array.isArray(value) ? value[0] : value;
10762
+ if (node && typeof node === "object") {
10763
+ const raw = node["@_val"];
10764
+ const str = String(raw ?? "").trim();
10765
+ return str.length > 0 ? str : void 0;
10766
+ }
10767
+ }
10768
+ return void 0;
10769
+ }
10770
+ function boolValue(container, name) {
10771
+ const raw = varValue(container, name);
10772
+ if (raw === void 0) {
10773
+ return void 0;
10774
+ }
10775
+ const lower = raw.toLowerCase();
10776
+ return lower === "1" || lower === "true" || lower === "on";
10777
+ }
10778
+ function intValue(container, name) {
10779
+ const raw = varValue(container, name);
10780
+ if (raw === void 0) {
10781
+ return void 0;
10782
+ }
10783
+ const parsed = Number.parseInt(raw, 10);
10784
+ return Number.isFinite(parsed) ? parsed : void 0;
10785
+ }
10786
+ var DIRECTIONS = /* @__PURE__ */ new Set(["norm", "rev"]);
10787
+ var HIER_BRANCHES = /* @__PURE__ */ new Set(["std", "init", "l", "r", "hang"]);
10788
+ function parseSmartArtPresLayoutVars(container) {
10789
+ if (!container) {
10790
+ return void 0;
10791
+ }
10792
+ const vars = findVarsContainer(container);
10793
+ if (!vars) {
10794
+ return void 0;
10795
+ }
10796
+ const result = {};
10797
+ const direction = varValue(vars, "dir");
10798
+ if (direction && DIRECTIONS.has(direction)) {
10799
+ result.direction = direction;
10800
+ }
10801
+ const hierBranch = varValue(vars, "hierBranch");
10802
+ if (hierBranch && HIER_BRANCHES.has(hierBranch)) {
10803
+ result.hierarchyBranch = hierBranch;
10804
+ }
10805
+ const orgChart = boolValue(vars, "orgChart");
10806
+ if (orgChart !== void 0) {
10807
+ result.orgChart = orgChart;
10808
+ }
10809
+ const chMax = intValue(vars, "chMax");
10810
+ if (chMax !== void 0) {
10811
+ result.childMax = chMax;
10812
+ }
10813
+ const chPref = intValue(vars, "chPref");
10814
+ if (chPref !== void 0) {
10815
+ result.childPreferred = chPref;
10816
+ }
10817
+ const bulletEnabled = boolValue(vars, "bulletEnabled");
10818
+ if (bulletEnabled !== void 0) {
10819
+ result.bulletEnabled = bulletEnabled;
10820
+ }
10821
+ const animLvl = varValue(vars, "animLvl");
10822
+ if (animLvl !== void 0) {
10823
+ result.animationLevel = animLvl;
10824
+ }
10825
+ const animOne = varValue(vars, "animOne");
10826
+ if (animOne !== void 0) {
10827
+ result.animateOne = animOne;
10828
+ }
10829
+ const resizeHandles = varValue(vars, "resizeHandles");
10830
+ if (resizeHandles !== void 0) {
10831
+ result.resizeHandles = resizeHandles;
10832
+ }
10833
+ return Object.keys(result).length > 0 ? result : void 0;
10834
+ }
10835
+
10688
10836
  // src/core/utils/smartart-decompose.ts
10689
10837
  function quickStyleStrokeScale(quickStyle) {
10690
10838
  if (!quickStyle?.effectIntensity) {
@@ -10790,15 +10938,27 @@ function decomposeSmartArt(smartArtData, containerBounds, themeColorMap, layoutD
10790
10938
  smartArtData.colorTransform?.fillColors
10791
10939
  );
10792
10940
  const layoutType = resolveEffectiveLayoutType(smartArtData);
10941
+ const layoutVars = smartArtData.presLayoutVars ?? parseSmartArtPresLayoutVars(smartArtData.layoutDefinition?.rawXml);
10942
+ const orderedNodes = layoutVars?.direction === "rev" ? [...nodes].reverse() : nodes;
10793
10943
  const namedLayout = smartArtData.layout;
10794
10944
  if (namedLayout) {
10795
- const namedResult = dispatchNamedLayout(namedLayout, nodes, containerBounds, effectiveThemeMap);
10945
+ const namedResult = dispatchNamedLayout(
10946
+ namedLayout,
10947
+ orderedNodes,
10948
+ containerBounds,
10949
+ effectiveThemeMap
10950
+ );
10796
10951
  if (namedResult) {
10797
- return applyNodeStylesToElements(namedResult, nodes);
10952
+ return applyNodeStylesToElements(namedResult, orderedNodes);
10798
10953
  }
10799
10954
  }
10800
- const algorithmic = dispatchLayoutByType(layoutType, nodes, containerBounds, effectiveThemeMap);
10801
- return algorithmic ? applyNodeStylesToElements(algorithmic, nodes) : algorithmic;
10955
+ const algorithmic = dispatchLayoutByType(
10956
+ layoutType,
10957
+ orderedNodes,
10958
+ containerBounds,
10959
+ effectiveThemeMap
10960
+ );
10961
+ return algorithmic ? applyNodeStylesToElements(algorithmic, orderedNodes) : algorithmic;
10802
10962
  }
10803
10963
  function dispatchLayoutByType(layoutType, nodes, containerBounds, effectiveThemeMap) {
10804
10964
  switch (layoutType) {
@@ -17016,6 +17176,19 @@ function xmlChild(node, key) {
17016
17176
  }
17017
17177
  return isXmlObject2(value) ? value : void 0;
17018
17178
  }
17179
+ function xmlChildren(node, key) {
17180
+ if (!isXmlObject2(node)) {
17181
+ return [];
17182
+ }
17183
+ const value = node[key];
17184
+ if (value === void 0 || value === null) {
17185
+ return [];
17186
+ }
17187
+ if (Array.isArray(value)) {
17188
+ return value.filter(isXmlObject2);
17189
+ }
17190
+ return isXmlObject2(value) ? [value] : [];
17191
+ }
17019
17192
  function xmlHasChild(node, key) {
17020
17193
  return isXmlObject2(node) && Object.hasOwn(node, key);
17021
17194
  }
@@ -17043,6 +17216,9 @@ function xmlPath(node, ...keys) {
17043
17216
  }
17044
17217
  return current;
17045
17218
  }
17219
+ function isXmlNode(value) {
17220
+ return isXmlObject2(value);
17221
+ }
17046
17222
 
17047
17223
  // src/core/utils/chart-bubble-options.ts
17048
17224
  var ORDER2 = [
@@ -17059,7 +17235,7 @@ var ORDER2 = [
17059
17235
  function findKey4(node, name, localName21) {
17060
17236
  return Object.keys(node).find((key) => localName21(key) === name);
17061
17237
  }
17062
- function boolValue(node) {
17238
+ function boolValue2(node) {
17063
17239
  if (!node) {
17064
17240
  return void 0;
17065
17241
  }
@@ -17075,7 +17251,7 @@ function parseBubbleChartOptions(container, localName21) {
17075
17251
  return key ? container[key] : void 0;
17076
17252
  };
17077
17253
  const options = {};
17078
- const bubble3D = boolValue(node("bubble3D"));
17254
+ const bubble3D = boolValue2(node("bubble3D"));
17079
17255
  if (bubble3D !== void 0) {
17080
17256
  options.bubble3D = bubble3D;
17081
17257
  }
@@ -17086,7 +17262,7 @@ function parseBubbleChartOptions(container, localName21) {
17086
17262
  options.bubbleScale = scale;
17087
17263
  }
17088
17264
  }
17089
- const showNegative = boolValue(node("showNegBubbles"));
17265
+ const showNegative = boolValue2(node("showNegBubbles"));
17090
17266
  if (showNegative !== void 0) {
17091
17267
  options.showNegativeBubbles = showNegative;
17092
17268
  }
@@ -17574,6 +17750,45 @@ function withThemePlaceholderColor(themeColorMap, placeholderColor, operation) {
17574
17750
  }
17575
17751
  }
17576
17752
 
17753
+ // src/core/utils/slide-title.ts
17754
+ var TITLE_PLACEHOLDER_TYPES = /* @__PURE__ */ new Set(["title", "ctrtitle"]);
17755
+ function getElementPlaceholderType(element) {
17756
+ const explicit = element.placeholderType;
17757
+ if (typeof explicit === "string" && explicit.trim().length > 0) {
17758
+ return explicit.trim().toLowerCase();
17759
+ }
17760
+ const ph = xmlPath(element.rawXml, "p:nvSpPr", "p:nvPr", "p:ph");
17761
+ const type = xmlAttr(ph, "type");
17762
+ return type ? type.trim().toLowerCase() : void 0;
17763
+ }
17764
+ function getElementPlainText(element) {
17765
+ const maybe = element;
17766
+ if (typeof maybe.text === "string" && maybe.text.trim().length > 0) {
17767
+ return maybe.text.trim();
17768
+ }
17769
+ if (Array.isArray(maybe.textSegments)) {
17770
+ const joined = maybe.textSegments.map((segment) => typeof segment?.text === "string" ? segment.text : "").join("");
17771
+ return joined.trim();
17772
+ }
17773
+ return "";
17774
+ }
17775
+ function deriveSlideTitle(slide) {
17776
+ const elements = slide.elements ?? [];
17777
+ for (const element of elements) {
17778
+ const phType = getElementPlaceholderType(element);
17779
+ if (phType && TITLE_PLACEHOLDER_TYPES.has(phType)) {
17780
+ const text2 = getElementPlainText(element);
17781
+ if (text2) {
17782
+ return text2;
17783
+ }
17784
+ }
17785
+ }
17786
+ return "";
17787
+ }
17788
+ function deriveSlideTitles(slides) {
17789
+ return slides.map((slide) => deriveSlideTitle(slide));
17790
+ }
17791
+
17577
17792
  // src/converter/svg-chart-extended.ts
17578
17793
  var DEFAULT_COLORS = ["#4472C4", "#ED7D31", "#A5A5A5", "#FFC000", "#5B9BD5", "#70AD47"];
17579
17794
  function esc(value) {
@@ -20149,6 +20364,7 @@ var TextShapeXmlFactory = class {
20149
20364
  createXmlElement(init) {
20150
20365
  const { element } = init;
20151
20366
  const isText = element.type === "text";
20367
+ const isTextBox = element.locks?.txBox ?? isText;
20152
20368
  const name = isText ? "TextBox" : "Rectangle";
20153
20369
  const geometry = this.context.normalizePresetGeometry(element.shapeType);
20154
20370
  const adjustmentEntries = Object.entries(element.shapeAdjustments || {}).filter(
@@ -20168,7 +20384,7 @@ var TextShapeXmlFactory = class {
20168
20384
  "@_name": `${name} ${elementId}`
20169
20385
  },
20170
20386
  "p:cNvSpPr": {
20171
- "@_txBox": isText ? "1" : "0"
20387
+ "@_txBox": isTextBox ? "1" : "0"
20172
20388
  },
20173
20389
  "p:nvPr": {}
20174
20390
  },
@@ -20626,8 +20842,18 @@ var PptxPresentationSaveBuilder = class {
20626
20842
  init.rawSlideHeightEmu,
20627
20843
  init.rawSlideSizeType
20628
20844
  );
20629
- applyCustomShows(presentation, init.options?.customShows, init.xmlLookupService);
20630
- applySections(presentation, init.options?.sections, init.xmlLookupService);
20845
+ applyCustomShows(
20846
+ presentation,
20847
+ init.options?.customShows,
20848
+ init.xmlLookupService,
20849
+ init.slideReferenceRemap
20850
+ );
20851
+ applySections(
20852
+ presentation,
20853
+ init.options?.sections,
20854
+ init.xmlLookupService,
20855
+ init.slideReferenceRemap
20856
+ );
20631
20857
  this.applyPhotoAlbum(presentation, init.options?.photoAlbum);
20632
20858
  presentation = this.applyKinsoku(presentation, init.options?.kinsoku);
20633
20859
  this.applyModifyVerifier(presentation, init.options?.modifyVerifier);
@@ -20722,6 +20948,53 @@ var PptxPresentationSaveBuilder = class {
20722
20948
  }
20723
20949
  };
20724
20950
 
20951
+ // src/core/core/builders/slide-reference-remap.ts
20952
+ function buildSlideReferenceRemap(init) {
20953
+ const pathToNewRId = /* @__PURE__ */ new Map();
20954
+ for (const slide of init.slides) {
20955
+ pathToNewRId.set(slide.id, slide.rId);
20956
+ }
20957
+ const newRIdToNumeric = /* @__PURE__ */ new Map();
20958
+ for (const entry of init.rebuiltSlideIds) {
20959
+ const relationshipId2 = String(entry?.["@_r:id"] ?? "");
20960
+ const numericSlideId = String(entry?.["@_id"] ?? "");
20961
+ if (relationshipId2.length > 0 && numericSlideId.length > 0) {
20962
+ newRIdToNumeric.set(relationshipId2, numericSlideId);
20963
+ }
20964
+ }
20965
+ const rIdByOldRId = /* @__PURE__ */ new Map();
20966
+ const removedRIds = /* @__PURE__ */ new Set();
20967
+ let changed = false;
20968
+ for (const [oldRId, path2] of init.originalRIdToPath.entries()) {
20969
+ const newRId = pathToNewRId.get(path2);
20970
+ if (newRId === void 0) {
20971
+ removedRIds.add(oldRId);
20972
+ changed = true;
20973
+ continue;
20974
+ }
20975
+ rIdByOldRId.set(oldRId, newRId);
20976
+ if (newRId !== oldRId) {
20977
+ changed = true;
20978
+ }
20979
+ }
20980
+ const sldIdByOldSldId = /* @__PURE__ */ new Map();
20981
+ const removedSldIds = /* @__PURE__ */ new Set();
20982
+ for (const [oldSldId, path2] of init.originalSldIdToPath.entries()) {
20983
+ const newRId = pathToNewRId.get(path2);
20984
+ const newSldId = newRId === void 0 ? void 0 : newRIdToNumeric.get(newRId);
20985
+ if (newSldId === void 0) {
20986
+ removedSldIds.add(oldSldId);
20987
+ changed = true;
20988
+ continue;
20989
+ }
20990
+ sldIdByOldSldId.set(oldSldId, newSldId);
20991
+ if (newSldId !== oldSldId) {
20992
+ changed = true;
20993
+ }
20994
+ }
20995
+ return { rIdByOldRId, sldIdByOldSldId, removedRIds, removedSldIds, changed };
20996
+ }
20997
+
20725
20998
  // src/core/core/builders/PptxPresentationSlidesReconciler.ts
20726
20999
  var PptxPresentationSlidesReconciler = class {
20727
21000
  async reconcile(input) {
@@ -20767,6 +21040,10 @@ var PptxPresentationSlidesReconciler = class {
20767
21040
  const existingSlideIds = slideIdList ? this.ensureArray(slideIdList["p:sldId"]) : [];
20768
21041
  const slideIdByRid = /* @__PURE__ */ new Map();
20769
21042
  let maxNumericSlideId = 255;
21043
+ const originalRIdToPath = /* @__PURE__ */ new Map();
21044
+ for (const [relationshipId2, target] of slideTargetByRid.entries()) {
21045
+ originalRIdToPath.set(relationshipId2, input.toSlidePathFromTarget(target));
21046
+ }
20770
21047
  for (const slideIdEntry of existingSlideIds) {
20771
21048
  const relationshipId2 = slideIdEntry?.["@_r:id"];
20772
21049
  if (typeof relationshipId2 === "string" && relationshipId2.length > 0) {
@@ -20777,6 +21054,15 @@ var PptxPresentationSlidesReconciler = class {
20777
21054
  maxNumericSlideId = Math.max(maxNumericSlideId, numericSlideId);
20778
21055
  }
20779
21056
  }
21057
+ const originalSldIdToPath = /* @__PURE__ */ new Map();
21058
+ for (const slideIdEntry of existingSlideIds) {
21059
+ const relationshipId2 = String(slideIdEntry?.["@_r:id"] ?? "");
21060
+ const numericSlideId = String(slideIdEntry?.["@_id"] ?? "");
21061
+ const slidePath = originalRIdToPath.get(relationshipId2);
21062
+ if (numericSlideId.length > 0 && slidePath !== void 0) {
21063
+ originalSldIdToPath.set(numericSlideId, slidePath);
21064
+ }
21065
+ }
20780
21066
  for (let index = 0; index < input.slides.length; index++) {
20781
21067
  const slide = input.slides[index];
20782
21068
  slide.slideNumber = index + 1;
@@ -20813,6 +21099,7 @@ var PptxPresentationSlidesReconciler = class {
20813
21099
  ];
20814
21100
  presentationRelsData["Relationships"] = relRoot;
20815
21101
  input.zip.file("ppt/_rels/presentation.xml.rels", input.xmlBuilder.build(presentationRelsData));
21102
+ const rebuiltSlideIds = [];
20816
21103
  if (presentation && slideIdList && input.presentationData) {
20817
21104
  slideIdList["p:sldId"] = input.slides.map((slide) => {
20818
21105
  const existing = slideIdByRid.get(slide.rId);
@@ -20825,11 +21112,18 @@ var PptxPresentationSlidesReconciler = class {
20825
21112
  "@_r:id": slide.rId
20826
21113
  };
20827
21114
  });
21115
+ rebuiltSlideIds.push(...slideIdList["p:sldId"]);
20828
21116
  input.presentationData["p:presentation"] = this.insertSlideIdListInOrder(
20829
21117
  presentation,
20830
21118
  slideIdList
20831
21119
  );
20832
21120
  }
21121
+ return buildSlideReferenceRemap({
21122
+ slides: input.slides,
21123
+ originalRIdToPath,
21124
+ originalSldIdToPath,
21125
+ rebuiltSlideIds
21126
+ });
20833
21127
  }
20834
21128
  /**
20835
21129
  * Return a new presentation XML object whose `p:sldIdLst` child sits in the
@@ -21415,7 +21709,7 @@ var PptxSlideNotesPartUpdater = class {
21415
21709
 
21416
21710
  // src/core/core/builders/PptxSlideBackgroundBuilder.ts
21417
21711
  var PptxSlideBackgroundBuilder = class {
21418
- applyBackground(init) {
21712
+ async applyBackground(init) {
21419
21713
  const hasBackgroundColor = typeof init.slide.backgroundColor === "string" && init.slide.backgroundColor.length > 0 && init.slide.backgroundColor !== "transparent";
21420
21714
  const rawBackgroundImage = typeof init.slide.backgroundImage === "string" ? init.slide.backgroundImage : "";
21421
21715
  const hasBackgroundImage = rawBackgroundImage.length > 0;
@@ -21436,8 +21730,8 @@ var PptxSlideBackgroundBuilder = class {
21436
21730
  return;
21437
21731
  }
21438
21732
  const backgroundProperties = {};
21439
- if (hasDataUrlBackgroundImage) {
21440
- const parsedBackgroundImage = init.parseDataUrlToBytes(rawBackgroundImage);
21733
+ if (hasBackgroundImage) {
21734
+ const parsedBackgroundImage = await init.resolveImageToBytes(rawBackgroundImage);
21441
21735
  if (parsedBackgroundImage) {
21442
21736
  const backgroundImagePath = init.saveState.nextMediaPath(parsedBackgroundImage.extension);
21443
21737
  init.zip.file(backgroundImagePath, parsedBackgroundImage.bytes);
@@ -21455,8 +21749,11 @@ var PptxSlideBackgroundBuilder = class {
21455
21749
  },
21456
21750
  BLIP_FILL_ORDER
21457
21751
  );
21752
+ } else {
21753
+ init.reportUnsupportedBackground?.(rawBackgroundImage);
21458
21754
  }
21459
- } else if (hasBackgroundColor && init.slide.backgroundColor) {
21755
+ }
21756
+ if (backgroundProperties["a:blipFill"] === void 0 && hasBackgroundColor && init.slide.backgroundColor) {
21460
21757
  backgroundProperties["a:solidFill"] = {
21461
21758
  "a:srgbClr": {
21462
21759
  "@_val": init.slide.backgroundColor.replace("#", "").toUpperCase()
@@ -21473,6 +21770,11 @@ var PptxSlideBackgroundBuilder = class {
21473
21770
  backgroundProperties["@_shadeToTitle"] = "0";
21474
21771
  }
21475
21772
  if (!hasFillChild) {
21773
+ if (existingBg !== void 0) {
21774
+ this.reorderCSldBgFirst(cSld, existingBg);
21775
+ init.slideNode["p:cSld"] = cSld;
21776
+ return;
21777
+ }
21476
21778
  delete cSld["p:bg"];
21477
21779
  init.slideNode["p:cSld"] = cSld;
21478
21780
  return;
@@ -21682,11 +21984,15 @@ var PptxColorTransformCodec = class {
21682
21984
  }
21683
21985
  if (colorChoice["a:scrgbClr"]) {
21684
21986
  const scrgb = colorChoice["a:scrgbClr"];
21685
- const red = this.percentAttrToUnit(scrgb["@_r"]);
21686
- const green = this.percentAttrToUnit(scrgb["@_g"]);
21687
- const blue = this.percentAttrToUnit(scrgb["@_b"]);
21987
+ const red = parseDrawingFraction(scrgb["@_r"]);
21988
+ const green = parseDrawingFraction(scrgb["@_g"]);
21989
+ const blue = parseDrawingFraction(scrgb["@_b"]);
21688
21990
  if (red !== void 0 && green !== void 0 && blue !== void 0) {
21689
- const base = this.rgbToHex(red * 255, green * 255, blue * 255);
21991
+ const base = this.rgbToHex(
21992
+ scrgbLinearToSrgb8(red),
21993
+ scrgbLinearToSrgb8(green),
21994
+ scrgbLinearToSrgb8(blue)
21995
+ );
21690
21996
  return this.applyColorTransforms(base, scrgb);
21691
21997
  }
21692
21998
  }
@@ -21777,8 +22083,8 @@ var PptxColorTransformCodec = class {
21777
22083
  };
21778
22084
  }
21779
22085
  rgbToHex(r, g, b) {
21780
- const toHex3 = (channelValue) => this.clampColorChannel(channelValue).toString(16).padStart(2, "0").toUpperCase();
21781
- return `#${toHex3(r)}${toHex3(g)}${toHex3(b)}`;
22086
+ const toHex4 = (channelValue) => this.clampColorChannel(channelValue).toString(16).padStart(2, "0").toUpperCase();
22087
+ return `#${toHex4(r)}${toHex4(g)}${toHex4(b)}`;
21782
22088
  }
21783
22089
  applyColorTransforms(baseColor, colorNode) {
21784
22090
  return applyDrawingColorTransforms(baseColor, colorNode);
@@ -21866,6 +22172,22 @@ function mergeDrawingFillXml(original, generated, modeledChildren, childOrder2)
21866
22172
  }
21867
22173
 
21868
22174
  // src/core/core/builders/PptxGradientStyleCodec.ts
22175
+ function extractGradientTileRect(gradFill) {
22176
+ const tileRect = drawingChild(gradFill, "tileRect");
22177
+ if (!tileRect) {
22178
+ return void 0;
22179
+ }
22180
+ const toFraction = (raw) => {
22181
+ const parsed = Number.parseInt(String(raw ?? "0"), 10);
22182
+ return Number.isFinite(parsed) ? parsed / 1e5 : 0;
22183
+ };
22184
+ return {
22185
+ l: toFraction(tileRect["@_l"]),
22186
+ t: toFraction(tileRect["@_t"]),
22187
+ r: toFraction(tileRect["@_r"]),
22188
+ b: toFraction(tileRect["@_b"])
22189
+ };
22190
+ }
21869
22191
  var PptxGradientStyleCodec = class {
21870
22192
  context;
21871
22193
  constructor(context) {
@@ -21976,6 +22298,9 @@ var PptxGradientStyleCodec = class {
21976
22298
  b: Number.isFinite(b) ? this.context.clampUnitInterval(b / 1e5) : 0
21977
22299
  };
21978
22300
  }
22301
+ extractGradientTileRect(gradFill) {
22302
+ return extractGradientTileRect(gradFill);
22303
+ }
21979
22304
  extractGradientFlip(gradFill) {
21980
22305
  const flipRaw = String(gradFill["@_flip"] || "").trim().toLowerCase();
21981
22306
  if (flipRaw === "x" || flipRaw === "y" || flipRaw === "xy" || flipRaw === "none") {
@@ -22147,6 +22472,15 @@ var PptxGradientStyleCodec = class {
22147
22472
  }
22148
22473
  gradientXml["a:lin"] = linNode;
22149
22474
  }
22475
+ if (shapeStyle.fillGradientTileRect) {
22476
+ const tr = shapeStyle.fillGradientTileRect;
22477
+ gradientXml["a:tileRect"] = {
22478
+ "@_l": String(Math.round(tr.l * 1e5)),
22479
+ "@_t": String(Math.round(tr.t * 1e5)),
22480
+ "@_r": String(Math.round(tr.r * 1e5)),
22481
+ "@_b": String(Math.round(tr.b * 1e5))
22482
+ };
22483
+ }
22150
22484
  return mergeDrawingFillXml(
22151
22485
  shapeStyle.fillGradientXml,
22152
22486
  gradientXml,
@@ -23625,7 +23959,7 @@ var PptxColorStyleCodec = class {
23625
23959
  const alphaMod = this.percentAttrToUnit(
23626
23960
  choiceNode["a:alphaMod"]?.["@_val"]
23627
23961
  );
23628
- const alphaOff = this.percentAttrToUnit(
23962
+ const alphaOff = this.signedPercentToUnit(
23629
23963
  choiceNode["a:alphaOff"]?.["@_val"]
23630
23964
  );
23631
23965
  if (alpha === void 0 && alphaMod === void 0 && alphaOff === void 0) {
@@ -23640,6 +23974,18 @@ var PptxColorStyleCodec = class {
23640
23974
  }
23641
23975
  return this.clampUnitInterval(opacity2);
23642
23976
  }
23977
+ /**
23978
+ * Parse an OOXML percentage (thousandths, `100000` = 100%) into a fraction
23979
+ * WITHOUT clamping to [0, 1]. Used for additive offsets like `a:alphaOff`
23980
+ * that legitimately carry negative values.
23981
+ */
23982
+ signedPercentToUnit(value) {
23983
+ const parsed = Number.parseFloat(String(value ?? "").trim());
23984
+ if (!Number.isFinite(parsed)) {
23985
+ return void 0;
23986
+ }
23987
+ return parsed / 1e5;
23988
+ }
23643
23989
  colorWithOpacity(color2, opacity2) {
23644
23990
  if (opacity2 === void 0) {
23645
23991
  return color2;
@@ -23823,10 +24169,12 @@ function applyLineProperties(lineNode, shapeProps, style, context, resolveHidden
23823
24169
  }
23824
24170
  const hiddenLineFill = hiddenLineProps["a:solidFill"];
23825
24171
  if (hiddenLineFill) {
24172
+ style.strokeFillMode = "solid";
23826
24173
  style.strokeColor = context.parseColor(hiddenLineFill);
23827
24174
  style.strokeOpacity = context.extractColorOpacity(hiddenLineFill);
23828
24175
  }
23829
24176
  } else {
24177
+ style.strokeFillMode = "none";
23830
24178
  style.strokeWidth = 0;
23831
24179
  style.strokeColor = "transparent";
23832
24180
  }
@@ -23844,6 +24192,7 @@ function applyLineProperties(lineNode, shapeProps, style, context, resolveHidden
23844
24192
  }
23845
24193
  function applyStrokeColor(lineNode, style, context) {
23846
24194
  if (lineNode["a:solidFill"]) {
24195
+ style.strokeFillMode = "solid";
23847
24196
  const lineFill = lineNode["a:solidFill"];
23848
24197
  style.strokeColor = context.parseColor(lineFill);
23849
24198
  style.strokeOpacity = context.extractColorOpacity(lineFill);
@@ -23852,10 +24201,15 @@ function applyStrokeColor(lineNode, style, context) {
23852
24201
  style.strokeColorXml = strokeColorXml;
23853
24202
  }
23854
24203
  } else if (lineNode["a:gradFill"]) {
23855
- style.strokeColor = context.extractGradientFillColor(lineNode["a:gradFill"]);
23856
- style.strokeOpacity = context.extractGradientOpacity(lineNode["a:gradFill"]);
24204
+ style.strokeFillMode = "gradient";
24205
+ const lineGradFill = lineNode["a:gradFill"];
24206
+ style.strokeGradientXml = lineGradFill;
24207
+ style.strokeColor = context.extractGradientFillColor(lineGradFill);
24208
+ style.strokeOpacity = context.extractGradientOpacity(lineGradFill);
23857
24209
  } else if (lineNode["a:pattFill"]) {
24210
+ style.strokeFillMode = "pattern";
23858
24211
  const linePatternFill = lineNode["a:pattFill"];
24212
+ style.strokePatternXml = linePatternFill;
23859
24213
  style.strokeColor = context.parseColor(linePatternFill["a:fgClr"]) || context.parseColor(linePatternFill["a:bgClr"]);
23860
24214
  style.strokeOpacity = context.extractColorOpacity(linePatternFill["a:fgClr"]) || context.extractColorOpacity(linePatternFill["a:bgClr"]);
23861
24215
  }
@@ -23984,6 +24338,10 @@ var PptxShapeStyleExtractor = class {
23984
24338
  style.fillGradientPathType = this.context.extractGradientPathType(gradFill);
23985
24339
  style.fillGradientFocalPoint = this.context.extractGradientFocalPoint(gradFill);
23986
24340
  style.fillGradientFillToRect = this.context.extractGradientFillToRect(gradFill);
24341
+ const gradTileRect = extractGradientTileRect(gradFill);
24342
+ if (gradTileRect) {
24343
+ style.fillGradientTileRect = gradTileRect;
24344
+ }
23987
24345
  const gradFlip = this.context.extractGradientFlip(gradFill);
23988
24346
  if (gradFlip) {
23989
24347
  style.fillGradientFlip = gradFlip;
@@ -25177,6 +25535,7 @@ var PptxLoadDataBuilder = class {
25177
25535
  layoutOptions = [];
25178
25536
  headerFooter;
25179
25537
  presentationProperties;
25538
+ viewProperties;
25180
25539
  customShows;
25181
25540
  sections;
25182
25541
  warnings = [];
@@ -25236,6 +25595,10 @@ var PptxLoadDataBuilder = class {
25236
25595
  this.presentationProperties = presentationProperties;
25237
25596
  return this;
25238
25597
  }
25598
+ withViewProperties(viewProperties) {
25599
+ this.viewProperties = viewProperties;
25600
+ return this;
25601
+ }
25239
25602
  withCustomShows(customShows) {
25240
25603
  this.customShows = customShows;
25241
25604
  return this;
@@ -25373,6 +25736,7 @@ var PptxLoadDataBuilder = class {
25373
25736
  layoutOptions: this.layoutOptions,
25374
25737
  headerFooter: this.headerFooter,
25375
25738
  presentationProperties: this.presentationProperties,
25739
+ viewProperties: this.viewProperties,
25376
25740
  customShows: this.customShows,
25377
25741
  sections: this.sections,
25378
25742
  warnings: this.warnings,
@@ -25755,7 +26119,7 @@ var PptxSlideCommentsXmlFactory = class {
25755
26119
  const createdAtIso = this.resolveCreatedAt(comment.createdAt);
25756
26120
  const x = init.saveState.toEmu(comment.x, 0);
25757
26121
  const y = init.saveState.toEmu(comment.y, 0);
25758
- return {
26122
+ const node = {
25759
26123
  ...withoutChildrenByLocalName(comment.rawXml ?? {}, /* @__PURE__ */ new Set(["pos", "text"])),
25760
26124
  "@_authorId": authorId,
25761
26125
  "@_dt": createdAtIso,
@@ -25766,6 +26130,28 @@ var PptxSlideCommentsXmlFactory = class {
25766
26130
  },
25767
26131
  "p:text": String(comment.text || "")
25768
26132
  };
26133
+ this.applyResolvedState(node, comment);
26134
+ return node;
26135
+ }
26136
+ /**
26137
+ * Reflect the (possibly edited) `resolved` flag onto the legacy comment
26138
+ * node. PowerPoint's legacy comment schema has no standard resolved marker,
26139
+ * but the parser reads a non-standard `@_done` / `@_resolved` attribute, so
26140
+ * we re-emit the current state rather than leaving the stale value carried
26141
+ * over from `rawXml`. The original attribute name is preserved when present.
26142
+ */
26143
+ applyResolvedState(node, comment) {
26144
+ const raw = comment.rawXml;
26145
+ const hadResolvedAttr = raw?.["@_resolved"] !== void 0;
26146
+ const hadDoneAttr = raw?.["@_done"] !== void 0;
26147
+ const key = hadResolvedAttr && !hadDoneAttr ? "@_resolved" : "@_done";
26148
+ delete node["@_done"];
26149
+ delete node["@_resolved"];
26150
+ if (comment.resolved === true) {
26151
+ node[key] = "1";
26152
+ } else if (hadResolvedAttr || hadDoneAttr) {
26153
+ node[key] = "0";
26154
+ }
25769
26155
  }
25770
26156
  resolveCreatedAt(createdAt) {
25771
26157
  const candidate = String(createdAt || "").trim();
@@ -26127,6 +26513,94 @@ var PptxCompatibilityService = class {
26127
26513
  }
26128
26514
  };
26129
26515
 
26516
+ // src/core/utils/app-properties-titles.ts
26517
+ var SLIDE_TITLES_NAME = "Slide Titles";
26518
+ function coerceText(value) {
26519
+ if (typeof value === "string") {
26520
+ return value;
26521
+ }
26522
+ if (typeof value === "number" || typeof value === "boolean") {
26523
+ return String(value);
26524
+ }
26525
+ if (isXmlNode(value)) {
26526
+ const text2 = value["#text"];
26527
+ return text2 === void 0 || text2 === null ? "" : String(text2);
26528
+ }
26529
+ return "";
26530
+ }
26531
+ function coerceCount(value) {
26532
+ const parsed = Number.parseInt(coerceText(value), 10);
26533
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
26534
+ }
26535
+ function readLpstrList(vector) {
26536
+ if (!vector) {
26537
+ return [];
26538
+ }
26539
+ const raw = vector["vt:lpstr"];
26540
+ if (raw === void 0 || raw === null) {
26541
+ return [];
26542
+ }
26543
+ return (Array.isArray(raw) ? raw : [raw]).map(coerceText);
26544
+ }
26545
+ function isSlideTitlesCategory(name) {
26546
+ const normalized = name.trim().toLowerCase();
26547
+ return normalized === "slide titles" || normalized.includes("slide") && normalized.includes("title");
26548
+ }
26549
+ function readCategories(headingPairs, titlesOfParts) {
26550
+ const variants = xmlChildren(xmlChild(headingPairs, "vt:vector"), "vt:variant");
26551
+ const entries = readLpstrList(xmlChild(titlesOfParts, "vt:vector"));
26552
+ const categories = [];
26553
+ let offset = 0;
26554
+ for (let i = 0; i + 1 < variants.length; i += 2) {
26555
+ const name = coerceText(variants[i]["vt:lpstr"]);
26556
+ const count = coerceCount(variants[i + 1]["vt:i4"]);
26557
+ categories.push({ name, entries: entries.slice(offset, offset + count) });
26558
+ offset += count;
26559
+ }
26560
+ return categories;
26561
+ }
26562
+ function writeHeadingPairs(appProps, categories) {
26563
+ const variants = [];
26564
+ for (const category of categories) {
26565
+ variants.push({ "vt:lpstr": category.name });
26566
+ variants.push({ "vt:i4": String(category.entries.length) });
26567
+ }
26568
+ appProps["HeadingPairs"] = {
26569
+ "vt:vector": {
26570
+ "@_size": String(variants.length),
26571
+ "@_baseType": "variant",
26572
+ "vt:variant": variants
26573
+ }
26574
+ };
26575
+ }
26576
+ function writeTitlesOfParts(appProps, categories) {
26577
+ const allEntries = categories.flatMap((category) => category.entries);
26578
+ const lpstr = allEntries.map((entry) => ({ "#text": entry }));
26579
+ appProps["TitlesOfParts"] = {
26580
+ "vt:vector": {
26581
+ "@_size": String(allEntries.length),
26582
+ "@_baseType": "lpstr",
26583
+ "vt:lpstr": lpstr
26584
+ }
26585
+ };
26586
+ }
26587
+ function applySlideTitlesToAppProps(appProps, titles) {
26588
+ const headingPairs = xmlChild(appProps, "HeadingPairs");
26589
+ if (!headingPairs) {
26590
+ return;
26591
+ }
26592
+ const titlesOfParts = xmlChild(appProps, "TitlesOfParts");
26593
+ const categories = readCategories(headingPairs, titlesOfParts);
26594
+ const slideCategory = categories.find((category) => isSlideTitlesCategory(category.name));
26595
+ if (slideCategory) {
26596
+ slideCategory.entries = titles;
26597
+ } else {
26598
+ categories.push({ name: SLIDE_TITLES_NAME, entries: titles });
26599
+ }
26600
+ writeHeadingPairs(appProps, categories);
26601
+ writeTitlesOfParts(appProps, categories);
26602
+ }
26603
+
26130
26604
  // src/core/services/PptxDocumentPropertiesUpdater.ts
26131
26605
  var PptxDocumentPropertiesUpdater = class {
26132
26606
  context;
@@ -26190,6 +26664,7 @@ var PptxDocumentPropertiesUpdater = class {
26190
26664
  appProps["Slides"] = String(slides.length);
26191
26665
  appProps["HiddenSlides"] = String(hiddenSlidesCount);
26192
26666
  appProps["Notes"] = String(notesCount);
26667
+ this.updateSlideTitleProperties(appProps, slides);
26193
26668
  appData["Properties"] = appProps;
26194
26669
  this.context.zip.file("docProps/app.xml", this.context.builder.build(appData));
26195
26670
  } catch (error) {
@@ -26232,6 +26707,15 @@ var PptxDocumentPropertiesUpdater = class {
26232
26707
  }
26233
26708
  }
26234
26709
  }
26710
+ /**
26711
+ * Recompute `TitlesOfParts` / `HeadingPairs` from the current slide set so
26712
+ * the per-slide title list in `app.xml` stays consistent after slides are
26713
+ * added, removed, or retitled. Delegates the vector rebuild to a pure
26714
+ * helper; here we only derive the ordered titles.
26715
+ */
26716
+ updateSlideTitleProperties(appProps, slides) {
26717
+ applySlideTitlesToAppProps(appProps, deriveSlideTitles(slides));
26718
+ }
26235
26719
  applyAppPropertiesOverrides(appProps, overrides) {
26236
26720
  if (!overrides) {
26237
26721
  return;
@@ -27851,6 +28335,16 @@ function extractChildKeyframes(childTnList) {
27851
28335
  }
27852
28336
  return void 0;
27853
28337
  }
28338
+ function parseTimingPercentFraction(raw) {
28339
+ if (raw === void 0 || raw === null) {
28340
+ return void 0;
28341
+ }
28342
+ const parsed = Number.parseInt(String(raw), 10);
28343
+ if (!Number.isFinite(parsed) || parsed <= 0) {
28344
+ return void 0;
28345
+ }
28346
+ return Math.min(1, parsed / 1e5);
28347
+ }
27854
28348
  function extractRepeatInfo(cTn) {
27855
28349
  let repeatCount;
27856
28350
  let autoReverse;
@@ -28332,6 +28826,8 @@ var PptxNativeAnimationService = class {
28332
28826
  const presetSubtype = cTn["@_presetSubtype"] !== void 0 ? Number.parseInt(String(cTn["@_presetSubtype"]), 10) : void 0;
28333
28827
  const durationMs = cTn["@_dur"] ? Number.parseInt(String(cTn["@_dur"]), 10) : void 0;
28334
28828
  const delayMs = cTn["@_delay"] ? Number.parseInt(String(cTn["@_delay"]), 10) : void 0;
28829
+ const accel = parseTimingPercentFraction(cTn["@_accel"]);
28830
+ const decel = parseTimingPercentFraction(cTn["@_decel"]);
28335
28831
  let trigger = currentTrigger;
28336
28832
  if (nodeType === "afterPrevious" || nodeType === "afterPrev") {
28337
28833
  trigger = "afterPrevious";
@@ -28384,6 +28880,8 @@ var PptxNativeAnimationService = class {
28384
28880
  presetSubtype,
28385
28881
  durationMs,
28386
28882
  delayMs,
28883
+ accel,
28884
+ decel,
28387
28885
  triggerDelayMs: trigger === "afterDelay" ? delayMs : void 0,
28388
28886
  motionPath: childMotion.motionPath,
28389
28887
  motionOrigin: childMotion.motionOrigin,
@@ -32142,6 +32640,128 @@ function applySmartArtConnectionAttributes(xml, connection, fallbackModelId) {
32142
32640
  applyNullableAttribute(xml, "@_presId", connection.presentationId);
32143
32641
  }
32144
32642
 
32643
+ // src/core/utils/smartart-color-lists.ts
32644
+ var COLOR_LOCAL_NAMES = /* @__PURE__ */ new Set([
32645
+ "srgbClr",
32646
+ "schemeClr",
32647
+ "scrgbClr",
32648
+ "sysClr",
32649
+ "prstClr",
32650
+ "hslClr"
32651
+ ]);
32652
+ var COLOR_METHODS2 = /* @__PURE__ */ new Set(["span", "cycle", "repeat"]);
32653
+ var HUE_DIRECTIONS2 = /* @__PURE__ */ new Set(["cw", "ccw"]);
32654
+ var PRIMARY_LABEL_PRIORITY = ["node0", "node1", "node2", "node3", "node4", "node"];
32655
+ function localNameOf3(key) {
32656
+ const idx = key.indexOf(":");
32657
+ return idx >= 0 ? key.slice(idx + 1) : key;
32658
+ }
32659
+ function parseSmartArtColorListHexes(list, deps) {
32660
+ if (!list) {
32661
+ return [];
32662
+ }
32663
+ const out = [];
32664
+ for (const [key, value] of Object.entries(list)) {
32665
+ if (key.startsWith("@_")) {
32666
+ continue;
32667
+ }
32668
+ const local = localNameOf3(key);
32669
+ if (!COLOR_LOCAL_NAMES.has(local)) {
32670
+ continue;
32671
+ }
32672
+ const nodes = Array.isArray(value) ? value : [value];
32673
+ for (const node of nodes) {
32674
+ if (!node || typeof node !== "object") {
32675
+ continue;
32676
+ }
32677
+ const wrapper = { [`a:${local}`]: node };
32678
+ const hex10 = deps.parseColorChoice(wrapper) ?? deps.resolveScheme(node);
32679
+ if (hex10) {
32680
+ out.push(hex10);
32681
+ }
32682
+ }
32683
+ }
32684
+ return out;
32685
+ }
32686
+ function listInterpolation(list) {
32687
+ if (!list) {
32688
+ return void 0;
32689
+ }
32690
+ const method = String(list["@_meth"] ?? "").trim();
32691
+ const hueDir = String(list["@_hueDir"] ?? "").trim();
32692
+ const meta = {};
32693
+ if (COLOR_METHODS2.has(method)) {
32694
+ meta.method = method;
32695
+ }
32696
+ if (HUE_DIRECTIONS2.has(hueDir)) {
32697
+ meta.hueDirection = hueDir;
32698
+ }
32699
+ return meta.method || meta.hueDirection ? meta : void 0;
32700
+ }
32701
+ function parseLabel(lbl, deps) {
32702
+ const fillList = deps.getChild(lbl, "fillClrLst");
32703
+ const lineList = deps.getChild(lbl, "linClrLst");
32704
+ return {
32705
+ name: String(lbl["@_name"] ?? "").trim(),
32706
+ fill: parseSmartArtColorListHexes(fillList, deps),
32707
+ line: parseSmartArtColorListHexes(lineList, deps),
32708
+ textFill: parseSmartArtColorListHexes(deps.getChild(lbl, "txFillClrLst"), deps),
32709
+ textLine: parseSmartArtColorListHexes(deps.getChild(lbl, "txLinClrLst"), deps),
32710
+ effect: parseSmartArtColorListHexes(deps.getChild(lbl, "effectClrLst"), deps),
32711
+ textEffect: parseSmartArtColorListHexes(deps.getChild(lbl, "txEffectClrLst"), deps),
32712
+ fillInterpolation: listInterpolation(fillList),
32713
+ lineInterpolation: listInterpolation(lineList)
32714
+ };
32715
+ }
32716
+ function selectPrimary(parsed) {
32717
+ const byName = new Map(parsed.map((p) => [p.name, p]));
32718
+ for (const name of PRIMARY_LABEL_PRIORITY) {
32719
+ const candidate = byName.get(name);
32720
+ if (candidate && candidate.fill.length > 0) {
32721
+ return candidate;
32722
+ }
32723
+ }
32724
+ for (const name of PRIMARY_LABEL_PRIORITY) {
32725
+ const candidate = byName.get(name);
32726
+ if (candidate && (candidate.line.length > 0 || candidate.fill.length > 0)) {
32727
+ return candidate;
32728
+ }
32729
+ }
32730
+ return parsed.find((p) => p.fill.length > 0) ?? parsed.find((p) => p.line.length > 0);
32731
+ }
32732
+ function buildSmartArtColorLists(styleLbls, deps) {
32733
+ const parsed = styleLbls.map((lbl) => parseLabel(lbl, deps));
32734
+ const primary = selectPrimary(parsed);
32735
+ let fillColors = primary?.fill ?? [];
32736
+ let lineColors = primary?.line ?? [];
32737
+ if (fillColors.length === 0) {
32738
+ fillColors = parsed.map((p) => p.fill[0]).filter((c) => Boolean(c));
32739
+ }
32740
+ if (lineColors.length === 0) {
32741
+ lineColors = parsed.map((p) => p.line[0]).filter((c) => Boolean(c));
32742
+ }
32743
+ const result = { fillColors, lineColors };
32744
+ if (primary?.textFill.length) {
32745
+ result.textFillColors = primary.textFill;
32746
+ }
32747
+ if (primary?.textLine.length) {
32748
+ result.textLineColors = primary.textLine;
32749
+ }
32750
+ if (primary?.effect.length) {
32751
+ result.effectColors = primary.effect;
32752
+ }
32753
+ if (primary?.textEffect.length) {
32754
+ result.textEffectColors = primary.textEffect;
32755
+ }
32756
+ if (primary?.fillInterpolation) {
32757
+ result.fillInterpolation = primary.fillInterpolation;
32758
+ }
32759
+ if (primary?.lineInterpolation) {
32760
+ result.lineInterpolation = primary.lineInterpolation;
32761
+ }
32762
+ return result;
32763
+ }
32764
+
32145
32765
  // src/core/utils/modern-comment-constants.ts
32146
32766
  var MODERN_COMMENT_NAMESPACE = "http://schemas.microsoft.com/office/powerpoint/2018/8/main";
32147
32767
  var MODERN_COMMENT_RELATIONSHIP = "http://schemas.microsoft.com/office/2018/10/relationships/comments";
@@ -34448,6 +35068,28 @@ function buildGeneratedChartAxis(axId, crossId, pos2, formatting) {
34448
35068
  return axis;
34449
35069
  }
34450
35070
 
35071
+ // src/core/utils/chart-xml-container-map.ts
35072
+ var CONTAINER_MAP = {
35073
+ pie: { tag: "c:pieChart", family: "pie" },
35074
+ pie3D: { tag: "c:pie3DChart", family: "pie" },
35075
+ ofPie: { tag: "c:ofPieChart", family: "ofPie" },
35076
+ doughnut: { tag: "c:doughnutChart", family: "doughnut" },
35077
+ scatter: { tag: "c:scatterChart", family: "scatter" },
35078
+ bubble: { tag: "c:bubbleChart", family: "bubble" },
35079
+ line: { tag: "c:lineChart", family: "line" },
35080
+ line3D: { tag: "c:line3DChart", family: "line" },
35081
+ area: { tag: "c:areaChart", family: "area" },
35082
+ area3D: { tag: "c:area3DChart", family: "area" },
35083
+ radar: { tag: "c:radarChart", family: "radar" },
35084
+ stock: { tag: "c:stockChart", family: "stock" },
35085
+ surface: { tag: "c:surfaceChart", family: "surface" },
35086
+ bar: { tag: "c:barChart", family: "bar" },
35087
+ bar3D: { tag: "c:bar3DChart", family: "bar" }
35088
+ };
35089
+ function resolveChartContainerType(type) {
35090
+ return CONTAINER_MAP[type] ?? { tag: "c:barChart", family: "bar" };
35091
+ }
35092
+
34451
35093
  // src/core/utils/chart-xml-generator.ts
34452
35094
  var NS_C = "http://schemas.openxmlformats.org/drawingml/2006/chart";
34453
35095
  var NS_A2 = "http://schemas.openxmlformats.org/drawingml/2006/main";
@@ -34478,29 +35120,6 @@ function strLit(values) {
34478
35120
  }
34479
35121
  };
34480
35122
  }
34481
- function resolveType(type) {
34482
- switch (type) {
34483
- case "pie":
34484
- case "pie3D":
34485
- return { tag: "c:pieChart", family: "pie" };
34486
- case "doughnut":
34487
- return { tag: "c:doughnutChart", family: "doughnut" };
34488
- case "scatter":
34489
- return { tag: "c:scatterChart", family: "scatter" };
34490
- case "bubble":
34491
- return { tag: "c:bubbleChart", family: "bubble" };
34492
- case "line":
34493
- case "line3D":
34494
- return { tag: "c:lineChart", family: "line" };
34495
- case "area":
34496
- case "area3D":
34497
- return { tag: "c:areaChart", family: "area" };
34498
- case "radar":
34499
- return { tag: "c:radarChart", family: "radar" };
34500
- default:
34501
- return { tag: "c:barChart", family: "bar" };
34502
- }
34503
- }
34504
35123
  function fillSpPr(color2, asLine) {
34505
35124
  const h = hex6(color2);
34506
35125
  if (!h) {
@@ -34568,7 +35187,10 @@ function buildChartTypeContainer(chartData, family) {
34568
35187
  } else if (family === "scatter") {
34569
35188
  container["c:scatterStyle"] = { "@_val": "lineMarker" };
34570
35189
  container["c:varyColors"] = { "@_val": "0" };
34571
- } else {
35190
+ } else if (family === "ofPie") {
35191
+ container["c:ofPieType"] = { "@_val": "pie" };
35192
+ container["c:varyColors"] = { "@_val": "1" };
35193
+ } else if (family === "stock" || family === "surface") ; else {
34572
35194
  container["c:varyColors"] = { "@_val": family === "bubble" ? "0" : "1" };
34573
35195
  }
34574
35196
  container["c:ser"] = chartData.series.map(
@@ -34580,12 +35202,13 @@ function buildChartTypeContainer(chartData, family) {
34580
35202
  if (family === "line" && chartData.upDownBars !== void 0) {
34581
35203
  applyChartUpDownBars(container, chartData.upDownBars, (key) => key.replace(/^.*:/u, ""));
34582
35204
  }
34583
- if (family === "bar") {
35205
+ if (family === "bar" || family === "ofPie") {
34584
35206
  container["c:gapWidth"] = { "@_val": "150" };
34585
- container["c:axId"] = [{ "@_val": String(CAT_AX_ID) }, { "@_val": String(VAL_AX_ID) }];
34586
- } else if (family === "line" || family === "area" || family === "radar") {
34587
- container["c:axId"] = [{ "@_val": String(CAT_AX_ID) }, { "@_val": String(VAL_AX_ID) }];
34588
- } else if (family === "scatter" || family === "bubble") {
35207
+ }
35208
+ if (family === "stock") {
35209
+ container["c:hiLowLines"] = {};
35210
+ }
35211
+ if (family === "bar" || family === "line" || family === "area" || family === "radar" || family === "scatter" || family === "bubble" || family === "stock" || family === "surface") {
34589
35212
  container["c:axId"] = [{ "@_val": String(CAT_AX_ID) }, { "@_val": String(VAL_AX_ID) }];
34590
35213
  } else if (family === "doughnut") {
34591
35214
  container["c:holeSize"] = { "@_val": "50" };
@@ -34598,7 +35221,8 @@ function buildPlotArea(chartData, tag, family) {
34598
35221
  if (chartData.style) {
34599
35222
  applyChartDataLabelsToXml(plotArea, chartData.style, (key) => key.replace(/^.*:/u, ""));
34600
35223
  }
34601
- if (family !== "pie" && family !== "doughnut" && SCATTER_LIKE.has(chartData.chartType)) {
35224
+ const hasAxes = family !== "pie" && family !== "doughnut" && family !== "ofPie";
35225
+ if (hasAxes && SCATTER_LIKE.has(chartData.chartType)) {
34602
35226
  plotArea["c:valAx"] = [
34603
35227
  buildGeneratedChartAxis(
34604
35228
  CAT_AX_ID,
@@ -34613,7 +35237,7 @@ function buildPlotArea(chartData, tag, family) {
34613
35237
  axisFormatting(chartData, "valAx", VAL_AX_ID, 1)
34614
35238
  )
34615
35239
  ];
34616
- } else if (family !== "pie" && family !== "doughnut") {
35240
+ } else if (hasAxes) {
34617
35241
  const dateAxis = chartData.dateCategories ? axisFormatting(chartData, "dateAx", CAT_AX_ID) : void 0;
34618
35242
  plotArea[dateAxis ? "c:dateAx" : "c:catAx"] = buildGeneratedChartAxis(
34619
35243
  CAT_AX_ID,
@@ -34632,7 +35256,7 @@ function buildPlotArea(chartData, tag, family) {
34632
35256
  return plotArea;
34633
35257
  }
34634
35258
  function buildChartSpaceXml(chartData) {
34635
- const { tag, family } = resolveType(chartData.chartType);
35259
+ const { tag, family } = resolveChartContainerType(chartData.chartType);
34636
35260
  const chart = {};
34637
35261
  if (chartData.title) {
34638
35262
  chart["c:title"] = {
@@ -36564,6 +37188,7 @@ function parseMediaExtensionData(mediaNode, cMediaNode, shapeId, ensureArray16)
36564
37188
  let playbackSpeed;
36565
37189
  let trimStartMs;
36566
37190
  let trimEndMs;
37191
+ let embedRId;
36567
37192
  const bookmarks = [];
36568
37193
  const extLst = mediaNode["p:extLst"] ?? cMediaNode["p:extLst"];
36569
37194
  if (extLst) {
@@ -36571,6 +37196,13 @@ function parseMediaExtensionData(mediaNode, cMediaNode, shapeId, ensureArray16)
36571
37196
  for (const ext of exts) {
36572
37197
  const p14Media = ext["p14:media"];
36573
37198
  if (p14Media) {
37199
+ if (embedRId === void 0) {
37200
+ const embedRaw = p14Media["@_r:embed"] ?? p14Media["@_embed"];
37201
+ const embedStr = embedRaw === void 0 ? "" : String(embedRaw).trim();
37202
+ if (embedStr.length > 0) {
37203
+ embedRId = embedStr;
37204
+ }
37205
+ }
36574
37206
  const p14Trim = p14Media["p14:trim"];
36575
37207
  if (p14Trim) {
36576
37208
  const st = p14Trim["@_st"];
@@ -36640,7 +37272,8 @@ function parseMediaExtensionData(mediaNode, cMediaNode, shapeId, ensureArray16)
36640
37272
  fadeInDuration,
36641
37273
  fadeOutDuration,
36642
37274
  playbackSpeed,
36643
- bookmarks
37275
+ bookmarks,
37276
+ embedRId
36644
37277
  };
36645
37278
  }
36646
37279
 
@@ -36870,6 +37503,12 @@ var PptxHandlerRuntime = class {
36870
37503
  loadedEmbeddedFonts = [];
36871
37504
  /** Typed source metadata for lossless embedded-font list round trips. */
36872
37505
  loadedEmbeddedFontList;
37506
+ /**
37507
+ * View properties parsed from `ppt/viewProps.xml` during load, preserved so
37508
+ * an unmodified load -> save round-trips the typed model and callers that do
37509
+ * not override `saveOptions.viewProperties` still persist the loaded state.
37510
+ */
37511
+ loadedViewProperties;
36873
37512
  /** Map of comment author IDs to display names (from `ppt/commentAuthors.xml`). */
36874
37513
  commentAuthorMap = /* @__PURE__ */ new Map();
36875
37514
  /** Full comment author details keyed by author ID, preserving initials/lastIdx/clrIdx for round-trip. */
@@ -37096,19 +37735,179 @@ function parseTableStyleBorders(tcStyle) {
37096
37735
  return has ? result : void 0;
37097
37736
  }
37098
37737
 
37738
+ // src/core/core/runtime/table-style-fill-parse.ts
37739
+ function toHex3(raw) {
37740
+ const hex10 = String(raw ?? "").trim();
37741
+ if (!hex10) {
37742
+ return void 0;
37743
+ }
37744
+ return hex10.startsWith("#") ? hex10 : `#${hex10}`;
37745
+ }
37746
+ function parseColorChoiceFill(node) {
37747
+ if (!node) {
37748
+ return void 0;
37749
+ }
37750
+ const scheme = parseSolidFillStyle(node);
37751
+ if (scheme) {
37752
+ return scheme;
37753
+ }
37754
+ const srgb = node["a:srgbClr"];
37755
+ const color2 = toHex3(srgb?.["@_val"]);
37756
+ if (!color2) {
37757
+ return void 0;
37758
+ }
37759
+ const fill = { schemeColor: "", color: color2 };
37760
+ const tintRaw = srgb?.["a:tint"];
37761
+ const tint = tintRaw ? parseInt(String(tintRaw["@_val"] || "0"), 10) || void 0 : void 0;
37762
+ if (tint !== void 0) {
37763
+ fill.tint = tint;
37764
+ }
37765
+ const shadeRaw = srgb?.["a:shade"];
37766
+ const shade = shadeRaw ? parseInt(String(shadeRaw["@_val"] || "0"), 10) || void 0 : void 0;
37767
+ if (shade !== void 0) {
37768
+ fill.shade = shade;
37769
+ }
37770
+ return fill;
37771
+ }
37772
+ function parseGradientFill(gradFill) {
37773
+ const gsLst = gradFill["a:gsLst"];
37774
+ const rawStops = gsLst?.["a:gs"];
37775
+ const gsNodes = Array.isArray(rawStops) ? rawStops : rawStops ? [rawStops] : [];
37776
+ const stops = [];
37777
+ for (const gs of gsNodes) {
37778
+ const fill = parseColorChoiceFill(gs);
37779
+ if (!fill) {
37780
+ continue;
37781
+ }
37782
+ const position2 = (parseInt(String(gs["@_pos"] || "0"), 10) || 0) / 1e3;
37783
+ stops.push({ position: position2, fill });
37784
+ }
37785
+ if (stops.length === 0) {
37786
+ return void 0;
37787
+ }
37788
+ const lin = gradFill["a:lin"];
37789
+ if (lin) {
37790
+ const angRaw = parseInt(String(lin["@_ang"] || "0"), 10) || 0;
37791
+ const angle = (angRaw / 6e4 % 360 + 360) % 360;
37792
+ return { stops, angle, type: "linear" };
37793
+ }
37794
+ if (gradFill["a:path"] !== void 0) {
37795
+ return { stops, type: "radial" };
37796
+ }
37797
+ return { stops, type: "linear" };
37798
+ }
37799
+ function parsePatternFill(pattFill) {
37800
+ const preset = String(pattFill["@_prst"] || "").trim();
37801
+ if (!preset) {
37802
+ return void 0;
37803
+ }
37804
+ const pattern = { preset };
37805
+ const foreground = parseColorChoiceFill(pattFill["a:fgClr"]);
37806
+ if (foreground) {
37807
+ pattern.foreground = foreground;
37808
+ }
37809
+ const background = parseColorChoiceFill(pattFill["a:bgClr"]);
37810
+ if (background) {
37811
+ pattern.background = background;
37812
+ }
37813
+ return pattern;
37814
+ }
37815
+ function parseTableStyleSectionFill(section) {
37816
+ if (!section) {
37817
+ return void 0;
37818
+ }
37819
+ const tcStyle = section["a:tcStyle"];
37820
+ const fillWrap = tcStyle?.["a:fill"];
37821
+ if (!fillWrap) {
37822
+ return void 0;
37823
+ }
37824
+ if (fillWrap["a:noFill"] !== void 0) {
37825
+ return { schemeColor: "", noFill: true };
37826
+ }
37827
+ const solid = fillWrap["a:solidFill"];
37828
+ if (solid) {
37829
+ return parseColorChoiceFill(solid);
37830
+ }
37831
+ const grad = fillWrap["a:gradFill"];
37832
+ if (grad) {
37833
+ const gradient = parseGradientFill(grad);
37834
+ if (gradient) {
37835
+ return { schemeColor: "", gradient };
37836
+ }
37837
+ }
37838
+ const patt = fillWrap["a:pattFill"];
37839
+ if (patt) {
37840
+ const pattern = parsePatternFill(patt);
37841
+ if (pattern) {
37842
+ return { schemeColor: "", pattern };
37843
+ }
37844
+ }
37845
+ return void 0;
37846
+ }
37847
+ function parseTableStyleSectionText(section) {
37848
+ const tcTxStyle = section?.["a:tcTxStyle"];
37849
+ if (!tcTxStyle) {
37850
+ return void 0;
37851
+ }
37852
+ const result = {};
37853
+ let hasProps = false;
37854
+ if (tcTxStyle["@_b"] === "on") {
37855
+ result.bold = true;
37856
+ hasProps = true;
37857
+ }
37858
+ if (tcTxStyle["@_i"] === "on") {
37859
+ result.italic = true;
37860
+ hasProps = true;
37861
+ }
37862
+ const underline = String(tcTxStyle["@_u"] || "").trim();
37863
+ if (underline && underline !== "none") {
37864
+ result.underline = true;
37865
+ hasProps = true;
37866
+ }
37867
+ const font = tcTxStyle["a:font"];
37868
+ const face = font ? String(font["@_typeface"] || "").trim() : "";
37869
+ if (face) {
37870
+ result.fontFace = face;
37871
+ hasProps = true;
37872
+ }
37873
+ const fontRef = tcTxStyle["a:fontRef"];
37874
+ const idx = fontRef ? String(fontRef["@_idx"] || "").trim() : "";
37875
+ if (idx) {
37876
+ result.fontRefIdx = idx;
37877
+ hasProps = true;
37878
+ }
37879
+ const schemeClr = fontRef?.["a:schemeClr"] ?? tcTxStyle["a:schemeClr"];
37880
+ if (schemeClr) {
37881
+ const val = String(schemeClr["@_val"] || "").trim();
37882
+ if (val) {
37883
+ result.fontSchemeColor = val;
37884
+ hasProps = true;
37885
+ const tintNode = schemeClr["a:tint"];
37886
+ if (tintNode) {
37887
+ result.fontTint = parseInt(String(tintNode["@_val"] || "0"), 10) || void 0;
37888
+ }
37889
+ const shadeNode = schemeClr["a:shade"];
37890
+ if (shadeNode) {
37891
+ result.fontShade = parseInt(String(shadeNode["@_val"] || "0"), 10) || void 0;
37892
+ }
37893
+ }
37894
+ } else {
37895
+ const srgb = fontRef?.["a:srgbClr"] ?? tcTxStyle["a:srgbClr"];
37896
+ const hex10 = toHex3(srgb?.["@_val"]);
37897
+ if (hex10) {
37898
+ result.fontColor = hex10;
37899
+ hasProps = true;
37900
+ }
37901
+ }
37902
+ return hasProps ? result : void 0;
37903
+ }
37904
+
37099
37905
  // src/core/core/runtime/PptxHandlerRuntimeTableStyles.ts
37100
37906
  var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
37101
37907
  /**
37102
- * Export slides to a raster/vector format.
37103
- *
37104
- * This is a stub that signals export intent. Actual rendering requires a
37105
- * platform-specific canvas or PDF library (e.g. Puppeteer, node-canvas,
37106
- * pdfkit). Host applications should override or extend this method with
37107
- * their own rendering pipeline.
37108
- *
37109
- * @param _slides The slides to export.
37110
- * @param _options Export options (format, DPI, slide indices, etc.).
37111
- * @returns A map of slide index → exported binary data.
37908
+ * Export slides to a raster/vector format. This is a stub that signals
37909
+ * export intent; actual rendering requires a platform-specific canvas or
37910
+ * PDF backend that host applications wire in by overriding this method.
37112
37911
  */
37113
37912
  async exportSlides(slides, options) {
37114
37913
  this.compatibilityService.reportWarning({
@@ -37173,15 +37972,11 @@ var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
37173
37972
  }
37174
37973
  /**
37175
37974
  * Extract fill information from a table style section element
37176
- * (e.g. `a:wholeTbl`, `a:band1H`, `a:firstRow`).
37975
+ * (e.g. `a:wholeTbl`, `a:band1H`, `a:firstRow`). Handles scheme + sRGB
37976
+ * solids, gradients, preset patterns, and `a:noFill` (issue #95).
37177
37977
  */
37178
37978
  extractTableStyleSectionFill(section) {
37179
- if (!section) {
37180
- return void 0;
37181
- }
37182
- const tcStyle = section["a:tcStyle"];
37183
- const fill = tcStyle?.["a:fill"];
37184
- return parseSolidFillStyle(fill?.["a:solidFill"]);
37979
+ return parseTableStyleSectionFill(section);
37185
37980
  }
37186
37981
  /**
37187
37982
  * Extract border styling from a table style section's
@@ -37191,44 +37986,12 @@ var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
37191
37986
  return parseTableStyleBorders(section?.["a:tcStyle"]);
37192
37987
  }
37193
37988
  /**
37194
- * Extract text properties from a:tcTxStyle in a table style section.
37989
+ * Extract text properties from `a:tcTxStyle` in a table style section.
37990
+ * Captures bold/italic/underline, typeface, font-collection index, and the
37991
+ * font colour (scheme or sRGB) (issue #95).
37195
37992
  */
37196
37993
  extractTableStyleSectionText(section) {
37197
- if (!section) {
37198
- return void 0;
37199
- }
37200
- const tcTxStyle = section["a:tcTxStyle"];
37201
- if (!tcTxStyle) {
37202
- return void 0;
37203
- }
37204
- const result = {};
37205
- let hasProps = false;
37206
- if (tcTxStyle["@_b"] === "on") {
37207
- result.bold = true;
37208
- hasProps = true;
37209
- }
37210
- if (tcTxStyle["@_i"] === "on") {
37211
- result.italic = true;
37212
- hasProps = true;
37213
- }
37214
- const fontClr = tcTxStyle["a:fontRef"];
37215
- const schemeClr = fontClr?.["a:schemeClr"] ?? tcTxStyle["a:schemeClr"];
37216
- if (schemeClr) {
37217
- const val = String(schemeClr["@_val"] || "").trim();
37218
- if (val) {
37219
- result.fontSchemeColor = val;
37220
- hasProps = true;
37221
- const tintNode = schemeClr["a:tint"];
37222
- if (tintNode) {
37223
- result.fontTint = parseInt(String(tintNode["@_val"] || "0"), 10) || void 0;
37224
- }
37225
- const shadeNode = schemeClr["a:shade"];
37226
- if (shadeNode) {
37227
- result.fontShade = parseInt(String(shadeNode["@_val"] || "0"), 10) || void 0;
37228
- }
37229
- }
37230
- }
37231
- return hasProps ? result : void 0;
37994
+ return parseTableStyleSectionText(section);
37232
37995
  }
37233
37996
  ensureArray(val) {
37234
37997
  if (!val) {
@@ -37908,6 +38671,7 @@ var PptxHandlerRuntime6 = class extends PptxHandlerRuntime5 {
37908
38671
  );
37909
38672
  const trimStartMs = timing.trimStartMs ?? extData.trimStartMs;
37910
38673
  const trimEndMs = timing.trimEndMs ?? extData.trimEndMs;
38674
+ const mediaEmbedPath = extData.embedRId ? this.resolveRelationshipTarget(slidePath, extData.embedRId) : void 0;
37911
38675
  result.set(shapeId, {
37912
38676
  trimStartMs: trimStartMs !== void 0 && !isNaN(trimStartMs) ? trimStartMs : void 0,
37913
38677
  trimEndMs: trimEndMs !== void 0 && !isNaN(trimEndMs) ? trimEndMs : void 0,
@@ -37921,7 +38685,8 @@ var PptxHandlerRuntime6 = class extends PptxHandlerRuntime5 {
37921
38685
  playAcrossSlides: timing.playAcrossSlides || void 0,
37922
38686
  hideWhenNotPlaying: hideWhenNotPlaying || void 0,
37923
38687
  bookmarks: extData.bookmarks.length > 0 ? extData.bookmarks : void 0,
37924
- playbackSpeed: extData.playbackSpeed
38688
+ playbackSpeed: extData.playbackSpeed,
38689
+ mediaEmbedPath
37925
38690
  });
37926
38691
  }
37927
38692
  }
@@ -38097,6 +38862,10 @@ var PptxHandlerRuntime7 = class extends PptxHandlerRuntime6 {
38097
38862
  if (!timing) {
38098
38863
  continue;
38099
38864
  }
38865
+ if (timing.mediaEmbedPath && (typeof el.mediaPath !== "string" || el.mediaPath.length === 0)) {
38866
+ el.mediaPath = timing.mediaEmbedPath;
38867
+ el.mediaMimeType = this.getImageMimeType(timing.mediaEmbedPath);
38868
+ }
38100
38869
  if (timing.trimStartMs !== void 0) {
38101
38870
  el.trimStartMs = timing.trimStartMs;
38102
38871
  }
@@ -39103,7 +39872,7 @@ var PptxHandlerRuntime11 = class extends PptxHandlerRuntime10 {
39103
39872
  }
39104
39873
  }
39105
39874
  async reconcilePresentationSlidesForSave(params) {
39106
- await this.presentationSlidesReconciler.reconcile({
39875
+ return await this.presentationSlidesReconciler.reconcile({
39107
39876
  ...params,
39108
39877
  zip: this.zip,
39109
39878
  parser: this.parser,
@@ -39396,6 +40165,31 @@ function applyFontMetadata(fontNode, panose, pitchFamily, charset) {
39396
40165
  }
39397
40166
  return fontNode;
39398
40167
  }
40168
+ function buildUnderlineLineXml(line2) {
40169
+ const uln = {};
40170
+ if (typeof line2.widthEmu === "number" && Number.isFinite(line2.widthEmu)) {
40171
+ uln["@_w"] = String(Math.round(line2.widthEmu));
40172
+ }
40173
+ if (line2.compound) {
40174
+ uln["@_cmpd"] = line2.compound;
40175
+ }
40176
+ if (line2.cap) {
40177
+ uln["@_cap"] = line2.cap;
40178
+ }
40179
+ if (line2.algn) {
40180
+ uln["@_algn"] = line2.algn;
40181
+ }
40182
+ if (line2.prstDash) {
40183
+ uln["a:prstDash"] = { "@_val": line2.prstDash };
40184
+ }
40185
+ if (line2.headEndXml) {
40186
+ uln["a:headEnd"] = line2.headEndXml;
40187
+ }
40188
+ if (line2.tailEndXml) {
40189
+ uln["a:tailEnd"] = line2.tailEndXml;
40190
+ }
40191
+ return uln;
40192
+ }
39399
40193
  var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime11 {
39400
40194
  createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId) {
39401
40195
  const runProps = {
@@ -39416,6 +40210,8 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39416
40210
  }
39417
40211
  if (style.underline) {
39418
40212
  runProps["@_u"] = style.underlineStyle || "sng";
40213
+ } else if (style.underlineExplicitNone) {
40214
+ runProps["@_u"] = "none";
39419
40215
  }
39420
40216
  if (style.strikethrough !== void 0) {
39421
40217
  runProps["@_strike"] = style.strikethrough ? style.strikeType || "sngStrike" : "noStrike";
@@ -39431,6 +40227,8 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39431
40227
  }
39432
40228
  if (style.textCaps && style.textCaps !== "none") {
39433
40229
  runProps["@_cap"] = style.textCaps;
40230
+ } else if (style.textCapsExplicitNone) {
40231
+ runProps["@_cap"] = "none";
39434
40232
  }
39435
40233
  if (style.kumimoji !== void 0) {
39436
40234
  runProps["@_kumimoji"] = style.kumimoji ? "1" : "0";
@@ -39539,13 +40337,21 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39539
40337
  runProps["a:effectDag"] = style.textEffectDagXml;
39540
40338
  }
39541
40339
  if (style.highlightColor) {
39542
- runProps["a:highlight"] = {
39543
- "a:srgbClr": {
39544
- "@_val": style.highlightColor.replace("#", "")
39545
- }
39546
- };
40340
+ const resolvedHighlight = style.highlightColorXml ? this.parseColor(style.highlightColorXml) : void 0;
40341
+ runProps["a:highlight"] = serializeColorChoice(
40342
+ style.highlightColorXml,
40343
+ resolvedHighlight,
40344
+ style.highlightColor
40345
+ );
40346
+ }
40347
+ if (style.underlineLineFollowsText) {
40348
+ runProps["a:uLnTx"] = {};
40349
+ } else if (style.underlineLine) {
40350
+ runProps["a:uLn"] = buildUnderlineLineXml(style.underlineLine);
39547
40351
  }
39548
- if (style.underline && style.underlineColor) {
40352
+ if (style.underlineFillFollowsText) {
40353
+ runProps["a:uFillTx"] = {};
40354
+ } else if (style.underline && style.underlineColor) {
39549
40355
  runProps["a:uFill"] = {
39550
40356
  "a:solidFill": {
39551
40357
  "a:srgbClr": {
@@ -39554,21 +40360,28 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39554
40360
  }
39555
40361
  };
39556
40362
  }
39557
- if (style.fontFamily) {
40363
+ const latinFace = style.latinFontThemeToken ?? style.fontFamily;
40364
+ if (latinFace) {
39558
40365
  runProps["a:latin"] = applyFontMetadata(
39559
- { "@_typeface": style.fontFamily },
40366
+ { "@_typeface": latinFace },
39560
40367
  style.latinFontPanose,
39561
40368
  style.latinFontPitchFamily,
39562
40369
  style.latinFontCharset
39563
40370
  );
40371
+ }
40372
+ const eastAsiaFace = style.eastAsiaFontThemeToken ?? style.eastAsiaFont;
40373
+ if (eastAsiaFace) {
39564
40374
  runProps["a:ea"] = applyFontMetadata(
39565
- { "@_typeface": style.eastAsiaFont || style.fontFamily },
40375
+ { "@_typeface": eastAsiaFace },
39566
40376
  style.eastAsiaFontPanose,
39567
40377
  style.eastAsiaFontPitchFamily,
39568
40378
  style.eastAsiaFontCharset
39569
40379
  );
40380
+ }
40381
+ const complexScriptFace = style.complexScriptFontThemeToken ?? style.complexScriptFont;
40382
+ if (complexScriptFace) {
39570
40383
  runProps["a:cs"] = applyFontMetadata(
39571
- { "@_typeface": style.complexScriptFont || style.fontFamily },
40384
+ { "@_typeface": complexScriptFace },
39572
40385
  style.complexScriptFontPanose,
39573
40386
  style.complexScriptFontPitchFamily,
39574
40387
  style.complexScriptFontCharset
@@ -39618,12 +40431,17 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39618
40431
  if (mouseOverTarget.length > 0) {
39619
40432
  const mouseOverRelId = resolveHyperlinkRelationshipId(mouseOverTarget);
39620
40433
  if (mouseOverRelId) {
39621
- runProps["a:hlinkMouseOver"] = {
39622
- "@_r:id": mouseOverRelId
39623
- };
40434
+ const mouseOverNode = { "@_r:id": mouseOverRelId };
40435
+ if (style.hyperlinkMouseOverSoundXml && typeof style.hyperlinkMouseOverSoundXml === "object") {
40436
+ mouseOverNode["a:snd"] = style.hyperlinkMouseOverSoundXml;
40437
+ }
40438
+ runProps["a:hlinkMouseOver"] = mouseOverNode;
39624
40439
  }
39625
40440
  }
39626
40441
  }
40442
+ if (style.runPropertiesExtLstXml && typeof style.runPropertiesExtLstXml === "object") {
40443
+ runProps["a:extLst"] = style.runPropertiesExtLstXml;
40444
+ }
39627
40445
  return runProps;
39628
40446
  }
39629
40447
  applyHyperlinkExtraAttrs(hlinkNode, style) {
@@ -39642,22 +40460,26 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39642
40460
  if (style.hyperlinkEndSound !== void 0) {
39643
40461
  hlinkNode["@_endSnd"] = style.hyperlinkEndSound ? "1" : "0";
39644
40462
  }
40463
+ if (style.hyperlinkSoundXml && typeof style.hyperlinkSoundXml === "object") {
40464
+ hlinkNode["a:snd"] = style.hyperlinkSoundXml;
40465
+ }
39645
40466
  }
39646
40467
  };
39647
40468
 
39648
40469
  // src/core/core/runtime/PptxHandlerRuntimeSaveParagraphs.ts
39649
40470
  var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39650
40471
  createParagraphsFromTextContent(text2, textStyle, textSegments, resolveHyperlinkRelationshipId) {
39651
- const paragraphAlign = this.textAlignToDrawingValue(textStyle?.align);
39652
- const spacing = {
39653
- spacingBefore: this.createParagraphSpacingXmlFromPx(textStyle?.paragraphSpacingBefore),
39654
- spacingAfter: this.createParagraphSpacingXmlFromPx(textStyle?.paragraphSpacingAfter),
39655
- lineSpacing: this.createLineSpacingXmlFromMultiplier(textStyle?.lineSpacing),
39656
- lineSpacingExactPt: textStyle?.lineSpacingExactPt
39657
- };
39658
- const createParagraph = (runs, bulletInfo, level, endParaRunProperties) => {
40472
+ const createParagraph = (runs, bulletInfo, level, endParaRunProperties, paragraphProperties2) => {
40473
+ const effectiveStyle = paragraphProperties2 ? { ...textStyle, ...paragraphProperties2 } : textStyle;
40474
+ const paragraphAlign = this.textAlignToDrawingValue(effectiveStyle?.align);
40475
+ const spacing = {
40476
+ spacingBefore: this.createParagraphSpacingXmlFromPx(effectiveStyle?.paragraphSpacingBefore),
40477
+ spacingAfter: this.createParagraphSpacingXmlFromPx(effectiveStyle?.paragraphSpacingAfter),
40478
+ lineSpacing: this.createLineSpacingXmlFromMultiplier(effectiveStyle?.lineSpacing),
40479
+ lineSpacingExactPt: effectiveStyle?.lineSpacingExactPt
40480
+ };
39659
40481
  const paragraphProps = buildParagraphPropertiesXml(
39660
- textStyle,
40482
+ effectiveStyle,
39661
40483
  paragraphAlign,
39662
40484
  bulletInfo,
39663
40485
  spacing,
@@ -39669,12 +40491,22 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39669
40491
  "a:rPr": this.createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId),
39670
40492
  "a:t": runText
39671
40493
  });
39672
- const createFieldRun = (runText, style, fieldType, fieldGuid) => ({
39673
- "@_type": fieldType,
39674
- ...fieldGuid ? { "@_id": fieldGuid } : {},
39675
- "a:rPr": this.createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId),
39676
- "a:t": runText
39677
- });
40494
+ const createFieldRun = (runText, style, fieldType, fieldGuid, fieldGuidAttr, fieldParagraphPropertiesXml) => {
40495
+ const fld = { "@_type": fieldType };
40496
+ if (fieldGuid) {
40497
+ if (fieldGuidAttr === "uuid") {
40498
+ fld["@_uuid"] = fieldGuid;
40499
+ } else {
40500
+ fld["@_id"] = fieldGuid;
40501
+ }
40502
+ }
40503
+ fld["a:rPr"] = this.createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId);
40504
+ if (fieldParagraphPropertiesXml && typeof fieldParagraphPropertiesXml === "object") {
40505
+ fld["a:pPr"] = fieldParagraphPropertiesXml;
40506
+ }
40507
+ fld["a:t"] = runText;
40508
+ return fld;
40509
+ };
39678
40510
  const createRubyRun = (segment, style) => {
39679
40511
  const rubyPr = {};
39680
40512
  if (segment.rubyAlignment) {
@@ -39713,17 +40545,27 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39713
40545
  let currentBulletInfo;
39714
40546
  let currentLevel;
39715
40547
  let currentEndParaRunProperties;
40548
+ let currentParagraphProperties;
40549
+ let capturedParagraphMeta = false;
39716
40550
  const pushParagraph = () => {
39717
40551
  if (currentRuns.length === 0) {
39718
40552
  currentRuns.push(createRun("", textStyle));
39719
40553
  }
39720
40554
  paragraphs.push(
39721
- createParagraph(currentRuns, currentBulletInfo, currentLevel, currentEndParaRunProperties)
40555
+ createParagraph(
40556
+ currentRuns,
40557
+ currentBulletInfo,
40558
+ currentLevel,
40559
+ currentEndParaRunProperties,
40560
+ currentParagraphProperties
40561
+ )
39722
40562
  );
39723
40563
  currentRuns = [];
39724
40564
  currentBulletInfo = void 0;
39725
40565
  currentLevel = void 0;
39726
40566
  currentEndParaRunProperties = void 0;
40567
+ currentParagraphProperties = void 0;
40568
+ capturedParagraphMeta = false;
39727
40569
  };
39728
40570
  if (textSegments && textSegments.length > 0) {
39729
40571
  const uniformSegmentOverrides = computeUniformSegmentOverrides(textStyle, textSegments);
@@ -39733,7 +40575,7 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39733
40575
  ...segment.style,
39734
40576
  ...uniformSegmentOverrides
39735
40577
  };
39736
- if (currentRuns.length === 0) {
40578
+ if (!capturedParagraphMeta) {
39737
40579
  if (segment.bulletInfo) {
39738
40580
  currentBulletInfo = segment.bulletInfo;
39739
40581
  }
@@ -39743,6 +40585,10 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39743
40585
  if (segment.endParaRunProperties) {
39744
40586
  currentEndParaRunProperties = segment.endParaRunProperties;
39745
40587
  }
40588
+ if (segment.paragraphProperties) {
40589
+ currentParagraphProperties = segment.paragraphProperties;
40590
+ }
40591
+ capturedParagraphMeta = true;
39746
40592
  }
39747
40593
  if (segment.isLineBreak) {
39748
40594
  const brNode = {};
@@ -39777,7 +40623,9 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39777
40623
  linePart,
39778
40624
  segmentStyle,
39779
40625
  segment.fieldType,
39780
- segment.fieldGuid
40626
+ segment.fieldGuid,
40627
+ segment.fieldGuidAttr,
40628
+ segment.fieldParagraphPropertiesXml
39781
40629
  );
39782
40630
  fieldRun.__isField = true;
39783
40631
  currentRuns.push(fieldRun);
@@ -40542,7 +41390,95 @@ var PptxHandlerRuntime16 = class extends PptxHandlerRuntime15 {
40542
41390
  };
40543
41391
 
40544
41392
  // src/core/core/runtime/PptxHandlerRuntimeTextStyleUtils.ts
41393
+ var SCRIPT_CANDIDATES = {
41394
+ cjk: ["Hans", "Hant", "Jpan", "Hang"],
41395
+ kana: ["Jpan", "Hans", "Hant"],
41396
+ hangul: ["Hang"],
41397
+ arabic: ["Arab"],
41398
+ hebrew: ["Hebr"],
41399
+ thai: ["Thai"]
41400
+ };
41401
+ function aggregateFontScriptOverrides(perPathMap) {
41402
+ const aggregate = {};
41403
+ for (const overrides of perPathMap.values()) {
41404
+ for (const [script, typeface] of Object.entries(overrides)) {
41405
+ if (!(script in aggregate)) {
41406
+ aggregate[script] = typeface;
41407
+ }
41408
+ }
41409
+ }
41410
+ return aggregate;
41411
+ }
41412
+ function detectDominantScript(text2) {
41413
+ const counts = {};
41414
+ for (const ch of text2) {
41415
+ const code = ch.codePointAt(0) ?? 0;
41416
+ let cat;
41417
+ if (code >= 4352 && code <= 4607) {
41418
+ cat = "hangul";
41419
+ } else if (code >= 44032 && code <= 55215) {
41420
+ cat = "hangul";
41421
+ } else if (code >= 12352 && code <= 12543) {
41422
+ cat = "kana";
41423
+ } else if (code >= 19968 && code <= 40959 || code >= 13312 && code <= 19903 || code >= 63744 && code <= 64255) {
41424
+ cat = "cjk";
41425
+ } else if (code >= 1536 && code <= 1791) {
41426
+ cat = "arabic";
41427
+ } else if (code >= 1424 && code <= 1535) {
41428
+ cat = "hebrew";
41429
+ } else if (code >= 3584 && code <= 3711) {
41430
+ cat = "thai";
41431
+ }
41432
+ if (cat) {
41433
+ counts[cat] = (counts[cat] ?? 0) + 1;
41434
+ }
41435
+ }
41436
+ let best;
41437
+ let bestCount = 0;
41438
+ for (const [cat, count] of Object.entries(counts)) {
41439
+ if (count > bestCount) {
41440
+ best = cat;
41441
+ bestCount = count;
41442
+ }
41443
+ }
41444
+ return best;
41445
+ }
40545
41446
  var PptxHandlerRuntime17 = class extends PptxHandlerRuntime16 {
41447
+ /**
41448
+ * Resolve the automatic per-script fallback face for a run's text from the
41449
+ * theme's `<a:font script="...">` overrides (#83). Body (minor) fonts win
41450
+ * over heading (major) fonts. Returns `undefined` when the deck declares no
41451
+ * script overrides or the text needs no fallback.
41452
+ */
41453
+ resolveScriptFallbackFont(text2) {
41454
+ if (!text2) {
41455
+ return void 0;
41456
+ }
41457
+ if (this.masterThemeMinorFontScripts.size === 0 && this.masterThemeMajorFontScripts.size === 0) {
41458
+ return void 0;
41459
+ }
41460
+ const category = detectDominantScript(text2);
41461
+ if (!category) {
41462
+ return void 0;
41463
+ }
41464
+ const candidates = SCRIPT_CANDIDATES[category];
41465
+ if (!candidates) {
41466
+ return void 0;
41467
+ }
41468
+ const minor = aggregateFontScriptOverrides(this.masterThemeMinorFontScripts);
41469
+ for (const key of candidates) {
41470
+ if (minor[key]) {
41471
+ return minor[key];
41472
+ }
41473
+ }
41474
+ const major = aggregateFontScriptOverrides(this.masterThemeMajorFontScripts);
41475
+ for (const key of candidates) {
41476
+ if (major[key]) {
41477
+ return major[key];
41478
+ }
41479
+ }
41480
+ return void 0;
41481
+ }
40546
41482
  textStylesEqual(left, right) {
40547
41483
  const keys = [
40548
41484
  "fontFamily",
@@ -40703,6 +41639,10 @@ var PptxHandlerRuntime18 = class extends PptxHandlerRuntime17 {
40703
41639
  const esVal = String(endSnd).trim().toLowerCase();
40704
41640
  style.hyperlinkEndSound = esVal === "1" || esVal === "true";
40705
41641
  }
41642
+ const clickSnd = hyperlinkNode["a:snd"];
41643
+ if (clickSnd && typeof clickSnd === "object") {
41644
+ style.hyperlinkSoundXml = clickSnd;
41645
+ }
40706
41646
  }
40707
41647
  const actionStr = String(hyperlinkNode?.["@_action"] || "").trim();
40708
41648
  if (actionStr) {
@@ -40732,6 +41672,10 @@ var PptxHandlerRuntime18 = class extends PptxHandlerRuntime17 {
40732
41672
  } else {
40733
41673
  style.hyperlinkMouseOver = mouseOverRelId;
40734
41674
  }
41675
+ const mouseOverSnd = hlinkMouseOver["a:snd"];
41676
+ if (mouseOverSnd && typeof mouseOverSnd === "object") {
41677
+ style.hyperlinkMouseOverSoundXml = mouseOverSnd;
41678
+ }
40735
41679
  }
40736
41680
  }
40737
41681
  }
@@ -40958,6 +41902,8 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40958
41902
  if (rawU.length > 0 && rawU !== "none") {
40959
41903
  style.underlineStyle = rawU;
40960
41904
  }
41905
+ } else if (underlineToken === "none") {
41906
+ style.underlineExplicitNone = true;
40961
41907
  }
40962
41908
  }
40963
41909
  const uFill = runProperties2["a:uFill"];
@@ -40969,6 +41915,46 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40969
41915
  style.underlineColor = underlineColor;
40970
41916
  }
40971
41917
  }
41918
+ if (uLn) {
41919
+ const line2 = {};
41920
+ const widthEmu = Number.parseInt(String(uLn["@_w"] ?? ""), 10);
41921
+ if (Number.isFinite(widthEmu)) {
41922
+ line2.widthEmu = widthEmu;
41923
+ }
41924
+ const compound = String(uLn["@_cmpd"] ?? "").trim();
41925
+ if (compound) {
41926
+ line2.compound = compound;
41927
+ }
41928
+ const cap = String(uLn["@_cap"] ?? "").trim();
41929
+ if (cap) {
41930
+ line2.cap = cap;
41931
+ }
41932
+ const algn = String(uLn["@_algn"] ?? "").trim();
41933
+ if (algn) {
41934
+ line2.algn = algn;
41935
+ }
41936
+ const prstDash = String(uLn["a:prstDash"]?.["@_val"] ?? "").trim();
41937
+ if (prstDash) {
41938
+ line2.prstDash = prstDash;
41939
+ }
41940
+ const headEnd = uLn["a:headEnd"];
41941
+ if (headEnd && typeof headEnd === "object") {
41942
+ line2.headEndXml = headEnd;
41943
+ }
41944
+ const tailEnd = uLn["a:tailEnd"];
41945
+ if (tailEnd && typeof tailEnd === "object") {
41946
+ line2.tailEndXml = tailEnd;
41947
+ }
41948
+ if (Object.keys(line2).length > 0) {
41949
+ style.underlineLine = line2;
41950
+ }
41951
+ }
41952
+ if (runProperties2["a:uLnTx"] !== void 0) {
41953
+ style.underlineLineFollowsText = true;
41954
+ }
41955
+ if (runProperties2["a:uFillTx"] !== void 0) {
41956
+ style.underlineFillFollowsText = true;
41957
+ }
40972
41958
  if (runProperties2["@_strike"] !== void 0) {
40973
41959
  const strikeToken = String(runProperties2["@_strike"] || "").trim().toLowerCase();
40974
41960
  style.strikethrough = strikeToken.length > 0 && strikeToken !== "nostrike" && strikeToken !== "none" && strikeToken !== "0" && strikeToken !== "false";
@@ -41012,10 +41998,15 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
41012
41998
  }
41013
41999
  }
41014
42000
  if (runProperties2["a:highlight"]) {
41015
- const highlightHex = this.parseColor(xmlChild(runProperties2, "a:highlight"));
42001
+ const highlightNode = xmlChild(runProperties2, "a:highlight");
42002
+ const highlightHex = this.parseColor(highlightNode);
41016
42003
  if (highlightHex) {
41017
42004
  style.highlightColor = highlightHex;
41018
42005
  }
42006
+ const highlightXml = extractColorChoiceXml(highlightNode);
42007
+ if (highlightXml) {
42008
+ style.highlightColorXml = highlightXml;
42009
+ }
41019
42010
  }
41020
42011
  const textFillVariants = this.extractTextFillVariants(runProperties2);
41021
42012
  if (textFillVariants.textFillGradient) {
@@ -41036,16 +42027,28 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
41036
42027
  const latin = xmlChild(runProperties2, "a:latin");
41037
42028
  const eastAsian = xmlChild(runProperties2, "a:ea");
41038
42029
  const complexScript = xmlChild(runProperties2, "a:cs");
41039
- const chosenTypeface = xmlAttr(latin, "typeface") || xmlAttr(eastAsian, "typeface") || xmlAttr(complexScript, "typeface");
42030
+ const latinTypefaceToken = xmlAttr(latin, "typeface");
42031
+ const eaTypefaceToken = xmlAttr(eastAsian, "typeface");
42032
+ const csTypefaceToken = xmlAttr(complexScript, "typeface");
42033
+ const chosenTypeface = latinTypefaceToken || eaTypefaceToken || csTypefaceToken;
41040
42034
  const resolvedTypeface = this.resolveThemeTypeface(chosenTypeface);
41041
42035
  if (resolvedTypeface) {
41042
42036
  style.fontFamily = resolvedTypeface;
41043
42037
  }
41044
- const eaTypeface = this.resolveThemeTypeface(xmlAttr(eastAsian, "typeface"));
42038
+ if (latinTypefaceToken && latinTypefaceToken.startsWith("+")) {
42039
+ style.latinFontThemeToken = latinTypefaceToken;
42040
+ }
42041
+ if (eaTypefaceToken && eaTypefaceToken.startsWith("+")) {
42042
+ style.eastAsiaFontThemeToken = eaTypefaceToken;
42043
+ }
42044
+ if (csTypefaceToken && csTypefaceToken.startsWith("+")) {
42045
+ style.complexScriptFontThemeToken = csTypefaceToken;
42046
+ }
42047
+ const eaTypeface = this.resolveThemeTypeface(eaTypefaceToken);
41045
42048
  if (eaTypeface) {
41046
42049
  style.eastAsiaFont = eaTypeface;
41047
42050
  }
41048
- const csTypeface = this.resolveThemeTypeface(xmlAttr(complexScript, "typeface"));
42051
+ const csTypeface = this.resolveThemeTypeface(csTypefaceToken);
41049
42052
  if (csTypeface) {
41050
42053
  style.complexScriptFont = csTypeface;
41051
42054
  }
@@ -41061,6 +42064,9 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
41061
42064
  const capAttr = String(runProperties2["@_cap"] || "").trim().toLowerCase();
41062
42065
  if (capAttr === "all" || capAttr === "small") {
41063
42066
  style.textCaps = capAttr;
42067
+ } else if (capAttr === "none") {
42068
+ style.textCaps = "none";
42069
+ style.textCapsExplicitNone = true;
41064
42070
  }
41065
42071
  const symNode = xmlChild(runProperties2, "a:sym");
41066
42072
  if (symNode) {
@@ -41120,6 +42126,12 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
41120
42126
  this.applyTextRunEffects(style, runEffectList);
41121
42127
  }
41122
42128
  this.applyTextRunEffectDag(style, runProperties2);
42129
+ if (includeDefaultAlignment) {
42130
+ const runExtLst = runProperties2["a:extLst"];
42131
+ if (runExtLst && typeof runExtLst === "object") {
42132
+ style.runPropertiesExtLstXml = runExtLst;
42133
+ }
42134
+ }
41123
42135
  return style;
41124
42136
  }
41125
42137
  /**
@@ -41791,12 +42803,63 @@ function writeCellTextFormatting(xmlCell, style, ensureArray16) {
41791
42803
  }
41792
42804
 
41793
42805
  // src/core/core/runtime/PptxHandlerRuntimeSaveTableStyles.ts
42806
+ function flattenCellTxBodyText(txBody, ensureArray16) {
42807
+ if (!txBody) {
42808
+ return "";
42809
+ }
42810
+ const paragraphs = ensureArray16(txBody["a:p"]);
42811
+ const lines = [];
42812
+ for (const paragraph of paragraphs) {
42813
+ const runs = ensureArray16(paragraph?.["a:r"]);
42814
+ const fields = ensureArray16(paragraph?.["a:fld"]);
42815
+ let lineText = "";
42816
+ for (const run of runs) {
42817
+ lineText += String(run?.["a:t"] ?? "");
42818
+ }
42819
+ for (const field of fields) {
42820
+ lineText += String(field?.["a:t"] ?? "");
42821
+ }
42822
+ lines.push(lineText);
42823
+ }
42824
+ return lines.join("\n");
42825
+ }
42826
+ function isRichCellTxBody(txBody, ensureArray16) {
42827
+ if (!txBody) {
42828
+ return false;
42829
+ }
42830
+ const paragraphs = ensureArray16(txBody["a:p"]);
42831
+ let totalRuns = 0;
42832
+ for (const paragraph of paragraphs) {
42833
+ const runs = ensureArray16(paragraph?.["a:r"]);
42834
+ totalRuns += runs.length;
42835
+ if (totalRuns > 1) {
42836
+ return true;
42837
+ }
42838
+ if (ensureArray16(paragraph?.["a:fld"]).length > 0) {
42839
+ return true;
42840
+ }
42841
+ for (const run of runs) {
42842
+ const rPr = run?.["a:rPr"];
42843
+ if (rPr?.["a:hlinkClick"] !== void 0) {
42844
+ return true;
42845
+ }
42846
+ }
42847
+ }
42848
+ return false;
42849
+ }
41794
42850
  var PptxHandlerRuntime22 = class _PptxHandlerRuntime extends PptxHandlerRuntime21 {
41795
42851
  /**
41796
42852
  * Write plain text into a table cell's txBody, preserving
41797
42853
  * existing run properties where possible.
41798
42854
  */
41799
42855
  writeTableCellText(xmlCell, text2) {
42856
+ const ensureArray16 = this.ensureArray.bind(this);
42857
+ const existingTxBody = xmlCell["a:txBody"];
42858
+ if (existingTxBody && ensureArray16(existingTxBody["a:p"]).length > 0) {
42859
+ if (flattenCellTxBodyText(existingTxBody, ensureArray16) === text2) {
42860
+ return;
42861
+ }
42862
+ }
41800
42863
  if (!xmlCell["a:txBody"]) {
41801
42864
  xmlCell["a:txBody"] = { "a:bodyPr": {}, "a:p": {} };
41802
42865
  }
@@ -41924,7 +42987,9 @@ var PptxHandlerRuntime22 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
41924
42987
  }
41925
42988
  delete tcPr["a:tcMar"];
41926
42989
  writeDiagonalBorders(tcPr, style, _PptxHandlerRuntime.EMU_PER_PX);
41927
- writeCellTextFormatting(xmlCell, style, this.ensureArray.bind(this));
42990
+ if (!isRichCellTxBody(xmlCell["a:txBody"], this.ensureArray.bind(this))) {
42991
+ writeCellTextFormatting(xmlCell, style, this.ensureArray.bind(this));
42992
+ }
41928
42993
  const reordered = reorderObjectKeys(tcPr, TC_PR_BORDERS_ORDER);
41929
42994
  for (const key of Object.keys(tcPr)) {
41930
42995
  delete tcPr[key];
@@ -43168,7 +44233,7 @@ function findKey19(obj, name, getLocalName2) {
43168
44233
  function hex9(value) {
43169
44234
  return value.replace("#", "");
43170
44235
  }
43171
- var COLOR_LOCAL_NAMES = /* @__PURE__ */ new Set([
44236
+ var COLOR_LOCAL_NAMES2 = /* @__PURE__ */ new Set([
43172
44237
  "srgbClr",
43173
44238
  "schemeClr",
43174
44239
  "sysClr",
@@ -43177,7 +44242,7 @@ var COLOR_LOCAL_NAMES = /* @__PURE__ */ new Set([
43177
44242
  "hslClr"
43178
44243
  ]);
43179
44244
  function applyColorToList(list, value, getLocalName2) {
43180
- const colorKey = Object.keys(list).find((k) => COLOR_LOCAL_NAMES.has(getLocalName2(k)));
44245
+ const colorKey = Object.keys(list).find((k) => COLOR_LOCAL_NAMES2.has(getLocalName2(k)));
43181
44246
  const srgb = { "@_val": hex9(value) };
43182
44247
  if (!colorKey) {
43183
44248
  list["a:srgbClr"] = srgb;
@@ -45669,6 +46734,33 @@ var PptxHandlerRuntime27 = class extends PptxHandlerRuntime26 {
45669
46734
  }
45670
46735
  };
45671
46736
 
46737
+ // src/core/core/runtime/save-line-fill.ts
46738
+ function writeLineFill(lineNode, shapeStyle, parseColor) {
46739
+ delete lineNode["a:noFill"];
46740
+ delete lineNode["a:solidFill"];
46741
+ delete lineNode["a:gradFill"];
46742
+ delete lineNode["a:pattFill"];
46743
+ if (shapeStyle.strokeColor === "transparent" || shapeStyle.strokeWidth === 0) {
46744
+ lineNode["a:noFill"] = {};
46745
+ return;
46746
+ }
46747
+ if (shapeStyle.strokeFillMode === "gradient" && shapeStyle.strokeGradientXml) {
46748
+ lineNode["a:gradFill"] = shapeStyle.strokeGradientXml;
46749
+ return;
46750
+ }
46751
+ if (shapeStyle.strokeFillMode === "pattern" && shapeStyle.strokePatternXml) {
46752
+ lineNode["a:pattFill"] = shapeStyle.strokePatternXml;
46753
+ return;
46754
+ }
46755
+ const resolvedStrokeOriginal = shapeStyle.strokeColorXml ? parseColor(shapeStyle.strokeColorXml) : void 0;
46756
+ lineNode["a:solidFill"] = serializeColorChoice(
46757
+ shapeStyle.strokeColorXml,
46758
+ resolvedStrokeOriginal,
46759
+ shapeStyle.strokeColor ?? "#000000",
46760
+ shapeStyle.strokeOpacity
46761
+ );
46762
+ }
46763
+
45672
46764
  // src/core/core/runtime/PptxHandlerRuntimeSaveShapeStyleWriter.ts
45673
46765
  var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime27 {
45674
46766
  /**
@@ -45739,26 +46831,14 @@ var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
45739
46831
  );
45740
46832
  }
45741
46833
  }
45742
- if (shapeStyle.strokeColor !== void 0) {
46834
+ if (shapeStyle.strokeColor !== void 0 || shapeStyle.strokeFillMode === "gradient" || shapeStyle.strokeFillMode === "pattern") {
45743
46835
  if (!spPr["a:ln"]) {
45744
46836
  spPr["a:ln"] = {};
45745
46837
  }
45746
46838
  const lineNode = spPr["a:ln"];
45747
46839
  const w = Math.round((shapeStyle.strokeWidth || 1) * _PptxHandlerRuntime.EMU_PER_PX);
45748
46840
  lineNode["@_w"] = String(w);
45749
- if (shapeStyle.strokeColor === "transparent" || shapeStyle.strokeWidth === 0) {
45750
- lineNode["a:noFill"] = {};
45751
- delete lineNode["a:solidFill"];
45752
- } else {
45753
- delete lineNode["a:noFill"];
45754
- const resolvedStrokeOriginal = shapeStyle.strokeColorXml ? this.parseColor(shapeStyle.strokeColorXml) : void 0;
45755
- lineNode["a:solidFill"] = serializeColorChoice(
45756
- shapeStyle.strokeColorXml,
45757
- resolvedStrokeOriginal,
45758
- shapeStyle.strokeColor,
45759
- shapeStyle.strokeOpacity
45760
- );
45761
- }
46841
+ this.applyLineFill(lineNode, shapeStyle);
45762
46842
  }
45763
46843
  if (shapeStyle.strokeDash !== void 0) {
45764
46844
  if (!spPr["a:ln"]) {
@@ -45848,6 +46928,15 @@ var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
45848
46928
  spPr["a:ln"]["a:effectLst"] = lineEffectListXml;
45849
46929
  }
45850
46930
  }
46931
+ /**
46932
+ * Emit the single fill child of an `<a:ln>` (CT_LineProperties allows at
46933
+ * most one of noFill/solidFill/gradFill/pattFill). Delegates to
46934
+ * {@link writeLineFill} so the logic stays unit-testable without the full
46935
+ * save runtime (issue #87).
46936
+ */
46937
+ applyLineFill(lineNode, shapeStyle) {
46938
+ writeLineFill(lineNode, shapeStyle, (colorNode) => this.parseColor(colorNode));
46939
+ }
45851
46940
  /**
45852
46941
  * Serialize the shape's `<p:style>` block (CT_ShapeStyle §20.1.2.2.36)
45853
46942
  * from the persisted ref indices/colour XML. Emits children in spec
@@ -48187,14 +49276,20 @@ var PptxHandlerRuntime41 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
48187
49276
  relationshipType: constants.slideSyncRelationshipType,
48188
49277
  contentType: constants.slideSyncContentType
48189
49278
  });
48190
- this.slideBackgroundBuilder.applyBackground({
49279
+ await this.slideBackgroundBuilder.applyBackground({
48191
49280
  slideNode,
48192
49281
  slide,
48193
49282
  zip: this.zip,
48194
49283
  saveState: saveSession,
48195
49284
  relationshipRegistry: slideRelationshipRegistry,
48196
49285
  slideImageRelationshipType: constants.slideImageRelationshipType,
48197
- parseDataUrlToBytes: (dataUrl) => this.parseDataUrlToBytes(dataUrl)
49286
+ resolveImageToBytes: (url) => this.resolveMediaToBytes(url),
49287
+ reportUnsupportedBackground: (imageUrl) => this.compatibilityService.reportWarning({
49288
+ code: "SAVE_BACKGROUND_IMAGE_UNSUPPORTED",
49289
+ message: `Slide background image could not be embedded and was preserved as-is or omitted: ${imageUrl.slice(0, 120)}`,
49290
+ scope: "save",
49291
+ slideId: slide.id
49292
+ })
48198
49293
  });
48199
49294
  this.slideCommentPartWriter.writeComments({
48200
49295
  slide,
@@ -49699,7 +50794,7 @@ var PptxHandlerRuntime51 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
49699
50794
  } = saveConstants;
49700
50795
  this.compatibilityService.resetWarnings();
49701
50796
  const saveSession = new PptxSaveStateBuilder().withZip(this.zip).withCommentAuthorMap(this.commentAuthorMap).withCommentAuthorDetails(this.commentAuthorDetails).withCommentAuthorsRootXml(this.commentAuthorsRootXml).withEmuPerPx(_PptxHandlerRuntime.EMU_PER_PX).build();
49702
- await this.reconcilePresentationSlidesForSave({
50797
+ const slideReferenceRemap = await this.reconcilePresentationSlidesForSave({
49703
50798
  slides,
49704
50799
  saveSession,
49705
50800
  slideRelationshipType,
@@ -49794,7 +50889,8 @@ var PptxHandlerRuntime51 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
49794
50889
  rawSlideWidthEmu: this.rawSlideWidthEmu,
49795
50890
  rawSlideHeightEmu: this.rawSlideHeightEmu,
49796
50891
  rawSlideSizeType: this.rawSlideSizeType,
49797
- xmlLookupService: this.xmlLookupService
50892
+ xmlLookupService: this.xmlLookupService,
50893
+ slideReferenceRemap
49798
50894
  });
49799
50895
  this.deduplicateExtensionLists(this.presentationData);
49800
50896
  if (effectiveConformance === "transitional") {
@@ -49811,7 +50907,7 @@ var PptxHandlerRuntime51 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
49811
50907
  printSlidesPerPage: options.handoutMaster.slidesPerPage
49812
50908
  } : options?.presentationProperties;
49813
50909
  await this.applyPresentationPropertiesPart(presentationProperties);
49814
- await this.applyViewPropertiesPart(options?.viewProperties);
50910
+ await this.applyViewPropertiesPart(options?.viewProperties ?? this.loadedViewProperties);
49815
50911
  await this.applyTableStylesPart(options?.tableStyles);
49816
50912
  await this.documentPropertiesUpdater.updateOnSave(slides, {
49817
50913
  coreProperties: options?.coreProperties,
@@ -50099,26 +51195,16 @@ var PptxHandlerRuntime52 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
50099
51195
  return true;
50100
51196
  }
50101
51197
  const typesMatch = source.type === target.type || source.type === "ctrtitle" && target.type === "title" || source.type === "subtitle" && target.type === "body";
50102
- if (source.idx !== void 0 && target.idx !== void 0) {
50103
- if (source.idx !== target.idx) {
50104
- return false;
50105
- }
50106
- if (source.type && target.type && !typesMatch) {
50107
- return false;
50108
- }
50109
- return true;
50110
- }
50111
- if (source.idx !== void 0 && target.idx === void 0) {
50112
- const singletonTypes = /* @__PURE__ */ new Set(["title", "ctrtitle", "subtitle", "dt", "ftr", "sldnum"]);
50113
- if (source.type && singletonTypes.has(source.type)) {
50114
- return typesMatch;
50115
- }
51198
+ const sourceIdx = source.idx ?? "0";
51199
+ const targetIdx = target.idx ?? "0";
51200
+ if (sourceIdx !== targetIdx) {
50116
51201
  return false;
50117
51202
  }
50118
51203
  if (source.type && target.type && !typesMatch) {
50119
51204
  return false;
50120
51205
  }
50121
- if (source.type && !target.type) {
51206
+ const bothHaveExplicitIdx = source.idx !== void 0 && target.idx !== void 0;
51207
+ if (!bothHaveExplicitIdx && source.type && !target.type) {
50122
51208
  return false;
50123
51209
  }
50124
51210
  return true;
@@ -51564,6 +52650,19 @@ var PptxHandlerRuntime61 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
51564
52650
  });
51565
52651
  return hasAny ? locks : void 0;
51566
52652
  }
52653
+ /**
52654
+ * Parse the `@txBox` attribute from a `p:cNvSpPr` node. Returns `true` /
52655
+ * `false` when the attribute is present, or `undefined` when absent so
52656
+ * callers can distinguish "not a text box" from "unspecified".
52657
+ */
52658
+ parseTxBoxFlag(cNvSpPr) {
52659
+ const raw = cNvSpPr?.["@_txBox"];
52660
+ if (raw === void 0) {
52661
+ return void 0;
52662
+ }
52663
+ const val = String(raw).trim().toLowerCase();
52664
+ return val === "1" || val === "true";
52665
+ }
51567
52666
  /**
51568
52667
  * Extract body-level text properties from `a:bodyPr` and apply them to the
51569
52668
  * provided {@link TextStyle}. Returns linked-textbox info when present.
@@ -51746,6 +52845,62 @@ var PptxHandlerRuntime61 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
51746
52845
 
51747
52846
  // src/core/core/runtime/PptxHandlerRuntimeShapeTextParsing.ts
51748
52847
  var PptxHandlerRuntime62 = class _PptxHandlerRuntime extends PptxHandlerRuntime61 {
52848
+ /**
52849
+ * Extract a paragraph's OWN `a:pPr` geometry (align, spacing, margins,
52850
+ * indent, tabs, rtl) as a partial {@link TextStyle} so per-paragraph
52851
+ * formatting round-trips rather than collapsing to one shape-level pPr
52852
+ * (#69). Inherited layout/master values are not re-stamped.
52853
+ */
52854
+ extractParagraphOwnProperties(p, basisFontSize) {
52855
+ const pPr = p["a:pPr"];
52856
+ if (!pPr) {
52857
+ return void 0;
52858
+ }
52859
+ const pp = { ...parseParagraphMargins(pPr) };
52860
+ const align = pPr["@_algn"] !== void 0 ? parseAlignmentAttr(String(pPr["@_algn"])) : void 0;
52861
+ if (align) {
52862
+ pp.align = align;
52863
+ }
52864
+ const rtl = parseParagraphRtl(pPr);
52865
+ if (rtl !== void 0) {
52866
+ pp.rtl = rtl;
52867
+ }
52868
+ const spcBef = this.parseParagraphSpacingPx(
52869
+ pPr["a:spcBef"],
52870
+ basisFontSize
52871
+ );
52872
+ if (spcBef !== void 0) {
52873
+ pp.paragraphSpacingBefore = spcBef;
52874
+ }
52875
+ const spcAft = this.parseParagraphSpacingPx(
52876
+ pPr["a:spcAft"],
52877
+ basisFontSize
52878
+ );
52879
+ if (spcAft !== void 0) {
52880
+ pp.paragraphSpacingAfter = spcAft;
52881
+ }
52882
+ const lnSpcNode = pPr["a:lnSpc"];
52883
+ const lineSpacing = this.parseLineSpacingMultiplier(lnSpcNode);
52884
+ const exactPt = lineSpacing === void 0 ? this.parseLineSpacingExactPt(lnSpcNode) : void 0;
52885
+ if (lineSpacing !== void 0) {
52886
+ pp.lineSpacing = lineSpacing;
52887
+ } else if (exactPt !== void 0) {
52888
+ pp.lineSpacingExactPt = exactPt;
52889
+ }
52890
+ const tabStops = parseTabStops(pPr);
52891
+ if (tabStops && tabStops.length > 0) {
52892
+ pp.tabStops = tabStops;
52893
+ }
52894
+ const defRPr = pPr["a:defRPr"];
52895
+ if (defRPr && typeof defRPr === "object") {
52896
+ pp.paragraphDefaultRunPropertiesXml = defRPr;
52897
+ }
52898
+ const pPrExtLst = pPr["a:extLst"];
52899
+ if (pPrExtLst && typeof pPrExtLst === "object") {
52900
+ pp.paragraphPropertiesExtLstXml = pPrExtLst;
52901
+ }
52902
+ return Object.keys(pp).length > 0 ? pp : void 0;
52903
+ }
51749
52904
  /**
51750
52905
  * Resolve paragraph-level styles (alignment, spacing, margins, tabs,
51751
52906
  * level styles) for a single paragraph. Modifies `textStyle` in place
@@ -51994,6 +53149,12 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
51994
53149
  ...mergedDefaultRunStyle,
51995
53150
  ...this.extractTextRunStyle(runProps, paraAlign, ctx.slideRelationshipMap)
51996
53151
  };
53152
+ if (!runStyle2.scriptFallbackFont) {
53153
+ const fallback = this.resolveScriptFallbackFont(runText);
53154
+ if (fallback) {
53155
+ runStyle2.scriptFallbackFont = fallback;
53156
+ }
53157
+ }
51997
53158
  parts.push(runText);
51998
53159
  segments.push({ text: runText, style: runStyle2 });
51999
53160
  maybeSeed(runStyle2);
@@ -52035,14 +53196,25 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
52035
53196
  )
52036
53197
  };
52037
53198
  const fldType = String(field["@_type"] || "").trim() || void 0;
52038
- const fldGuid = String(field["@_uuid"] || field["@_id"] || "").trim() || void 0;
53199
+ const uuidAttr = String(field["@_uuid"] || "").trim();
53200
+ const idAttr = String(field["@_id"] || "").trim();
53201
+ const fldGuid = uuidAttr || idAttr || void 0;
53202
+ const fldGuidAttr = uuidAttr ? "uuid" : idAttr ? "id" : void 0;
52039
53203
  parts.push(fieldText);
52040
- segments.push({
53204
+ const fieldSegment = {
52041
53205
  text: fieldText,
52042
53206
  style: fieldRunStyle,
52043
53207
  fieldType: fldType,
52044
53208
  fieldGuid: fldGuid
52045
- });
53209
+ };
53210
+ if (fldGuidAttr) {
53211
+ fieldSegment.fieldGuidAttr = fldGuidAttr;
53212
+ }
53213
+ const fieldPPr = field["a:pPr"];
53214
+ if (fieldPPr && typeof fieldPPr === "object") {
53215
+ fieldSegment.fieldParagraphPropertiesXml = fieldPPr;
53216
+ }
53217
+ segments.push(fieldSegment);
52046
53218
  maybeSeed(fieldRunStyle);
52047
53219
  };
52048
53220
  const processMathElement = (mathEl) => {
@@ -52169,6 +53341,11 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
52169
53341
  ...endParaRPrRaw
52170
53342
  };
52171
53343
  }
53344
+ const basisFontSize = typeof mergedDefaultRunStyle.fontSize === "number" ? mergedDefaultRunStyle.fontSize : void 0;
53345
+ const paragraphOwnProps = this.extractParagraphOwnProperties(p, basisFontSize);
53346
+ if (paragraphOwnProps) {
53347
+ segments[firstSegmentIndex].paragraphProperties = paragraphOwnProps;
53348
+ }
52172
53349
  }
52173
53350
  return { parts, segments, seedStyle };
52174
53351
  }
@@ -52477,7 +53654,11 @@ var PptxHandlerRuntime64 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
52477
53654
  const inheritedCNvSpPr = xmlPath(inheritedPlaceholder?.shape, "p:nvSpPr", "p:cNvSpPr") ?? xmlPath(inheritedPlaceholder?.picture, "p:nvPicPr", "p:cNvPicPr");
52478
53655
  const inheritedLockNode = inheritedCNvSpPr?.["a:spLocks"] ?? inheritedCNvSpPr?.["a:picLocks"];
52479
53656
  const inheritedLocks = this.parseShapeLocks(inheritedLockNode);
52480
- const locks = inheritedLocks ? { ...inheritedLocks, ...slideLocks } : slideLocks;
53657
+ let locks = inheritedLocks ? { ...inheritedLocks, ...slideLocks } : slideLocks;
53658
+ const txBox = this.parseTxBoxFlag(cNvSpPr);
53659
+ if (txBox !== void 0) {
53660
+ locks = { ...locks ?? {}, txBox };
53661
+ }
52481
53662
  const promptText = !hasText && phDefaults?.promptText ? phDefaults.promptText : void 0;
52482
53663
  const opaqueExtLstXml = this.extractOpaqueSpPrExtLst(effectiveSpPr);
52483
53664
  const commonProps = {
@@ -56030,16 +57211,20 @@ var PptxHandlerRuntime80 = class extends PptxHandlerRuntime79 {
56030
57211
  }
56031
57212
  let fontScheme;
56032
57213
  if (hasFonts) {
57214
+ const majorByScript = this.aggregateFontScriptOverrides(this.masterThemeMajorFontScripts);
57215
+ const minorByScript = this.aggregateFontScriptOverrides(this.masterThemeMinorFontScripts);
56033
57216
  fontScheme = {
56034
57217
  majorFont: {
56035
57218
  latin: this.themeFontMap["mj-lt"],
56036
57219
  eastAsia: this.themeFontMap["mj-ea"],
56037
- complexScript: this.themeFontMap["mj-cs"]
57220
+ complexScript: this.themeFontMap["mj-cs"],
57221
+ ...Object.keys(majorByScript).length > 0 ? { byScript: majorByScript } : {}
56038
57222
  },
56039
57223
  minorFont: {
56040
57224
  latin: this.themeFontMap["mn-lt"],
56041
57225
  eastAsia: this.themeFontMap["mn-ea"],
56042
- complexScript: this.themeFontMap["mn-cs"]
57226
+ complexScript: this.themeFontMap["mn-cs"],
57227
+ ...Object.keys(minorByScript).length > 0 ? { byScript: minorByScript } : {}
56043
57228
  }
56044
57229
  };
56045
57230
  }
@@ -56247,6 +57432,23 @@ var PptxHandlerRuntime80 = class extends PptxHandlerRuntime79 {
56247
57432
  *
56248
57433
  * Phase 4 Stream A / M4.
56249
57434
  */
57435
+ /**
57436
+ * Flatten a per-theme-path script-override map (`themePath -> {script ->
57437
+ * typeface}`) into a single `{script -> typeface}` lookup for
57438
+ * {@link buildThemeObject}. Earlier entries win on collision, which matches
57439
+ * the primary-theme-first parse order. Phase 4 Stream A / M4 (#83).
57440
+ */
57441
+ aggregateFontScriptOverrides(perPathMap) {
57442
+ const aggregate = {};
57443
+ for (const overrides of perPathMap.values()) {
57444
+ for (const [script, typeface] of Object.entries(overrides)) {
57445
+ if (!(script in aggregate)) {
57446
+ aggregate[script] = typeface;
57447
+ }
57448
+ }
57449
+ }
57450
+ return aggregate;
57451
+ }
56250
57452
  collectFontScriptOverrides(fontNode) {
56251
57453
  const overrides = {};
56252
57454
  if (!fontNode) {
@@ -56882,33 +58084,16 @@ var PptxHandlerRuntime83 = class extends PptxHandlerRuntime82 {
56882
58084
  const metadata = parseSmartArtDefinitionMetadata(colorsDef, localName21);
56883
58085
  const labels = parseSmartArtColorStyleLabels(colorsDef, localName21);
56884
58086
  const name = metadata.titles?.[0]?.value || String(colorsDef["@_title"] || colorsDef["@_uniqueId"] || "").trim() || void 0;
56885
- const fillColors = [];
56886
- const lineColors = [];
56887
58087
  const styleLbls = this.xmlLookupService.getChildrenArrayByLocalName(colorsDef, "styleLbl");
56888
- for (const lbl of styleLbls) {
56889
- const fillClrLst = this.xmlLookupService.getChildByLocalName(lbl, "fillClrLst");
56890
- const linClrLst = this.xmlLookupService.getChildByLocalName(lbl, "linClrLst");
56891
- if (fillClrLst) {
56892
- const color2 = this.parseColor(fillClrLst) ?? this.resolveSmartArtSchemeColor(
56893
- this.xmlLookupService.getChildByLocalName(fillClrLst, "schemeClr")
56894
- );
56895
- if (color2) {
56896
- fillColors.push(color2);
56897
- }
56898
- }
56899
- if (linClrLst) {
56900
- const color2 = this.parseColor(linClrLst) ?? this.resolveSmartArtSchemeColor(
56901
- this.xmlLookupService.getChildByLocalName(linClrLst, "schemeClr")
56902
- );
56903
- if (color2) {
56904
- lineColors.push(color2);
56905
- }
56906
- }
56907
- }
56908
- if (fillColors.length === 0 && lineColors.length === 0) {
58088
+ const colorLists = buildSmartArtColorLists(styleLbls, {
58089
+ getChild: (node, childName) => this.xmlLookupService.getChildByLocalName(node, childName),
58090
+ parseColorChoice: (colorChoice) => this.parseColor(colorChoice),
58091
+ resolveScheme: (colorNode) => this.resolveSmartArtSchemeColor(colorNode)
58092
+ });
58093
+ if (colorLists.fillColors.length === 0 && colorLists.lineColors.length === 0) {
56909
58094
  return void 0;
56910
58095
  }
56911
- return { ...metadata, name, fillColors, lineColors, labels };
58096
+ return { ...metadata, name, ...colorLists, labels };
56912
58097
  } catch {
56913
58098
  return void 0;
56914
58099
  }
@@ -57260,6 +58445,109 @@ var PptxHandlerRuntime84 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
57260
58445
  }
57261
58446
  };
57262
58447
 
58448
+ // src/core/core/runtime/smartart-drawing-blip.ts
58449
+ function collectDrawingShapeNodes(root, getChildren) {
58450
+ const out = [];
58451
+ const walk = (container) => {
58452
+ if (!container) {
58453
+ return;
58454
+ }
58455
+ for (const sp of getChildren(container, "sp")) {
58456
+ out.push({ node: sp, isPic: false });
58457
+ }
58458
+ for (const pic of getChildren(container, "pic")) {
58459
+ out.push({ node: pic, isPic: true });
58460
+ }
58461
+ for (const grp of getChildren(container, "grpSp")) {
58462
+ walk(grp);
58463
+ }
58464
+ };
58465
+ walk(root);
58466
+ return out;
58467
+ }
58468
+ function picBlipEmbedId(pic, getChild) {
58469
+ const blip = getChild(getChild(pic, "blipFill"), "blip");
58470
+ if (!blip) {
58471
+ return void 0;
58472
+ }
58473
+ const embed = String(blip["@_r:embed"] || blip["@_embed"] || blip["@_r:link"] || "").trim();
58474
+ return embed.length > 0 ? embed : void 0;
58475
+ }
58476
+ function parseDrawingRelTargets(relsXml, parse, ensureArray16) {
58477
+ const map = /* @__PURE__ */ new Map();
58478
+ try {
58479
+ const relsRoot = parse(relsXml)["Relationships"];
58480
+ if (!relsRoot) {
58481
+ return map;
58482
+ }
58483
+ for (const rel of ensureArray16(relsRoot["Relationship"])) {
58484
+ const id = String(rel?.["@_Id"] || "").trim();
58485
+ const target = String(rel?.["@_Target"] || "").trim();
58486
+ if (id.length > 0 && target.length > 0) {
58487
+ map.set(id, target);
58488
+ }
58489
+ }
58490
+ } catch {
58491
+ }
58492
+ return map;
58493
+ }
58494
+ async function resolveDrawingBlipFills(shapes, drawingPath, deps) {
58495
+ const pending = shapes.filter((shape) => shape.fillBlipEmbedId && !shape.fillImageUrl);
58496
+ if (pending.length === 0) {
58497
+ return;
58498
+ }
58499
+ const dir = drawingPath.replace(/\/[^/]+$/u, "");
58500
+ const file = drawingPath.split("/").pop() ?? "";
58501
+ const relsXml = await deps.readText(`${dir}/_rels/${file}.rels`);
58502
+ if (!relsXml) {
58503
+ return;
58504
+ }
58505
+ const targets = parseDrawingRelTargets(relsXml, deps.parse, deps.ensureArray);
58506
+ for (const shape of pending) {
58507
+ const target = targets.get(shape.fillBlipEmbedId ?? "");
58508
+ if (!target) {
58509
+ continue;
58510
+ }
58511
+ const source = /^(?:https?:|data:)/u.test(target) ? target : deps.resolveImagePath(drawingPath, target);
58512
+ const resolved = await deps.getImageData(source);
58513
+ if (resolved) {
58514
+ shape.fillImageUrl = resolved;
58515
+ }
58516
+ }
58517
+ }
58518
+ async function parseDrawingShapesFromPart(drawingPath, deps) {
58519
+ const xmlString = await deps.readText(drawingPath);
58520
+ if (!xmlString) {
58521
+ return [];
58522
+ }
58523
+ try {
58524
+ const xml = deps.parse(xmlString);
58525
+ const drawing = deps.getChild(xml, "drawing");
58526
+ const spTree = deps.getChild(drawing || xml, "spTree");
58527
+ if (!spTree) {
58528
+ return [];
58529
+ }
58530
+ const shapes = [];
58531
+ collectDrawingShapeNodes(spTree, deps.getChildren).forEach(({ node, isPic }, index) => {
58532
+ const shape = deps.parseDrawingShape(node, index, deps.emuPerPx);
58533
+ if (!shape) {
58534
+ return;
58535
+ }
58536
+ if (isPic && !shape.fillBlipEmbedId) {
58537
+ const embed = picBlipEmbedId(node, deps.getChild);
58538
+ if (embed) {
58539
+ shape.fillBlipEmbedId = embed;
58540
+ }
58541
+ }
58542
+ shapes.push(shape);
58543
+ });
58544
+ await resolveDrawingBlipFills(shapes, drawingPath, deps);
58545
+ return shapes;
58546
+ } catch {
58547
+ return [];
58548
+ }
58549
+ }
58550
+
57263
58551
  // src/core/core/runtime/smartart-layout-category.ts
57264
58552
  var CATEGORY_FAMILY = {
57265
58553
  list: "list",
@@ -57395,6 +58683,7 @@ var PptxHandlerRuntime85 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
57395
58683
  layoutDefinition,
57396
58684
  nodes,
57397
58685
  connections: parsedConnections.length > 0 ? parsedConnections : void 0,
58686
+ presLayoutVars: parseSmartArtPresLayoutVars(dataModel),
57398
58687
  drawingShapes: drawingShapes.length > 0 ? drawingShapes : void 0,
57399
58688
  chrome,
57400
58689
  colorTransform,
@@ -57473,30 +58762,28 @@ var PptxHandlerRuntime85 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
57473
58762
  }
57474
58763
  }
57475
58764
  /**
57476
- * Parse SmartArt drawing shapes given an absolute part path.
58765
+ * Parse cached SmartArt drawing shapes from an absolute part path.
57477
58766
  *
57478
- * Wraps `parseSmartArtDrawingShapes` (which expects a slide-relative
57479
- * relationship id) with a path-based lookup so the resolution layer
57480
- * can pull the part from anywhere in the package.
58767
+ * Enumerates `dsp:sp` / bare `dsp:pic` (incl. nested `dsp:grpSp`) and
58768
+ * resolves picture (blip) fills to data URLs via the drawing part's own
58769
+ * relationships. Delegates to a pure helper with an injected dep bundle.
57481
58770
  */
57482
58771
  async parseSmartArtDrawingShapesFromPath(drawingPath) {
57483
- const xmlString = await this.zip.file(drawingPath)?.async("string");
57484
- if (!xmlString) {
57485
- return [];
57486
- }
57487
- try {
57488
- const xml = this.parser.parse(xmlString);
57489
- const drawing = this.xmlLookupService.getChildByLocalName(xml, "drawing");
57490
- const spTree = this.xmlLookupService.getChildByLocalName(drawing || xml, "spTree");
57491
- if (!spTree) {
57492
- return [];
57493
- }
57494
- const shapes = this.xmlLookupService.getChildrenArrayByLocalName(spTree, "sp");
57495
- const emuPerPx = _PptxHandlerRuntime.EMU_PER_PX;
57496
- return shapes.map((sp, index) => this.parseDrawingShape(sp, index, emuPerPx)).filter((entry) => entry !== null);
57497
- } catch {
57498
- return [];
57499
- }
58772
+ return parseDrawingShapesFromPart(drawingPath, this.drawingBlipDeps());
58773
+ }
58774
+ /** Bind runtime zip / parser / lookup / image helpers for the drawing parser. */
58775
+ drawingBlipDeps() {
58776
+ return {
58777
+ readText: (path2) => this.zip.file(path2)?.async("string") ?? Promise.resolve(void 0),
58778
+ parse: (xml) => this.parser.parse(xml),
58779
+ getChild: (node, local) => this.xmlLookupService.getChildByLocalName(node, local),
58780
+ getChildren: (node, local) => this.xmlLookupService.getChildrenArrayByLocalName(node, local),
58781
+ parseDrawingShape: (sp, index, emuPerPx) => this.parseDrawingShape(sp, index, emuPerPx),
58782
+ emuPerPx: _PptxHandlerRuntime.EMU_PER_PX,
58783
+ ensureArray: (value) => this.ensureArray(value),
58784
+ resolveImagePath: (base, target) => this.resolveImagePath(base, target),
58785
+ getImageData: (path2) => this.getImageData(path2)
58786
+ };
57500
58787
  }
57501
58788
  };
57502
58789
 
@@ -58194,6 +59481,11 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
58194
59481
  grouping = "clustered";
58195
59482
  }
58196
59483
  }
59484
+ const varyColors = this.parseChartBoolVal(seriesContainer, "varyColors");
59485
+ const firstSliceAngle = this.parseChartNumberVal(seriesContainer, "firstSliceAng");
59486
+ const doughnutHoleSize = this.parseChartNumberVal(seriesContainer, "holeSize");
59487
+ const barGapWidth = this.parseChartNumberVal(seriesContainer, "gapWidth");
59488
+ const barOverlap = this.parseChartNumberVal(seriesContainer, "overlap");
58197
59489
  const chartPartPath = chartPart.partPath;
58198
59490
  const dataTable = parseDataTable(plotArea, this.xmlLookupService);
58199
59491
  const dropLines = parseLineStyle(
@@ -58270,6 +59562,11 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
58270
59562
  title: titleTextValues[0],
58271
59563
  style: chartStyle,
58272
59564
  grouping,
59565
+ ...varyColors !== void 0 ? { varyColors } : {},
59566
+ ...firstSliceAngle !== void 0 ? { firstSliceAngle } : {},
59567
+ ...doughnutHoleSize !== void 0 ? { doughnutHoleSize } : {},
59568
+ ...barGapWidth !== void 0 ? { barGapWidth } : {},
59569
+ ...barOverlap !== void 0 ? { barOverlap } : {},
58273
59570
  chartPartPath,
58274
59571
  chartRelationshipId,
58275
59572
  ...dataTable ? { dataTable } : {},
@@ -58346,6 +59643,35 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
58346
59643
  }
58347
59644
  return { categories, series };
58348
59645
  }
59646
+ /**
59647
+ * Read a numeric `@val` from a named child of a chart-type container.
59648
+ * Returns `undefined` when the child or its `@val` is absent/non-finite.
59649
+ */
59650
+ parseChartNumberVal(container, localName21) {
59651
+ const node = this.xmlLookupService.getChildByLocalName(container, localName21);
59652
+ const raw = node?.["@_val"];
59653
+ if (raw === void 0 || raw === null || raw === "") {
59654
+ return void 0;
59655
+ }
59656
+ const num = Number.parseFloat(String(raw));
59657
+ return Number.isFinite(num) ? num : void 0;
59658
+ }
59659
+ /**
59660
+ * Read a boolean `@val` from a named child of a chart-type container.
59661
+ * A present element with no `@val` follows the OOXML `CT_Boolean` default
59662
+ * of `true`; `undefined` when the child is absent.
59663
+ */
59664
+ parseChartBoolVal(container, localName21) {
59665
+ const node = this.xmlLookupService.getChildByLocalName(container, localName21);
59666
+ if (!node) {
59667
+ return void 0;
59668
+ }
59669
+ const raw = node["@_val"];
59670
+ if (raw === void 0 || raw === null || raw === "") {
59671
+ return true;
59672
+ }
59673
+ return !(raw === "0" || raw === "false");
59674
+ }
58349
59675
  /**
58350
59676
  * Build the series array from raw OOXML `c:ser` nodes.
58351
59677
  *
@@ -58389,6 +59715,10 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
58389
59715
  );
58390
59716
  const dataLabels = parseSeriesDataLabels(seriesNode, this.xmlLookupService);
58391
59717
  const explosion = parseSeriesExplosion(seriesNode, this.xmlLookupService);
59718
+ const smoothNode = this.xmlLookupService.getChildByLocalName(seriesNode, "smooth");
59719
+ const smooth = smoothNode ? !(smoothNode["@_val"] === "0" || smoothNode["@_val"] === "false") : void 0;
59720
+ const invertNode = this.xmlLookupService.getChildByLocalName(seriesNode, "invertIfNegative");
59721
+ const invertIfNegative = invertNode ? !(invertNode["@_val"] === "0" || invertNode["@_val"] === "false") : void 0;
58392
59722
  return {
58393
59723
  name: seriesName.trim().length > 0 ? seriesName : `Series ${seriesIndex + 1}`,
58394
59724
  values: fallbackValues,
@@ -58399,6 +59729,8 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
58399
59729
  ...seriesMarker ? { marker: seriesMarker } : {},
58400
59730
  ...dataLabels.length > 0 ? { dataLabels } : {},
58401
59731
  ...explosion !== void 0 ? { explosion } : {},
59732
+ ...invertIfNegative !== void 0 ? { invertIfNegative } : {},
59733
+ ...smooth !== void 0 ? { smooth } : {},
58402
59734
  ...axisId !== void 0 ? { axisId } : {},
58403
59735
  ...seriesChartType ? { seriesChartType } : {}
58404
59736
  };
@@ -59225,6 +60557,8 @@ var PptxHandlerRuntime94 = class extends PptxHandlerRuntime93 {
59225
60557
  async buildLoadData(presentationState, slidesWithWarnings, slideMasters) {
59226
60558
  const headerFooter = this.extractHeaderFooter();
59227
60559
  const presentationProperties = await this.parsePresentationProperties();
60560
+ const viewProperties = await this.parseViewProperties();
60561
+ this.loadedViewProperties = viewProperties;
59228
60562
  const customShows = this.parseCustomShows();
59229
60563
  const tableStyleMap = await this.parseTableStyles();
59230
60564
  const embeddedFontList = parseEmbeddedFontList(this.presentationData);
@@ -59254,7 +60588,7 @@ var PptxHandlerRuntime94 = class extends PptxHandlerRuntime93 {
59254
60588
  presentationState.height,
59255
60589
  this.rawSlideWidthEmu,
59256
60590
  this.rawSlideHeightEmu
59257
- ).withNotesDimensions(presentationState.notesWidthEmu, presentationState.notesHeightEmu).withSlides(slidesWithWarnings).withLayoutOptions(this.getLayoutOptions()).withHeaderFooter(headerFooter).withPresentationProperties(presentationProperties).withCustomShows(customShows).withSections(
60591
+ ).withNotesDimensions(presentationState.notesWidthEmu, presentationState.notesHeightEmu).withSlides(slidesWithWarnings).withLayoutOptions(this.getLayoutOptions()).withHeaderFooter(headerFooter).withPresentationProperties(presentationProperties).withViewProperties(viewProperties).withCustomShows(customShows).withSections(
59258
60592
  presentationState.orderedSections.length > 0 ? presentationState.orderedSections : void 0
59259
60593
  ).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(
59260
60594
  this.signatureDetection?.signatureCount && this.signatureDetection.signatureCount > 0 ? this.signatureDetection.signatureCount : void 0
@@ -59385,6 +60719,7 @@ var PptxHandlerRuntime94 = class extends PptxHandlerRuntime93 {
59385
60719
  this.customXmlParts = [];
59386
60720
  this.loadedEmbeddedFonts = [];
59387
60721
  this.loadedEmbeddedFontList = void 0;
60722
+ this.loadedViewProperties = void 0;
59388
60723
  this.orderedSlidePaths = [];
59389
60724
  this.zip = null;
59390
60725
  }