pptx-viewer-core 1.6.8 → 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
 
@@ -7227,36 +7259,200 @@ async function fetchUrlToBytes(url, options = {}) {
7227
7259
  }
7228
7260
  }
7229
7261
 
7262
+ // src/core/utils/inkml-trace-decode.ts
7263
+ function resolveChannelOrder(root) {
7264
+ const traceFormat = findFirstByLocalName(root, "traceFormat");
7265
+ if (!traceFormat) {
7266
+ return ["X", "Y"];
7267
+ }
7268
+ const channels = ensureArray(nsGet(traceFormat, "channel"));
7269
+ const names = channels.map(
7270
+ (channel) => String(nsAttr(channel, "name") ?? "").trim().toUpperCase()
7271
+ ).filter((name) => name.length > 0);
7272
+ return names.length > 0 ? names : ["X", "Y"];
7273
+ }
7274
+ function decodeTracePoints(text2, channelOrder) {
7275
+ const points3 = [];
7276
+ const modes = channelOrder.map(() => "explicit");
7277
+ const lastValue = channelOrder.map(() => 0);
7278
+ const lastVelocity = channelOrder.map(() => 0);
7279
+ for (const rawPoint of text2.split(",")) {
7280
+ const tokens = rawPoint.trim().split(/\s+/u).filter((token2) => token2.length > 0);
7281
+ if (tokens.length === 0) {
7282
+ continue;
7283
+ }
7284
+ const decoded = [];
7285
+ for (let i = 0; i < tokens.length && i < channelOrder.length; i++) {
7286
+ const parsed = parseValueToken(tokens[i], modes[i]);
7287
+ if (parsed === void 0) {
7288
+ decoded.push(lastValue[i]);
7289
+ continue;
7290
+ }
7291
+ modes[i] = parsed.mode;
7292
+ const value = applyDiffMode(parsed, i, lastValue, lastVelocity);
7293
+ decoded.push(value);
7294
+ }
7295
+ if (decoded.length >= 2) {
7296
+ points3.push(decoded);
7297
+ }
7298
+ }
7299
+ return points3;
7300
+ }
7301
+ function parseValueToken(token2, currentMode) {
7302
+ let mode = currentMode;
7303
+ let body = token2;
7304
+ const prefix = token2[0];
7305
+ if (prefix === "!") {
7306
+ mode = "explicit";
7307
+ body = token2.slice(1);
7308
+ } else if (prefix === "'") {
7309
+ mode = "single";
7310
+ body = token2.slice(1);
7311
+ } else if (prefix === '"') {
7312
+ mode = "double";
7313
+ body = token2.slice(1);
7314
+ }
7315
+ if (body.length === 0) {
7316
+ return void 0;
7317
+ }
7318
+ const value = Number(body);
7319
+ return Number.isFinite(value) ? { value, mode } : void 0;
7320
+ }
7321
+ function applyDiffMode(parsed, index, lastValue, lastVelocity) {
7322
+ if (parsed.mode === "single") {
7323
+ lastVelocity[index] = parsed.value;
7324
+ lastValue[index] += parsed.value;
7325
+ } else if (parsed.mode === "double") {
7326
+ lastVelocity[index] += parsed.value;
7327
+ lastValue[index] += lastVelocity[index];
7328
+ } else {
7329
+ lastValue[index] = parsed.value;
7330
+ lastVelocity[index] = 0;
7331
+ }
7332
+ return lastValue[index];
7333
+ }
7334
+ function pointsToSvgPath(points3, channelOrder) {
7335
+ const xi = channelOrder.indexOf("X");
7336
+ const yi = channelOrder.indexOf("Y");
7337
+ const xIndex = xi >= 0 ? xi : 0;
7338
+ const yIndex = yi >= 0 ? yi : 1;
7339
+ const segments = [];
7340
+ for (const point of points3) {
7341
+ const x = point[xIndex];
7342
+ const y = point[yIndex];
7343
+ if (!Number.isFinite(x) || !Number.isFinite(y)) {
7344
+ continue;
7345
+ }
7346
+ segments.push(`${segments.length === 0 ? "M" : "L"} ${x} ${y}`);
7347
+ }
7348
+ return segments.join(" ");
7349
+ }
7350
+ function pointsToPressures(points3, channelOrder) {
7351
+ const fIndex = channelOrder.indexOf("F");
7352
+ if (fIndex < 0) {
7353
+ return [];
7354
+ }
7355
+ const pressures = [];
7356
+ for (const point of points3) {
7357
+ const raw = point[fIndex];
7358
+ if (Number.isFinite(raw)) {
7359
+ const normalised = raw > 1 ? raw / 32767 : raw;
7360
+ pressures.push(Math.max(0, Math.min(1, normalised)));
7361
+ }
7362
+ }
7363
+ return pressures;
7364
+ }
7365
+ function nsGet(obj, localName21) {
7366
+ if (localName21 in obj) {
7367
+ return obj[localName21];
7368
+ }
7369
+ for (const key of Object.keys(obj)) {
7370
+ if (localNameOf(key) === localName21 && !key.startsWith("@_")) {
7371
+ return obj[key];
7372
+ }
7373
+ }
7374
+ return void 0;
7375
+ }
7376
+ function nsAttr(obj, localName21) {
7377
+ const direct = obj[`@_${localName21}`];
7378
+ if (direct !== void 0) {
7379
+ return direct;
7380
+ }
7381
+ for (const key of Object.keys(obj)) {
7382
+ if (key.startsWith("@_") && localNameOf(key.slice(2)) === localName21) {
7383
+ return obj[key];
7384
+ }
7385
+ }
7386
+ return void 0;
7387
+ }
7388
+ function localNameOf(key) {
7389
+ const colon = key.indexOf(":");
7390
+ return colon >= 0 ? key.slice(colon + 1) : key;
7391
+ }
7392
+ function findFirstByLocalName(node, localName21) {
7393
+ const direct = nsGet(node, localName21);
7394
+ if (direct && typeof direct === "object") {
7395
+ return Array.isArray(direct) ? direct[0] : direct;
7396
+ }
7397
+ for (const key of Object.keys(node)) {
7398
+ if (key.startsWith("@_") || key === "#text") {
7399
+ continue;
7400
+ }
7401
+ for (const child20 of ensureArray(node[key])) {
7402
+ if (typeof child20 !== "object") {
7403
+ continue;
7404
+ }
7405
+ const found = findFirstByLocalName(child20, localName21);
7406
+ if (found) {
7407
+ return found;
7408
+ }
7409
+ }
7410
+ }
7411
+ return void 0;
7412
+ }
7413
+ function ensureArray(value) {
7414
+ if (value === void 0 || value === null) {
7415
+ return [];
7416
+ }
7417
+ return Array.isArray(value) ? value : [value];
7418
+ }
7419
+
7230
7420
  // src/core/utils/inkml-content-part.ts
7231
7421
  var INKML_NAMESPACE = "http://www.w3.org/2003/InkML";
7232
7422
  var METADATA_NAMESPACE = "https://pptx-viewer.dev/inkml/metadata";
7233
7423
  function parseInkMlContent(data) {
7234
- const root = data["ink:ink"] ?? data["ink"];
7424
+ const root = nsGet(data, "ink") ?? data["ink"];
7235
7425
  if (!root) {
7236
7426
  return { strokes: [], rawXml: data };
7237
7427
  }
7238
7428
  const brushes = /* @__PURE__ */ new Map();
7239
- for (const brush of ensureArray(root["ink:brush"] ?? root["brush"])) {
7240
- const properties = ensureArray(brush["ink:brushProperty"] ?? brush["brushProperty"]);
7429
+ for (const brush of ensureArray(nsGet(root, "brush"))) {
7430
+ const properties = ensureArray(nsGet(brush, "brushProperty"));
7241
7431
  const valueByName = new Map(
7242
- properties.map((property) => [String(property["@_name"] ?? ""), property["@_value"]])
7432
+ properties.map((property) => [
7433
+ String(nsAttr(property, "name") ?? ""),
7434
+ nsAttr(property, "value")
7435
+ ])
7243
7436
  );
7244
- brushes.set(String(brush["@_id"] ?? ""), {
7437
+ brushes.set(String(nsAttr(brush, "id") ?? ""), {
7245
7438
  color: String(valueByName.get("color") ?? "#000000"),
7246
7439
  width: finiteNumber(valueByName.get("width"), 1),
7247
7440
  opacity: finiteNumber(valueByName.get("opacity"), 1)
7248
7441
  });
7249
7442
  }
7443
+ const channelOrder = resolveChannelOrder(root);
7250
7444
  const strokes = [];
7251
- for (const trace of ensureArray(root["ink:trace"] ?? root["trace"])) {
7445
+ for (const trace of ensureArray(nsGet(root, "trace"))) {
7252
7446
  const text2 = typeof trace === "string" ? trace : String(trace["#text"] ?? "").trim();
7253
- const path2 = typeof trace === "string" ? text2 : String(trace["@_pva:path"] ?? "").trim() || text2;
7447
+ const authored = typeof trace === "string" ? "" : String(nsAttr(trace, "path") ?? "").trim();
7448
+ const points3 = authored ? [] : decodeTracePoints(text2, channelOrder);
7449
+ const path2 = authored || pointsToSvgPath(points3, channelOrder);
7254
7450
  if (!path2) {
7255
7451
  continue;
7256
7452
  }
7257
- const brushRef = typeof trace === "string" ? "" : String(trace["@_brushRef"] ?? "").replace("#", "");
7453
+ const brushRef = typeof trace === "string" ? "" : String(nsAttr(trace, "brushRef") ?? "").replace("#", "");
7258
7454
  const brush = brushes.get(brushRef) ?? { color: "#000000", width: 1, opacity: 1 };
7259
- const pressures = tracePressures(text2);
7455
+ const pressures = authored ? tracePressures(text2) : pointsToPressures(points3, channelOrder);
7260
7456
  strokes.push({ ...brush, path: path2, ...pressures.length > 0 ? { pressures } : {} });
7261
7457
  }
7262
7458
  return { strokes, rawXml: data };
@@ -7315,12 +7511,6 @@ function finiteNumber(value, fallback) {
7315
7511
  const parsed = Number(value);
7316
7512
  return Number.isFinite(parsed) ? parsed : fallback;
7317
7513
  }
7318
- function ensureArray(value) {
7319
- if (value === void 0 || value === null) {
7320
- return [];
7321
- }
7322
- return Array.isArray(value) ? value : [value];
7323
- }
7324
7514
 
7325
7515
  // src/core/utils/strip-parent-dir-segments.ts
7326
7516
  function stripParentDirSegments(path2) {
@@ -10527,6 +10717,122 @@ function applyNodeStylesToElements(elements, nodes) {
10527
10717
  });
10528
10718
  }
10529
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
+
10530
10836
  // src/core/utils/smartart-decompose.ts
10531
10837
  function quickStyleStrokeScale(quickStyle) {
10532
10838
  if (!quickStyle?.effectIntensity) {
@@ -10632,15 +10938,27 @@ function decomposeSmartArt(smartArtData, containerBounds, themeColorMap, layoutD
10632
10938
  smartArtData.colorTransform?.fillColors
10633
10939
  );
10634
10940
  const layoutType = resolveEffectiveLayoutType(smartArtData);
10941
+ const layoutVars = smartArtData.presLayoutVars ?? parseSmartArtPresLayoutVars(smartArtData.layoutDefinition?.rawXml);
10942
+ const orderedNodes = layoutVars?.direction === "rev" ? [...nodes].reverse() : nodes;
10635
10943
  const namedLayout = smartArtData.layout;
10636
10944
  if (namedLayout) {
10637
- const namedResult = dispatchNamedLayout(namedLayout, nodes, containerBounds, effectiveThemeMap);
10945
+ const namedResult = dispatchNamedLayout(
10946
+ namedLayout,
10947
+ orderedNodes,
10948
+ containerBounds,
10949
+ effectiveThemeMap
10950
+ );
10638
10951
  if (namedResult) {
10639
- return applyNodeStylesToElements(namedResult, nodes);
10952
+ return applyNodeStylesToElements(namedResult, orderedNodes);
10640
10953
  }
10641
10954
  }
10642
- const algorithmic = dispatchLayoutByType(layoutType, nodes, containerBounds, effectiveThemeMap);
10643
- 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;
10644
10962
  }
10645
10963
  function dispatchLayoutByType(layoutType, nodes, containerBounds, effectiveThemeMap) {
10646
10964
  switch (layoutType) {
@@ -16858,6 +17176,19 @@ function xmlChild(node, key) {
16858
17176
  }
16859
17177
  return isXmlObject2(value) ? value : void 0;
16860
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
+ }
16861
17192
  function xmlHasChild(node, key) {
16862
17193
  return isXmlObject2(node) && Object.hasOwn(node, key);
16863
17194
  }
@@ -16885,6 +17216,9 @@ function xmlPath(node, ...keys) {
16885
17216
  }
16886
17217
  return current;
16887
17218
  }
17219
+ function isXmlNode(value) {
17220
+ return isXmlObject2(value);
17221
+ }
16888
17222
 
16889
17223
  // src/core/utils/chart-bubble-options.ts
16890
17224
  var ORDER2 = [
@@ -16901,7 +17235,7 @@ var ORDER2 = [
16901
17235
  function findKey4(node, name, localName21) {
16902
17236
  return Object.keys(node).find((key) => localName21(key) === name);
16903
17237
  }
16904
- function boolValue(node) {
17238
+ function boolValue2(node) {
16905
17239
  if (!node) {
16906
17240
  return void 0;
16907
17241
  }
@@ -16917,7 +17251,7 @@ function parseBubbleChartOptions(container, localName21) {
16917
17251
  return key ? container[key] : void 0;
16918
17252
  };
16919
17253
  const options = {};
16920
- const bubble3D = boolValue(node("bubble3D"));
17254
+ const bubble3D = boolValue2(node("bubble3D"));
16921
17255
  if (bubble3D !== void 0) {
16922
17256
  options.bubble3D = bubble3D;
16923
17257
  }
@@ -16928,7 +17262,7 @@ function parseBubbleChartOptions(container, localName21) {
16928
17262
  options.bubbleScale = scale;
16929
17263
  }
16930
17264
  }
16931
- const showNegative = boolValue(node("showNegBubbles"));
17265
+ const showNegative = boolValue2(node("showNegBubbles"));
16932
17266
  if (showNegative !== void 0) {
16933
17267
  options.showNegativeBubbles = showNegative;
16934
17268
  }
@@ -17240,7 +17574,7 @@ var MEDIA_REFERENCE_NAMES = [
17240
17574
  "videoFile",
17241
17575
  "quickTimeFile"
17242
17576
  ];
17243
- function parseDrawingMediaReference(container) {
17577
+ function parseDrawingMediaReference(container, externalRelIds) {
17244
17578
  if (!container) {
17245
17579
  return void 0;
17246
17580
  }
@@ -17249,11 +17583,17 @@ function parseDrawingMediaReference(container) {
17249
17583
  if (!node) {
17250
17584
  continue;
17251
17585
  }
17586
+ const linkId = String(attribute2(node, "link") ?? "").trim() || void 0;
17587
+ const embedId = String(attribute2(node, "embed") ?? "").trim() || void 0;
17252
17588
  return {
17253
17589
  kind,
17254
17590
  mediaType: kind === "videoFile" || kind === "quickTimeFile" ? "video" : "audio",
17255
- relationshipId: String(attribute2(node, "link") ?? attribute2(node, "embed") ?? "").trim() || void 0,
17256
- isLinked: attribute2(node, "link") !== void 0,
17591
+ relationshipId: linkId ?? embedId,
17592
+ // Embedded media legitimately uses r:link pointing at an INTERNAL
17593
+ // media part, so link presence alone does not imply a linked clip.
17594
+ // It is only truly linked when the referenced relationship is
17595
+ // external (TargetMode="External"), mirroring the OLE parser.
17596
+ isLinked: linkId !== void 0 && externalRelIds?.has(linkId) === true,
17257
17597
  name: kind === "wavAudioFile" ? String(attribute2(node, "name") ?? "") || void 0 : void 0,
17258
17598
  contentType: kind === "audioFile" ? String(attribute2(node, "contentType") ?? "") || void 0 : void 0,
17259
17599
  audioCdStart: kind === "audioCd" ? parseAudioCdPosition(child11(node, "st")) : void 0,
@@ -17410,6 +17750,45 @@ function withThemePlaceholderColor(themeColorMap, placeholderColor, operation) {
17410
17750
  }
17411
17751
  }
17412
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
+
17413
17792
  // src/converter/svg-chart-extended.ts
17414
17793
  var DEFAULT_COLORS = ["#4472C4", "#ED7D31", "#A5A5A5", "#FFC000", "#5B9BD5", "#70AD47"];
17415
17794
  function esc(value) {
@@ -19985,6 +20364,7 @@ var TextShapeXmlFactory = class {
19985
20364
  createXmlElement(init) {
19986
20365
  const { element } = init;
19987
20366
  const isText = element.type === "text";
20367
+ const isTextBox = element.locks?.txBox ?? isText;
19988
20368
  const name = isText ? "TextBox" : "Rectangle";
19989
20369
  const geometry = this.context.normalizePresetGeometry(element.shapeType);
19990
20370
  const adjustmentEntries = Object.entries(element.shapeAdjustments || {}).filter(
@@ -20004,7 +20384,7 @@ var TextShapeXmlFactory = class {
20004
20384
  "@_name": `${name} ${elementId}`
20005
20385
  },
20006
20386
  "p:cNvSpPr": {
20007
- "@_txBox": isText ? "1" : "0"
20387
+ "@_txBox": isTextBox ? "1" : "0"
20008
20388
  },
20009
20389
  "p:nvPr": {}
20010
20390
  },
@@ -20462,8 +20842,18 @@ var PptxPresentationSaveBuilder = class {
20462
20842
  init.rawSlideHeightEmu,
20463
20843
  init.rawSlideSizeType
20464
20844
  );
20465
- applyCustomShows(presentation, init.options?.customShows, init.xmlLookupService);
20466
- 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
+ );
20467
20857
  this.applyPhotoAlbum(presentation, init.options?.photoAlbum);
20468
20858
  presentation = this.applyKinsoku(presentation, init.options?.kinsoku);
20469
20859
  this.applyModifyVerifier(presentation, init.options?.modifyVerifier);
@@ -20558,6 +20948,53 @@ var PptxPresentationSaveBuilder = class {
20558
20948
  }
20559
20949
  };
20560
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
+
20561
20998
  // src/core/core/builders/PptxPresentationSlidesReconciler.ts
20562
20999
  var PptxPresentationSlidesReconciler = class {
20563
21000
  async reconcile(input) {
@@ -20603,6 +21040,10 @@ var PptxPresentationSlidesReconciler = class {
20603
21040
  const existingSlideIds = slideIdList ? this.ensureArray(slideIdList["p:sldId"]) : [];
20604
21041
  const slideIdByRid = /* @__PURE__ */ new Map();
20605
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
+ }
20606
21047
  for (const slideIdEntry of existingSlideIds) {
20607
21048
  const relationshipId2 = slideIdEntry?.["@_r:id"];
20608
21049
  if (typeof relationshipId2 === "string" && relationshipId2.length > 0) {
@@ -20613,6 +21054,15 @@ var PptxPresentationSlidesReconciler = class {
20613
21054
  maxNumericSlideId = Math.max(maxNumericSlideId, numericSlideId);
20614
21055
  }
20615
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
+ }
20616
21066
  for (let index = 0; index < input.slides.length; index++) {
20617
21067
  const slide = input.slides[index];
20618
21068
  slide.slideNumber = index + 1;
@@ -20649,6 +21099,7 @@ var PptxPresentationSlidesReconciler = class {
20649
21099
  ];
20650
21100
  presentationRelsData["Relationships"] = relRoot;
20651
21101
  input.zip.file("ppt/_rels/presentation.xml.rels", input.xmlBuilder.build(presentationRelsData));
21102
+ const rebuiltSlideIds = [];
20652
21103
  if (presentation && slideIdList && input.presentationData) {
20653
21104
  slideIdList["p:sldId"] = input.slides.map((slide) => {
20654
21105
  const existing = slideIdByRid.get(slide.rId);
@@ -20661,11 +21112,18 @@ var PptxPresentationSlidesReconciler = class {
20661
21112
  "@_r:id": slide.rId
20662
21113
  };
20663
21114
  });
21115
+ rebuiltSlideIds.push(...slideIdList["p:sldId"]);
20664
21116
  input.presentationData["p:presentation"] = this.insertSlideIdListInOrder(
20665
21117
  presentation,
20666
21118
  slideIdList
20667
21119
  );
20668
21120
  }
21121
+ return buildSlideReferenceRemap({
21122
+ slides: input.slides,
21123
+ originalRIdToPath,
21124
+ originalSldIdToPath,
21125
+ rebuiltSlideIds
21126
+ });
20669
21127
  }
20670
21128
  /**
20671
21129
  * Return a new presentation XML object whose `p:sldIdLst` child sits in the
@@ -21251,7 +21709,7 @@ var PptxSlideNotesPartUpdater = class {
21251
21709
 
21252
21710
  // src/core/core/builders/PptxSlideBackgroundBuilder.ts
21253
21711
  var PptxSlideBackgroundBuilder = class {
21254
- applyBackground(init) {
21712
+ async applyBackground(init) {
21255
21713
  const hasBackgroundColor = typeof init.slide.backgroundColor === "string" && init.slide.backgroundColor.length > 0 && init.slide.backgroundColor !== "transparent";
21256
21714
  const rawBackgroundImage = typeof init.slide.backgroundImage === "string" ? init.slide.backgroundImage : "";
21257
21715
  const hasBackgroundImage = rawBackgroundImage.length > 0;
@@ -21272,8 +21730,8 @@ var PptxSlideBackgroundBuilder = class {
21272
21730
  return;
21273
21731
  }
21274
21732
  const backgroundProperties = {};
21275
- if (hasDataUrlBackgroundImage) {
21276
- const parsedBackgroundImage = init.parseDataUrlToBytes(rawBackgroundImage);
21733
+ if (hasBackgroundImage) {
21734
+ const parsedBackgroundImage = await init.resolveImageToBytes(rawBackgroundImage);
21277
21735
  if (parsedBackgroundImage) {
21278
21736
  const backgroundImagePath = init.saveState.nextMediaPath(parsedBackgroundImage.extension);
21279
21737
  init.zip.file(backgroundImagePath, parsedBackgroundImage.bytes);
@@ -21291,8 +21749,11 @@ var PptxSlideBackgroundBuilder = class {
21291
21749
  },
21292
21750
  BLIP_FILL_ORDER
21293
21751
  );
21752
+ } else {
21753
+ init.reportUnsupportedBackground?.(rawBackgroundImage);
21294
21754
  }
21295
- } else if (hasBackgroundColor && init.slide.backgroundColor) {
21755
+ }
21756
+ if (backgroundProperties["a:blipFill"] === void 0 && hasBackgroundColor && init.slide.backgroundColor) {
21296
21757
  backgroundProperties["a:solidFill"] = {
21297
21758
  "a:srgbClr": {
21298
21759
  "@_val": init.slide.backgroundColor.replace("#", "").toUpperCase()
@@ -21309,6 +21770,11 @@ var PptxSlideBackgroundBuilder = class {
21309
21770
  backgroundProperties["@_shadeToTitle"] = "0";
21310
21771
  }
21311
21772
  if (!hasFillChild) {
21773
+ if (existingBg !== void 0) {
21774
+ this.reorderCSldBgFirst(cSld, existingBg);
21775
+ init.slideNode["p:cSld"] = cSld;
21776
+ return;
21777
+ }
21312
21778
  delete cSld["p:bg"];
21313
21779
  init.slideNode["p:cSld"] = cSld;
21314
21780
  return;
@@ -21518,11 +21984,15 @@ var PptxColorTransformCodec = class {
21518
21984
  }
21519
21985
  if (colorChoice["a:scrgbClr"]) {
21520
21986
  const scrgb = colorChoice["a:scrgbClr"];
21521
- const red = this.percentAttrToUnit(scrgb["@_r"]);
21522
- const green = this.percentAttrToUnit(scrgb["@_g"]);
21523
- const blue = this.percentAttrToUnit(scrgb["@_b"]);
21987
+ const red = parseDrawingFraction(scrgb["@_r"]);
21988
+ const green = parseDrawingFraction(scrgb["@_g"]);
21989
+ const blue = parseDrawingFraction(scrgb["@_b"]);
21524
21990
  if (red !== void 0 && green !== void 0 && blue !== void 0) {
21525
- 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
+ );
21526
21996
  return this.applyColorTransforms(base, scrgb);
21527
21997
  }
21528
21998
  }
@@ -21613,8 +22083,8 @@ var PptxColorTransformCodec = class {
21613
22083
  };
21614
22084
  }
21615
22085
  rgbToHex(r, g, b) {
21616
- const toHex3 = (channelValue) => this.clampColorChannel(channelValue).toString(16).padStart(2, "0").toUpperCase();
21617
- 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)}`;
21618
22088
  }
21619
22089
  applyColorTransforms(baseColor, colorNode) {
21620
22090
  return applyDrawingColorTransforms(baseColor, colorNode);
@@ -21702,6 +22172,22 @@ function mergeDrawingFillXml(original, generated, modeledChildren, childOrder2)
21702
22172
  }
21703
22173
 
21704
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
+ }
21705
22191
  var PptxGradientStyleCodec = class {
21706
22192
  context;
21707
22193
  constructor(context) {
@@ -21812,6 +22298,9 @@ var PptxGradientStyleCodec = class {
21812
22298
  b: Number.isFinite(b) ? this.context.clampUnitInterval(b / 1e5) : 0
21813
22299
  };
21814
22300
  }
22301
+ extractGradientTileRect(gradFill) {
22302
+ return extractGradientTileRect(gradFill);
22303
+ }
21815
22304
  extractGradientFlip(gradFill) {
21816
22305
  const flipRaw = String(gradFill["@_flip"] || "").trim().toLowerCase();
21817
22306
  if (flipRaw === "x" || flipRaw === "y" || flipRaw === "xy" || flipRaw === "none") {
@@ -21983,6 +22472,15 @@ var PptxGradientStyleCodec = class {
21983
22472
  }
21984
22473
  gradientXml["a:lin"] = linNode;
21985
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
+ }
21986
22484
  return mergeDrawingFillXml(
21987
22485
  shapeStyle.fillGradientXml,
21988
22486
  gradientXml,
@@ -23461,7 +23959,7 @@ var PptxColorStyleCodec = class {
23461
23959
  const alphaMod = this.percentAttrToUnit(
23462
23960
  choiceNode["a:alphaMod"]?.["@_val"]
23463
23961
  );
23464
- const alphaOff = this.percentAttrToUnit(
23962
+ const alphaOff = this.signedPercentToUnit(
23465
23963
  choiceNode["a:alphaOff"]?.["@_val"]
23466
23964
  );
23467
23965
  if (alpha === void 0 && alphaMod === void 0 && alphaOff === void 0) {
@@ -23476,6 +23974,18 @@ var PptxColorStyleCodec = class {
23476
23974
  }
23477
23975
  return this.clampUnitInterval(opacity2);
23478
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
+ }
23479
23989
  colorWithOpacity(color2, opacity2) {
23480
23990
  if (opacity2 === void 0) {
23481
23991
  return color2;
@@ -23584,26 +24094,49 @@ function applyScene3dStyle(shapeProps, style) {
23584
24094
  const camera = scene3dNode["a:camera"];
23585
24095
  const lightRig = scene3dNode["a:lightRig"];
23586
24096
  const cameraRot = camera?.["a:rot"];
24097
+ const lightRigRot = lightRig?.["a:rot"];
23587
24098
  style.scene3d = {
23588
24099
  cameraPreset: String(camera?.["@_prst"] || "").trim() || void 0,
23589
- cameraRotX: cameraRot?.["@_lat"] !== void 0 ? parseInt(String(cameraRot["@_lat"]), 10) : void 0,
23590
- cameraRotY: cameraRot?.["@_lon"] !== void 0 ? parseInt(String(cameraRot["@_lon"]), 10) : void 0,
23591
- cameraRotZ: cameraRot?.["@_rev"] !== void 0 ? parseInt(String(cameraRot["@_rev"]), 10) : void 0,
24100
+ cameraFieldOfView: intAttr(camera?.["@_fov"]),
24101
+ cameraZoom: floatAttr(camera?.["@_zoom"]),
24102
+ cameraRotX: intAttr(cameraRot?.["@_lat"]),
24103
+ cameraRotY: intAttr(cameraRot?.["@_lon"]),
24104
+ cameraRotZ: intAttr(cameraRot?.["@_rev"]),
23592
24105
  lightRigType: String(lightRig?.["@_rig"] || "").trim() || void 0,
23593
- lightRigDirection: String(lightRig?.["@_dir"] || "").trim() || void 0
24106
+ lightRigDirection: String(lightRig?.["@_dir"] || "").trim() || void 0,
24107
+ lightRigRotX: intAttr(lightRigRot?.["@_lat"]),
24108
+ lightRigRotY: intAttr(lightRigRot?.["@_lon"]),
24109
+ lightRigRotZ: intAttr(lightRigRot?.["@_rev"])
23594
24110
  };
23595
24111
  const backdrop = scene3dNode["a:backdrop"];
23596
24112
  if (backdrop) {
23597
24113
  style.scene3d.hasBackdrop = true;
23598
24114
  const anchor = backdrop["a:anchor"];
23599
- const anchorAttrs = anchor;
23600
- if (anchorAttrs) {
23601
- style.scene3d.backdropAnchorX = parseInt(String(anchorAttrs["@_x"] || "0"), 10);
23602
- style.scene3d.backdropAnchorY = parseInt(String(anchorAttrs["@_y"] || "0"), 10);
23603
- style.scene3d.backdropAnchorZ = parseInt(String(anchorAttrs["@_z"] || "0"), 10);
24115
+ if (anchor) {
24116
+ style.scene3d.backdropAnchorX = intAttr(anchor["@_x"]) ?? 0;
24117
+ style.scene3d.backdropAnchorY = intAttr(anchor["@_y"]) ?? 0;
24118
+ style.scene3d.backdropAnchorZ = intAttr(anchor["@_z"]) ?? 0;
24119
+ }
24120
+ const norm = backdrop["a:norm"];
24121
+ if (norm) {
24122
+ style.scene3d.backdropNormalX = intAttr(norm["@_dx"]) ?? 0;
24123
+ style.scene3d.backdropNormalY = intAttr(norm["@_dy"]) ?? 0;
24124
+ style.scene3d.backdropNormalZ = intAttr(norm["@_dz"]) ?? 0;
24125
+ }
24126
+ const up = backdrop["a:up"];
24127
+ if (up) {
24128
+ style.scene3d.backdropUpX = intAttr(up["@_dx"]) ?? 0;
24129
+ style.scene3d.backdropUpY = intAttr(up["@_dy"]) ?? 0;
24130
+ style.scene3d.backdropUpZ = intAttr(up["@_dz"]) ?? 0;
23604
24131
  }
23605
24132
  }
23606
24133
  }
24134
+ function intAttr(value) {
24135
+ return value !== void 0 ? parseInt(String(value), 10) : void 0;
24136
+ }
24137
+ function floatAttr(value) {
24138
+ return value !== void 0 ? parseFloat(String(value)) : void 0;
24139
+ }
23607
24140
  function applyShape3dStyle(shapeProps, style, context) {
23608
24141
  const shape3dNode = shapeProps["a:sp3d"];
23609
24142
  if (!shape3dNode) {
@@ -23636,10 +24169,12 @@ function applyLineProperties(lineNode, shapeProps, style, context, resolveHidden
23636
24169
  }
23637
24170
  const hiddenLineFill = hiddenLineProps["a:solidFill"];
23638
24171
  if (hiddenLineFill) {
24172
+ style.strokeFillMode = "solid";
23639
24173
  style.strokeColor = context.parseColor(hiddenLineFill);
23640
24174
  style.strokeOpacity = context.extractColorOpacity(hiddenLineFill);
23641
24175
  }
23642
24176
  } else {
24177
+ style.strokeFillMode = "none";
23643
24178
  style.strokeWidth = 0;
23644
24179
  style.strokeColor = "transparent";
23645
24180
  }
@@ -23657,6 +24192,7 @@ function applyLineProperties(lineNode, shapeProps, style, context, resolveHidden
23657
24192
  }
23658
24193
  function applyStrokeColor(lineNode, style, context) {
23659
24194
  if (lineNode["a:solidFill"]) {
24195
+ style.strokeFillMode = "solid";
23660
24196
  const lineFill = lineNode["a:solidFill"];
23661
24197
  style.strokeColor = context.parseColor(lineFill);
23662
24198
  style.strokeOpacity = context.extractColorOpacity(lineFill);
@@ -23665,10 +24201,15 @@ function applyStrokeColor(lineNode, style, context) {
23665
24201
  style.strokeColorXml = strokeColorXml;
23666
24202
  }
23667
24203
  } else if (lineNode["a:gradFill"]) {
23668
- style.strokeColor = context.extractGradientFillColor(lineNode["a:gradFill"]);
23669
- 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);
23670
24209
  } else if (lineNode["a:pattFill"]) {
24210
+ style.strokeFillMode = "pattern";
23671
24211
  const linePatternFill = lineNode["a:pattFill"];
24212
+ style.strokePatternXml = linePatternFill;
23672
24213
  style.strokeColor = context.parseColor(linePatternFill["a:fgClr"]) || context.parseColor(linePatternFill["a:bgClr"]);
23673
24214
  style.strokeOpacity = context.extractColorOpacity(linePatternFill["a:fgClr"]) || context.extractColorOpacity(linePatternFill["a:bgClr"]);
23674
24215
  }
@@ -23797,6 +24338,10 @@ var PptxShapeStyleExtractor = class {
23797
24338
  style.fillGradientPathType = this.context.extractGradientPathType(gradFill);
23798
24339
  style.fillGradientFocalPoint = this.context.extractGradientFocalPoint(gradFill);
23799
24340
  style.fillGradientFillToRect = this.context.extractGradientFillToRect(gradFill);
24341
+ const gradTileRect = extractGradientTileRect(gradFill);
24342
+ if (gradTileRect) {
24343
+ style.fillGradientTileRect = gradTileRect;
24344
+ }
23800
24345
  const gradFlip = this.context.extractGradientFlip(gradFill);
23801
24346
  if (gradFlip) {
23802
24347
  style.fillGradientFlip = gradFlip;
@@ -24486,7 +25031,10 @@ var PptxMediaDataParser = class {
24486
25031
  parseMediaData(graphicData, slidePath) {
24487
25032
  const result = {};
24488
25033
  try {
24489
- const reference = parseDrawingMediaReference(graphicData);
25034
+ const reference = parseDrawingMediaReference(
25035
+ graphicData,
25036
+ this.context.externalRelsMap.get(slidePath)
25037
+ );
24490
25038
  if (reference) {
24491
25039
  result.mediaType = reference.mediaType;
24492
25040
  result.mediaReferenceKind = reference.kind;
@@ -24987,6 +25535,7 @@ var PptxLoadDataBuilder = class {
24987
25535
  layoutOptions = [];
24988
25536
  headerFooter;
24989
25537
  presentationProperties;
25538
+ viewProperties;
24990
25539
  customShows;
24991
25540
  sections;
24992
25541
  warnings = [];
@@ -25046,6 +25595,10 @@ var PptxLoadDataBuilder = class {
25046
25595
  this.presentationProperties = presentationProperties;
25047
25596
  return this;
25048
25597
  }
25598
+ withViewProperties(viewProperties) {
25599
+ this.viewProperties = viewProperties;
25600
+ return this;
25601
+ }
25049
25602
  withCustomShows(customShows) {
25050
25603
  this.customShows = customShows;
25051
25604
  return this;
@@ -25183,6 +25736,7 @@ var PptxLoadDataBuilder = class {
25183
25736
  layoutOptions: this.layoutOptions,
25184
25737
  headerFooter: this.headerFooter,
25185
25738
  presentationProperties: this.presentationProperties,
25739
+ viewProperties: this.viewProperties,
25186
25740
  customShows: this.customShows,
25187
25741
  sections: this.sections,
25188
25742
  warnings: this.warnings,
@@ -25565,7 +26119,7 @@ var PptxSlideCommentsXmlFactory = class {
25565
26119
  const createdAtIso = this.resolveCreatedAt(comment.createdAt);
25566
26120
  const x = init.saveState.toEmu(comment.x, 0);
25567
26121
  const y = init.saveState.toEmu(comment.y, 0);
25568
- return {
26122
+ const node = {
25569
26123
  ...withoutChildrenByLocalName(comment.rawXml ?? {}, /* @__PURE__ */ new Set(["pos", "text"])),
25570
26124
  "@_authorId": authorId,
25571
26125
  "@_dt": createdAtIso,
@@ -25576,6 +26130,28 @@ var PptxSlideCommentsXmlFactory = class {
25576
26130
  },
25577
26131
  "p:text": String(comment.text || "")
25578
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
+ }
25579
26155
  }
25580
26156
  resolveCreatedAt(createdAt) {
25581
26157
  const candidate = String(createdAt || "").trim();
@@ -25937,6 +26513,94 @@ var PptxCompatibilityService = class {
25937
26513
  }
25938
26514
  };
25939
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
+
25940
26604
  // src/core/services/PptxDocumentPropertiesUpdater.ts
25941
26605
  var PptxDocumentPropertiesUpdater = class {
25942
26606
  context;
@@ -26000,6 +26664,7 @@ var PptxDocumentPropertiesUpdater = class {
26000
26664
  appProps["Slides"] = String(slides.length);
26001
26665
  appProps["HiddenSlides"] = String(hiddenSlidesCount);
26002
26666
  appProps["Notes"] = String(notesCount);
26667
+ this.updateSlideTitleProperties(appProps, slides);
26003
26668
  appData["Properties"] = appProps;
26004
26669
  this.context.zip.file("docProps/app.xml", this.context.builder.build(appData));
26005
26670
  } catch (error) {
@@ -26042,6 +26707,15 @@ var PptxDocumentPropertiesUpdater = class {
26042
26707
  }
26043
26708
  }
26044
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
+ }
26045
26719
  applyAppPropertiesOverrides(appProps, overrides) {
26046
26720
  if (!overrides) {
26047
26721
  return;
@@ -27661,6 +28335,16 @@ function extractChildKeyframes(childTnList) {
27661
28335
  }
27662
28336
  return void 0;
27663
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
+ }
27664
28348
  function extractRepeatInfo(cTn) {
27665
28349
  let repeatCount;
27666
28350
  let autoReverse;
@@ -28139,8 +28823,11 @@ var PptxNativeAnimationService = class {
28139
28823
  const nodeType = String(cTn["@_nodeType"] || "");
28140
28824
  const presetClass = cTn["@_presetClass"];
28141
28825
  const presetId = cTn["@_presetID"] ? Number.parseInt(String(cTn["@_presetID"]), 10) : void 0;
28826
+ const presetSubtype = cTn["@_presetSubtype"] !== void 0 ? Number.parseInt(String(cTn["@_presetSubtype"]), 10) : void 0;
28142
28827
  const durationMs = cTn["@_dur"] ? Number.parseInt(String(cTn["@_dur"]), 10) : void 0;
28143
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"]);
28144
28831
  let trigger = currentTrigger;
28145
28832
  if (nodeType === "afterPrevious" || nodeType === "afterPrev") {
28146
28833
  trigger = "afterPrevious";
@@ -28190,8 +28877,11 @@ var PptxNativeAnimationService = class {
28190
28877
  trigger,
28191
28878
  presetClass: validPresetClass,
28192
28879
  presetId,
28880
+ presetSubtype,
28193
28881
  durationMs,
28194
28882
  delayMs,
28883
+ accel,
28884
+ decel,
28195
28885
  triggerDelayMs: trigger === "afterDelay" ? delayMs : void 0,
28196
28886
  motionPath: childMotion.motionPath,
28197
28887
  motionOrigin: childMotion.motionOrigin,
@@ -28500,6 +29190,74 @@ function buildP14ExtLst(transitionType, direction, orient, pattern, rawExtLst, x
28500
29190
  return { "p:ext": transitionExt };
28501
29191
  }
28502
29192
 
29193
+ // src/core/services/p15-transition-parser.ts
29194
+ var P15_TRANSITION_PRESETS = /* @__PURE__ */ new Set([
29195
+ "fallOver",
29196
+ "drape",
29197
+ "curtains",
29198
+ "wind",
29199
+ "prestige",
29200
+ "fracture",
29201
+ "crush",
29202
+ "peelOff",
29203
+ "pageCurlDouble",
29204
+ "pageCurlSingle",
29205
+ "airplane",
29206
+ "origami"
29207
+ ]);
29208
+ var PRSTTRANS_EXT_URI = "{D42A27DB-BD31-4B8C-83A1-F6EECF244321}";
29209
+ function optionalBoolean(value) {
29210
+ const valueToken = value === void 0 || value === null ? "" : String(value).trim().toLowerCase();
29211
+ if (valueToken === "1" || valueToken === "true") {
29212
+ return true;
29213
+ }
29214
+ if (valueToken === "0" || valueToken === "false") {
29215
+ return false;
29216
+ }
29217
+ return void 0;
29218
+ }
29219
+ function parseP15FromExtLst(extLstNode, xmlLookupService, getXmlLocalName) {
29220
+ const extEntries = xmlLookupService.getChildrenArrayByLocalName(extLstNode, "ext");
29221
+ for (const ext of extEntries) {
29222
+ if (!ext) {
29223
+ continue;
29224
+ }
29225
+ for (const [key, value] of Object.entries(ext)) {
29226
+ if (key.startsWith("@_")) {
29227
+ continue;
29228
+ }
29229
+ if (getXmlLocalName(key) !== "prstTrans") {
29230
+ continue;
29231
+ }
29232
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
29233
+ continue;
29234
+ }
29235
+ const detail = value;
29236
+ const prst = String(detail["@_prst"] || "").trim();
29237
+ if (!P15_TRANSITION_PRESETS.has(prst)) {
29238
+ continue;
29239
+ }
29240
+ return {
29241
+ type: prst,
29242
+ invX: optionalBoolean(detail["@_invX"]),
29243
+ invY: optionalBoolean(detail["@_invY"])
29244
+ };
29245
+ }
29246
+ }
29247
+ return void 0;
29248
+ }
29249
+ function buildP15ExtLst(transitionType, invX, invY) {
29250
+ const prstTrans = {
29251
+ "@_xmlns:p15": "http://schemas.microsoft.com/office/powerpoint/2012/main",
29252
+ "@_prst": transitionType
29253
+ };
29254
+ const ext = {
29255
+ "@_uri": PRSTTRANS_EXT_URI,
29256
+ "p15:prstTrans": prstTrans
29257
+ };
29258
+ return { "p:ext": ext };
29259
+ }
29260
+
28503
29261
  // src/core/services/slide-transition-xml.ts
28504
29262
  var STANDARD_TRANSITION_TYPES = /* @__PURE__ */ new Set([
28505
29263
  "fade",
@@ -28565,7 +29323,7 @@ function parseTransitionDetails(node, localName21) {
28565
29323
  if (pattern) {
28566
29324
  result.pattern = pattern;
28567
29325
  }
28568
- const thruBlk = optionalBoolean(detail["@_thruBlk"]);
29326
+ const thruBlk = optionalBoolean2(detail["@_thruBlk"]);
28569
29327
  if (thruBlk !== void 0) {
28570
29328
  result.thruBlk = thruBlk;
28571
29329
  }
@@ -28576,7 +29334,7 @@ function parseTransitionAttributes(node) {
28576
29334
  const speedToken = token(node["@_spd"]);
28577
29335
  const speed = SPEEDS.has(speedToken) ? speedToken : void 0;
28578
29336
  const durationMs = unsignedInteger2(node["@_dur"] ?? node["@_p14:dur"], 1);
28579
- const advanceOnClick = optionalBoolean(node["@_advClick"]);
29337
+ const advanceOnClick = optionalBoolean2(node["@_advClick"]);
28580
29338
  const advanceAfterMs = unsignedInteger2(node["@_advTm"]);
28581
29339
  return { speed, durationMs, advanceOnClick, advanceAfterMs };
28582
29340
  }
@@ -28590,7 +29348,7 @@ function parseTransitionSound(raw, lookup, localName21) {
28590
29348
  return {
28591
29349
  soundRId: sound ? attributeByLocalName(sound, "embed", localName21) : void 0,
28592
29350
  soundName: sound ? attributeByLocalName(sound, "name", localName21) : void 0,
28593
- soundLoop: optionalBoolean(start["@_loop"])
29351
+ soundLoop: optionalBoolean2(start["@_loop"])
28594
29352
  };
28595
29353
  }
28596
29354
  const stopSound = Object.keys(raw).some(
@@ -28699,7 +29457,7 @@ function attributeByLocalName(node, name, localName21) {
28699
29457
  function token(value) {
28700
29458
  return value === void 0 || value === null ? "" : String(value).trim();
28701
29459
  }
28702
- function optionalBoolean(value) {
29460
+ function optionalBoolean2(value) {
28703
29461
  const valueToken = token(value).toLowerCase();
28704
29462
  if (!valueToken) {
28705
29463
  return void 0;
@@ -28745,6 +29503,7 @@ var PptxSlideTransitionService = class {
28745
29503
  const { spokes, thruBlk, rawSoundAction, rawExtLst } = details;
28746
29504
  if (rawExtLst && transitionType === "cut") {
28747
29505
  const p14Result = parseP14FromExtLst(rawExtLst, this.xmlLookupService, this.getXmlLocalName);
29506
+ const p15Result = p14Result ? void 0 : parseP15FromExtLst(rawExtLst, this.xmlLookupService, this.getXmlLocalName);
28748
29507
  if (p14Result) {
28749
29508
  transitionType = p14Result.type;
28750
29509
  if (p14Result.direction) {
@@ -28756,6 +29515,8 @@ var PptxSlideTransitionService = class {
28756
29515
  if (p14Result.pattern) {
28757
29516
  pattern = p14Result.pattern;
28758
29517
  }
29518
+ } else if (p15Result) {
29519
+ transitionType = p15Result.type;
28759
29520
  } else if (this.parseMorphFromExtLst(rawExtLst)) {
28760
29521
  transitionType = "morph";
28761
29522
  }
@@ -28837,6 +29598,7 @@ var PptxSlideTransitionService = class {
28837
29598
  }
28838
29599
  const transitionType = transition.type || "cut";
28839
29600
  const isP14Type = P14_TRANSITION_TYPES.has(transitionType);
29601
+ const isP15Type = P15_TRANSITION_PRESETS.has(transitionType);
28840
29602
  const isMorphType = transitionType === "morph";
28841
29603
  const node = createPreservedTransitionNode(transition.rawTransition, this.getXmlLocalName);
28842
29604
  if (isP14Type) {
@@ -28849,6 +29611,8 @@ var PptxSlideTransitionService = class {
28849
29611
  this.xmlLookupService,
28850
29612
  this.getXmlLocalName
28851
29613
  );
29614
+ } else if (isP15Type) {
29615
+ node["p:extLst"] = transition.rawExtLst ?? buildP15ExtLst(transitionType);
28852
29616
  } else if (isMorphType) {
28853
29617
  node["p:extLst"] = this.buildMorphExtLst(transition.rawExtLst);
28854
29618
  } else {
@@ -28859,7 +29623,7 @@ var PptxSlideTransitionService = class {
28859
29623
  if (soundAction) {
28860
29624
  node["p:sndAc"] = soundAction;
28861
29625
  }
28862
- if (transition.rawExtLst && !isP14Type && !isMorphType) {
29626
+ if (transition.rawExtLst && !isP14Type && !isP15Type && !isMorphType) {
28863
29627
  node["p:extLst"] = transition.rawExtLst;
28864
29628
  }
28865
29629
  return node;
@@ -31876,6 +32640,128 @@ function applySmartArtConnectionAttributes(xml, connection, fallbackModelId) {
31876
32640
  applyNullableAttribute(xml, "@_presId", connection.presentationId);
31877
32641
  }
31878
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
+
31879
32765
  // src/core/utils/modern-comment-constants.ts
31880
32766
  var MODERN_COMMENT_NAMESPACE = "http://schemas.microsoft.com/office/powerpoint/2018/8/main";
31881
32767
  var MODERN_COMMENT_RELATIONSHIP = "http://schemas.microsoft.com/office/2018/10/relationships/comments";
@@ -34182,6 +35068,28 @@ function buildGeneratedChartAxis(axId, crossId, pos2, formatting) {
34182
35068
  return axis;
34183
35069
  }
34184
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
+
34185
35093
  // src/core/utils/chart-xml-generator.ts
34186
35094
  var NS_C = "http://schemas.openxmlformats.org/drawingml/2006/chart";
34187
35095
  var NS_A2 = "http://schemas.openxmlformats.org/drawingml/2006/main";
@@ -34212,29 +35120,6 @@ function strLit(values) {
34212
35120
  }
34213
35121
  };
34214
35122
  }
34215
- function resolveType(type) {
34216
- switch (type) {
34217
- case "pie":
34218
- case "pie3D":
34219
- return { tag: "c:pieChart", family: "pie" };
34220
- case "doughnut":
34221
- return { tag: "c:doughnutChart", family: "doughnut" };
34222
- case "scatter":
34223
- return { tag: "c:scatterChart", family: "scatter" };
34224
- case "bubble":
34225
- return { tag: "c:bubbleChart", family: "bubble" };
34226
- case "line":
34227
- case "line3D":
34228
- return { tag: "c:lineChart", family: "line" };
34229
- case "area":
34230
- case "area3D":
34231
- return { tag: "c:areaChart", family: "area" };
34232
- case "radar":
34233
- return { tag: "c:radarChart", family: "radar" };
34234
- default:
34235
- return { tag: "c:barChart", family: "bar" };
34236
- }
34237
- }
34238
35123
  function fillSpPr(color2, asLine) {
34239
35124
  const h = hex6(color2);
34240
35125
  if (!h) {
@@ -34302,7 +35187,10 @@ function buildChartTypeContainer(chartData, family) {
34302
35187
  } else if (family === "scatter") {
34303
35188
  container["c:scatterStyle"] = { "@_val": "lineMarker" };
34304
35189
  container["c:varyColors"] = { "@_val": "0" };
34305
- } 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 {
34306
35194
  container["c:varyColors"] = { "@_val": family === "bubble" ? "0" : "1" };
34307
35195
  }
34308
35196
  container["c:ser"] = chartData.series.map(
@@ -34314,12 +35202,13 @@ function buildChartTypeContainer(chartData, family) {
34314
35202
  if (family === "line" && chartData.upDownBars !== void 0) {
34315
35203
  applyChartUpDownBars(container, chartData.upDownBars, (key) => key.replace(/^.*:/u, ""));
34316
35204
  }
34317
- if (family === "bar") {
35205
+ if (family === "bar" || family === "ofPie") {
34318
35206
  container["c:gapWidth"] = { "@_val": "150" };
34319
- container["c:axId"] = [{ "@_val": String(CAT_AX_ID) }, { "@_val": String(VAL_AX_ID) }];
34320
- } else if (family === "line" || family === "area" || family === "radar") {
34321
- container["c:axId"] = [{ "@_val": String(CAT_AX_ID) }, { "@_val": String(VAL_AX_ID) }];
34322
- } 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") {
34323
35212
  container["c:axId"] = [{ "@_val": String(CAT_AX_ID) }, { "@_val": String(VAL_AX_ID) }];
34324
35213
  } else if (family === "doughnut") {
34325
35214
  container["c:holeSize"] = { "@_val": "50" };
@@ -34332,7 +35221,8 @@ function buildPlotArea(chartData, tag, family) {
34332
35221
  if (chartData.style) {
34333
35222
  applyChartDataLabelsToXml(plotArea, chartData.style, (key) => key.replace(/^.*:/u, ""));
34334
35223
  }
34335
- 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)) {
34336
35226
  plotArea["c:valAx"] = [
34337
35227
  buildGeneratedChartAxis(
34338
35228
  CAT_AX_ID,
@@ -34347,7 +35237,7 @@ function buildPlotArea(chartData, tag, family) {
34347
35237
  axisFormatting(chartData, "valAx", VAL_AX_ID, 1)
34348
35238
  )
34349
35239
  ];
34350
- } else if (family !== "pie" && family !== "doughnut") {
35240
+ } else if (hasAxes) {
34351
35241
  const dateAxis = chartData.dateCategories ? axisFormatting(chartData, "dateAx", CAT_AX_ID) : void 0;
34352
35242
  plotArea[dateAxis ? "c:dateAx" : "c:catAx"] = buildGeneratedChartAxis(
34353
35243
  CAT_AX_ID,
@@ -34366,7 +35256,7 @@ function buildPlotArea(chartData, tag, family) {
34366
35256
  return plotArea;
34367
35257
  }
34368
35258
  function buildChartSpaceXml(chartData) {
34369
- const { tag, family } = resolveType(chartData.chartType);
35259
+ const { tag, family } = resolveChartContainerType(chartData.chartType);
34370
35260
  const chart = {};
34371
35261
  if (chartData.title) {
34372
35262
  chart["c:title"] = {
@@ -36298,6 +37188,7 @@ function parseMediaExtensionData(mediaNode, cMediaNode, shapeId, ensureArray16)
36298
37188
  let playbackSpeed;
36299
37189
  let trimStartMs;
36300
37190
  let trimEndMs;
37191
+ let embedRId;
36301
37192
  const bookmarks = [];
36302
37193
  const extLst = mediaNode["p:extLst"] ?? cMediaNode["p:extLst"];
36303
37194
  if (extLst) {
@@ -36305,6 +37196,13 @@ function parseMediaExtensionData(mediaNode, cMediaNode, shapeId, ensureArray16)
36305
37196
  for (const ext of exts) {
36306
37197
  const p14Media = ext["p14:media"];
36307
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
+ }
36308
37206
  const p14Trim = p14Media["p14:trim"];
36309
37207
  if (p14Trim) {
36310
37208
  const st = p14Trim["@_st"];
@@ -36374,7 +37272,8 @@ function parseMediaExtensionData(mediaNode, cMediaNode, shapeId, ensureArray16)
36374
37272
  fadeInDuration,
36375
37273
  fadeOutDuration,
36376
37274
  playbackSpeed,
36377
- bookmarks
37275
+ bookmarks,
37276
+ embedRId
36378
37277
  };
36379
37278
  }
36380
37279
 
@@ -36604,6 +37503,12 @@ var PptxHandlerRuntime = class {
36604
37503
  loadedEmbeddedFonts = [];
36605
37504
  /** Typed source metadata for lossless embedded-font list round trips. */
36606
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;
36607
37512
  /** Map of comment author IDs to display names (from `ppt/commentAuthors.xml`). */
36608
37513
  commentAuthorMap = /* @__PURE__ */ new Map();
36609
37514
  /** Full comment author details keyed by author ID, preserving initials/lastIdx/clrIdx for round-trip. */
@@ -36743,19 +37648,266 @@ var PptxHandlerRuntime = class {
36743
37648
  }
36744
37649
  };
36745
37650
 
37651
+ // src/core/core/runtime/table-style-border-parse.ts
37652
+ var EMU_PER_PIXEL = 9525;
37653
+ var BORDER_SIDES = [
37654
+ "left",
37655
+ "right",
37656
+ "top",
37657
+ "bottom",
37658
+ "insideH",
37659
+ "insideV",
37660
+ "tl2br",
37661
+ "bl2tr"
37662
+ ];
37663
+ function parseSolidFillStyle(solidFill2) {
37664
+ if (!solidFill2) {
37665
+ return void 0;
37666
+ }
37667
+ const schemeClr = solidFill2["a:schemeClr"];
37668
+ if (!schemeClr) {
37669
+ return void 0;
37670
+ }
37671
+ const schemeColor = String(schemeClr["@_val"] || "").trim() || void 0;
37672
+ if (!schemeColor) {
37673
+ return void 0;
37674
+ }
37675
+ const tintRaw = schemeClr["a:tint"];
37676
+ const tint = tintRaw ? parseInt(String(tintRaw["@_val"] || "0"), 10) || void 0 : void 0;
37677
+ const shadeRaw = schemeClr["a:shade"];
37678
+ const shade = shadeRaw ? parseInt(String(shadeRaw["@_val"] || "0"), 10) || void 0 : void 0;
37679
+ return { schemeColor, tint, shade };
37680
+ }
37681
+ function parseBorderSide(side) {
37682
+ if (!side) {
37683
+ return void 0;
37684
+ }
37685
+ const ln = side["a:ln"];
37686
+ if (!ln) {
37687
+ return void 0;
37688
+ }
37689
+ const border = {};
37690
+ let has = false;
37691
+ if (ln["a:noFill"] !== void 0) {
37692
+ border.noFill = true;
37693
+ has = true;
37694
+ }
37695
+ const widthEmu = parseInt(String(ln["@_w"] || "0"), 10);
37696
+ if (widthEmu > 0) {
37697
+ border.width = Math.max(1, Math.round(widthEmu / EMU_PER_PIXEL));
37698
+ has = true;
37699
+ }
37700
+ const prstDash = ln["a:prstDash"];
37701
+ const dashVal = prstDash ? String(prstDash["@_val"] || "").trim() : "";
37702
+ if (dashVal) {
37703
+ border.dash = dashVal;
37704
+ has = true;
37705
+ }
37706
+ const solidFill2 = ln["a:solidFill"];
37707
+ const fill = parseSolidFillStyle(solidFill2);
37708
+ if (fill) {
37709
+ border.fill = fill;
37710
+ has = true;
37711
+ } else {
37712
+ const srgb = solidFill2?.["a:srgbClr"];
37713
+ const hex10 = srgb ? String(srgb["@_val"] || "").trim() : "";
37714
+ if (hex10) {
37715
+ border.color = hex10.startsWith("#") ? hex10 : `#${hex10}`;
37716
+ has = true;
37717
+ }
37718
+ }
37719
+ return has ? border : void 0;
37720
+ }
37721
+ function parseTableStyleBorders(tcStyle) {
37722
+ const tcBdr = tcStyle?.["a:tcBdr"];
37723
+ if (!tcBdr) {
37724
+ return void 0;
37725
+ }
37726
+ const result = {};
37727
+ let has = false;
37728
+ for (const name of BORDER_SIDES) {
37729
+ const border = parseBorderSide(tcBdr[`a:${name}`]);
37730
+ if (border) {
37731
+ result[name] = border;
37732
+ has = true;
37733
+ }
37734
+ }
37735
+ return has ? result : void 0;
37736
+ }
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
+
36746
37905
  // src/core/core/runtime/PptxHandlerRuntimeTableStyles.ts
36747
37906
  var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
36748
37907
  /**
36749
- * Export slides to a raster/vector format.
36750
- *
36751
- * This is a stub that signals export intent. Actual rendering requires a
36752
- * platform-specific canvas or PDF library (e.g. Puppeteer, node-canvas,
36753
- * pdfkit). Host applications should override or extend this method with
36754
- * their own rendering pipeline.
36755
- *
36756
- * @param _slides The slides to export.
36757
- * @param _options Export options (format, DPI, slide indices, etc.).
36758
- * @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.
36759
37911
  */
36760
37912
  async exportSlides(slides, options) {
36761
37913
  this.compatibilityService.reportWarning({
@@ -36820,77 +37972,26 @@ var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
36820
37972
  }
36821
37973
  /**
36822
37974
  * Extract fill information from a table style section element
36823
- * (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).
36824
37977
  */
36825
37978
  extractTableStyleSectionFill(section) {
36826
- if (!section) {
36827
- return void 0;
36828
- }
36829
- const tcStyle = section["a:tcStyle"];
36830
- if (!tcStyle) {
36831
- return void 0;
36832
- }
36833
- const fill = tcStyle["a:fill"];
36834
- if (!fill) {
36835
- return void 0;
36836
- }
36837
- const solidFill2 = fill["a:solidFill"];
36838
- if (!solidFill2) {
36839
- return void 0;
36840
- }
36841
- const schemeClr = solidFill2["a:schemeClr"];
36842
- if (!schemeClr) {
36843
- return void 0;
36844
- }
36845
- const schemeColor = String(schemeClr["@_val"] || "").trim() || void 0;
36846
- if (!schemeColor) {
36847
- return void 0;
36848
- }
36849
- const tintRaw = schemeClr["a:tint"];
36850
- const tint = tintRaw ? parseInt(String(tintRaw["@_val"] || "0"), 10) || void 0 : void 0;
36851
- const shadeRaw = schemeClr["a:shade"];
36852
- const shade = shadeRaw ? parseInt(String(shadeRaw["@_val"] || "0"), 10) || void 0 : void 0;
36853
- return { schemeColor, tint, shade };
37979
+ return parseTableStyleSectionFill(section);
37980
+ }
37981
+ /**
37982
+ * Extract border styling from a table style section's
37983
+ * `a:tcStyle/a:tcBdr` (per-side line width, dash, and colour).
37984
+ */
37985
+ extractTableStyleSectionBorders(section) {
37986
+ return parseTableStyleBorders(section?.["a:tcStyle"]);
36854
37987
  }
36855
37988
  /**
36856
- * 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).
36857
37992
  */
36858
37993
  extractTableStyleSectionText(section) {
36859
- if (!section) {
36860
- return void 0;
36861
- }
36862
- const tcTxStyle = section["a:tcTxStyle"];
36863
- if (!tcTxStyle) {
36864
- return void 0;
36865
- }
36866
- const result = {};
36867
- let hasProps = false;
36868
- if (tcTxStyle["@_b"] === "on") {
36869
- result.bold = true;
36870
- hasProps = true;
36871
- }
36872
- if (tcTxStyle["@_i"] === "on") {
36873
- result.italic = true;
36874
- hasProps = true;
36875
- }
36876
- const fontClr = tcTxStyle["a:fontRef"];
36877
- const schemeClr = fontClr?.["a:schemeClr"] ?? tcTxStyle["a:schemeClr"];
36878
- if (schemeClr) {
36879
- const val = String(schemeClr["@_val"] || "").trim();
36880
- if (val) {
36881
- result.fontSchemeColor = val;
36882
- hasProps = true;
36883
- const tintNode = schemeClr["a:tint"];
36884
- if (tintNode) {
36885
- result.fontTint = parseInt(String(tintNode["@_val"] || "0"), 10) || void 0;
36886
- }
36887
- const shadeNode = schemeClr["a:shade"];
36888
- if (shadeNode) {
36889
- result.fontShade = parseInt(String(shadeNode["@_val"] || "0"), 10) || void 0;
36890
- }
36891
- }
36892
- }
36893
- return hasProps ? result : void 0;
37994
+ return parseTableStyleSectionText(section);
36894
37995
  }
36895
37996
  ensureArray(val) {
36896
37997
  if (!val) {
@@ -36997,6 +38098,15 @@ var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
36997
38098
  textProps[`${name}Text`] = text2;
36998
38099
  }
36999
38100
  }
38101
+ const borderProps = {};
38102
+ for (const name of sectionNames) {
38103
+ const borders = this.extractTableStyleSectionBorders(
38104
+ style[`a:${name}`]
38105
+ );
38106
+ if (borders) {
38107
+ borderProps[`${name}Borders`] = borders;
38108
+ }
38109
+ }
37000
38110
  const entry = {
37001
38111
  styleId,
37002
38112
  styleName,
@@ -37015,7 +38125,8 @@ var PptxHandlerRuntime2 = class extends PptxHandlerRuntime {
37015
38125
  ...swCellFill ? { swCellFill } : {},
37016
38126
  ...neCellFill ? { neCellFill } : {},
37017
38127
  ...nwCellFill ? { nwCellFill } : {},
37018
- ...textProps
38128
+ ...textProps,
38129
+ ...borderProps
37019
38130
  };
37020
38131
  map[styleId] = entry;
37021
38132
  }
@@ -37560,6 +38671,7 @@ var PptxHandlerRuntime6 = class extends PptxHandlerRuntime5 {
37560
38671
  );
37561
38672
  const trimStartMs = timing.trimStartMs ?? extData.trimStartMs;
37562
38673
  const trimEndMs = timing.trimEndMs ?? extData.trimEndMs;
38674
+ const mediaEmbedPath = extData.embedRId ? this.resolveRelationshipTarget(slidePath, extData.embedRId) : void 0;
37563
38675
  result.set(shapeId, {
37564
38676
  trimStartMs: trimStartMs !== void 0 && !isNaN(trimStartMs) ? trimStartMs : void 0,
37565
38677
  trimEndMs: trimEndMs !== void 0 && !isNaN(trimEndMs) ? trimEndMs : void 0,
@@ -37573,7 +38685,8 @@ var PptxHandlerRuntime6 = class extends PptxHandlerRuntime5 {
37573
38685
  playAcrossSlides: timing.playAcrossSlides || void 0,
37574
38686
  hideWhenNotPlaying: hideWhenNotPlaying || void 0,
37575
38687
  bookmarks: extData.bookmarks.length > 0 ? extData.bookmarks : void 0,
37576
- playbackSpeed: extData.playbackSpeed
38688
+ playbackSpeed: extData.playbackSpeed,
38689
+ mediaEmbedPath
37577
38690
  });
37578
38691
  }
37579
38692
  }
@@ -37749,6 +38862,10 @@ var PptxHandlerRuntime7 = class extends PptxHandlerRuntime6 {
37749
38862
  if (!timing) {
37750
38863
  continue;
37751
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
+ }
37752
38869
  if (timing.trimStartMs !== void 0) {
37753
38870
  el.trimStartMs = timing.trimStartMs;
37754
38871
  }
@@ -38755,7 +39872,7 @@ var PptxHandlerRuntime11 = class extends PptxHandlerRuntime10 {
38755
39872
  }
38756
39873
  }
38757
39874
  async reconcilePresentationSlidesForSave(params) {
38758
- await this.presentationSlidesReconciler.reconcile({
39875
+ return await this.presentationSlidesReconciler.reconcile({
38759
39876
  ...params,
38760
39877
  zip: this.zip,
38761
39878
  parser: this.parser,
@@ -38826,6 +39943,15 @@ var PptxHandlerRuntime11 = class extends PptxHandlerRuntime10 {
38826
39943
  if (align === "justify") {
38827
39944
  return "just";
38828
39945
  }
39946
+ if (align === "justLow") {
39947
+ return "justLow";
39948
+ }
39949
+ if (align === "dist") {
39950
+ return "dist";
39951
+ }
39952
+ if (align === "thaiDist") {
39953
+ return "thaiDist";
39954
+ }
38829
39955
  return void 0;
38830
39956
  }
38831
39957
  pixelsToPoints(px) {
@@ -39039,6 +40165,31 @@ function applyFontMetadata(fontNode, panose, pitchFamily, charset) {
39039
40165
  }
39040
40166
  return fontNode;
39041
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
+ }
39042
40193
  var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime11 {
39043
40194
  createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId) {
39044
40195
  const runProps = {
@@ -39059,6 +40210,8 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39059
40210
  }
39060
40211
  if (style.underline) {
39061
40212
  runProps["@_u"] = style.underlineStyle || "sng";
40213
+ } else if (style.underlineExplicitNone) {
40214
+ runProps["@_u"] = "none";
39062
40215
  }
39063
40216
  if (style.strikethrough !== void 0) {
39064
40217
  runProps["@_strike"] = style.strikethrough ? style.strikeType || "sngStrike" : "noStrike";
@@ -39074,6 +40227,8 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39074
40227
  }
39075
40228
  if (style.textCaps && style.textCaps !== "none") {
39076
40229
  runProps["@_cap"] = style.textCaps;
40230
+ } else if (style.textCapsExplicitNone) {
40231
+ runProps["@_cap"] = "none";
39077
40232
  }
39078
40233
  if (style.kumimoji !== void 0) {
39079
40234
  runProps["@_kumimoji"] = style.kumimoji ? "1" : "0";
@@ -39182,13 +40337,21 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39182
40337
  runProps["a:effectDag"] = style.textEffectDagXml;
39183
40338
  }
39184
40339
  if (style.highlightColor) {
39185
- runProps["a:highlight"] = {
39186
- "a:srgbClr": {
39187
- "@_val": style.highlightColor.replace("#", "")
39188
- }
39189
- };
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);
39190
40351
  }
39191
- if (style.underline && style.underlineColor) {
40352
+ if (style.underlineFillFollowsText) {
40353
+ runProps["a:uFillTx"] = {};
40354
+ } else if (style.underline && style.underlineColor) {
39192
40355
  runProps["a:uFill"] = {
39193
40356
  "a:solidFill": {
39194
40357
  "a:srgbClr": {
@@ -39197,21 +40360,28 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39197
40360
  }
39198
40361
  };
39199
40362
  }
39200
- if (style.fontFamily) {
40363
+ const latinFace = style.latinFontThemeToken ?? style.fontFamily;
40364
+ if (latinFace) {
39201
40365
  runProps["a:latin"] = applyFontMetadata(
39202
- { "@_typeface": style.fontFamily },
40366
+ { "@_typeface": latinFace },
39203
40367
  style.latinFontPanose,
39204
40368
  style.latinFontPitchFamily,
39205
40369
  style.latinFontCharset
39206
40370
  );
40371
+ }
40372
+ const eastAsiaFace = style.eastAsiaFontThemeToken ?? style.eastAsiaFont;
40373
+ if (eastAsiaFace) {
39207
40374
  runProps["a:ea"] = applyFontMetadata(
39208
- { "@_typeface": style.eastAsiaFont || style.fontFamily },
40375
+ { "@_typeface": eastAsiaFace },
39209
40376
  style.eastAsiaFontPanose,
39210
40377
  style.eastAsiaFontPitchFamily,
39211
40378
  style.eastAsiaFontCharset
39212
40379
  );
40380
+ }
40381
+ const complexScriptFace = style.complexScriptFontThemeToken ?? style.complexScriptFont;
40382
+ if (complexScriptFace) {
39213
40383
  runProps["a:cs"] = applyFontMetadata(
39214
- { "@_typeface": style.complexScriptFont || style.fontFamily },
40384
+ { "@_typeface": complexScriptFace },
39215
40385
  style.complexScriptFontPanose,
39216
40386
  style.complexScriptFontPitchFamily,
39217
40387
  style.complexScriptFontCharset
@@ -39261,12 +40431,17 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39261
40431
  if (mouseOverTarget.length > 0) {
39262
40432
  const mouseOverRelId = resolveHyperlinkRelationshipId(mouseOverTarget);
39263
40433
  if (mouseOverRelId) {
39264
- runProps["a:hlinkMouseOver"] = {
39265
- "@_r:id": mouseOverRelId
39266
- };
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;
39267
40439
  }
39268
40440
  }
39269
40441
  }
40442
+ if (style.runPropertiesExtLstXml && typeof style.runPropertiesExtLstXml === "object") {
40443
+ runProps["a:extLst"] = style.runPropertiesExtLstXml;
40444
+ }
39270
40445
  return runProps;
39271
40446
  }
39272
40447
  applyHyperlinkExtraAttrs(hlinkNode, style) {
@@ -39285,22 +40460,26 @@ var PptxHandlerRuntime12 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39285
40460
  if (style.hyperlinkEndSound !== void 0) {
39286
40461
  hlinkNode["@_endSnd"] = style.hyperlinkEndSound ? "1" : "0";
39287
40462
  }
40463
+ if (style.hyperlinkSoundXml && typeof style.hyperlinkSoundXml === "object") {
40464
+ hlinkNode["a:snd"] = style.hyperlinkSoundXml;
40465
+ }
39288
40466
  }
39289
40467
  };
39290
40468
 
39291
40469
  // src/core/core/runtime/PptxHandlerRuntimeSaveParagraphs.ts
39292
40470
  var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39293
40471
  createParagraphsFromTextContent(text2, textStyle, textSegments, resolveHyperlinkRelationshipId) {
39294
- const paragraphAlign = this.textAlignToDrawingValue(textStyle?.align);
39295
- const spacing = {
39296
- spacingBefore: this.createParagraphSpacingXmlFromPx(textStyle?.paragraphSpacingBefore),
39297
- spacingAfter: this.createParagraphSpacingXmlFromPx(textStyle?.paragraphSpacingAfter),
39298
- lineSpacing: this.createLineSpacingXmlFromMultiplier(textStyle?.lineSpacing),
39299
- lineSpacingExactPt: textStyle?.lineSpacingExactPt
39300
- };
39301
- 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
+ };
39302
40481
  const paragraphProps = buildParagraphPropertiesXml(
39303
- textStyle,
40482
+ effectiveStyle,
39304
40483
  paragraphAlign,
39305
40484
  bulletInfo,
39306
40485
  spacing,
@@ -39312,12 +40491,22 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39312
40491
  "a:rPr": this.createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId),
39313
40492
  "a:t": runText
39314
40493
  });
39315
- const createFieldRun = (runText, style, fieldType, fieldGuid) => ({
39316
- "@_type": fieldType,
39317
- ...fieldGuid ? { "@_id": fieldGuid } : {},
39318
- "a:rPr": this.createRunPropertiesFromTextStyle(style, resolveHyperlinkRelationshipId),
39319
- "a:t": runText
39320
- });
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
+ };
39321
40510
  const createRubyRun = (segment, style) => {
39322
40511
  const rubyPr = {};
39323
40512
  if (segment.rubyAlignment) {
@@ -39356,17 +40545,27 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39356
40545
  let currentBulletInfo;
39357
40546
  let currentLevel;
39358
40547
  let currentEndParaRunProperties;
40548
+ let currentParagraphProperties;
40549
+ let capturedParagraphMeta = false;
39359
40550
  const pushParagraph = () => {
39360
40551
  if (currentRuns.length === 0) {
39361
40552
  currentRuns.push(createRun("", textStyle));
39362
40553
  }
39363
40554
  paragraphs.push(
39364
- createParagraph(currentRuns, currentBulletInfo, currentLevel, currentEndParaRunProperties)
40555
+ createParagraph(
40556
+ currentRuns,
40557
+ currentBulletInfo,
40558
+ currentLevel,
40559
+ currentEndParaRunProperties,
40560
+ currentParagraphProperties
40561
+ )
39365
40562
  );
39366
40563
  currentRuns = [];
39367
40564
  currentBulletInfo = void 0;
39368
40565
  currentLevel = void 0;
39369
40566
  currentEndParaRunProperties = void 0;
40567
+ currentParagraphProperties = void 0;
40568
+ capturedParagraphMeta = false;
39370
40569
  };
39371
40570
  if (textSegments && textSegments.length > 0) {
39372
40571
  const uniformSegmentOverrides = computeUniformSegmentOverrides(textStyle, textSegments);
@@ -39376,7 +40575,7 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39376
40575
  ...segment.style,
39377
40576
  ...uniformSegmentOverrides
39378
40577
  };
39379
- if (currentRuns.length === 0) {
40578
+ if (!capturedParagraphMeta) {
39380
40579
  if (segment.bulletInfo) {
39381
40580
  currentBulletInfo = segment.bulletInfo;
39382
40581
  }
@@ -39386,6 +40585,10 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39386
40585
  if (segment.endParaRunProperties) {
39387
40586
  currentEndParaRunProperties = segment.endParaRunProperties;
39388
40587
  }
40588
+ if (segment.paragraphProperties) {
40589
+ currentParagraphProperties = segment.paragraphProperties;
40590
+ }
40591
+ capturedParagraphMeta = true;
39389
40592
  }
39390
40593
  if (segment.isLineBreak) {
39391
40594
  const brNode = {};
@@ -39420,7 +40623,9 @@ var PptxHandlerRuntime13 = class extends PptxHandlerRuntime12 {
39420
40623
  linePart,
39421
40624
  segmentStyle,
39422
40625
  segment.fieldType,
39423
- segment.fieldGuid
40626
+ segment.fieldGuid,
40627
+ segment.fieldGuidAttr,
40628
+ segment.fieldParagraphPropertiesXml
39424
40629
  );
39425
40630
  fieldRun.__isField = true;
39426
40631
  currentRuns.push(fieldRun);
@@ -39880,6 +41085,16 @@ var PptxHandlerRuntime15 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39880
41085
  const chOffY = 0;
39881
41086
  const chExtCx = extCx;
39882
41087
  const chExtCy = extCy;
41088
+ const xfrmAttrs = {};
41089
+ if (typeof group.rotation === "number" && group.rotation !== 0) {
41090
+ xfrmAttrs["@_rot"] = String(Math.round(group.rotation * 6e4));
41091
+ }
41092
+ if (group.flipHorizontal) {
41093
+ xfrmAttrs["@_flipH"] = "1";
41094
+ }
41095
+ if (group.flipVertical) {
41096
+ xfrmAttrs["@_flipV"] = "1";
41097
+ }
39883
41098
  const grpXml = {
39884
41099
  "p:nvGrpSpPr": {
39885
41100
  "p:cNvPr": { "@_id": "0", "@_name": group.id },
@@ -39888,6 +41103,7 @@ var PptxHandlerRuntime15 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
39888
41103
  },
39889
41104
  "p:grpSpPr": {
39890
41105
  "a:xfrm": {
41106
+ ...xfrmAttrs,
39891
41107
  "a:off": {
39892
41108
  "@_x": String(offX),
39893
41109
  "@_y": String(offY)
@@ -40174,7 +41390,95 @@ var PptxHandlerRuntime16 = class extends PptxHandlerRuntime15 {
40174
41390
  };
40175
41391
 
40176
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
+ }
40177
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
+ }
40178
41482
  textStylesEqual(left, right) {
40179
41483
  const keys = [
40180
41484
  "fontFamily",
@@ -40335,6 +41639,10 @@ var PptxHandlerRuntime18 = class extends PptxHandlerRuntime17 {
40335
41639
  const esVal = String(endSnd).trim().toLowerCase();
40336
41640
  style.hyperlinkEndSound = esVal === "1" || esVal === "true";
40337
41641
  }
41642
+ const clickSnd = hyperlinkNode["a:snd"];
41643
+ if (clickSnd && typeof clickSnd === "object") {
41644
+ style.hyperlinkSoundXml = clickSnd;
41645
+ }
40338
41646
  }
40339
41647
  const actionStr = String(hyperlinkNode?.["@_action"] || "").trim();
40340
41648
  if (actionStr) {
@@ -40364,6 +41672,10 @@ var PptxHandlerRuntime18 = class extends PptxHandlerRuntime17 {
40364
41672
  } else {
40365
41673
  style.hyperlinkMouseOver = mouseOverRelId;
40366
41674
  }
41675
+ const mouseOverSnd = hlinkMouseOver["a:snd"];
41676
+ if (mouseOverSnd && typeof mouseOverSnd === "object") {
41677
+ style.hyperlinkMouseOverSoundXml = mouseOverSnd;
41678
+ }
40367
41679
  }
40368
41680
  }
40369
41681
  }
@@ -40590,6 +41902,8 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40590
41902
  if (rawU.length > 0 && rawU !== "none") {
40591
41903
  style.underlineStyle = rawU;
40592
41904
  }
41905
+ } else if (underlineToken === "none") {
41906
+ style.underlineExplicitNone = true;
40593
41907
  }
40594
41908
  }
40595
41909
  const uFill = runProperties2["a:uFill"];
@@ -40601,6 +41915,46 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40601
41915
  style.underlineColor = underlineColor;
40602
41916
  }
40603
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
+ }
40604
41958
  if (runProperties2["@_strike"] !== void 0) {
40605
41959
  const strikeToken = String(runProperties2["@_strike"] || "").trim().toLowerCase();
40606
41960
  style.strikethrough = strikeToken.length > 0 && strikeToken !== "nostrike" && strikeToken !== "none" && strikeToken !== "0" && strikeToken !== "false";
@@ -40644,10 +41998,15 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40644
41998
  }
40645
41999
  }
40646
42000
  if (runProperties2["a:highlight"]) {
40647
- const highlightHex = this.parseColor(xmlChild(runProperties2, "a:highlight"));
42001
+ const highlightNode = xmlChild(runProperties2, "a:highlight");
42002
+ const highlightHex = this.parseColor(highlightNode);
40648
42003
  if (highlightHex) {
40649
42004
  style.highlightColor = highlightHex;
40650
42005
  }
42006
+ const highlightXml = extractColorChoiceXml(highlightNode);
42007
+ if (highlightXml) {
42008
+ style.highlightColorXml = highlightXml;
42009
+ }
40651
42010
  }
40652
42011
  const textFillVariants = this.extractTextFillVariants(runProperties2);
40653
42012
  if (textFillVariants.textFillGradient) {
@@ -40668,16 +42027,28 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40668
42027
  const latin = xmlChild(runProperties2, "a:latin");
40669
42028
  const eastAsian = xmlChild(runProperties2, "a:ea");
40670
42029
  const complexScript = xmlChild(runProperties2, "a:cs");
40671
- 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;
40672
42034
  const resolvedTypeface = this.resolveThemeTypeface(chosenTypeface);
40673
42035
  if (resolvedTypeface) {
40674
42036
  style.fontFamily = resolvedTypeface;
40675
42037
  }
40676
- 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);
40677
42048
  if (eaTypeface) {
40678
42049
  style.eastAsiaFont = eaTypeface;
40679
42050
  }
40680
- const csTypeface = this.resolveThemeTypeface(xmlAttr(complexScript, "typeface"));
42051
+ const csTypeface = this.resolveThemeTypeface(csTypefaceToken);
40681
42052
  if (csTypeface) {
40682
42053
  style.complexScriptFont = csTypeface;
40683
42054
  }
@@ -40693,6 +42064,9 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40693
42064
  const capAttr = String(runProperties2["@_cap"] || "").trim().toLowerCase();
40694
42065
  if (capAttr === "all" || capAttr === "small") {
40695
42066
  style.textCaps = capAttr;
42067
+ } else if (capAttr === "none") {
42068
+ style.textCaps = "none";
42069
+ style.textCapsExplicitNone = true;
40696
42070
  }
40697
42071
  const symNode = xmlChild(runProperties2, "a:sym");
40698
42072
  if (symNode) {
@@ -40752,6 +42126,12 @@ var PptxHandlerRuntime19 = class _PptxHandlerRuntime extends PptxHandlerRuntime1
40752
42126
  this.applyTextRunEffects(style, runEffectList);
40753
42127
  }
40754
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
+ }
40755
42135
  return style;
40756
42136
  }
40757
42137
  /**
@@ -41423,12 +42803,63 @@ function writeCellTextFormatting(xmlCell, style, ensureArray16) {
41423
42803
  }
41424
42804
 
41425
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
+ }
41426
42850
  var PptxHandlerRuntime22 = class _PptxHandlerRuntime extends PptxHandlerRuntime21 {
41427
42851
  /**
41428
42852
  * Write plain text into a table cell's txBody, preserving
41429
42853
  * existing run properties where possible.
41430
42854
  */
41431
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
+ }
41432
42863
  if (!xmlCell["a:txBody"]) {
41433
42864
  xmlCell["a:txBody"] = { "a:bodyPr": {}, "a:p": {} };
41434
42865
  }
@@ -41556,7 +42987,9 @@ var PptxHandlerRuntime22 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
41556
42987
  }
41557
42988
  delete tcPr["a:tcMar"];
41558
42989
  writeDiagonalBorders(tcPr, style, _PptxHandlerRuntime.EMU_PER_PX);
41559
- 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
+ }
41560
42993
  const reordered = reorderObjectKeys(tcPr, TC_PR_BORDERS_ORDER);
41561
42994
  for (const key of Object.keys(tcPr)) {
41562
42995
  delete tcPr[key];
@@ -42800,7 +44233,7 @@ function findKey19(obj, name, getLocalName2) {
42800
44233
  function hex9(value) {
42801
44234
  return value.replace("#", "");
42802
44235
  }
42803
- var COLOR_LOCAL_NAMES = /* @__PURE__ */ new Set([
44236
+ var COLOR_LOCAL_NAMES2 = /* @__PURE__ */ new Set([
42804
44237
  "srgbClr",
42805
44238
  "schemeClr",
42806
44239
  "sysClr",
@@ -42809,7 +44242,7 @@ var COLOR_LOCAL_NAMES = /* @__PURE__ */ new Set([
42809
44242
  "hslClr"
42810
44243
  ]);
42811
44244
  function applyColorToList(list, value, getLocalName2) {
42812
- 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)));
42813
44246
  const srgb = { "@_val": hex9(value) };
42814
44247
  if (!colorKey) {
42815
44248
  list["a:srgbClr"] = srgb;
@@ -45301,6 +46734,33 @@ var PptxHandlerRuntime27 = class extends PptxHandlerRuntime26 {
45301
46734
  }
45302
46735
  };
45303
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
+
45304
46764
  // src/core/core/runtime/PptxHandlerRuntimeSaveShapeStyleWriter.ts
45305
46765
  var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime27 {
45306
46766
  /**
@@ -45371,26 +46831,14 @@ var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
45371
46831
  );
45372
46832
  }
45373
46833
  }
45374
- if (shapeStyle.strokeColor !== void 0) {
46834
+ if (shapeStyle.strokeColor !== void 0 || shapeStyle.strokeFillMode === "gradient" || shapeStyle.strokeFillMode === "pattern") {
45375
46835
  if (!spPr["a:ln"]) {
45376
46836
  spPr["a:ln"] = {};
45377
46837
  }
45378
46838
  const lineNode = spPr["a:ln"];
45379
46839
  const w = Math.round((shapeStyle.strokeWidth || 1) * _PptxHandlerRuntime.EMU_PER_PX);
45380
46840
  lineNode["@_w"] = String(w);
45381
- if (shapeStyle.strokeColor === "transparent" || shapeStyle.strokeWidth === 0) {
45382
- lineNode["a:noFill"] = {};
45383
- delete lineNode["a:solidFill"];
45384
- } else {
45385
- delete lineNode["a:noFill"];
45386
- const resolvedStrokeOriginal = shapeStyle.strokeColorXml ? this.parseColor(shapeStyle.strokeColorXml) : void 0;
45387
- lineNode["a:solidFill"] = serializeColorChoice(
45388
- shapeStyle.strokeColorXml,
45389
- resolvedStrokeOriginal,
45390
- shapeStyle.strokeColor,
45391
- shapeStyle.strokeOpacity
45392
- );
45393
- }
46841
+ this.applyLineFill(lineNode, shapeStyle);
45394
46842
  }
45395
46843
  if (shapeStyle.strokeDash !== void 0) {
45396
46844
  if (!spPr["a:ln"]) {
@@ -45480,6 +46928,15 @@ var PptxHandlerRuntime28 = class _PptxHandlerRuntime extends PptxHandlerRuntime2
45480
46928
  spPr["a:ln"]["a:effectLst"] = lineEffectListXml;
45481
46929
  }
45482
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
+ }
45483
46940
  /**
45484
46941
  * Serialize the shape's `<p:style>` block (CT_ShapeStyle §20.1.2.2.36)
45485
46942
  * from the persisted ref indices/colour XML. Emits children in spec
@@ -45635,45 +47092,18 @@ var PptxHandlerRuntime29 = class extends PptxHandlerRuntime28 {
45635
47092
  const s3d = shapeStyle.scene3d;
45636
47093
  const hasData = s3d.cameraPreset || s3d.lightRigType;
45637
47094
  if (hasData) {
45638
- const cameraObj = {};
45639
- if (s3d.cameraPreset) {
45640
- cameraObj["@_prst"] = s3d.cameraPreset;
45641
- }
45642
- if (s3d.cameraRotX !== void 0 || s3d.cameraRotY !== void 0 || s3d.cameraRotZ !== void 0) {
45643
- const rot = {};
45644
- if (s3d.cameraRotX !== void 0) {
45645
- rot["@_lat"] = String(s3d.cameraRotX);
45646
- }
45647
- if (s3d.cameraRotY !== void 0) {
45648
- rot["@_lon"] = String(s3d.cameraRotY);
45649
- }
45650
- if (s3d.cameraRotZ !== void 0) {
45651
- rot["@_rev"] = String(s3d.cameraRotZ);
45652
- }
45653
- cameraObj["a:rot"] = rot;
45654
- }
45655
- const lightRigObj = {};
45656
- if (s3d.lightRigType) {
45657
- lightRigObj["@_rig"] = s3d.lightRigType;
45658
- }
45659
- if (s3d.lightRigDirection) {
45660
- lightRigObj["@_dir"] = s3d.lightRigDirection;
45661
- }
45662
- const scene3dXml = {};
45663
- scene3dXml["a:camera"] = cameraObj;
45664
- if (Object.keys(lightRigObj).length > 0) {
45665
- scene3dXml["a:lightRig"] = lightRigObj;
45666
- }
45667
- if (s3d.hasBackdrop) {
45668
- const backdropObj = {};
45669
- if (s3d.backdropAnchorX !== void 0 || s3d.backdropAnchorY !== void 0 || s3d.backdropAnchorZ !== void 0) {
45670
- backdropObj["a:anchor"] = {
45671
- "@_x": String(s3d.backdropAnchorX ?? 0),
45672
- "@_y": String(s3d.backdropAnchorY ?? 0),
45673
- "@_z": String(s3d.backdropAnchorZ ?? 0)
45674
- };
45675
- }
45676
- scene3dXml["a:backdrop"] = backdropObj;
47095
+ const source = spPr["a:scene3d"] ?? {};
47096
+ const scene3dXml = { ...source };
47097
+ scene3dXml["a:camera"] = buildScene3dCamera(s3d, source);
47098
+ const lightRig = buildScene3dLightRig(s3d, source);
47099
+ if (lightRig) {
47100
+ scene3dXml["a:lightRig"] = lightRig;
47101
+ }
47102
+ const backdrop = buildScene3dBackdrop(s3d);
47103
+ if (backdrop) {
47104
+ scene3dXml["a:backdrop"] = backdrop;
47105
+ } else {
47106
+ delete scene3dXml["a:backdrop"];
45677
47107
  }
45678
47108
  spPr["a:scene3d"] = scene3dXml;
45679
47109
  } else {
@@ -45718,12 +47148,12 @@ var PptxHandlerRuntime29 = class extends PptxHandlerRuntime28 {
45718
47148
  }
45719
47149
  if (sh3d.extrusionColor) {
45720
47150
  sp3dXml["a:extrusionClr"] = {
45721
- "a:srgbClr": { "@_val": sh3d.extrusionColor }
47151
+ "a:srgbClr": { "@_val": sh3d.extrusionColor.replace("#", "") }
45722
47152
  };
45723
47153
  }
45724
47154
  if (sh3d.contourColor) {
45725
47155
  sp3dXml["a:contourClr"] = {
45726
- "a:srgbClr": { "@_val": sh3d.contourColor }
47156
+ "a:srgbClr": { "@_val": sh3d.contourColor.replace("#", "") }
45727
47157
  };
45728
47158
  }
45729
47159
  spPr["a:sp3d"] = sp3dXml;
@@ -45735,6 +47165,77 @@ var PptxHandlerRuntime29 = class extends PptxHandlerRuntime28 {
45735
47165
  }
45736
47166
  }
45737
47167
  };
47168
+ function buildSphereRot(lat, lon, rev) {
47169
+ if (lat === void 0 && lon === void 0 && rev === void 0) {
47170
+ return void 0;
47171
+ }
47172
+ const rot = {};
47173
+ if (lat !== void 0) {
47174
+ rot["@_lat"] = String(lat);
47175
+ }
47176
+ if (lon !== void 0) {
47177
+ rot["@_lon"] = String(lon);
47178
+ }
47179
+ if (rev !== void 0) {
47180
+ rot["@_rev"] = String(rev);
47181
+ }
47182
+ return rot;
47183
+ }
47184
+ function buildScene3dCamera(s3d, source) {
47185
+ const camera = { ...source["a:camera"] ?? {} };
47186
+ if (s3d.cameraPreset) {
47187
+ camera["@_prst"] = s3d.cameraPreset;
47188
+ }
47189
+ if (s3d.cameraFieldOfView !== void 0) {
47190
+ camera["@_fov"] = String(s3d.cameraFieldOfView);
47191
+ }
47192
+ if (s3d.cameraZoom !== void 0) {
47193
+ camera["@_zoom"] = String(s3d.cameraZoom);
47194
+ }
47195
+ const rot = buildSphereRot(s3d.cameraRotX, s3d.cameraRotY, s3d.cameraRotZ);
47196
+ if (rot) {
47197
+ camera["a:rot"] = rot;
47198
+ }
47199
+ return camera;
47200
+ }
47201
+ function buildScene3dLightRig(s3d, source) {
47202
+ const lightRig = { ...source["a:lightRig"] ?? {} };
47203
+ if (s3d.lightRigType) {
47204
+ lightRig["@_rig"] = s3d.lightRigType;
47205
+ }
47206
+ if (s3d.lightRigDirection) {
47207
+ lightRig["@_dir"] = s3d.lightRigDirection;
47208
+ }
47209
+ const rot = buildSphereRot(s3d.lightRigRotX, s3d.lightRigRotY, s3d.lightRigRotZ);
47210
+ if (rot) {
47211
+ lightRig["a:rot"] = rot;
47212
+ }
47213
+ return Object.keys(lightRig).length > 0 ? lightRig : void 0;
47214
+ }
47215
+ function buildScene3dBackdrop(s3d) {
47216
+ const hasNorm = s3d.backdropNormalX !== void 0 || s3d.backdropNormalY !== void 0 || s3d.backdropNormalZ !== void 0;
47217
+ const hasUp = s3d.backdropUpX !== void 0 || s3d.backdropUpY !== void 0 || s3d.backdropUpZ !== void 0;
47218
+ if (!s3d.hasBackdrop || !hasNorm || !hasUp) {
47219
+ return void 0;
47220
+ }
47221
+ return {
47222
+ "a:anchor": {
47223
+ "@_x": String(s3d.backdropAnchorX ?? 0),
47224
+ "@_y": String(s3d.backdropAnchorY ?? 0),
47225
+ "@_z": String(s3d.backdropAnchorZ ?? 0)
47226
+ },
47227
+ "a:norm": {
47228
+ "@_dx": String(s3d.backdropNormalX ?? 0),
47229
+ "@_dy": String(s3d.backdropNormalY ?? 0),
47230
+ "@_dz": String(s3d.backdropNormalZ ?? 0)
47231
+ },
47232
+ "a:up": {
47233
+ "@_dx": String(s3d.backdropUpX ?? 0),
47234
+ "@_dy": String(s3d.backdropUpY ?? 0),
47235
+ "@_dz": String(s3d.backdropUpZ ?? 0)
47236
+ }
47237
+ };
47238
+ }
45738
47239
 
45739
47240
  // src/core/core/runtime/PptxHandlerRuntimeSaveTextWriter.ts
45740
47241
  var PptxHandlerRuntime30 = class _PptxHandlerRuntime extends PptxHandlerRuntime29 {
@@ -47775,14 +49276,20 @@ var PptxHandlerRuntime41 = class _PptxHandlerRuntime extends PptxHandlerRuntime4
47775
49276
  relationshipType: constants.slideSyncRelationshipType,
47776
49277
  contentType: constants.slideSyncContentType
47777
49278
  });
47778
- this.slideBackgroundBuilder.applyBackground({
49279
+ await this.slideBackgroundBuilder.applyBackground({
47779
49280
  slideNode,
47780
49281
  slide,
47781
49282
  zip: this.zip,
47782
49283
  saveState: saveSession,
47783
49284
  relationshipRegistry: slideRelationshipRegistry,
47784
49285
  slideImageRelationshipType: constants.slideImageRelationshipType,
47785
- 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
+ })
47786
49293
  });
47787
49294
  this.slideCommentPartWriter.writeComments({
47788
49295
  slide,
@@ -49287,7 +50794,7 @@ var PptxHandlerRuntime51 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
49287
50794
  } = saveConstants;
49288
50795
  this.compatibilityService.resetWarnings();
49289
50796
  const saveSession = new PptxSaveStateBuilder().withZip(this.zip).withCommentAuthorMap(this.commentAuthorMap).withCommentAuthorDetails(this.commentAuthorDetails).withCommentAuthorsRootXml(this.commentAuthorsRootXml).withEmuPerPx(_PptxHandlerRuntime.EMU_PER_PX).build();
49290
- await this.reconcilePresentationSlidesForSave({
50797
+ const slideReferenceRemap = await this.reconcilePresentationSlidesForSave({
49291
50798
  slides,
49292
50799
  saveSession,
49293
50800
  slideRelationshipType,
@@ -49382,7 +50889,8 @@ var PptxHandlerRuntime51 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
49382
50889
  rawSlideWidthEmu: this.rawSlideWidthEmu,
49383
50890
  rawSlideHeightEmu: this.rawSlideHeightEmu,
49384
50891
  rawSlideSizeType: this.rawSlideSizeType,
49385
- xmlLookupService: this.xmlLookupService
50892
+ xmlLookupService: this.xmlLookupService,
50893
+ slideReferenceRemap
49386
50894
  });
49387
50895
  this.deduplicateExtensionLists(this.presentationData);
49388
50896
  if (effectiveConformance === "transitional") {
@@ -49399,7 +50907,7 @@ var PptxHandlerRuntime51 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
49399
50907
  printSlidesPerPage: options.handoutMaster.slidesPerPage
49400
50908
  } : options?.presentationProperties;
49401
50909
  await this.applyPresentationPropertiesPart(presentationProperties);
49402
- await this.applyViewPropertiesPart(options?.viewProperties);
50910
+ await this.applyViewPropertiesPart(options?.viewProperties ?? this.loadedViewProperties);
49403
50911
  await this.applyTableStylesPart(options?.tableStyles);
49404
50912
  await this.documentPropertiesUpdater.updateOnSave(slides, {
49405
50913
  coreProperties: options?.coreProperties,
@@ -49687,26 +51195,16 @@ var PptxHandlerRuntime52 = class _PptxHandlerRuntime extends PptxHandlerRuntime5
49687
51195
  return true;
49688
51196
  }
49689
51197
  const typesMatch = source.type === target.type || source.type === "ctrtitle" && target.type === "title" || source.type === "subtitle" && target.type === "body";
49690
- if (source.idx !== void 0 && target.idx !== void 0) {
49691
- if (source.idx !== target.idx) {
49692
- return false;
49693
- }
49694
- if (source.type && target.type && !typesMatch) {
49695
- return false;
49696
- }
49697
- return true;
49698
- }
49699
- if (source.idx !== void 0 && target.idx === void 0) {
49700
- const singletonTypes = /* @__PURE__ */ new Set(["title", "ctrtitle", "subtitle", "dt", "ftr", "sldnum"]);
49701
- if (source.type && singletonTypes.has(source.type)) {
49702
- return typesMatch;
49703
- }
51198
+ const sourceIdx = source.idx ?? "0";
51199
+ const targetIdx = target.idx ?? "0";
51200
+ if (sourceIdx !== targetIdx) {
49704
51201
  return false;
49705
51202
  }
49706
51203
  if (source.type && target.type && !typesMatch) {
49707
51204
  return false;
49708
51205
  }
49709
- if (source.type && !target.type) {
51206
+ const bothHaveExplicitIdx = source.idx !== void 0 && target.idx !== void 0;
51207
+ if (!bothHaveExplicitIdx && source.type && !target.type) {
49710
51208
  return false;
49711
51209
  }
49712
51210
  return true;
@@ -51152,6 +52650,19 @@ var PptxHandlerRuntime61 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
51152
52650
  });
51153
52651
  return hasAny ? locks : void 0;
51154
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
+ }
51155
52666
  /**
51156
52667
  * Extract body-level text properties from `a:bodyPr` and apply them to the
51157
52668
  * provided {@link TextStyle}. Returns linked-textbox info when present.
@@ -51334,6 +52845,62 @@ var PptxHandlerRuntime61 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
51334
52845
 
51335
52846
  // src/core/core/runtime/PptxHandlerRuntimeShapeTextParsing.ts
51336
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
+ }
51337
52904
  /**
51338
52905
  * Resolve paragraph-level styles (alignment, spacing, margins, tabs,
51339
52906
  * level styles) for a single paragraph. Modifies `textStyle` in place
@@ -51582,6 +53149,12 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
51582
53149
  ...mergedDefaultRunStyle,
51583
53150
  ...this.extractTextRunStyle(runProps, paraAlign, ctx.slideRelationshipMap)
51584
53151
  };
53152
+ if (!runStyle2.scriptFallbackFont) {
53153
+ const fallback = this.resolveScriptFallbackFont(runText);
53154
+ if (fallback) {
53155
+ runStyle2.scriptFallbackFont = fallback;
53156
+ }
53157
+ }
51585
53158
  parts.push(runText);
51586
53159
  segments.push({ text: runText, style: runStyle2 });
51587
53160
  maybeSeed(runStyle2);
@@ -51623,14 +53196,25 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
51623
53196
  )
51624
53197
  };
51625
53198
  const fldType = String(field["@_type"] || "").trim() || void 0;
51626
- 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;
51627
53203
  parts.push(fieldText);
51628
- segments.push({
53204
+ const fieldSegment = {
51629
53205
  text: fieldText,
51630
53206
  style: fieldRunStyle,
51631
53207
  fieldType: fldType,
51632
53208
  fieldGuid: fldGuid
51633
- });
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);
51634
53218
  maybeSeed(fieldRunStyle);
51635
53219
  };
51636
53220
  const processMathElement = (mathEl) => {
@@ -51757,6 +53341,11 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
51757
53341
  ...endParaRPrRaw
51758
53342
  };
51759
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
+ }
51760
53349
  }
51761
53350
  return { parts, segments, seedStyle };
51762
53351
  }
@@ -52065,7 +53654,11 @@ var PptxHandlerRuntime64 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
52065
53654
  const inheritedCNvSpPr = xmlPath(inheritedPlaceholder?.shape, "p:nvSpPr", "p:cNvSpPr") ?? xmlPath(inheritedPlaceholder?.picture, "p:nvPicPr", "p:cNvPicPr");
52066
53655
  const inheritedLockNode = inheritedCNvSpPr?.["a:spLocks"] ?? inheritedCNvSpPr?.["a:picLocks"];
52067
53656
  const inheritedLocks = this.parseShapeLocks(inheritedLockNode);
52068
- 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
+ }
52069
53662
  const promptText = !hasText && phDefaults?.promptText ? phDefaults.promptText : void 0;
52070
53663
  const opaqueExtLstXml = this.extractOpaqueSpPrExtLst(effectiveSpPr);
52071
53664
  const commonProps = {
@@ -52164,7 +53757,7 @@ var PptxHandlerRuntime65 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
52164
53757
  const skewY = xfrm["@_skewY"] ? parseEmuInt(xfrm["@_skewY"]) / 6e4 : void 0;
52165
53758
  const { flipHorizontal, flipVertical } = this.readFlipState(xfrm);
52166
53759
  const nvPr = pic?.["p:nvPicPr"]?.["p:nvPr"];
52167
- const mediaReference = parseDrawingMediaReference(nvPr);
53760
+ const mediaReference = parseDrawingMediaReference(nvPr, this.externalRelsMap.get(slidePath));
52168
53761
  if (mediaReference) {
52169
53762
  this.compatibilityService.inspectMediaReferenceCompatibility(
52170
53763
  mediaReference.kind,
@@ -52932,6 +54525,9 @@ var PptxHandlerRuntime67 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
52932
54525
  const grpSpPr = group["p:grpSpPr"];
52933
54526
  const xfrm = grpSpPr?.["a:xfrm"];
52934
54527
  let parentX = 0, parentY = 0, parentW = 0, parentH = 0;
54528
+ let groupRotation;
54529
+ let flipHorizontal = false;
54530
+ let flipVertical = false;
52935
54531
  if (xfrm) {
52936
54532
  const off = xfrm["a:off"];
52937
54533
  if (off) {
@@ -52943,6 +54539,12 @@ var PptxHandlerRuntime67 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
52943
54539
  parentW = Math.round(parseEmuInt2(ext["@_cx"]) / _PptxHandlerRuntime.EMU_PER_PX);
52944
54540
  parentH = Math.round(parseEmuInt2(ext["@_cy"]) / _PptxHandlerRuntime.EMU_PER_PX);
52945
54541
  }
54542
+ if (xfrm["@_rot"] !== void 0 && xfrm["@_rot"] !== null) {
54543
+ const rot = parseInt(String(xfrm["@_rot"]), 10) / 6e4;
54544
+ groupRotation = Number.isFinite(rot) && rot !== 0 ? rot : void 0;
54545
+ }
54546
+ flipHorizontal = this.parseBooleanAttr(xfrm["@_flipH"]);
54547
+ flipVertical = this.parseBooleanAttr(xfrm["@_flipV"]);
52946
54548
  }
52947
54549
  const grpFillStyle = grpSpPr ? this.extractShapeStyle(grpSpPr) : void 0;
52948
54550
  const hasGroupFill = grpFillStyle && grpFillStyle.fillMode && grpFillStyle.fillMode !== "none";
@@ -52988,6 +54590,9 @@ var PptxHandlerRuntime67 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
52988
54590
  y: parentY,
52989
54591
  width: parentW || Math.max(...children9.map((c) => c.x + c.width)),
52990
54592
  height: parentH || Math.max(...children9.map((c) => c.y + c.height)),
54593
+ rotation: groupRotation,
54594
+ flipHorizontal: flipHorizontal || void 0,
54595
+ flipVertical: flipVertical || void 0,
52991
54596
  children: children9,
52992
54597
  rawXml: group,
52993
54598
  actionClick: grpActionClick,
@@ -54004,9 +55609,9 @@ var PptxHandlerRuntime72 = class _PptxHandlerRuntime extends PptxHandlerRuntime7
54004
55609
  }
54005
55610
  const buClr = levelProps["a:buClr"];
54006
55611
  if (buClr) {
54007
- const srgb = buClr["a:srgbClr"];
54008
- if (srgb?.["@_val"]) {
54009
- style.bulletColor = String(srgb["@_val"]);
55612
+ const bulletColor = this.parseColor(buClr);
55613
+ if (bulletColor) {
55614
+ style.bulletColor = bulletColor;
54010
55615
  }
54011
55616
  }
54012
55617
  const buSzPts = levelProps["a:buSzPts"];
@@ -55606,16 +57211,20 @@ var PptxHandlerRuntime80 = class extends PptxHandlerRuntime79 {
55606
57211
  }
55607
57212
  let fontScheme;
55608
57213
  if (hasFonts) {
57214
+ const majorByScript = this.aggregateFontScriptOverrides(this.masterThemeMajorFontScripts);
57215
+ const minorByScript = this.aggregateFontScriptOverrides(this.masterThemeMinorFontScripts);
55609
57216
  fontScheme = {
55610
57217
  majorFont: {
55611
57218
  latin: this.themeFontMap["mj-lt"],
55612
57219
  eastAsia: this.themeFontMap["mj-ea"],
55613
- complexScript: this.themeFontMap["mj-cs"]
57220
+ complexScript: this.themeFontMap["mj-cs"],
57221
+ ...Object.keys(majorByScript).length > 0 ? { byScript: majorByScript } : {}
55614
57222
  },
55615
57223
  minorFont: {
55616
57224
  latin: this.themeFontMap["mn-lt"],
55617
57225
  eastAsia: this.themeFontMap["mn-ea"],
55618
- complexScript: this.themeFontMap["mn-cs"]
57226
+ complexScript: this.themeFontMap["mn-cs"],
57227
+ ...Object.keys(minorByScript).length > 0 ? { byScript: minorByScript } : {}
55619
57228
  }
55620
57229
  };
55621
57230
  }
@@ -55823,6 +57432,23 @@ var PptxHandlerRuntime80 = class extends PptxHandlerRuntime79 {
55823
57432
  *
55824
57433
  * Phase 4 Stream A / M4.
55825
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
+ }
55826
57452
  collectFontScriptOverrides(fontNode) {
55827
57453
  const overrides = {};
55828
57454
  if (!fontNode) {
@@ -56458,33 +58084,16 @@ var PptxHandlerRuntime83 = class extends PptxHandlerRuntime82 {
56458
58084
  const metadata = parseSmartArtDefinitionMetadata(colorsDef, localName21);
56459
58085
  const labels = parseSmartArtColorStyleLabels(colorsDef, localName21);
56460
58086
  const name = metadata.titles?.[0]?.value || String(colorsDef["@_title"] || colorsDef["@_uniqueId"] || "").trim() || void 0;
56461
- const fillColors = [];
56462
- const lineColors = [];
56463
58087
  const styleLbls = this.xmlLookupService.getChildrenArrayByLocalName(colorsDef, "styleLbl");
56464
- for (const lbl of styleLbls) {
56465
- const fillClrLst = this.xmlLookupService.getChildByLocalName(lbl, "fillClrLst");
56466
- const linClrLst = this.xmlLookupService.getChildByLocalName(lbl, "linClrLst");
56467
- if (fillClrLst) {
56468
- const color2 = this.parseColor(fillClrLst) ?? this.resolveSmartArtSchemeColor(
56469
- this.xmlLookupService.getChildByLocalName(fillClrLst, "schemeClr")
56470
- );
56471
- if (color2) {
56472
- fillColors.push(color2);
56473
- }
56474
- }
56475
- if (linClrLst) {
56476
- const color2 = this.parseColor(linClrLst) ?? this.resolveSmartArtSchemeColor(
56477
- this.xmlLookupService.getChildByLocalName(linClrLst, "schemeClr")
56478
- );
56479
- if (color2) {
56480
- lineColors.push(color2);
56481
- }
56482
- }
56483
- }
56484
- 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) {
56485
58094
  return void 0;
56486
58095
  }
56487
- return { ...metadata, name, fillColors, lineColors, labels };
58096
+ return { ...metadata, name, ...colorLists, labels };
56488
58097
  } catch {
56489
58098
  return void 0;
56490
58099
  }
@@ -56508,6 +58117,89 @@ var PptxHandlerRuntime83 = class extends PptxHandlerRuntime82 {
56508
58117
  }
56509
58118
  };
56510
58119
 
58120
+ // src/core/core/runtime/smartart-drawing-shape-style.ts
58121
+ function extractDrawingShapeFill(spPr, deps) {
58122
+ const result = {};
58123
+ const solidFill2 = deps.getChild(spPr, "solidFill");
58124
+ if (solidFill2) {
58125
+ result.fillColor = deps.parseColor(solidFill2) ?? void 0;
58126
+ }
58127
+ const gradFill = !solidFill2 ? deps.getChild(spPr, "gradFill") : void 0;
58128
+ if (gradFill) {
58129
+ const stops = deps.extractGradientStops(gradFill).map((stop) => ({
58130
+ color: stop.color,
58131
+ position: stop.position,
58132
+ ...stop.opacity !== void 0 ? { opacity: stop.opacity } : {}
58133
+ }));
58134
+ if (stops.length > 0) {
58135
+ result.fillGradientStops = stops;
58136
+ result.fillGradientType = deps.extractGradientType(gradFill);
58137
+ result.fillGradientAngle = deps.extractGradientAngle(gradFill);
58138
+ result.fillColor ??= stops[Math.floor(stops.length / 2)]?.color;
58139
+ }
58140
+ }
58141
+ const pattFill = !solidFill2 && !gradFill ? deps.getChild(spPr, "pattFill") : void 0;
58142
+ if (pattFill) {
58143
+ const preset = String(pattFill["@_prst"] || "").trim();
58144
+ if (preset) {
58145
+ result.fillPatternPreset = preset;
58146
+ }
58147
+ const fg = deps.parseColor(deps.getChild(pattFill, "fgClr"));
58148
+ const bg = deps.parseColor(deps.getChild(pattFill, "bgClr"));
58149
+ if (fg) {
58150
+ result.fillPatternForegroundColor = fg;
58151
+ }
58152
+ if (bg) {
58153
+ result.fillPatternBackgroundColor = bg;
58154
+ }
58155
+ result.fillColor ??= fg ?? bg;
58156
+ }
58157
+ const blipFill = !solidFill2 && !gradFill && !pattFill ? deps.getChild(spPr, "blipFill") : void 0;
58158
+ if (blipFill) {
58159
+ const blip = deps.getChild(blipFill, "blip");
58160
+ const embed = String(
58161
+ blip?.["@_r:embed"] || blip?.["@_embed"] || blip?.["@_r:link"] || ""
58162
+ ).trim();
58163
+ if (embed) {
58164
+ result.fillBlipEmbedId = embed;
58165
+ }
58166
+ }
58167
+ const shadowColor = deps.extractShadowColor(spPr);
58168
+ if (shadowColor) {
58169
+ result.hasShadow = true;
58170
+ result.shadowColor = shadowColor;
58171
+ }
58172
+ return result;
58173
+ }
58174
+ function extractDrawingShapeTextStyle(txBody, deps) {
58175
+ let fontSize;
58176
+ let fontColor;
58177
+ if (!txBody) {
58178
+ return { fontSize, fontColor };
58179
+ }
58180
+ const paragraphs = deps.getChildren(txBody, "p");
58181
+ for (const p of paragraphs) {
58182
+ const runs = deps.getChildren(p, "r");
58183
+ for (const r of runs) {
58184
+ const rPr = deps.getChild(r, "rPr");
58185
+ if (rPr && !fontSize) {
58186
+ const szRaw = parseInt(String(rPr["@_sz"] || ""), 10);
58187
+ if (Number.isFinite(szRaw) && szRaw > 0) {
58188
+ fontSize = szRaw / 100;
58189
+ }
58190
+ fontColor = deps.parseColor(deps.getChild(rPr, "solidFill")) ?? void 0;
58191
+ }
58192
+ if (fontSize) {
58193
+ break;
58194
+ }
58195
+ }
58196
+ if (fontSize) {
58197
+ break;
58198
+ }
58199
+ }
58200
+ return { fontSize, fontColor };
58201
+ }
58202
+
56511
58203
  // src/core/core/runtime/smartart-text-style-resolution.ts
56512
58204
  function resolveSmartArtTextStyles(paragraphs, resolve2) {
56513
58205
  for (const paragraph of paragraphs ?? []) {
@@ -56683,8 +58375,7 @@ var PptxHandlerRuntime84 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
56683
58375
  };
56684
58376
  }
56685
58377
  }
56686
- const solidFill2 = this.xmlLookupService.getChildByLocalName(spPr, "solidFill");
56687
- const fillColor = this.parseColor(solidFill2);
58378
+ const fill = extractDrawingShapeFill(spPr, this.drawingShapeStyleDeps());
56688
58379
  const lnNode = this.xmlLookupService.getChildByLocalName(spPr, "ln");
56689
58380
  const lnFill = lnNode ? this.xmlLookupService.getChildByLocalName(lnNode, "solidFill") : void 0;
56690
58381
  const strokeColor = this.parseColor(lnFill);
@@ -56696,7 +58387,10 @@ var PptxHandlerRuntime84 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
56696
58387
  this.collectLocalTextValues(txBody, "t", textValues2);
56697
58388
  }
56698
58389
  const text2 = textValues2.join("").trim() || void 0;
56699
- const { fontSize, fontColor } = this.extractDrawingShapeTextStyle(txBody);
58390
+ const { fontSize, fontColor } = extractDrawingShapeTextStyle(
58391
+ txBody,
58392
+ this.drawingShapeStyleDeps()
58393
+ );
56700
58394
  const paragraphs = txBody ? resolveSmartArtTextStyles(
56701
58395
  parseSmartArtTextParagraphs({ "dgm:t": txBody }),
56702
58396
  (rPr) => this.extractTextRunStyle(rPr, void 0, void 0, false)
@@ -56722,7 +58416,8 @@ var PptxHandlerRuntime84 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
56722
58416
  rotation,
56723
58417
  skewX,
56724
58418
  skewY,
56725
- fillColor: fillColor ?? void 0,
58419
+ ...fill,
58420
+ fillColor: fill.fillColor ?? void 0,
56726
58421
  strokeColor: strokeColor ?? void 0,
56727
58422
  strokeWidth,
56728
58423
  text: structuredText,
@@ -56732,36 +58427,126 @@ var PptxHandlerRuntime84 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
56732
58427
  ...customGeometry
56733
58428
  };
56734
58429
  }
56735
- extractDrawingShapeTextStyle(txBody) {
56736
- let fontSize;
56737
- let fontColor;
56738
- if (!txBody) {
56739
- return { fontSize, fontColor };
56740
- }
56741
- const paragraphs = this.xmlLookupService.getChildrenArrayByLocalName(txBody, "p");
56742
- for (const p of paragraphs) {
56743
- const runs = this.xmlLookupService.getChildrenArrayByLocalName(p, "r");
56744
- for (const r of runs) {
56745
- const rPr = this.xmlLookupService.getChildByLocalName(r, "rPr");
56746
- if (rPr && !fontSize) {
56747
- const szRaw = parseInt(String(rPr["@_sz"] || ""), 10);
56748
- if (Number.isFinite(szRaw) && szRaw > 0) {
56749
- fontSize = szRaw / 100;
56750
- }
56751
- const rprFill = this.xmlLookupService.getChildByLocalName(rPr, "solidFill");
56752
- fontColor = this.parseColor(rprFill) ?? void 0;
56753
- }
56754
- if (fontSize) {
56755
- break;
56756
- }
56757
- }
56758
- if (fontSize) {
56759
- break;
58430
+ /**
58431
+ * Build the injected accessor bundle used by the pure drawing-shape style
58432
+ * helpers, binding the shared XML-lookup / colour / gradient / shadow codec
58433
+ * methods so no new colour logic is duplicated here.
58434
+ */
58435
+ drawingShapeStyleDeps() {
58436
+ return {
58437
+ getChild: (node, local) => this.xmlLookupService.getChildByLocalName(node, local),
58438
+ getChildren: (node, local) => this.xmlLookupService.getChildrenArrayByLocalName(node, local),
58439
+ parseColor: (node) => this.parseColor(node),
58440
+ extractGradientStops: (gradFill) => this.extractGradientStops(gradFill),
58441
+ extractGradientType: (gradFill) => this.extractGradientType(gradFill),
58442
+ extractGradientAngle: (gradFill) => this.extractGradientAngle(gradFill),
58443
+ extractShadowColor: (spPr) => this.extractShadowStyle(spPr).shadowColor
58444
+ };
58445
+ }
58446
+ };
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);
56760
58488
  }
56761
58489
  }
56762
- return { fontSize, fontColor };
58490
+ } catch {
56763
58491
  }
56764
- };
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
+ }
56765
58550
 
56766
58551
  // src/core/core/runtime/smartart-layout-category.ts
56767
58552
  var CATEGORY_FAMILY = {
@@ -56898,6 +58683,7 @@ var PptxHandlerRuntime85 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
56898
58683
  layoutDefinition,
56899
58684
  nodes,
56900
58685
  connections: parsedConnections.length > 0 ? parsedConnections : void 0,
58686
+ presLayoutVars: parseSmartArtPresLayoutVars(dataModel),
56901
58687
  drawingShapes: drawingShapes.length > 0 ? drawingShapes : void 0,
56902
58688
  chrome,
56903
58689
  colorTransform,
@@ -56976,30 +58762,28 @@ var PptxHandlerRuntime85 = class _PptxHandlerRuntime extends PptxHandlerRuntime8
56976
58762
  }
56977
58763
  }
56978
58764
  /**
56979
- * Parse SmartArt drawing shapes given an absolute part path.
58765
+ * Parse cached SmartArt drawing shapes from an absolute part path.
56980
58766
  *
56981
- * Wraps `parseSmartArtDrawingShapes` (which expects a slide-relative
56982
- * relationship id) with a path-based lookup so the resolution layer
56983
- * 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.
56984
58770
  */
56985
58771
  async parseSmartArtDrawingShapesFromPath(drawingPath) {
56986
- const xmlString = await this.zip.file(drawingPath)?.async("string");
56987
- if (!xmlString) {
56988
- return [];
56989
- }
56990
- try {
56991
- const xml = this.parser.parse(xmlString);
56992
- const drawing = this.xmlLookupService.getChildByLocalName(xml, "drawing");
56993
- const spTree = this.xmlLookupService.getChildByLocalName(drawing || xml, "spTree");
56994
- if (!spTree) {
56995
- return [];
56996
- }
56997
- const shapes = this.xmlLookupService.getChildrenArrayByLocalName(spTree, "sp");
56998
- const emuPerPx = _PptxHandlerRuntime.EMU_PER_PX;
56999
- return shapes.map((sp, index) => this.parseDrawingShape(sp, index, emuPerPx)).filter((entry) => entry !== null);
57000
- } catch {
57001
- return [];
57002
- }
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
+ };
57003
58787
  }
57004
58788
  };
57005
58789
 
@@ -57697,6 +59481,11 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
57697
59481
  grouping = "clustered";
57698
59482
  }
57699
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");
57700
59489
  const chartPartPath = chartPart.partPath;
57701
59490
  const dataTable = parseDataTable(plotArea, this.xmlLookupService);
57702
59491
  const dropLines = parseLineStyle(
@@ -57773,6 +59562,11 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
57773
59562
  title: titleTextValues[0],
57774
59563
  style: chartStyle,
57775
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 } : {},
57776
59570
  chartPartPath,
57777
59571
  chartRelationshipId,
57778
59572
  ...dataTable ? { dataTable } : {},
@@ -57849,6 +59643,35 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
57849
59643
  }
57850
59644
  return { categories, series };
57851
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
+ }
57852
59675
  /**
57853
59676
  * Build the series array from raw OOXML `c:ser` nodes.
57854
59677
  *
@@ -57892,6 +59715,10 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
57892
59715
  );
57893
59716
  const dataLabels = parseSeriesDataLabels(seriesNode, this.xmlLookupService);
57894
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;
57895
59722
  return {
57896
59723
  name: seriesName.trim().length > 0 ? seriesName : `Series ${seriesIndex + 1}`,
57897
59724
  values: fallbackValues,
@@ -57902,6 +59729,8 @@ var PptxHandlerRuntime90 = class extends PptxHandlerRuntime89 {
57902
59729
  ...seriesMarker ? { marker: seriesMarker } : {},
57903
59730
  ...dataLabels.length > 0 ? { dataLabels } : {},
57904
59731
  ...explosion !== void 0 ? { explosion } : {},
59732
+ ...invertIfNegative !== void 0 ? { invertIfNegative } : {},
59733
+ ...smooth !== void 0 ? { smooth } : {},
57905
59734
  ...axisId !== void 0 ? { axisId } : {},
57906
59735
  ...seriesChartType ? { seriesChartType } : {}
57907
59736
  };
@@ -58728,6 +60557,8 @@ var PptxHandlerRuntime94 = class extends PptxHandlerRuntime93 {
58728
60557
  async buildLoadData(presentationState, slidesWithWarnings, slideMasters) {
58729
60558
  const headerFooter = this.extractHeaderFooter();
58730
60559
  const presentationProperties = await this.parsePresentationProperties();
60560
+ const viewProperties = await this.parseViewProperties();
60561
+ this.loadedViewProperties = viewProperties;
58731
60562
  const customShows = this.parseCustomShows();
58732
60563
  const tableStyleMap = await this.parseTableStyles();
58733
60564
  const embeddedFontList = parseEmbeddedFontList(this.presentationData);
@@ -58757,7 +60588,7 @@ var PptxHandlerRuntime94 = class extends PptxHandlerRuntime93 {
58757
60588
  presentationState.height,
58758
60589
  this.rawSlideWidthEmu,
58759
60590
  this.rawSlideHeightEmu
58760
- ).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(
58761
60592
  presentationState.orderedSections.length > 0 ? presentationState.orderedSections : void 0
58762
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(
58763
60594
  this.signatureDetection?.signatureCount && this.signatureDetection.signatureCount > 0 ? this.signatureDetection.signatureCount : void 0
@@ -58888,6 +60719,7 @@ var PptxHandlerRuntime94 = class extends PptxHandlerRuntime93 {
58888
60719
  this.customXmlParts = [];
58889
60720
  this.loadedEmbeddedFonts = [];
58890
60721
  this.loadedEmbeddedFontList = void 0;
60722
+ this.loadedViewProperties = void 0;
58891
60723
  this.orderedSlidePaths = [];
58892
60724
  this.zip = null;
58893
60725
  }
@@ -59233,6 +61065,7 @@ var PptxHandlerRuntime95 = class _PptxHandlerRuntime extends PptxHandlerRuntime9
59233
61065
  });
59234
61066
  this.mediaDataParser = new PptxMediaDataParser({
59235
61067
  slideRelsMap: this.slideRelsMap,
61068
+ externalRelsMap: this.externalRelsMap,
59236
61069
  resolvePath: (base, relative) => this.resolvePath(base, relative),
59237
61070
  getPathExtension: (pathValue) => this.getPathExtension(pathValue)
59238
61071
  });